You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sec(iac): rename-proof OIDC deploy trust + branch-restricted environments for the split platform repo #2
The CI/CD deploy trust is keyed on the repository name (var.github_repo) in terraform/environments/aws/ci-cd-permissions/role.tf:92-144, terraform/environments/azure/ci-cd-permissions/sp.tf:47,58,73 and terraform/environments/gcp/ci-cd-permissions/github_oidc.tf:37,46. GitHub's sub/repository claims follow the repo's current name. So:
The live trusts still name the pre-split monorepo. After the split, that repo holds only CLI code and is renamed cloud-commitments-cli. This repo cannot deploy until the three ci-cd-permissions modules are re-applied with github_repo = LeanerCloud/cloud-commitments-platform.
A future rename, or a new repo that reuses a freed name, silently gains or loses deploy rights.
This repo has no environments yet. The first workflow_dispatch auto-creates them with no branch policy, and because the environment-scoped subjects are ref-agnostic, any branch could then deploy.
Fix
Create every environment the workflows use (dev, staging, prod, aws-fargate-, aws-db-, gcp-db-, azure-db-, *-rollback) with deployment_branch_policy.custom_branch_policies = true limited to main, before applying trust.
Make the trust rename-proof. GCP: map attribute.repository_id = assertion.repository_id and condition on it. AWS/Azure: customize the repo's OIDC sub claim template to include repository_id (and repository_owner_id), then match on the immutable ids.
Re-apply the three ci-cd-permissions modules (bootstrap: a privileged human, per CLAUDE.md), and remove the trust entries for the old monorepo name.
Copy the missing Actions secrets/vars (full list in the split log).
Acceptance
A token from any other LeanerCloud repo, or from a non-main branch, is rejected by all three clouds.
Evidence after the split PR merged (bd67009): the push-triggered deploys fail at the auth step exactly as expected. Deploy to Azure (run 36347968686) fails at Azure Login, GCP (36347968701) at Authenticate to Google Cloud, and AWS Lambda (36347968765) at Configure AWS credentials. CI - Build & Test, pre-commit and frontend-build-sentinel are green. Until the bootstrap in this issue is done, every push to main produces these three red runs. Consider gh workflow disable on the deploy/rollback/migration workflows in the meantime.
Working several overlapping p1 CI/OIDC issues in this repo; noting the
overlap with this issue's bootstrap re-apply so whoever picks this up has
the full picture:
sec(ci): main is unprotected while ref:refs/heads/main is a trusted OIDC subject for the AWS deploy role #154 (main unprotected while trusted as an OIDC subject): confirmed
independently live on this split repo (0 rulesets, 404 branch protection).
Sequencing note added there: protecting main narrows who can reach the ref:refs/heads/main subject this issue's trust re-apply will restore;
do that before or in the same window as the re-apply, not after.
None of the above perform the bootstrap re-apply itself (creating
environments live, re-applying ci-cd-permissions with the correct github_repo, or making the trust rename-proof) -- that's still this
issue's scope and still needs the privileged-human bootstrap step per CLAUDE.md.
Repo secrets and variables restored. The 6 IDs and backend configs come from live infra, and the 3 email/URL values from the dev Lambda environment.
The trust re-pointed in all three ci-cd-permissions roots and applied on 2026-09-29:
AWS and Azure match the immutable subject prefix repo:LeanerCloud@86753534/cloud-commitments-platform@1391259743:.... That prefix embeds owner and repo IDs, so it is already rename-proof, and no custom sub template is needed (sec(iac): key CI/CD deploy trust on immutable repository IDs #451 closed).
GCP matches repository == LeanerCloud/cloud-commitments-platform on refs/heads/main.
The old-name subjects and the stale PR and feat-branch Azure credentials are removed.
AWS was applied with -target on the deploy role only, using bucket cudly-terraform-state-909626172446. The KMS and boundary drift is still unapplied and needs its own review.
Dev deploys from main passed their auth steps on all three clouds (runs 36632649449, 36632653655, 36632658361).
Follow-up to the status comment above: #154 and #141 are now applied on this repo (2026-10-04).
main has ruleset 24469860 (PR + CI Success + Run pre-commit hooks, no bypass actors).
15 environments exist, each limited to a deployment-branch policy of exactly main, including the six gcp-db-* and azure-db-* ones that would otherwise auto-create bare.
Verified per environment against the live API. Not tested by dispatching from a feature branch.
Open consequence: release-triggered deploys to prod and aws-fargate-prod run from a tag ref and will be refused until a tag policy is added. No releases exist yet. Details, rollback and logs are in data/platform-hardening-2026-10-04/ in the split workspace.
Verification sweep (cc-platform-w3, 2026-10-07). Every part of the acceptance criteria that is a GitHub-side or live-IaC operation is already applied. What is left is in this repo's Terraform, and closing it needs one thing I cannot verify from here.
Verified applied
15 environments exist, each custom_branch_policies: true with exactly one branch policy, main (type=branch). Checked per environment against the API: aws-db-{dev,staging,prod}, aws-fargate-{dev,staging,prod}, azure-db-{dev,staging,prod}, dev, gcp-db-{dev,staging,prod}, prod, staging.
main ruleset 24469860 (PR + CI Success + Run pre-commit hooks, no bypass actors).
main-to-main deploys authenticate on all three clouds, e.g. Deploy to AWS Lambda run 37427743382 at 2026-10-06T07:07Z. The re-pointed trust is live.
The durable half is missing from this repo
All three ci-cd-permissions roots still key the trust on var.github_repo:
terraform/environments/aws/ci-cd-permissions/role.tf:92-128 lists repo:${var.github_repo}:ref:refs/heads/main and the ten repo:${var.github_repo}:environment:<name> entries.
terraform/environments/azure/ci-cd-permissions/sp.tf:47,77 builds the same two subject shapes.
terraform/environments/gcp/ci-cd-permissions/github_oidc.tf:37 conditions on assertion.repository == '${var.github_repo}', and :46 binds the principal set to attribute.repository/${var.github_repo}.
The immutable ids from the 2026-10-04 status comment (owner 86753534, repo 1391259743) appear nowhere in this repository. The next bootstrap re-apply therefore reverts the hardening to name-keyed and brings back the rename vector this issue exists to close, silently, because the live state would look correct until it is not.
Two halves, one of which needs the owner
GCP needs no GitHub-side prerequisite. repository_id is a claim GitHub always mints, so attribute.repository_id = "assertion.repository_id" in the attribute mapping, an assertion.repository_id == '<id>' condition, and a principalSet://.../attribute.repository_id/<id> member make the GCP trust rename-proof entirely inside this repo. I can do this one.
AWS and Azure can only present the id form if the repository's OIDC sub claim template is customized, which is a GitHub repository setting and not a Terraform resource. That is also what the live trust already assumes, since it matches only repo:LeanerCloud@86753534/cloud-commitments-platform@1391259743:... and main-to-main deploys authenticate, so it is very likely configured. I am not going to commit Terraform that stops matching the presented sub on the strength of a status comment: if the template is not configured, the next apply breaks every deploy on every cloud. Confirm the setting exists (repository settings, Actions, OIDC, customize sub) and I will land the AWS and Azure half in the same pass, one atomic commit per cloud.
Also open, and still true
prod and aws-fargate-prod are limited to a main branch policy while release-triggered deploys run from a tag ref, so they will be refused. No github provider resource exists under terraform/ or iac/, so environments and their policies are manual repository settings, not a PR in this repo. A tag policy for those two is the fix once a release actually exists.
Parking rather than claiming: items 1 and 2 above are the only mergeable work, and item 2 is blocked on the sub claim template confirmation. I will pick this back up on confirmation.
@cristim the claim above from 2026-10-07 has had no linked PR or activity for over 7 days. Is it still active? If not, I can take this over. [claude-cc-impl]
Owner decision (2026-10-17): the 2026-10-07 claim on this issue by an earlier agent session is released. That session has ended and no PR was opened. The platform implementation driver will pick it up in priority order.
Claiming: working on this [claude-cc-impl]. Scope: the durable in-repo half. The three ci-cd-permissions Terraform roots key trust on the immutable owner and repository IDs instead of var.github_repo. Applying it remains a bootstrap step for a privileged human, per CLAUDE.md. No apply will be done by agents.
Taking over the earlier claim (2026-10-17, no PR since, and that session is no longer active). I'll pick this up after my current PR. Scope stays the in-repo half: key the three ci-cd-permissions Terraform roots' trust on the immutable GitHub owner and repository IDs, and restrict deploy environments by branch. Validated with terraform validate/plan locally only. Applying remains a bootstrap step for a privileged human, staging first.
Activity
cristim commentedon Sep 27, 2026
Evidence after the split PR merged (bd67009): the push-triggered deploys fail at the auth step exactly as expected. Deploy to Azure (run 36347968686) fails at Azure Login, GCP (36347968701) at Authenticate to Google Cloud, and AWS Lambda (36347968765) at Configure AWS credentials. CI - Build & Test, pre-commit and frontend-build-sentinel are green. Until the bootstrap in this issue is done, every push to main produces these three red runs. Consider
gh workflow disableon the deploy/rollback/migration workflows in the meantime.cristim commentedon Sep 28, 2026
Cross-links from the CI/OIDC p1 batch
Working several overlapping p1 CI/OIDC issues in this repo; noting the
overlap with this issue's bootstrap re-apply so whoever picks this up has
the full picture:
duplicate of this issue. Same root cause (credentials keyed on repo name,
not an immutable id) and same fix (rename-proof
repository_idsubjects +bootstrap re-apply).
pull_requestfederated credential): PR sec(iac/azure): drop pull_request federated credential from CI/CD deploy SP #352 deletes thatcredential outright (unused -- PR sanity checks moved to
cloud-commitments-go) rather than re-keying it, so it's a smalleradjacent fix, not part of this issue's re-key work. Still needs the same
manual
terraform applythis issue tracks.mainunprotected while trusted as an OIDC subject): confirmedindependently live on this split repo (0 rulesets, 404 branch protection).
Sequencing note added there: protecting
mainnarrows who can reach theref:refs/heads/mainsubject this issue's trust re-apply will restore;do that before or in the same window as the re-apply, not after.
environments this issue's step 1 asks to create (with
deployment_branch_policy.custom_branch_policieslimited tomain)overlap exactly with sec(ci): deployment environments have no protection rules, so environment-bound credentialed jobs run unapproved #141's environment list. PR docs(ci): regenerate the environments list from actual environment: bindings #369 documents the
correct environment set; actually creating them with protection rules is
common ground between this issue and sec(ci): deployment environments have no protection rules, so environment-bound credentialed jobs run unapproved #141 and only needs doing once.
missing
environment:bindings on deploy jobs) that are prerequisites forthis issue's step 1 ("create every environment the workflows use... before
applying trust") to have an accurate list to create against. Both merged
code, not bootstrap state.
None of the above perform the bootstrap re-apply itself (creating
environments live, re-applying
ci-cd-permissionswith the correctgithub_repo, or making the trust rename-proof) -- that's still thisissue's scope and still needs the privileged-human bootstrap step per
CLAUDE.md.fix(ci): bind rollback.yml jobs to dev/staging/prod, not <cloud>-<env…
cristim commentedon Oct 4, 2026
Status (2026-10-04):
Done:
repo:LeanerCloud@86753534/cloud-commitments-platform@1391259743:.... That prefix embeds owner and repo IDs, so it is already rename-proof, and no custom sub template is needed (sec(iac): key CI/CD deploy trust on immutable repository IDs #451 closed).repository == LeanerCloud/cloud-commitments-platformonrefs/heads/main.-targeton the deploy role only, using bucketcudly-terraform-state-909626172446. The KMS and boundary drift is still unapplied and needs its own review.Remaining:
v*tags on prod and aws-fargate-prod for release deploys). Today onlydevexists, with no policy, and the environment subjects are ref-agnostic. So until this is done, any branch can deploy through a workflow_dispatch that binds an environment. Tracked with sec(ci): deployment environments have no protection rules, so environment-bound credentialed jobs run unapproved #141.aws/ci-cd-permissionsbackend in main.tf still names the wrong-account bucketcudly-terraform-state-dev.cristim commentedon Oct 4, 2026
Follow-up to the status comment above: #154 and #141 are now applied on this repo (2026-10-04).
mainhas ruleset24469860(PR +CI Success+Run pre-commit hooks, no bypass actors).main, including the sixgcp-db-*andazure-db-*ones that would otherwise auto-create bare.Open consequence: release-triggered deploys to
prodandaws-fargate-prodrun from a tag ref and will be refused until a tag policy is added. No releases exist yet. Details, rollback and logs are indata/platform-hardening-2026-10-04/in the split workspace.cristim commentedon Oct 7, 2026
claimed by cc-platform-w3
Working my rank 1. Starting with a verification sweep of the live state against the issue acceptance criteria before changing anything.
cristim commentedon Oct 7, 2026
Verification sweep (cc-platform-w3, 2026-10-07). Every part of the acceptance criteria that is a GitHub-side or live-IaC operation is already applied. What is left is in this repo's Terraform, and closing it needs one thing I cannot verify from here.
Verified applied
custom_branch_policies: truewith exactly one branch policy,main(type=branch). Checked per environment against the API:aws-db-{dev,staging,prod},aws-fargate-{dev,staging,prod},azure-db-{dev,staging,prod},dev,gcp-db-{dev,staging,prod},prod,staging.mainruleset24469860(PR +CI Success+Run pre-commit hooks, no bypass actors).Deploy to AWS Lambdarun 37427743382 at 2026-10-06T07:07Z. The re-pointed trust is live.The durable half is missing from this repo
All three
ci-cd-permissionsroots still key the trust onvar.github_repo:terraform/environments/aws/ci-cd-permissions/role.tf:92-128listsrepo:${var.github_repo}:ref:refs/heads/mainand the tenrepo:${var.github_repo}:environment:<name>entries.terraform/environments/azure/ci-cd-permissions/sp.tf:47,77builds the same two subject shapes.terraform/environments/gcp/ci-cd-permissions/github_oidc.tf:37conditions onassertion.repository == '${var.github_repo}', and:46binds the principal set toattribute.repository/${var.github_repo}.The immutable ids from the 2026-10-04 status comment (owner
86753534, repo1391259743) appear nowhere in this repository. The next bootstrap re-apply therefore reverts the hardening to name-keyed and brings back the rename vector this issue exists to close, silently, because the live state would look correct until it is not.Two halves, one of which needs the owner
repository_idis a claim GitHub always mints, soattribute.repository_id = "assertion.repository_id"in the attribute mapping, anassertion.repository_id == '<id>'condition, and aprincipalSet://.../attribute.repository_id/<id>member make the GCP trust rename-proof entirely inside this repo. I can do this one.subclaim template is customized, which is a GitHub repository setting and not a Terraform resource. That is also what the live trust already assumes, since it matches onlyrepo:LeanerCloud@86753534/cloud-commitments-platform@1391259743:...and main-to-main deploys authenticate, so it is very likely configured. I am not going to commit Terraform that stops matching the presentedsubon the strength of a status comment: if the template is not configured, the next apply breaks every deploy on every cloud. Confirm the setting exists (repository settings, Actions, OIDC, customizesub) and I will land the AWS and Azure half in the same pass, one atomic commit per cloud.Also open, and still true
prodandaws-fargate-prodare limited to amainbranch policy while release-triggered deploys run from a tag ref, so they will be refused. Nogithubprovider resource exists underterraform/oriac/, so environments and their policies are manual repository settings, not a PR in this repo. A tag policy for those two is the fix once a release actually exists.Parking rather than claiming: items 1 and 2 above are the only mergeable work, and item 2 is blocked on the
subclaim template confirmation. I will pick this back up on confirmation.cristim commentedon Oct 16, 2026
@cristim the claim above from 2026-10-07 has had no linked PR or activity for over 7 days. Is it still active? If not, I can take this over. [claude-cc-impl]
cristim commentedon Oct 17, 2026
Owner decision (2026-10-17): the 2026-10-07 claim on this issue by an earlier agent session is released. That session has ended and no PR was opened. The platform implementation driver will pick it up in priority order.
cristim commentedon Oct 17, 2026
Claiming: working on this [claude-cc-impl]. Scope: the durable in-repo half. The three ci-cd-permissions Terraform roots key trust on the immutable owner and repository IDs instead of var.github_repo. Applying it remains a bootstrap step for a privileged human, per CLAUDE.md. No apply will be done by agents.
fix(iac): key the GCP deploy trust on immutable repository ids
fix(iac): key the GCP deploy trust on immutable repository ids (#1066)
chore(iac/azure): reconcile prod in github_environments with its gati…
cristim commentedon Nov 4, 2026
Taking over the earlier claim (2026-10-17, no PR since, and that session is no longer active). I'll pick this up after my current PR. Scope stays the in-repo half: key the three ci-cd-permissions Terraform roots' trust on the immutable GitHub owner and repository IDs, and restrict deploy environments by branch. Validated with terraform validate/plan locally only. Applying remains a bootstrap step for a privileged human, staging first.