Public record
Software health reportschema 0.27.0 · metrics 1.13.0 · 2026-07-28 10:08 UTC

wso2 / open-cloud-datacenter

Open cloud datacenter initiative

HCLApache-2.0★ 7 stars⑂ 12 forkssince Feb 2026View on GitHub ↗

wso2/open-cloud-datacenter holds a health index of 66 out of 100, placing it in the Moderate band. It scores highest on Vitality (85/100) and lowest on AI Readiness (26/100). It was last updated 1 day ago. A single contributor accounts for most of its recent work.

66
overall / 100
Moderate

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At risk ceiling of 49. AI Readiness sits outside the overall score.

66
Excellent85-100Exemplary; meets essentially all checked criteria
Good70-84Healthy; minor gaps
Moderate50-69Acceptable with notable gaps; review recommended
At risk30-49Significant weaknesses; adoption warrants caution
Critical1-29Severe problems (abandoned, single-maintainer, no hygiene)
VitalityCommunity &AdoptionSustainability &GovernanceEngineeringQualitySecurityAI Readiness

Score profile

Each axis is a category. The shape matters more than the average — a healthy subject fills the whole shape, while a spike-and-crater profile means strength in one dimension is masking risk in another.

Ownership

WSO2Organization
1,731 followers383 public repossince Dec 2010

This repository is backed by an organization — shared, accountable stewardship that can outlive any single maintainer.

Metrics by category

Vitality

Is the project alive — is code being written and are releases shipping?

85Excellent · 22% of overall
How it's scored
36/36Push recency — last push 1 days ago
11.1/36Commit cadence — 16/52 weeks with commits
18/18Commit volume — 173 commits in the last year
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Inputs used
commits_last_year173
human_commit_share1
days_since_last_push1
active_weeks_last_year16

Release discipline

100Excellent
How it's scored
27/27Ships releases — 34 releases published
36/36Release recency — latest release 4 days ago
27/27Release cadence — a release every ~6.3 days
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count34
latest_release_tagterraform/v0.1.9
releases_from_tagsno
days_since_latest_release4
mean_days_between_releases6.3
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.

Community & Adoption

Does the project have users, downloads, attention, and a welcoming setup for contributors?

58Moderate · 18% of overall
How it's scored
12.6/60Stars — 7 stars
8.7/25Forks — 12 forks
0/15Watchers — 1 watchers
Inputs used
forks12
stars7
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

Community health

100Excellent
How it's scored
22.5/22.5README
22.5/22.5License — recognized license (Apache-2.0)
18/18CONTRIBUTING guide
13.5/13.5Code of conduct
7.2/7.2Issue template
6.3/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
has_contributingyes
has_issue_templateyes
has_code_of_conductyes
has_pull_request_templateyes

Sustainability & Governance

Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?

60Moderate · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
7.3/22.5Commit distribution — top contributor authored 68% of commits
9.5/13.5Contributor breadth — 7 contributors
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Inputs used
bus_factor1
contributors_sampled7
top_contributor_share0.677
How it's scored
27.1/46.8Issue resolution — 58% of issues closed
36.1/38.3PR acceptance — 167/177 decided PRs merged
15/15OpenSSF Scorecard: Code-Review — all changesets reviewed
Inputs used
merged_prs167
open_issues21
closed_issues29
issue_closed_ratio0.58
closed_unmerged_prs10
How it's scored
30/30Ownership backing — organization-owned
0/20Verified domain
23.3/25Owner reach — 1,731 followers of wso2
25/25Track record — 383 public repos, account ~15 yr old
Inputs used
followers1,731
owner_typeOrganization
is_verified
owner_loginwso2
public_repos383
account_age_days5,697

Engineering Quality

Are baseline engineering and documentation practices in place?

58Moderate · 20% of overall
How it's scored
24/24CI workflows — 2 workflow(s)
0/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
12/20OpenSSF Scorecard: CI-Tests — 10 out of 15 merged PRs checked by a CI test -- score normalized to 6
Inputs used
has_ciyes
has_testsno
has_editorconfigno
has_linter_configno
has_precommit_configno

Documentation

90Excellent
How it's scored
30/30README
25/25Documentation directory
15/15Documentation / homepage site — https://github.com/wso2/open-cloud-datacenter
10/10Repository description
10/10Topics — 2 topics
0/10Wiki
Inputs used
topicsasgardeo, choreo
has_wikino
homepagehttps://github.com/wso2/open-cloud-datacenter
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

Are visible security and supply-chain practices strong, without unresolved high-risk jurisdiction exposure?

67Moderate · 16% of overall
How it's scored
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — no data
1.5/2.5CI-Tests — 10 out of 15 merged PRs checked by a CI test -- score normalized to 6
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
7.5/7.5Code-Review — all changesets reviewed
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5License — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — no data
5/5Pinned-Dependencies — all dependencies are pinned
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — no data
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate6.7
Excluded from scoring (no data or not applicable): branch_protection, packaging, signed_releases. Remaining weights renormalized.

AI Readiness

How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score.

26Critical · 0% of overall
How it's scored
0/45Agent instructions — no CLAUDE.md / AGENTS.md / editor rules
0/15Machine-readable docs (llms.txt)
40/40Legible commit history — 88 of 100 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtno
legible_history_share0.88
agent_instruction_files
agent_instruction_max_bytes
How it's scored
0/18One-command bootstrap
0/22Automated tests
0/11Lint / format config
0/11Static type checking
0/10Reproducible environment
10/10Demonstrated agent practice — 68 of the last 100 commits agent-authored or agent-credited
0/8Automated maintenance — no automated dependency updates observed
10/10OpenSSF Scorecard: Pinned-Dependencies — all dependencies are pinned
Inputs used
has_nixno
has_testsno
lockfiles
has_dockerfileno
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0.68
toolchain_manifests
dependency_bot_commit_share0
How it's scored
0/45Type-checkable code — HCL without a type-check config
0/55Manageable file sizes — no source files detected
Inputs used
primary_languageHCL
largest_source_bytes
source_files_sampled0
oversized_source_files0
Excluded from scoring (no data or not applicable): Manageable file sizes. Remaining weights renormalized.
How it's scored
0/40API schema (OpenAPI/GraphQL/proto)
0/20MCP server
40/40Runnable examples — examples
Inputs used
example_dirsexamples
has_mcp_signalno
api_schema_files

Key facts

7GitHub stars
7contributors
173commits, last 12 months
1days since last push
34releases
1bus factor
21open issues
package ecosystems

Data collection warnings

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

More detail

Star and fork history 0 ★ / 12 ⇿
0Stars
12Forks
27Releases

When each star and fork was added, collected from GitHub and bucketed by day. Cumulative growth sits directly above the daily additions it is made of, so the two read against each other: steady organic accretion looks nothing like an abrupt, short-lived burst. Where that difference is measurable, it is reported as growth authenticity.

246810121222026-022026-042026-06
Major 0Minor 8Patch 16
OpenSSF Scorecard 6.7 / 10
6.7aggregate

Independent, tool-agnostic security assessment from the open-source OpenSSF Scorecard. Each check rewards a security practice, not a specific vendor's tool. Checks Scorecard could not determine are marked n/a and excluded from the security score (never counted as zero).Scorecard v5.5.0 · 2026-07-28 10:08 UTC

10Binary-Artifactsno binaries found in the repo
n/aBranch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
6CI-Tests10 out of 15 merged PRs checked by a CI test -- score normalized to 6
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
10Code-Reviewall changesets reviewed
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
n/aPackagingpackaging workflow not detected
10Pinned-Dependenciesall dependencies are pinned
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
n/aSigned-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
10Vulnerabilities0 existing vulnerabilities detected
All dependencies not collected

The resolved dependency set could not be collected for this report: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Raw JSON report machine-readable
{
  "data": {
    "repo": {
      "topics": [
        "asgardeo",
        "choreo"
      ],
      "is_fork": false,
      "size_kb": 5404,
      "has_wiki": false,
      "homepage": "https://github.com/wso2/open-cloud-datacenter",
      "languages": {
        "HCL": 371036,
        "Shell": 25622,
        "Smarty": 7856,
        "Go Template": 4789
      },
      "pushed_at": "2026-07-27T09:22:47Z",
      "created_at": "2026-02-02T05:22:04Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-27T04:59:22Z",
      "description": "Open cloud datacenter initiative",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "HCL",
      "significant_languages": [
        "HCL"
      ]
    },
    "owner": {
      "blog": "https://wso2.com",
      "name": "WSO2",
      "type": "Organization",
      "login": "wso2",
      "company": null,
      "location": "787 Castro Street, Mountain View, CA 94041",
      "followers": 1731,
      "avatar_url": "https://avatars.githubusercontent.com/u/533043?v=4",
      "created_at": "2010-12-22T08:54:38Z",
      "is_verified": null,
      "public_repos": 383,
      "account_age_days": 5697
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "terraform/v0.1.9",
          "kind": "other",
          "published_at": "2026-07-24T04:47:13Z"
        },
        {
          "tag": "terraform/v0.1.8",
          "kind": "other",
          "published_at": "2026-07-13T05:55:24Z"
        },
        {
          "tag": "terraform/v0.1.7",
          "kind": "other",
          "published_at": "2026-06-30T10:31:05Z"
        },
        {
          "tag": "terraform/v0.1.6",
          "kind": "other",
          "published_at": "2026-06-30T08:27:45Z"
        },
        {
          "tag": "terraform/v0.1.5",
          "kind": "other",
          "published_at": "2026-06-26T04:17:50Z"
        },
        {
          "tag": "terraform/v0.1.4",
          "kind": "other",
          "published_at": "2026-06-22T05:16:12Z"
        },
        {
          "tag": "terraform/v0.1.3",
          "kind": "other",
          "published_at": "2026-06-18T12:18:14Z"
        },
        {
          "tag": "terraform/v0.1.2",
          "kind": "other",
          "published_at": "2026-05-29T10:47:24Z"
        },
        {
          "tag": "terraform/v0.1.1",
          "kind": "other",
          "published_at": "2026-05-29T05:53:07Z"
        },
        {
          "tag": "terraform/v0.1.0",
          "kind": "other",
          "published_at": "2026-05-28T10:22:30Z"
        },
        {
          "tag": "v0.8.3",
          "kind": "patch",
          "published_at": "2026-05-25T15:02:33Z"
        },
        {
          "tag": "v0.8.2",
          "kind": "patch",
          "published_at": "2026-05-25T10:49:26Z"
        },
        {
          "tag": "v0.8.1",
          "kind": "patch",
          "published_at": "2026-05-25T05:15:42Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-05-19T06:16:11Z"
        },
        {
          "tag": "v0.7.9",
          "kind": "patch",
          "published_at": "2026-05-18T15:11:19Z"
        },
        {
          "tag": "v0.7.8",
          "kind": "patch",
          "published_at": "2026-05-15T10:28:07Z"
        },
        {
          "tag": "v0.7.7",
          "kind": "patch",
          "published_at": "2026-05-15T04:00:00Z"
        },
        {
          "tag": "v0.7.6",
          "kind": "patch",
          "published_at": "2026-05-06T07:40:02Z"
        },
        {
          "tag": "v0.7.5",
          "kind": "patch",
          "published_at": "2026-04-28T13:55:26Z"
        },
        {
          "tag": "v0.7.4",
          "kind": "patch",
          "published_at": "2026-04-21T08:50:02Z"
        },
        {
          "tag": "v0.7.3",
          "kind": "patch",
          "published_at": "2026-04-21T05:20:12Z"
        },
        {
          "tag": "v0.7.2",
          "kind": "patch",
          "published_at": "2026-04-17T11:41:20Z"
        },
        {
          "tag": "v0.7.1",
          "kind": "patch",
          "published_at": "2026-04-16T05:55:38Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-04-16T03:32:30Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-04-10T11:37:11Z"
        },
        {
          "tag": "v0.5.8",
          "kind": "patch",
          "published_at": "2026-04-09T09:33:16Z"
        },
        {
          "tag": "v0.5.7",
          "kind": "patch",
          "published_at": "2026-04-07T17:48:40Z"
        },
        {
          "tag": "v0.5.6",
          "kind": "patch",
          "published_at": "2026-04-03T05:21:06Z"
        },
        {
          "tag": "v0.5.5",
          "kind": "patch",
          "published_at": "2026-04-02T07:38:30Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-03-31T08:31:53Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-03-30T05:15:38Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-03-27T17:15:18Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-03-27T01:59:56Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-03-13T04:48:11Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "25cb78eacee2ae426e3171b1113f24f1f46bb586",
          "body": null,
          "is_bot": false,
          "headline": "fix: update the precondition check and namespace quota divided nonzeoro",
          "author_name": "sathindudezoysa",
          "author_login": "sathindudezoysa",
          "committed_at": "2026-07-27T04:59:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0f580e76be15c0348ed240a77775abae313b8e2",
          "body": null,
          "is_bot": false,
          "headline": "fix: the auto split namespaces getting near zero resources",
          "author_name": "sathindudezoysa",
          "author_login": "sathindudezoysa",
          "committed_at": "2026-07-27T04:59:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e8d4b2c7eb567e57e4dc4852a19a373388dba49",
          "body": "…project quota limits",
          "is_bot": false,
          "headline": "fix: set default namespace limits and set unit validation check with …",
          "author_name": "sathindudezoysa",
          "author_login": "sathindudezoysa",
          "committed_at": "2026-07-27T04:59:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "73ded4dd7b2d608de63cf5ec7d2bca5db7eefefa",
          "body": null,
          "is_bot": false,
          "headline": "fix: add preflight validation for namespace resource quotas",
          "author_name": "sathindudezoysa",
          "author_login": "sathindudezoysa",
          "committed_at": "2026-07-27T04:59:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67b3d7fe516f5af519fde5be4fd5903724e3b4d4",
          "body": "CodeRabbit reads its configuration only from the repository's default\nbranch, so base_branches must be set here on main. Without it, CodeRabbit\nuses dashboard defaults and reviews only the default branch, skipping\npull requests targeting the long-lived controlplane, terraform,\noperators, and terrafo\n[…]\nis supersedes the per-branch .coderabbit.yaml files added earlier;\nthey live on non-default branches and are therefore never read.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Enable CodeRabbit on non-default branches",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-06-26T04:58:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "142a6ae7d5d547dad9c47f6340ff82c3fe67e13d",
          "body": "The repository PR template was the generic WSO2-product template\n(Certification, Marketing, Training, FindSecurityBugs, a JDK/DB/browser\ntest matrix, ...). Almost none of it applies to this repo's products —\nthe Go control plane, the Terraform module catalog, or the operators —\nso contributors faced\n[…]\ner-repo names).\n\nGitHub serves the PR template only from the default branch, so this\nsingle file governs PRs against every branch.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Replace the legacy PR template with a lean one",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-06-11T08:12:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "73db130de358640948c900fcd78da90d03e2a4f9",
          "body": "Add short dcctl and cloud-ui VNet-creation clips to the entry-point README, laid out side by side so the two demos stay compact.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add CLI and console demo clips to the README",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-30T12:13:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "686e76842e7aaf3dd6cacaa7ed7e4e4fdb72e271",
          "body": "Repurpose the deprecated main branch as the repository's front door.\nGitHub renders this branch's README first, so it now opens with a\nbranch-navigation map and the OCD roadmap instead of Terraform module\nusage (which belongs on the terraform branch).\n\n  - ASCII diagram + table mapping the terraform\n[…]\nES.md for detail.\n\nmain carries no code; the previous Terraform-flavored README content\nremains available on the terraform branch.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Make main the repo entry point and roadmap",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-30T09:22:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1cbfa40f8e0ddb1b9d3d00def3abeb4bc875043d",
          "body": "Add structured issue forms under .github/ISSUE_TEMPLATE so issues\nare filed with consistent, triage-ready fields:\n\n  - 01-bug: area, description, repro steps, severity, version\n  - 02-improvement: area, current limitation, suggested improvement\n  - 03-task: area, description, related issues\n  - 04-e\n[…]\nform auto-applies its Type/* label. The broader label taxonomy\nis managed in repository settings, not in this change.\n\nCloses #127\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add GitHub issue form templates",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-30T04:56:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "81062c591e091a824e592e890fee17abf62f01a5",
          "body": "Four fixes from automated review:\n\n* dc-controlplane-services: cloud-ui probe path is now configurable\n  via cloudui_health_path. Default stays /healthz because the wso2\n  cloud-ui image's nginx.conf serves it; consumers that ship a stock\n  nginx-unprivileged image (no /healthz) override to /.\n\n* dc\n[…]\nts.\n\n* dc-controlplane: vm_storage_class_override is trimspace'd before\n  the empty-string check so a whitespace-only override no longer\n  wins precedence and propagates an invalid storage class name.",
          "is_bot": false,
          "headline": "Address CodeRabbit feedback on PR #107",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-27T03:23:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3f6672f2174fb2b3390c2a0f64880e98d75962b2",
          "body": "Convert the dc-controlplane RKE2 cluster to a 3-node HA layout with\nkube-vip serving the apiserver VIP, and bring the cloud-ui Deployment\n+ Service + Ingress into the dc-controlplane-services module so a\ncluster rebuild restores routing without waiting for the cloud-ui CI\nworkflow.\n\nStorage:\n\n* Crea\n[…]\ns\n  >= 1.7.\n\n* Apply trimspace() to user_data + storage_class_name override\n  checks in workloads/k8s-cluster so whitespace-only inputs fall\n  through to defaults instead of masking as real overrides.",
          "is_bot": false,
          "headline": "Add 3-node HA dc-controlplane + cloud-ui in TF",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-27T03:23:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5c3b20ae132f0230d94d15c0574fa6d30a1e68c1",
          "body": "…ole binding for_each",
          "is_bot": false,
          "headline": "Fix same network multi attachemnts + static principal+index key for r…",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-25T15:02:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "82661f446182d20418ed0dc33b8f79414efa644d",
          "body": null,
          "is_bot": false,
          "headline": "Fix description with uuid instead of email",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-25T10:48:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a12ae12bea06d601d62cbb22681d57234ab5e90",
          "body": null,
          "is_bot": false,
          "headline": "Add user_principal_id and user_id support for tenant role bindings",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-25T10:48:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "63caf20827baf5d28480fc7e3295b48480216694",
          "body": null,
          "is_bot": false,
          "headline": "Address code rabbit issue regarding userdata template",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-25T05:14:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67a7e1f8ea8de48947734b9b882e030b93b4c31b",
          "body": null,
          "is_bot": false,
          "headline": "Addressing code rabbit concerns",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-25T05:14:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f66b284a28ab000608371b64fa5b9be30e4baa9a",
          "body": "… tenants",
          "is_bot": false,
          "headline": "Feat: DHCP support for storage network + restricted images access for…",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-25T05:14:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "91ee1ffafd8c7ebe144867f42935f07d6d00970d",
          "body": null,
          "is_bot": false,
          "headline": "Fix: bug when using harvester cluster name instead of id",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-25T05:14:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fdddf3581607be9d86f9b3f177bfc4467a3cede7",
          "body": "Two fixes from the review on the OCD PR:\n\n  * main.tf: base64-decode harvester_kubeconfig_b64 before storing\n    it in the kubernetes_secret data field. The kubernetes provider\n    auto-base64-encodes whatever string is passed into data, so the\n    live Secret was holding base64-of-base64 — the webh\n[…]\nin description said\n    \"ValidatingWebhookConfiguration\" but the module creates a\n    MutatingWebhookConfiguration. Word-fix only.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Address CodeRabbit review on dc-webhook module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-19T06:15:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f89a6ad73be61c8b9822bea0787862f968d7a2b9",
          "body": "KubeVirt admission webhook that pins VM NIC MAC addresses for tenants\nwhose workloads sit behind a kube-ovn LB. Without MAC pinning,\nKubeVirt regenerates NIC MACs on VM restart, which breaks\nsticky-by-MAC connections that depend on a stable backend.\n\nThe module covers:\n  * Deployment + Service for t\n[…]\n's\nenvironments/<env>/02-dc-webhooks layer instantiates this module\nper-environment with the appropriate kubeconfig and image SHA.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add dc-webhook module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-19T06:15:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "49e9eab3cf988b23468eb56d84680bb1622e5ad0",
          "body": "A batch of dc-controlplane-services module changes that surfaced\nwhile verifying a real-world consumer's plan. Together they push\nevery per-environment knob out of consumer layers and into the\nmodule, so consumers only pass parameters going forward.\n\nChanges:\n\n  * Eight BFF input variables (bff_clie\n[…]\n terraform validate clean; terraform plan\nagainst a representative dev environment shows only intentional\nchanges; apply succeeds.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Land BFF, VPC, hostname, env-order and lifecycle fixes",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-19T06:15:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e58680e1cc75d709e6781363f14d67b1a353eed6",
          "body": "Introduce a self-signed RSA-4096 certificate (1-year validity) via the\nhashicorp/tls provider. The cert covers dcapi.lk.internal.wso2.com and\n*.lk.internal.wso2.com. A kubernetes.io/tls Secret (dc-api-tls) is\ncreated in dc-system and referenced by the Ingress tls block so\nnginx-ingress serves HTTPS on port 443.\n\nPort-80 rules are preserved unchanged. No new variables are required.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add TLS termination to dc-api ingress",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-19T06:15:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2f931c065aa19c25671ff70d21cb2c9cee377158",
          "body": null,
          "is_bot": false,
          "headline": "Introduce support to provision RKE2 clusters with dynamic harvester",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-18T14:37:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "04c160cf16ace509ac793dc3d4fc216cf9bedbb0",
          "body": "Bind tenant SAs to harvesterhci.io:csi-driver for RWX",
          "is_bot": false,
          "headline": "Merge pull request #98 from wso2/fix/97-csi-driver-clusterrolebinding",
          "author_name": "Deependra Ariyadewa",
          "author_login": "gnudeep",
          "committed_at": "2026-05-15T10:17:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4d942a597f9fbd92d7b667a57b63120cf672dcd6",
          "body": "PR #96 added a custom harvester-cloud-provider-rwx ClusterRole and\ntwo namespaced RoleBindings to cover networkfilesystems + longhorn\nvolumes. End-to-end testing on kasun-test-cluster after that landed\nshowed RWX PVCs went Bound but pods failed to mount with\n`Failed to get NetworkFS ...: not found`.\n[…]\n logs quiet\non already-provisioned tenants. Namespace deletion explicitly removes\nthe ClusterRoleBinding since cluster-scoped resources are not GC'd\nwhen their tenant namespace is removed.\n\nCloses #97",
          "is_bot": false,
          "headline": "Bind tenant SAs to harvesterhci.io:csi-driver for RWX",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-15T10:10:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "96db11551a95e31da82f9e4382c36e3810f89f0f",
          "body": null,
          "is_bot": false,
          "headline": "fix: typo in comment - coderabbit",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-15T06:50:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7593a6683d904c7d745ca1c0c36c32ed8c3dbaba",
          "body": null,
          "is_bot": false,
          "headline": "fix: remove label platform role from default namespace",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-15T06:50:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "416557c14cdca2d021c51ea5ee9edb48c8eb367e",
          "body": null,
          "is_bot": false,
          "headline": "fix: addrss coderabbit issues",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-15T06:50:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba18d94f0b5a4612a36e2f7dec4f0f53d25f0cf0",
          "body": null,
          "is_bot": false,
          "headline": "fix: management/tenant-module quota management + vm module enhancements",
          "author_name": "iamtrazy",
          "author_login": "iamtrazy",
          "committed_at": "2026-05-15T06:50:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3dddc058ca07466f771724fd2b3c21ecf02890da",
          "body": "The harvester-csi-driver running on guest RKE2 clusters probes\nnetworkfilesystems.harvesterhci.io and volumes.longhorn.io on the\nhost Harvester cluster at startup. On a Forbidden response it\nsilently disables RWX support and only advertises SINGLE_NODE_WRITER,\nso every subsequent RWX CreateVolume fa\n[…]\nnamespace, backfills them in the init pass\nfor already-provisioned namespaces, and removes them in\non_deleted_namespace. All operations use the existing idempotent\n`kubectl apply` pattern.\n\nCloses #95",
          "is_bot": false,
          "headline": "Grant tenant cloud-provider SAs RWX RBAC on Harvester",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-15T03:59:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ed820b15c09815f0ee714dad93f970dfbb0bd2ac",
          "body": "Two findings from CodeRabbit on PR #93:\n\n1. Avoid fixed runtime files under path.module\n   The helm kubeconfig and dc-runner values files used hardcoded names\n   in the module source dir, which would collide if the module is\n   instantiated more than once or two applies share a checkout. Append\n   a\n[…]\n--values) so values containing\n   spaces don't break the command line. Destroy guards no-op via an\n   if [[ -z … ]] short-circuit.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Address CodeRabbit review on helm CLI bypass",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-10T13:04:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e5a9c5f92f047742c63b29d4f42f541ab4a5b038",
          "body": "The TF helm provider repeatedly fails when posting the ARC controller's\nrelease Secret through Rancher 2.14's cluster-router proxy with\n\"http: request body too large\" — even with public-api-body-limit and\nthe rancher Ingress proxy-body-size both raised to 50Mi/50m. The\ncluster-router has its own har\n[…]\n hashicorp/local and hashicorp/null providers in versions.tf\n  - destroy-time helm uninstall provisioners with on_failure=continue\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bypass helm provider with helm CLI for ARC chart install",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-10T13:04:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "32a4e6c2fa7fe583335a35f60b0313d5bccb1444",
          "body": "Add PostgreSQL liveness probe so Kubernetes can restart a hung or\ndeadlocked Postgres process; readiness alone only gates traffic.\n\nAdd pod-security.kubernetes.io/enforce=privileged label to the\narc-runners namespace so dind runner pods are not silently blocked\nby PSA admission on clusters with non-default security policies.\nThe dind container mode is preserved as the runner may need Docker\nbuild capabilities in future workflows.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(dc-controlplane-services): address CodeRabbit review",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-06T05:01:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "33c7b3f1dca73920813fc1eade56c7c78ff684ad",
          "body": "tenant-space requires kubernetes.harvester via configuration_aliases.\ndc-controlplane must declare it in required_providers and forward it\nto module \"project\" via the providers meta-argument.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Wire kubernetes.harvester provider through dc-controlplane",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-06T05:01:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e25677b1e4001342ecc93abc29997f0888396532",
          "body": "Rancher injects cattle.io/status, lifecycle.cattle.io/create.namespace-auth,\nand field.cattle.io/publicEndpoints automatically. kube-vip injects\nkube-vip.io/loadbalancerIPs and kube-vip.io/vipHost on the ingress LB\nservice. Without lifecycle ignore_changes, terraform plan always shows\nthese as diffs to remove even though the apply is a no-op.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Ignore Rancher/kube-vip managed annotations on k8s resources",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-06T05:01:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2a1bb84cae6c42b1ca4059f07cb17073f01f1fb2",
          "body": "- Fix invalid trim() call: use trimspace() in credential_namespace\n  validation (trim() requires two args; trimspace() strips whitespace)\n- Drop namespaces from dc-api-deployer Role: namespaces is cluster-\n  scoped and silently ineffective inside a namespace-scoped Role\n- Add validation block to log_level variable: enforce the four allowed\n  values so typos fail at plan time instead of propagating to the\n  ConfigMap\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Address CodeRabbit review on dc-controlplane-services",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-06T05:01:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3355d9fc6a64da7642f5d4e6e2ff6787415f947b",
          "body": "dc-controlplane: wraps the RKE2 cluster, Harvester NAD, and LB\nIPPool for the DC-API control plane. Includes the kubectl patch\nthat sets selector.scope on the IPPool (workaround until the\nHarvester provider exposes the field declaratively).\n\ndc-controlplane-services: wraps all workloads that run on \n[…]\nster — PostgreSQL StatefulSet, DC-API Deployment and\nIngress, ARC controller + runner scale set, and all Kubernetes\nsecrets. Environment layers become thin callers with no inline\nresource definitions.",
          "is_bot": false,
          "headline": "Add dc-controlplane and dc-controlplane-services modules",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-06T05:01:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "61b04a55858dcba6abf9e1bd29b389f9d4c6ec6b",
          "body": "Add VM image and storage management to the bootstrap module:\nnew variables for image source URL, disk size, and storage class;\ncloud-init template extended with additional packages and disk\nsetup; outputs expose the provisioned image ID for downstream\nlayers.\n\nImprove the namespace-credential-provisioner reconcile script to\nhandle edge cases and surface clearer error messages on failure.",
          "is_bot": false,
          "headline": "Extend bootstrap and reconcile modules",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-06T05:01:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fa14460d931f4d5fd87646c09d3fc05f91739cd9",
          "body": "Cloud-init user_data carries SSH authorized keys, bootstrap tokens,\nand other credentials. Without sensitive = true, the value is emitted\nin plain text during terraform plan and stored without redaction in\nstate.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Mark user_data variable as sensitive",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-05T16:40:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "87996c727af13b9205b5229a2dd9a4e5d0ccb7c7",
          "body": "Wraps tenant-space + workloads/k8s-cluster into a single opinionated\nmodule for provisioning a Rancher project, its DC-API VM namespace,\nthe Harvester NAD and IPPool for that namespace, and a managed RKE2\ncluster with the Harvester cloud provider attached. Consumers pass\nmachine pool definitions and\n[…]\nter\nLonghorn-backed VM disks; without them, both controllers lose their\nleases and crashloop every ~80 seconds during initial cluster\nbring-up.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add dc-controlplane management module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-05T16:40:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "673126d1e4266ad205622b5015efcf55b5486909",
          "body": "Two reconciler hardening fixes for the namespace-credential-provisioner:\n\n1. Cluster watch race with namespace watch\n   When a cluster is created in close succession with its tenant\n   namespace, the cluster event can arrive before the namespace watch\n   has minted the cloud-provider ServiceAccount \n[…]\nredentials provisioned. Skip them in both the watch\n   loop and the reconciler-restart sweep, alongside the existing\n   network-namespace skip.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Wait for SA token and skip infrastructure namespaces",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-05T16:27:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "acde3cbe79c2eb4ee3e21564e8f2668873241236",
          "body": "Move cloud image download into the module via image_url,\nimage_name, and image_display_name variables. ubuntu_image_id\nis kept as an optional brownfield escape hatch when the image\nalready exists in the cluster.\n\nAdd storage class management: creates harvester-longhorn-2r as\nthe cluster default (con\n[…]\nfy the server certificate,\nand add a wait loop for the supervisor port before joining.\nAdd LB port 9345 listener for RKE2 HA supervisor join.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(bootstrap): add image and storage management",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-04T06:57:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bdf2c0fe0646b1a4ab1474a853400678ad9181a2",
          "body": "Add validation block to credential_namespace to reject empty or\nwhitespace-only values before plan/apply.\n\nAdd check block for coredns_patch_vars_set so that setting\npatch_coredns = true without both rancher_lb_ip and rancher_hostname\nfails early with a clear error instead of silently rendering an empty\nhosts entry in the CoreDNS Corefile.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Address CodeRabbit review on harvester-integration module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-04T06:57:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "588e6a2b5b1da653e5cf8b2c6334659dcbab8f17",
          "body": "The SA and token Secret for the cloud credential were hardcoded to\nkube-system. Brownfield deployments that created these resources in\na different namespace (e.g. default) would see a forced replacement\non every apply due to the namespace drift.\n\nExpose credential_namespace (default: kube-system) so consumers can\npin the value to match their existing state.\n\nCloses #82",
          "is_bot": false,
          "headline": "Add credential_namespace variable to harvester-integration",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-05-04T06:57:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "291c8a35140588d2f23ada81f5b18074fe4dfaa9",
          "body": "Kubernetes auto-adds kubernetes.io/metadata.name to every namespace\non creation. The rancher2 provider does not manage this label but\ndetects it as drift, producing a spurious remove-label diff on every\nplan run.\n\nAdding it to lifecycle ignore_changes on both rancher2_namespace.this\nand rancher2_namespace.network suppresses the noise permanently without\naffecting any managed label.\n\nCloses #79\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Ignore kubernetes.io/metadata.name label drift in namespaces",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-28T13:55:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "567f84d1e94bf0c4e1ac399bca940aa685e31606",
          "body": "Replace the fine-grained per-API-group rules with a wildcard grant\ncovering all Kubernetes resources, subresources (*/scale, pods/exec,\npods/log), and non-resource URLs. This is the same permission set as\nthe built-in cluster-admin ClusterRole.\n\nRancher cluster lifecycle operations (delete, reconfigure) are\nenforced at the Rancher management-plane level independently of\nthis Kubernetes RBAC role.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Broaden cluster-contributor to full cluster-admin-equivalent access",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-28T13:37:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9590fea384401f2ae1749c5198ccf5e5061c2a87",
          "body": "Introduces a cluster-scoped role template that grants SRE teams full\nkubectl operational access to downstream RKE2 clusters without\nRancher management-plane permissions. Members can deploy, scale,\nexec, stream logs, and manage workload config but cannot delete or\nreconfigure the cluster from the Ran\n[…]\nility. Explicitly excludes node mutation, RBAC\nmutation, and namespace lifecycle operations, which remain with the\nplatform team.\n\nCloses #78\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add cluster-contributor role for SRE operational access",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-28T13:37:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "184e145c75448745cc534ff60ffbc39ba5f137d4",
          "body": "Introduces the project-contributor RoleTemplate for Rancher projects.\nThe role allows namespace and project member management (full CRUD on\nnamespaces and projectroletemplatebindings), read-only access to the\nproject resource itself to prevent quota modification or deletion, and\nread-only visibility\n[…]\nand Claude Code artefacts to .gitignore\nto keep module-level lock files and personal editor configs out of the\nmodule repository.\n\nCloses #75\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add project-contributor role with batch workload access",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-28T11:26:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a94b203affc3058fb9bed814e6d2dd50efe1520c",
          "body": null,
          "is_bot": false,
          "headline": "feat(vm): add brownfield override variables",
          "author_name": "Akini Karunarathne",
          "author_login": "Akini98",
          "committed_at": "2026-04-28T05:17:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "974efa83d62f6d94cc7bae1ef57768f09c011ac0",
          "body": "Adds README for namespace-credential-provisioner documenting the\nmodule's purpose, deployment sequence relative to harvester-integration\nand tenant-space, and usage example.\n\nUpdates docs/architecture.md:\n- Adds namespace-credential-provisioner (Phase 2e) to the dependency\n  graph between rbac (Phas\n[…]\nxes harvester-cloud-credential README: replaces non-existent\nkubeconfig output entry with the actual service_account_name output.\n\nCloses #73\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bundle namespace-credential-provisioner into management setup phase",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-28T05:07:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b61386fee27c4a4831a86d529de1151e56d2e3a5",
          "body": "Extends the namespace-credential-provisioner reconciler to create\nper-namespace VM-access credentials alongside cloud-provider creds:\n  - SA harvester-vm-access-<ns> with harvesterhci.io:edit RoleBinding\n    in the tenant namespace, edit in harvester-public for shared images\n  - harvester-vm-kubecon\n[…]\n.\n\nUpdates READMEs for vm, k8s-cluster, and harvester-cloud-credential\nmodules with inline kubeconfig pattern and usage examples.\n\nCloses #71\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add VM access kubeconfig provisioning and consumer onboarding docs",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-27T10:00:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ad8797a693a1f98a057ddb00d69208696b6c422",
          "body": "On init, check whether the SA token secret already exists before\ncalling on_added_namespace. Distinguishes NotFound (provision) from\ntransient kubectl errors (skip with warning, retry on watch event).\nOnly marks the namespace processed when provisioning succeeds.\n\nAlso adds:\n- vlan_id uniqueness val\n[…]\n4)\n- harvester_api_server variable to tenant-space for VM access kubeconfig\n- Removes \"or empty\" wording from vlan_id description\n\nCloses #69\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Skip already-provisioned namespaces on reconciler restart",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-27T04:57:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9d502de9f7e3617fc7db4a81bf51289295cc83a6",
          "body": "Guard against an empty string being passed as the network namespace\noverride — coalesce accepts \"\" as truthy so validation is the right\nfix, consistent with other string variables in this module.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add non-empty validation for network_namespace_name",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T08:49:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "42349d5e50d56fa96ebc0b9307617120ffad9584",
          "body": "- vlan_id is now list(number); each entry creates a harvester_network\n  via for_each so networks can be added/removed independently\n- Auto-route path (no vyos_endpoint) supports multiple VLANs; VyOS\n  path still requires exactly one VLAN (precondition enforced)\n- network_namespace_name override lets\n[…]\nwnfield\n  harvester_network resources with non-default names\n- network_name output replaced by network_names map keyed by VLAN ID\n\nCloses #67\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Support multiple VLAN networks per tenant space",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T08:49:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "71d351dd66dd4f73e9803f1c0e2ac8cf361fe41c",
          "body": null,
          "is_bot": false,
          "headline": "Address CodeRabbit review",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T06:39:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "75b04a8c678e085f9071b58e2b50f78c76313f18",
          "body": null,
          "is_bot": false,
          "headline": "Add flag to control default namespace creation",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T06:39:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "72cb731b6d05a75a957ba74445f2ef02de825d3c",
          "body": "Checkov CKV_K8S_21 flags resources placed in the default namespace.\nMove the rancher-cloud-credential ServiceAccount and its token Secret\nto kube-system, which is the conventional namespace for infrastructure-\nlevel service accounts.\n\nThe ClusterRoleBinding subject namespace reference is derived from\nthe ServiceAccount metadata, so no separate change is needed there.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Move cloud credential SA and token to kube-system namespace",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T05:19:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "83033f835e512b6124ca68826eaa579fbde202c9",
          "body": "Exposes the Harvester Kubernetes API server URL extracted from\nthe kubeconfig so downstream layers can pass it to the\nharvester-cloud-credential module without hardcoding the VIP.\n\nMarked sensitive because it derives from the kubeconfig input.\nReturns null when create_cloud_credential = false.\n\nCloses #57\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add harvester_api_server output to harvester-integration module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T05:19:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c64fe870fddfc18f5d0154d31d14b0c479577c67",
          "body": "When vlan_id is set without vyos_endpoint, use route_mode=auto so the\nupstream router (DigiOps / physical switch) handles DHCP and routing.\nThe manual route_mode with deterministic 10.0.0.0/8 subnetting is now\ngated on vyos_endpoint being set.\n\n- Add use_vyos local; gate tenant_subnet/tenant_gateway\n[…]\ntional\n- Relax vlan_id validation from >= 1000 to valid 802.1Q range (1–4094)\n- Update subnet_cidr/gateway_ip output descriptions (VyOS-only)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Support auto route mode for non-VyOS VLAN networks in tenant-space",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T05:05:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f1b43b93d109df80912a8a6cf2f78981b017d2f5",
          "body": "- tenant-space/variables.tf: vyos_endpoint and vyos_api_key were\n  declared twice after the create_network_namespace commit merged\n  them in alongside pre-existing copies from the decouple branch.\n- vyos-tenant/outputs.tf: subnet_cidr output was declared twice,\n  once as the canonical output and once as an alias added earlier.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Remove duplicate variable and output declarations",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T05:05:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "730ce9b918eea20a154d8da24fd47fd264a89b05",
          "body": "The vyos provider was listed unconditionally, forcing every caller to\nconfigure it even when vyos_endpoint is null and no VyOS resources are\ncreated. The provider is only needed by the child vyos-tenant module,\nwhich declares its own required_providers — Terraform picks it up\ntransitively without it being declared in the parent.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Remove vyos from tenant-space required_providers",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T05:05:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "59dbfb577ec59bcfaaac587d98a82d0a12439386",
          "body": "tenant-space:\n- Add create_network_namespace (bool, default false) to pre-provision\n  the <project_name>-net namespace before a VLAN is assigned. The\n  network namespace is created when create_network_namespace = true OR\n  when vlan_id is set (backward compat: existing callers with vlan_id\n  are una\n[…]\narvester_network moving from the vyos-tenant child module address to\nthe tenant-space address — a targeted import is required on first apply.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add create_network_namespace flag; fix harvester_network ownership",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T05:05:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ff093ce961533f2e57752dec7d51725779e7c4f6",
          "body": "Previously, setting vlan_id always invoked the vyos-tenant module,\nmaking it impossible to create a network namespace + harvester_network\nwithout VyOS config calls.\n\nNow vlan_id and vyos_endpoint are independent gates:\n- vlan_id only: creates network namespace + harvester_network (for\n  environments\n[…]\no the network\nnamespace (used by the namespace credential provisioner), and fixes\na pre-existing missing newline in variables.tf.\n\nCloses #63\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Decouple VyOS integration from network namespace in tenant-space",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T05:05:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c35e894cfdcdecb8049b6db46c00c23ef380fd5",
          "body": "- Change harvesterconfig Secret type from non-standard \"secret\" to\n  \"Opaque\" to match Kubernetes convention and avoid potential\n  filtering by Rancher controllers\n- Skip Terminating namespaces in the initial pass by reading\n  deletionTimestamp from the jq pipeline; prevents failed kubectl\n  apply calls against namespaces in the process of being deleted\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix secret type and skip Terminating namespaces at startup",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T04:39:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "47e427aed0b19e0e34ec65f1d8b09a87747c4845",
          "body": "- Remove token-presence early return in on_added_namespace so all\n  SA/RBAC resources are re-applied idempotently on every ADDED event,\n  repairing drift caused by deleted ServiceAccounts or RoleBindings\n- Mark namespaces/clusters as processed only after the handler\n  succeeds; transient failures (n\n[…]\nt\n- Replace `func || true` with `func || log \"...exited with error\"` so\n  watch-loop failures are visible in logs instead of silently ignored\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix reconciler idempotency and error handling",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T04:39:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c19f412ec899b43421e2b319858d67515406baeb",
          "body": "The net-read RoleBinding creation was failing with:\n  user ... is attempting to grant RBAC permissions not currently held\n\nKubernetes RBAC escalation prevention blocks a subject from granting\npermissions it doesn't hold. Fix by adding the escalate verb to the\nrolebindings rule — the approved mechani\n[…]\nrovider (cloudprovider\nSA binding) and view (net-read binding). Restricting to a single name\nprevented the second binding from being created.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add escalate verb and broaden clusterroles bind in provisioner RBAC",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T04:39:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "00b8461e10f9a18ee9cd63e7778bec083acc54be",
          "body": "Replace the substring kubeconfig body search with an exact annotation\nmatch when finding harvesterconfig-* secrets to delete on namespace\nremoval. The previous contains(\"namespace: \" + $ns) check would match\nprefix namespaces (e.g. \"team-a\" incorrectly matching \"team-a2\").\n\nAdd platform.wso2.com/cre\n[…]\nsource-namespace annotation to the\nsecret at creation time so the deletion path can do a precise lookup\nwithout decoding the kubeconfig body.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix stale-secret cleanup to use exact annotation match",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T04:39:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ca59d867ad991607ba3a40a48778b16931f9ad5e",
          "body": "Adds modules/management/namespace-credential-provisioner — a Kubernetes\nDeployment that runs a reconciler script to automate harvesterconfig\nsecret management across tenant lifecycle events.\n\nWhat it does:\n- Watches Harvester namespaces; on new tenant namespace provisions a\n  ServiceAccount (harvest\n[…]\ne includes configmaps get (kube-root-ca.crt for CA\ncert), patch/update on serviceaccounts/secrets/rolebindings for\nkubectl apply idempotency.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add namespace credential provisioner module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-21T04:39:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "034f12ec0b6bacf59fb7c17f33ae6ffbd1d72022",
          "body": "Downstream layers that provision RKE2 clusters need the\ncattle-global-data:cc-xxxx ID for the k8s-cluster module.\nReturns null when create_cloud_credential = false so brownfield\nenvironments that manage the credential outside Terraform are\nnot affected.\n\nCloses #55\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Expose cloud_credential_id from harvester-integration module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-17T11:37:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "db8282a7afd73e12f907ee570c219660fbfe78a3",
          "body": "Callers can now pass node_password, ssh_authorized_keys, and\nntp_server instead of composing raw cloud-init YAML. The module\ngenerates a full RKE2-ready cloud-init (packages, IPVS kernel\nmodules, sysctl, NTP) via templatefile.\n\nuser_data remains a full override. ssh_user (existing variable)\nis reused as the username in the generated chpasswd.list entry.\n\nCloses #53\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add node_password and ssh_authorized_keys to k8s-cluster module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-17T11:37:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9ca3818c6f0b8a7821153ac37e346c811531ebd1",
          "body": "Callers can now pass `password`, `ssh_authorized_keys`, and\n`default_user` instead of composing raw cloud-init YAML. The\nmodule generates a correct chpasswd.list-based cloud-init using\na templatefile, avoiding heredoc indentation pitfalls.\n\n`user_data` remains a full override — when set, the new\nvariables are ignored entirely. `default_user` defaults to\n\"ubuntu\" but can be changed for non-Ubuntu images.\n\nCloses #53\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add password and ssh_authorized_keys to vm module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-17T11:37:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e8f209f14e8d1e5552a6e628168666ff7aec9471",
          "body": "The dynamic resource_quota on rancher2_namespace.this was wrong:\nit assigned the full project quota to every namespace, which would\nprevent users from adding more namespaces and causes double\nenforcement. The project-level quota is already the ceiling —\nRancher enforces it across all namespaces without a per-namespace\nResourceQuota object. Remove the block and document why.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Revert per-namespace quota block from tenant-space module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-16T05:55:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dcf23cf9bcad9614b28bb7a36e779d5247bb5254",
          "body": "The vyos-tenant submodule requires both variables but tenant-space\nwas not declaring or passing them. Add vyos_endpoint and\nvyos_api_key as optional (default null) variables to tenant-space\nand pass them through to the module \"vyos_tenant\" call.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Thread vyos_endpoint and vyos_api_key through tenant-space module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-16T05:55:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "91a445e1ecb8a08736a61d399f702dd9723af67e",
          "body": "Rancher does not reliably propagate namespace_default_limit to\nnamespaces created via the API. Without an explicit resource_quota\nblock on the rancher2_namespace resource, the namespace ResourceQuota\ncan end up with limits.cpu=0 / limits.memory=0, which blocks all\nVM creation with \"exceeded quota\".\n\n[…]\nat\nmirrors the project's per-namespace limits whenever cpu_limit is set.\n\nAlso fix a cosmetic syntax error (missing newline) in variables.tf.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Explicitly set namespace resource quota in tenant-space module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-16T05:55:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "066762c17b683aac7f5d2d10cf563d549ffbb93a",
          "body": "Move network-attachment-definitions read from vm-creator (cluster)\nto vm-manager (project). Keeping it cluster-scoped let tenants list\nNADs in all namespaces, exposing other tenants' networks and platform\ninfrastructure in the VM creation network dropdown.\n\nWith it project-scoped, the Harvester UI o\n[…]\nrom\nthe tenant's own project namespaces (e.g. choreo-sre-net) — no\nvisibility into default/, harvester-public/, or other tenants.\n\nCloses #51\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Scope network visibility to tenant project in RBAC roles",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-16T05:55:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b05d5efb986238245e88cf19478ed6ea784ec9a9",
          "body": "tenant-space/outputs.tf references module.vyos_tenant[0].subnet_cidr\nbut the vyos-tenant module only exposed subnet. Add subnet_cidr as\nan alias so both names resolve correctly.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add subnet_cidr output alias to vyos-tenant module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-16T05:54:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c28714385193a817c99ae3d4a87996ba9e03d465",
          "body": "Rewrite all vyos_config_block_tree resources to use the\nhiranadikari/vyos provider schema:\n- path: list of strings (was a space-separated string)\n- section: jsonencode({...}) (was configs = {key = value} map)\n\nMerge the separate dhcp_dns resource into the main dhcp section —\ndns_servers is now a JSO\n[…]\nider source from thomasfinstad/vyos-rolling (~> 19.0)\nto hiranadikari/vyos (~> 0.1). Remove unused locals: vif_path,\nsubnet_base.\n\nCloses #49\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix vyos-tenant module for hiranadikari/vyos provider schema",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-16T05:54:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b4d101aad7a8d62d870caabe5704150b93e55717",
          "body": "Change thomasfinstad/vyos-rolling (~> 19.0) to hiranadikari/vyos\n(~> 0.1) — the published provider that exposes the\nvyos_config_block_tree resource used in this module. Without this,\nterraform init pulls the wrong provider and plan fails with\n\"does not support resource type vyos_config_block_tree\".\n\nCloses #49\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix vyos provider source in vyos-tenant module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-16T05:54:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fd74aae8bfec8b770f59c4c9c73ae5e9cf4a2983",
          "body": "- vlan_id (optional): when set, creates a <project_name>-net network\n  namespace and calls the vyos-tenant submodule to provision the\n  Harvester NAD, VyOS vif sub-interface, DHCP server, and NAT rule.\n  Adds harvester and vyos to required_providers.\n\n- namespaces defaults to null, resolved to [proj\n[…]\ncenter uses a different name.\n\n- network_name, subnet_cidr, gateway_ip, network_namespace outputs\n  added (all null when vlan_id is not set).\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Extend tenant-space with optional VyOS VLAN network integration",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-12T04:09:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "91f449c433465cd2cd9bf9b52e4e0824d6abfc9b",
          "body": "Narrow lifecycle ignore_changes from [disk] to [disk[0].auto_delete]\nso only the specific Harvester-caused drift (auto_delete flag flip on\nrootdisk post-CDROM removal) is suppressed; other disk attributes\nremain Terraform-managed.\n\nAdd validation block to management_network_name enforcing null or\nthe required namespace/name format, catching malformed values at\nplan time rather than failing at provider apply.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Address CodeRabbit review on vyos bootstrap module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-12T04:09:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2c21e3203c2a26259a6015b56ff2745779430500",
          "body": "- Optional eth2 NIC via management_network_name variable. When set,\n  attaches VyOS to the Harvester management cluster network (mgmt-br)\n  so in-cluster processes (DHCP reconciler pods with hostNetwork) can\n  reach the VyOS HTTPS API at a stable IP without routing through the\n  external uplink inte\n[…]\nM resource prevents a\n  perpetual diff caused by Harvester flipping auto_delete on the\n  rootdisk after the CDROM is removed on second apply.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add optional management NIC and fix disk lifecycle in vyos module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-12T04:09:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "24192322e7c5330fb91fb206fadf1737ef6ef9ea",
          "body": "The provider is published at registry.terraform.io/hiranadikari/asgardeo.\nThe previous source 'asgardeo/asgardeo' does not exist on the registry\nand would fail on terraform init without a dev_override.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix asgardeo provider source to hiranadikari/asgardeo",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-11T17:18:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7613d4dc88affee6595e21ee7802e30be63510ba",
          "body": "cloud-init runs only on first boot. Any subsequent changes to\nuser_data (template reformats, key rotation, etc.) have no\nruntime effect but previously triggered an in-place VM restart.\n\nCloses #41\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Ignore cloudinit changes after VM is provisioned",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-11T16:51:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "39a5f2fd4f571dc504d5b861297d5f816b67e038",
          "body": "Use a template for-loop instead of indent()/join()/formatlist()\nto emit ssh_authorized_keys list items — the previous expression\nproduced 8 spaces of leading whitespace (4 from the heredoc + 6\nfrom indent), which broke cloud-init YAML parsing.\n\nAdd prose note and example variable declarations to make clear\nthat vm_password and ssh_authorized_keys are root-module variables,\nnot inputs to this module.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix cloud-init SSH key indentation and clarify variable scope",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:36:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1cc0c2a204ab1bb8c573634ecfe0659621cedc76",
          "body": "Replace the generic nginx example with a validated pattern that avoids\ntwo known issues on Ubuntu 22.04 with cloud-init 25.x:\n\n- Do not use package_update: true — it races with apt-daily timers on\n  first boot, causing silent package install failures\n- Do not use a users: block with password: — clou\n[…]\n Notes entry explaining that qemu-guest-agent is required for\nHarvester to display the guest IP for VMs on private VLAN networks.\n\nCloses #39\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Update workloads/vm README with correct cloud-init pattern",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:36:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e35b6ab0a867170a0cbb5fbbc5f7e1d7deac4ea3",
          "body": "Individual range bounds (2–510) were already validated per-variable.\nAdd a check block to enforce start_offset <= end_offset, which cannot\nbe expressed in variable validation blocks without Terraform >= 1.9.\n\nUsing check block (Terraform >= 1.5, already required) keeps the\nrequired_version constraint unchanged.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add cross-variable DHCP offset order validation",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:36:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e536225e0d8786938b370d50dd3e3007b2880c22",
          "body": "- bootstrap/vyos/main.tf: explicitly state the route_cidr as\n  10.0.0.0/8 in the eth1 trunk comment so it matches the resource\n- tenant-space/variables.tf: soften \"At minimum, provide one\n  namespace named after the project\" to \"It is recommended\" to\n  match the actual (non-enforced) behaviour\n- vyo\n[…]\nues for consumers\n- vyos-tenant/versions.tf: correct vyos-rolling version constraint\n  from ~> 19.1 (non-existent) to ~> 19.0 (latest series)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Address remaining CodeRabbit comments on PR #38",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:36:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d3de050aaaf68cbbc9f02da7f50eceafc4a9ef28",
          "body": "- Remove unused rancher2 provider from versions.tf; the module\n  only uses harvester and vyos providers\n- Add validation blocks to dhcp_range_start_offset and\n  dhcp_range_end_offset: valid range 2–510, offset 1 is reserved\n  for the gateway IP\n- Consolidate dhcp_dns into a single vyos_config_block_\n[…]\n is now a unique config key\n- Replace 0.0.0.0/0 in the API setup comment with\n  <management_cidr> placeholder to avoid suggesting open access\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Address CodeRabbit review on vyos-tenant module",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:36:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7e98e3dc3759e6a10a01d4c01ace649b9b09f30a",
          "body": "Replace DigiOps references and WSO2-specific defaults with generic\nterminology so the modules are usable by any Harvester operator.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Remove internal naming from VyOS module comments and variables",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:36:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0eebf94162268bece096b1ac127f5f199bafcac1",
          "body": "Introduces two modules for deploying and configuring a VyOS VM as a\nprivate cloud gateway on Harvester, enabling per-tenant VLAN isolation,\nDHCP, NAT, and internet egress without DigiOps involvement per tenant.\n\nmodules/bootstrap/vyos/\n- Deploys VyOS VM with two NICs: eth0 (DigiOps uplink) and eth1 \n[…]\n NAT rules, and harvester_network resources\n- Creates harvester_network with vlan_id matching the VyOS vif tag exactly\n\nCloses #77\nCloses #78\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add VyOS multi-tenant gateway modules",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:36:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f6324ee06991f1f97db53d3a70277ea3527ebce4",
          "body": "- Rename duplicate Phase 4 (Asgardeo Auth) to Phase 5 to resolve\n  numbering conflict with the Workloads phase added in this PR\n- Update Provider Dependency Summary table: replace stale ~> 0.6.0 /\n  ~> 3.0 / ~> 8.0.0 constraints with versions from actual module\n  versions.tf files (harvester ~> 1.7,\n[…]\nasgardeo ~> 0.1)\n- Fix storage example source: update from wso2-enterprise org and\n  stale v0.1.0 tag to wso2/open-cloud-datacenter at v0.5.8\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix CodeRabbit review comments on architecture docs",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:35:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "afd0a0fef5e62d2ce503cdceda18e52f9e108010",
          "body": "…odules and fix broken references",
          "is_bot": false,
          "headline": "Update README and architecture documentation to include all missing m…",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T11:35:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "54757306ee37eb48c45418fbeca409654cb9d307",
          "body": "Add three new role templates to the cluster-roles module to extend the\nDC platform RBAC framework:\n\nvm-creator (cluster): minimum cluster-level read access for tenants who\ncreate VMs — VM images, network attachment definitions, and SSH keypairs\nlive outside project namespaces so project-owner alone \n[…]\nnamed after the project, ensuring\nthe namespace dropdown is populated in the Rancher/Harvester VM and RKE2\ncluster creation flow.\n\nCloses #36\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add vm-creator, vm-operator, and cluster-operator role templates",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-10T08:02:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "06c962f3941acfd573e7ac0b4a18c1def5712a29",
          "body": null,
          "is_bot": false,
          "headline": "Add optional scheduled backup support to vm module",
          "author_name": "Akini Karunarathne",
          "author_login": "Akini98",
          "committed_at": "2026-04-09T09:32:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9440407a4bbbaf140629d3a17559a62318e8e94d",
          "body": "…rs[0]\n\nFollow Kubernetes kubeconfig resolution semantics: parse current-context,\nfind the matching context, extract its cluster reference, then look up the\ncluster entry by name. This correctly handles multi-cluster kubeconfigs\nwhere the target cluster may not be the first entry.\n\nAlso add a check block validating that certificate-authority-data (embedded\nCA) is present, since file-path certificate-authority references are not\nsupported when building the portable SA kubeconfig for Rancher.",
          "is_bot": false,
          "headline": "fix: resolve kubeconfig cluster via current-context instead of cluste…",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-07T17:47:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cd4844bfd5d5ac9b62b828ac5536677346039fae",
          "body": "The Harvester UI kubeconfig embeds a Rancher-internal token that\nstandalone Rancher cannot validate against the Harvester API,\ncausing 500 errors on cloud credential creation. Generate a\ndedicated Kubernetes ServiceAccount token instead so Harvester\ncan authenticate the credential directly.\n\nAlso ad\n[…]\ne management interface.\n\nAll new SA resources are gated on create_cloud_credential to\npreserve brownfield environments (lk prod).\n\nCloses #32\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix Harvester cloud credential and IP pool VLAN selector",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-07T17:47:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b60b4566c3fe08db6f39ef51d0cddc6848173f34",
          "body": "- Use double quotes for chpasswd entry in cloud-init template so\n  passwords containing single quotes do not break YAML parsing\n- Gate rancher2_secret_v2.registry_auth on manage_rke_config so\n  secrets are not created for brownfield clusters that never reference\n  them\n- Tighten registries validation: require non-empty hostname (unique,\n  case-insensitive), enforce non-empty username/password when set, and\n  enforce non-empty auth_config_secret_name when set",
          "is_bot": false,
          "headline": "Address CodeRabbit review comments on PR #31",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-07T17:22:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6bc5ec54e28f6f66d481f49ad1b593d32265c500",
          "body": "regexreplace() is not available in all Terraform-compatible\nruntimes. replace() with /pattern/ regex delimiter achieves\nthe same result and has broader compatibility.",
          "is_bot": false,
          "headline": "Use replace() instead of regexreplace() for secret name",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-07T17:22:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c1d668dcd357568bdbbf520ba4d1de5d765cf581",
          "body": "- Reflect current API (provider ~> 13.1, terraform >= 1.7)\n- Document all current inputs including machine_pools fields,\n  registries (inline credentials vs brownfield secret), and etcd_s3\n- Add registry credential modes reference table and usage examples\n- Add outputs table and brownfield import instructions\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Update k8s-cluster module README",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-07T17:22:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5364817cbfe0650d0d13a4415625e1c1e41995f4",
          "body": "- Quote password in chpasswd list to handle special characters\n- Replace ping connectivity check with curl — more reliable through\n  firewalls that block ICMP\n- Redirect deployment echo messages to /dev/console so progress is\n  visible in Harvester VM serial console during boot, not only in\n  /var/log/rancher-install.log\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Improve cloud-init bootstrap script reliability",
          "author_name": "HiranAdikari",
          "author_login": "HiranAdikari",
          "committed_at": "2026-04-07T17:22:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 34,
      "commits_last_year": 173,
      "latest_release_at": "2026-07-24T04:47:13Z",
      "latest_release_tag": "terraform/v0.1.9",
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 16,
      "days_since_latest_release": 4,
      "mean_days_between_releases": 6.3
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 87,
      "has_issue_template": true,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 12,
      "stars": 7,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2026-02-25",
            "count": 2
          },
          {
            "date": "2026-03-03",
            "count": 1
          },
          {
            "date": "2026-03-31",
            "count": 2
          },
          {
            "date": "2026-04-22",
            "count": 1
          },
          {
            "date": "2026-05-13",
            "count": 1
          },
          {
            "date": "2026-05-28",
            "count": 1
          },
          {
            "date": "2026-06-02",
            "count": 1
          },
          {
            "date": "2026-06-10",
            "count": 1
          },
          {
            "date": "2026-06-11",
            "count": 1
          },
          {
            "date": "2026-06-12",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 12,
        "total_forks": 12
      },
      "star_history": null,
      "open_issues_and_prs": 26
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": null,
      "source_files_sampled": 0,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [],
      "dependencies": [],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 5,
        "merged_prs": 167,
        "open_issues": 21,
        "closed_ratio": 0.58,
        "closed_issues": 29,
        "closed_unmerged_prs": 10
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "HiranAdikari",
          "commits": 109,
          "avatar_url": "https://avatars.githubusercontent.com/u/13211597?v=4"
        },
        {
          "type": "User",
          "login": "VimukthiPerera",
          "commits": 30,
          "avatar_url": "https://avatars.githubusercontent.com/u/15902071?v=4"
        },
        {
          "type": "User",
          "login": "iamtrazy",
          "commits": 12,
          "avatar_url": "https://avatars.githubusercontent.com/u/73080739?v=4"
        },
        {
          "type": "User",
          "login": "sathindudezoysa",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/59018854?v=4"
        },
        {
          "type": "User",
          "login": "git-repo-creation-app",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/216828136?v=4"
        },
        {
          "type": "User",
          "login": "Akini98",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/116425440?v=4"
        },
        {
          "type": "User",
          "login": "gnudeep",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/155502?v=4"
        }
      ],
      "contributors_sampled": 7,
      "top_contributor_share": 0.677
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": false,
      "ci_workflows": [
        "linter.yml",
        "terraform-scan.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 6,
            "reason": "10 out of 15 merged PRs checked by a CI test -- score normalized to 6",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 10,
            "reason": "all changesets reviewed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 10,
            "reason": "all dependencies are pinned",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "25cb78eacee2ae426e3171b1113f24f1f46bb586",
        "ran_at": "2026-07-28T10:08:20Z",
        "aggregate_score": 6.7,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-27T04:59:02Z",
      "oldest_open_prs": [
        {
          "number": 21,
          "created_at": "2026-03-05T11:59:06Z",
          "last_comment_at": "2026-03-05T11:59:21Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 150,
          "created_at": "2026-06-11T04:57:42Z",
          "last_comment_at": "2026-06-11T04:57:50Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 205,
          "created_at": "2026-06-30T10:04:10Z",
          "last_comment_at": "2026-06-30T10:04:35Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 215,
          "created_at": "2026-07-03T06:26:47Z",
          "last_comment_at": "2026-07-03T06:26:53Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 230,
          "created_at": "2026-07-16T09:09:32Z",
          "last_comment_at": "2026-07-16T09:09:41Z",
          "last_comment_author": "coderabbitai"
        }
      ],
      "last_merged_pr_at": "2026-07-27T09:22:47Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 34,
          "created_at": "2026-04-07T17:29:12Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 58,
          "created_at": "2026-04-17T11:38:31Z",
          "last_comment_at": "2026-06-16T07:32:27Z",
          "last_comment_author": "kavix"
        },
        {
          "number": 59,
          "created_at": "2026-04-17T12:14:17Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 85,
          "created_at": "2026-05-04T06:58:09Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 86,
          "created_at": "2026-05-04T06:58:10Z",
          "last_comment_at": "2026-06-16T07:32:47Z",
          "last_comment_author": "kavix"
        },
        {
          "number": 87,
          "created_at": "2026-05-04T06:58:14Z",
          "last_comment_at": "2026-06-16T07:33:19Z",
          "last_comment_author": "kavix"
        },
        {
          "number": 92,
          "created_at": "2026-05-05T17:17:27Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 109,
          "created_at": "2026-05-28T06:53:48Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 120,
          "created_at": "2026-05-29T09:43:06Z",
          "last_comment_at": "2026-05-31T03:06:34Z",
          "last_comment_author": "Akini98"
        },
        {
          "number": 131,
          "created_at": "2026-05-30T12:52:09Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 139,
          "created_at": "2026-06-02T13:02:48Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 218,
          "created_at": "2026-07-07T00:00:31Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 220,
          "created_at": "2026-07-07T00:26:16Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 223,
          "created_at": "2026-07-09T05:31:00Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 226,
          "created_at": "2026-07-10T09:55:05Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 228,
          "created_at": "2026-07-14T06:43:24Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 229,
          "created_at": "2026-07-16T06:05:24Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 231,
          "created_at": "2026-07-20T00:45:26Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 233,
          "created_at": "2026-07-22T09:52:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 239,
          "created_at": "2026-07-25T18:39:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/wso2/open-cloud-datacenter",
    "host": "github.com",
    "name": "open-cloud-datacenter",
    "owner": "wso2"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 66,
      "inputs": {
        "security": 67,
        "vitality": 85,
        "community": 58,
        "governance": 60,
        "engineering": 58
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 85,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "commits_last_year": 173,
              "human_commit_share": 1,
              "days_since_last_push": 1,
              "active_weeks_last_year": 16
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "16/52 weeks with commits",
                "points": 11.1,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 16
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "173 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 173
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 34,
              "latest_release_tag": "terraform/v0.1.9",
              "releases_from_tags": false,
              "days_since_latest_release": 4,
              "mean_days_between_releases": 6.3
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "34 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 34
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 4 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~6.3 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 6.3
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "moderate",
        "name": "Community & Adoption",
        "value": 58,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 21,
            "inputs": {
              "forks": 12,
              "stars": 7,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "7 stars",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "12 forks",
                "points": 8.7,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 12
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": true,
              "has_code_of_conduct": true,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 13.5,
                "status": "met",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 7.2,
                "status": "met",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 60,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 29,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 7,
              "top_contributor_share": 0.677
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 68% of commits",
                "points": 7.3,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 68
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "7 contributors",
                "points": 9.5,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 78,
            "inputs": {
              "merged_prs": 167,
              "open_issues": 21,
              "closed_issues": 29,
              "issue_closed_ratio": 0.58,
              "closed_unmerged_prs": 10
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "58% of issues closed",
                "points": 27.1,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 58
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "167/177 decided PRs merged",
                "points": 36.1,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 167,
                      "decided": 177
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "all changesets reviewed",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 78,
            "inputs": {
              "followers": 1731,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "wso2",
              "public_repos": 383,
              "account_age_days": 5697
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "1,731 followers of wso2",
                "points": 23.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 1731,
                      "login": "wso2"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "383 public repos, account ~15 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 383
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 58,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 36,
            "inputs": {
              "has_ci": true,
              "has_tests": false,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "10 out of 15 merged PRs checked by a CI test -- score normalized to 6",
                "points": 12,
                "status": "partial",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "topics": [
                "asgardeo",
                "choreo"
              ],
              "has_wiki": false,
              "homepage": "https://github.com/wso2/open-cloud-datacenter",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://github.com/wso2/open-cloud-datacenter",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "2 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 67,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection, Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection",
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 67,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 15,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 3,
              "scorecard_aggregate": 6.7
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "10 out of 15 merged PRs checked by a CI test -- score normalized to 6",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "all changesets reviewed",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "all dependencies are pinned",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 4
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "critical",
        "name": "AI Readiness",
        "value": 26,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.88,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "88 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 88,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "critical",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "has_nix": false,
              "has_tests": false,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.68,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "68 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 68,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "all dependencies are pinned",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "critical",
            "name": "Code legibility for models",
            "note": "Excluded from scoring (no data or not applicable): Manageable file sizes. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "manageable_file_sizes"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "primary_language": "HCL",
              "largest_source_bytes": null,
              "source_files_sampled": 0,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "HCL without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "HCL"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "no source files detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_source_files",
                    "params": {}
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-28T10:08:39.159260Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/w/wso2/open-cloud-datacenter.svg",
  "full_name": "wso2/open-cloud-datacenter",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

Scores are signals, not warranties. They reflect publicly visible practices on GitHub — not a code audit, and not a security guarantee.

Missing data is excluded and weights renormalized, never scored as zero. Methodology is versioned and open: metrics v1.13.0, schema v0.27.0 — full methodology · metrics wiki.

How one result sits in the wider record: aggregate statistics.