From f2b75bbb66addabd688195b1d3c0947cd92e5803 Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Fri, 4 Sep 2026 15:56:23 -0700 Subject: [PATCH] docs(token-rotation): one token in five places, expiring 2027-06-29 The table I filled in last commit implied five independently minted tokens with five unknown expiries. There is one token, minted 2026-06-29 and expiring 2027-06-29, copied into five locations -- the migration reused the existing credential rather than minting new ones, to avoid adding a variable mid-migration. That distinction is the whole point of the doc: a rotation has to update every location, and a reader who thinks these are separate credentials will rotate one and leave four live on an expiring token. Step 2 of the runbook now says so. The dates from `gh secret list` are when each copy was written, not when the token was minted. Renamed that column to "Secret last set" so it cannot be read as a rotation input. photo-game-poc is the exception: its copy predates 2026-06-29, so it holds an older token whose expiry is unrecorded. Marked unknown rather than assumed. The repo is archived and runs nothing, so it is not urgent -- re-setting the secret from the current token folds it in. Calendar reminder set for 2027-06-15, two weeks before expiry, naming all five locations. Claude-Session: https://claude.ai/code/session_01MM2jf6c7eNN4QMq32GdC5X --- docs/token-rotation.md | 51 ++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/docs/token-rotation.md b/docs/token-rotation.md index c9c05ee..aaf7847 100644 --- a/docs/token-rotation.md +++ b/docs/token-rotation.md @@ -13,23 +13,37 @@ on that. The Team plan was bought to file a support ticket and will be dropped; a repo whose copy was deleted on that basis fails silently at the downgrade. -| Scope | Minted | Expires | Minted on | +**One token is installed in several places.** It was minted 2026-06-29 and +expires **2027-06-29**. The migration copied the existing token rather than +minting new ones, deliberately, to avoid adding a variable mid-migration. +So a single rotation covers every row below that names it — these are +locations, not separate credentials. + +| Scope | Token | Expires | Secret last set | | --- | --- | --- | --- | -| org `smartwatermelon` | 2026-09-04 | unrecorded | ASIAGO | -| org `nightowlstudiollc` | 2026-07-01 | unrecorded | unrecorded | -| repo `smartwatermelon/scripts` | 2026-07-29 | unrecorded | unrecorded | -| repo `nightowlstudiollc/photo-game-poc` | 2026-03-02 | unrecorded | unrecorded | -| repo `nightowlstudiollc/cleanroom` | 2026-08-31 | unrecorded | unrecorded | - -Minted dates are the secret's `updated_at` from -`gh secret list`, which is when the value was last set — accurate for -rotation planning. **Expiry is not recoverable from the API.** It exists only -in what `claude setup-token` printed at mint time, so fill each row in at -step 4 of the runbook below rather than reconstructing it later. Until a row -has a real expiry, its calendar event cannot be scheduled. - -Each row gets a Google Calendar event "Rotate CLAUDE_CODE_OAUTH_TOKEN -()" two weeks before the expiry date, pointing here. +| org `smartwatermelon` | 2026-06-29 | 2027-06-29 | 2026-09-04 | +| org `nightowlstudiollc` | 2026-06-29 | 2027-06-29 | 2026-07-01 | +| repo `smartwatermelon/scripts` | 2026-06-29 | 2027-06-29 | 2026-07-29 | +| repo `nightowlstudiollc/cleanroom` | 2026-06-29 | 2027-06-29 | 2026-08-31 | +| repo `nightowlstudiollc/photo-game-poc` | unknown | unknown | 2026-03-02 | + +"Secret last set" is the secret's `updated_at` from `gh secret list` — when +that copy was written, which is not when the token behind it was minted. +Do not read it as an expiry input. + +`photo-game-poc` is the exception: its copy predates 2026-06-29, so it holds +an older token whose expiry is not recorded anywhere. The repo is archived +and runs nothing, so this is not urgent; resolve it by re-setting that +secret from the current token, at which point the row folds into the block +above. + +Expiry is not recoverable from the API — it exists only in what +`claude setup-token` printed at mint time. When a future rotation splits +these into separate tokens, give each its own row and record the expiry at +step 4 of the runbook below. + +One Google Calendar event, "Rotate CLAUDE_CODE_OAUTH_TOKEN (all scopes)", +sits two weeks before 2027-06-29 and points here. One token, one reminder. ## Rotation runbook @@ -45,7 +59,10 @@ between. Copy the token from the terminal. Do not paste it anywhere but step 2. -2. Set it (the wrapper prints this exact line if you forget `env -u`): +2. Set it in **every** location below — they currently share one token, so a + rotation that updates only some of them leaves the rest on a credential + that is about to expire. (The wrapper prints this exact line if you + forget `env -u`.) ```bash env -u GH_TOKEN gh secret set CLAUDE_CODE_OAUTH_TOKEN --org smartwatermelon --visibility all