| name | token-minting |
| description | Mint and provision the fleet's git-forge credentials without static PATs - short-lived GitHub App tokens for warded github.com runs, plus Forgejo bot / CI / Flux / tap / scoop PATs in SSM. Aliases - mint token, github app token, forgejo pat, ci release token, tap bump token, scoop write token. |
Token minting
Status: 🛠 Runbook | Last updated: 2026-07-05
The fleet's git-forge credentials. No long-lived personal PAT in agent hands - a
leaked one is durable and spans Kai's identity across every repo. Prefer
short-lived managed-bot tokens in SSM. The lookup table is
references/forgejo-token-family.md.
Seven traps (read before touching any forge credential)
Provisioning a Forgejo CI credential re-derives these every time until you read
them once (coilyco-flight-deck/infrastructure#452):
- MSYS leading-slash mangling - Git Bash rewrites a bare
--name /forgejo/...
to a Windows path before aws.exe sees it, so ssm 404s and put-parameter
mangles the name. Every script exports MSYS_NO_PATHCONV=1. [[kai-windows-env]], #448.
- Minting needs basic auth -
POST /users/{u}/tokens refuses token and admin
auth (probed: HTTP 401); only a password works.
- A real user has no password - login is GitHub OAuth, so API-mint as Kai is
out. The
coilyco-ops bot is the headless minter (password in SSM) - use it.
- The org-secret PUT needs an admin token - the bot 403s on
PUT /orgs/{org}/actions/secrets/.... CI_RELEASE_TOKEN is minted as the
coilyco-ops bot over basic auth and stashed in SSM /forgejo/ci-release-token.
The org PUT still finishes with the attended Forgejo admin-token helper. A
repo secret needs no admin.
write:repository is not write:package - the package registry PUT needs
write:package explicitly, or it 401s. The whole of #448.
- No headless release re-run (Forgejo 15.0.2) - no
workflow_dispatch, no rerun
API (only GET runs/{id}). Re-run a failed job by a UI click or a fresh push.
- Verify the payoff, not the write - SSM + the secret set proves nothing. The
real check is the consumer succeeding: package registry filling, Flux syncing, CI green.
These are yours to rotate
The Forgejo CI / tap / flux / scoop scripts are agent-run, not a human handoff.
When a token is missing, stale, or a release job fails its PUT, re-run its provision
script yourself from any box with AWS/SSM (--aws on a warded engineer). Each is
idempotent and self-rotating. Do not park the run on a "grant" - the grant is a
script you run.
One split (trap 4): tap, scoop, and flux are fully yours (SSM-only, or a repo secret
set by basic auth). CI_RELEASE_TOKEN is an org secret from the bot-minted
/forgejo/ci-release-token; the coilyco-ops bot token in
/forgejo/coilyco-ops/api-token stays the headless identity. The org PUT is
still the operator's.
provision-coilyco-ops-bot and grant-coilyco-ops-org-repo-create are the operator-only
pair (site-admin PAT). A director surface (bot token, no minting password)
dispatches a warded engineer ... --aws.
GitHub App tokens (the warded-github lane)
A warded github.com/owner/repo#N run mints a ~1h single-repo installation token via
ward exec github-app-token repo=owner/name, never a PAT. Key in SSM via
provision-github-app.sh; design + scopes ->
references/github-app-dispatch-token.md.
Safety
Never print a decrypted SSM value - pipe it into the target (gh secret set,
ward). Rotate a GitHub App key in App settings, then re-run provision-github-app.sh.
See also
[[kai-windows-env]] - the MSYS trap (#1) and Git Bash specifics.
[[kai-aws-auth]] - which AWS identity reads/writes SSM (readonly vs admin).
[[kai-brew-release]] - the release pipeline these CI tokens feed; never bypass it.