chore(auth): prepare production Wolfi publication grant - #133
Merged
cpanato merged 2 commits intoSep 29, 2026
Merged
Conversation
cpanato
previously approved these changes
Sep 29, 2026
joedborg
marked this pull request as draft
September 29, 2026 13:07
joedborg
marked this pull request as ready for review
September 29, 2026 13:10
joedborg
enabled auto-merge (squash)
September 29, 2026 13:40
jmeridth
approved these changes
Sep 29, 2026
joedborg
added a commit
to chainguard-dev/.github
that referenced
this pull request
Sep 29, 2026
## Why Export and publication require distinct, narrowly scoped access to the production intermediate repository. ## How Add organization policies outside mirrored history: exporter gets `contents: write` only on `wolfi-staging`; publisher gets `contents: read` only on `wolfi-staging`. Exact Google subjects are separate; no public-write or git-export grant is added. **Merge in step 2 after staging acceptance, fresh CI, and review.** The paused foundation deployment is confirmed and the verified production numeric subjects are now populated. Keep the new schedules paused through policy installation and handover. ## Proof The [production foundation deployment](https://github.com/chainguard-dev/mono/actions/runs/36571602400/job/109416724297) applied successfully at **2026-09-29 13:01:33 UTC** (27 added, 0 changed, 0 destroyed). It deployed `20b01d2cc011307f62d7e389dc31355ea4ad1c8e`, a verified descendant of merged foundation `f605768657b04638e6d2a552ec3ff4cdd09c8514`. Direct GCP IAM reads and the run's `tf-output-env-enforce.dev-iac-400-export-wolfi` artifact agree: | Account | Numeric subject | |---|---| | `export-wolfi@prod-enforce-fabc.iam.gserviceaccount.com` | `100496071258544612791` | | `export-wolfi-publish@prod-enforce-fabc.iam.gserviceaccount.com` | `111686246305885758377` | All four prepared policy YAMLs structurally equal the deployment's `octosts_policies` outputs. Live read-only checks confirmed both jobs Ready at observed generation 1, saved `DRY_RUN=true`, empty bootstrap, separate runtime accounts, expected repositories/branches/horizon/signer, 2 CPU/8 GiB, and zero task retries. Both Scheduler jobs are **PAUSED** (hourly export; daily 14:00 UTC publication). Both deployed image signatures were independently verified with cosign against exact identity `https://github.com/chainguard-dev/mono/.github/workflows/.terraform.yaml@refs/heads/main` and issuer `https://token.actions.githubusercontent.com`. Export digest: `sha256:6027800bd11f80eeaecc6df67b4c7d158df1da87657524f29c87853e7f867027`; publication digest: `sha256:3d99353bb87f53adaf822cdc24789f6b5ccb2252e6e44a1c41b3bee2c999a279`. Both job-failure alert policies are enabled with troubleshooting documentation and the expected enabled destinations: `#eng-os-prod-alerts`, shared Pub/Sub `alerts`, and OS Pub/Sub `alerts_os`. This is a configuration check, not notification-delivery proof. Pinned yam formatting, strict OctoSTS v0.8.0 schema/compile/scope/permission checks, and diff checks pass. For each policy, synthetic claims with the configured production subject are allowed; the opposite production identity, staging/dev identities, fixture subjects, empty subject, wrong issuer and wrong audience are rejected. These are offline authorization checks; production runtime token exchange and Git writes remain part of the later handover proof. Two independent reviews found no remaining findings. The source-policy PR additionally passed all applicable stereo pre-commit hooks individually (yam, misspell, YAML, Markdown, large-file/case/conflict/private-key/todo checks). The all-hooks launcher initially failed installing the unrelated wolfictl package linter after a Go proxy stream error; that linter does not apply to these files. The temporary checker passed gofmt, go mod tidy, go test (no test files), and golangci-lint. No proof files were committed. ## Merge order 0. **Staging gate:** [mono#62720](chainguard-dev/mono#62720) deployed; real-publication peak-memory evidence accepted. 1. **Foundation:** [chainguard-dev/mono#62783](chainguard-dev/mono#62783). Merged and deployed paused/dry-run on September 29; [successful deployment evidence](https://github.com/chainguard-dev/mono/actions/runs/36571602400/job/109416724297). 2. **Runtime policies, parallel after step 1:** [chainguard-dev/stereo#356262](chainguard-dev/stereo#356262); [#324](#324); [wolfi-dev/.github#133](wolfi-dev/.github#133). Production numeric subjects are populated and verified against IAM and deployment outputs. Require fresh CI and review before merging. 3. **Stop Actions:** [chainguard-dev/stereo#356263](chainguard-dev/stereo#356263). During the owned handover window, disable schedules/manual dispatch and drain queued/active runs before new writers may run. 4. **Legacy retirement after step 3:** [chainguard-dev/wolfi-staging#25](chainguard-dev/wolfi-staging#25) and [chainguard-dev/git-export#160](chainguard-dev/git-export#160). Remove the destination grant in wolfi-staging only, before selecting the bootstrap SHA. Publication carries the same deletion into public; do not open a divergent public-policy removal commit. Keep mono's build-time policy. 5. **Operator handover proof:** freeze/review destination history, review the exact bootstrap SHA, prove real export parity/signing and exact-commit publication with schedules still paused. Recheck every export advancement and publish only the final verified tip. 6. **Activation LAST:** [chainguard-dev/mono#62787](chainguard-dev/mono#62787). Merge only after the handover evidence is accepted, then have an authorized operator deploy it and verify natural scheduled execution. Merging is not deployment. This PR set does not authorize or perform production releases, local production plans/applies, or runtime writes. Full procedure: [production runbook](https://github.com/chainguard-dev/mono/blob/main/env/enforce.dev/iac/400-export-wolfi/README.md). Tracking: [OS-2867](https://linear.app/chainguard/issue/OS-2867).
cpanato
approved these changes
Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The production publisher needs public repository write access without granting that access to the exporter.
How
Add an organization-hosted policy for the dedicated production publisher, restricted to
repositories: [os]andcontents: write. Keeping it outside mirrored history avoids policy commits diverging the publication branch.Merge in step 2 after staging acceptance, fresh CI, and review. The paused foundation deployment is confirmed and the verified production numeric subjects are now populated. Keep the new schedules paused through policy installation and handover.
Proof
The production foundation deployment applied successfully at 2026-09-29 13:01:33 UTC (27 added, 0 changed, 0 destroyed). It deployed
20b01d2cc011307f62d7e389dc31355ea4ad1c8e, a verified descendant of merged foundationf605768657b04638e6d2a552ec3ff4cdd09c8514.Direct GCP IAM reads and the run's
tf-output-env-enforce.dev-iac-400-export-wolfiartifact agree:export-wolfi@prod-enforce-fabc.iam.gserviceaccount.com100496071258544612791export-wolfi-publish@prod-enforce-fabc.iam.gserviceaccount.com111686246305885758377All four prepared policy YAMLs structurally equal the deployment's
octosts_policiesoutputs. Live read-only checks confirmed both jobs Ready at observed generation 1, savedDRY_RUN=true, empty bootstrap, separate runtime accounts, expected repositories/branches/horizon/signer, 2 CPU/8 GiB, and zero task retries. Both Scheduler jobs are PAUSED (hourly export; daily 14:00 UTC publication).Both deployed image signatures were independently verified with cosign against exact identity
https://github.com/chainguard-dev/mono/.github/workflows/.terraform.yaml@refs/heads/mainand issuerhttps://token.actions.githubusercontent.com. Export digest:sha256:6027800bd11f80eeaecc6df67b4c7d158df1da87657524f29c87853e7f867027; publication digest:sha256:3d99353bb87f53adaf822cdc24789f6b5ccb2252e6e44a1c41b3bee2c999a279.Both job-failure alert policies are enabled with troubleshooting documentation and the expected enabled destinations:
#eng-os-prod-alerts, shared Pub/Subalerts, and OS Pub/Subalerts_os. This is a configuration check, not notification-delivery proof.Pinned yam formatting, strict OctoSTS v0.8.0 schema/compile/scope/permission checks, and diff checks pass. For each policy, synthetic claims with the configured production subject are allowed; the opposite production identity, staging/dev identities, fixture subjects, empty subject, wrong issuer and wrong audience are rejected. These are offline authorization checks; production runtime token exchange and Git writes remain part of the later handover proof. Two independent reviews found no remaining findings.
The source-policy PR additionally passed all applicable stereo pre-commit hooks individually (yam, misspell, YAML, Markdown, large-file/case/conflict/private-key/todo checks). The all-hooks launcher initially failed installing the unrelated wolfictl package linter after a Go proxy stream error; that linter does not apply to these files. The temporary checker passed gofmt, go mod tidy, go test (no test files), and golangci-lint. No proof files were committed.
Merge order
Merging is not deployment. This PR set does not authorize or perform production releases, local production plans/applies, or runtime writes. Full procedure: production runbook. Tracking: OS-2867.