ci: read the blocks credential from OpenBao instead of a stored secret #139

Merged
peterswimm merged 1 commit from ci/bao-approle-checkout into main 2026-09-14 21:36:33 +00:00
Owner

Follow-up to #138. The gate needs the block definitions from the private Toilville_Rituals, and asked for a CI_TOKEN Actions secret that exists on neither repo. Rather than park a long-lived secret in Actions, fetch the credential at run time — the forge's own pattern, and the one the Rituals workflows already use for Sentry.

The ci-runner AppRole (the CI_VAULT_* org secrets) logs in to OpenBao and reads secret/forge/rituals-read, whose token belongs to ci-rituals-reader — an account with read on Toilville_Rituals and nothing else. Same shape as secret/forge/forge-kv-cache-read. Nothing long-lived sits in Actions, the fetch is audited through bastia, and a leak reads one repository.

Scope

  • .forgejo/actions/bastia-secret/ — the credential-broker action, copied verbatim from Toilville_Rituals@11220e9. Copied rather than referenced because uses: ./… resolves inside the repo running the workflow, and reaching the original would require the very checkout this credential is for. README.md records the provenance; the honest fix is a shared actions repository, worth doing if a third repo needs it.
  • .forgejo/workflows/block-validation.yml — fetch the token, check out with it, and drop CI_TOKEN. The error message now names the OpenBao path and the AppRole secrets.
  • Corrects the note above ref:. It claimed checkout without a ref looks for the current branch in the sibling repository. It does not — it uses that repository's default branch, and the failure it blamed was the token's scope. The pin stays, for the real reason: validate against the branch the site deploys from.

Testing

  • yamllint, test_workflow_invariants.py (57 passing), and a grep confirming no expression appears inside a run: comment — one of those took the whole workflow down in #137.
  • The job stays red until secret/forge/rituals-read holds a token that can read the repository. Provisioning ci-rituals-reader is blocked on an unrelated bug: forgejo:admin grants have been unapprovable since 2026-09-07, because ritual-consumer inserts the pending grant with ON CONFLICT into what migration 20260907_0045 made a view. Fix merged in ritual-engine #622; it needs a build and deploy.
  • The gate itself is unchanged and was verified in #137: 31 generated files clean, 47 inherited blocks reported, and a reintroduced #136 bug caught with the file, block and attribute named.

Impact Statement

CI only — no change to any generated artifact, the theme, or the site. Removes a dependency on an Actions secret that was never created, in favour of a short-lived token fetched per run. Until ci-rituals-reader exists the job still fails, and says exactly what is missing.

Follow-up to #138. The gate needs the block definitions from the private `Toilville_Rituals`, and asked for a `CI_TOKEN` Actions secret that exists on neither repo. Rather than park a long-lived secret in Actions, fetch the credential at run time — the forge's own pattern, and the one the Rituals workflows already use for Sentry. The ci-runner AppRole (the `CI_VAULT_*` org secrets) logs in to OpenBao and reads `secret/forge/rituals-read`, whose token belongs to `ci-rituals-reader` — an account with read on `Toilville_Rituals` and nothing else. Same shape as `secret/forge/forge-kv-cache-read`. Nothing long-lived sits in Actions, the fetch is audited through bastia, and a leak reads one repository. ## Scope - `.forgejo/actions/bastia-secret/` — the credential-broker action, copied verbatim from `Toilville_Rituals@11220e9`. Copied rather than referenced because `uses: ./…` resolves inside the repo running the workflow, and reaching the original would require the very checkout this credential is for. `README.md` records the provenance; the honest fix is a shared actions repository, worth doing if a third repo needs it. - `.forgejo/workflows/block-validation.yml` — fetch the token, check out with it, and drop `CI_TOKEN`. The error message now names the OpenBao path and the AppRole secrets. - Corrects the note above `ref:`. It claimed checkout without a ref looks for the current branch in the sibling repository. It does not — it uses that repository's default branch, and the failure it blamed was the token's scope. The pin stays, for the real reason: validate against the branch the site deploys from. ## Testing - `yamllint`, `test_workflow_invariants.py` (57 passing), and a grep confirming no expression appears inside a `run:` comment — one of those took the whole workflow down in #137. - The job stays red until `secret/forge/rituals-read` holds a token that can read the repository. Provisioning `ci-rituals-reader` is blocked on an unrelated bug: `forgejo:admin` grants have been unapprovable since 2026-09-07, because `ritual-consumer` inserts the pending grant with `ON CONFLICT` into what migration `20260907_0045` made a view. Fix merged in ritual-engine #622; it needs a build and deploy. - The gate itself is unchanged and was verified in #137: 31 generated files clean, 47 inherited blocks reported, and a reintroduced #136 bug caught with the file, block and attribute named. ## Impact Statement CI only — no change to any generated artifact, the theme, or the site. Removes a dependency on an Actions secret that was never created, in favour of a short-lived token fetched per run. Until `ci-rituals-reader` exists the job still fails, and says exactly what is missing.
ci: read the blocks credential from OpenBao instead of a stored secret
Some checks failed
PR policy check / policy-gate (pull_request) Successful in 0s
Block Validation / validate (pull_request) Failing after 24s
Security Scans / Trivy filesystem scan (pull_request) Successful in 45s
Security Scans / Gitleaks secret scan (pull_request) Successful in 37s
Test Generator / test (pull_request) Failing after 21s
Test Generator / lint-workflows (pull_request) Successful in 22s
Test Generator / lint-prose (pull_request) Successful in 25s
UDG dist drift gate / dist/ matches dtcg + udg sources (pull_request) Successful in 17s
Copy coverage / Design copy reaching rendered HTML (pull_request) Failing after 30s
a8744be882
The gate checks out the private Toilville_Rituals for the block.json files
it validates against, and asked for a CI_TOKEN Actions secret that exists
on neither repo. FORGEJO_TOKEN, the one org secret that is supplied,
cannot read repositories.

Fetch the token at run time instead, the way the Rituals workflows fetch
Sentry's: the ci-runner AppRole (CI_VAULT_* org secrets) logs in to
OpenBao and reads secret/forge/rituals-read. That path holds a token for
ci-rituals-reader, an account with read on Toilville_Rituals and nothing
else — the same shape as secret/forge/forge-kv-cache-read. No long-lived
secret sits in Actions, and the fetch is audited through bastia.

bastia-secret is copied from Toilville_Rituals rather than referenced:
`uses: ./…` resolves inside the repository running the workflow, and
reaching the original would need the checkout this credential is for.

Also corrects the note above `ref:`. It claimed checkout without a ref
looks for the current branch in the sibling repository; it does not — it
uses that repository's default branch, and the failure it blamed was the
token's scope.
peterswimm deleted branch ci/bao-approle-checkout 2026-09-14 21:36:33 +00:00
Sign in to join this conversation.
No description provided.