ttr_app_...), session-assurance transfers, signed
access tokens (sat1.), email unsubscribe tokens and inventory simulated-order
tokens are HMAC-signed with a server secret. Every runtime that verifies or
mints them must resolve the same secret chain, so a new secret is rolled out in
stages. The first value of the chain signs; every value is accepted.
Env names
With none of the three new names set, behavior is identical to before. The
purpose-bound tokens (
getServerTokenSecretCandidates, email unsubscribe,
inventory simulated order) resolve their own dedicated names first, then follow
the same three rules, through resolveServerTokenSecrets in
packages/utils/src/app-coordination-token.ts.
Mint the next value as 32 or more random bytes (for example 64 hex
characters) in the secret manager. Never paste it into a commit, PR or chat.
SUPABASE_SECRET_KEY itself stays on every Worker: the database client still
needs it. Only its use as a token-signing fallback is retired.
Order
Each step is complete only when every runtime in the table below has the new deployment and a smoke passes. Run steps in order; wait the stated time before the next.- Deploy the code everywhere with no new env set. Verify that sign and verify behave as before (cross-app sign-in, app-token exchange).
- Add
APP_COORDINATION_TOKEN_NEXT_SECRET(same value) to Web and every Worker below, as a secret, then redeploy or restart each. Tokens still sign with the current signer. Smoke: sign in from Web into two satellites. An invalid or short value surfaces immediately as a thrown error, not as a silent downgrade. - Promote: set
APP_COORDINATION_TOKEN_SIGNER=nexton every runtime. Roll Web last. Until Web flips, satellites already sign withnext, and Web still verifies them because it holds the slot. Tokens issued before the flip keep verifying through the chain. - Wait for the longest token lifetime to elapse. App coordination
tokens default to 8 hours (
DEFAULT_EXPIRES_IN_SECONDSinpackages/utils/src/app-coordination-token.ts; callers may set less), signed access tokens take a TTL per call, and simulated-order tokens last 24 hours. Email unsubscribe tokens carry no expiry: links already sent stay valid only while the secret that signed them remains in the chain. - Retire the fallbacks: set
APP_COORDINATION_TOKEN_DISABLE_SUPABASE_FALLBACK=1everywhere. Make sureTUTURUUU_APP_COORDINATION_SECRET(or the slot) is present first, because an empty list fails closed. If that secret equals the old Supabase signer value, existing unsubscribe links keep verifying. - Hold: leave
APP_COORDINATION_TOKEN_NEXT_SECRETandAPP_COORDINATION_TOKEN_SIGNER=nextset. Moving the promoted value intoTUTURUUU_APP_COORDINATION_SECRETand dropping the old one is a separate, later change that retires every token the old value signed, including unsent-yet-valid unsubscribe links.
Rollback
If a deployment is partial after step 3 (some runtimes without the slot), flip
the signer back to
current first and redeploy the stragglers before trying
again.
Runtimes that read the secret
Web (apps/web, Next.js) and every satellite that verifies tokens through
@tuturuuu/auth, @tuturuuu/utils or @tuturuuu/inventory-core.
Native Start Workers whose packet or startup check names the secret (see each
packet for its Worker name, vars and secrets):
ai,
chat,
cms,
drive,
external,
finance,
forms,
git,
hive,
infrastructure,
inventory,
learn,
mind,
nova,
pay,
rewise,
shortener,
storefront,
tasks,
teach,
track,
workspace.
Other packets that name it: finance-pay,
mastermind,
playground,
tools,
wave 1,
web Docker and
TanStack/Rust local deploy
(inactive runtimes).
Apps with env.example entries for the secret: calendar, cms, drive,
finance, forms, hive, inventory, learn, mind, nova, pay,
rewise, shortener, tasks, teach, track, workspace, plus web.
Worker startup checks require TUTURUUU_APP_COORDINATION_SECRET (tasks,
tools, forms, playground, storefront and others, see their cloudflare/
folder). Those checks keep requiring it; the new names are optional and are
read directly from the runtime environment.
The paused Rust backend (apps/backend) verifies app tokens with its own
implementation and does not read the new names. It must adopt the same rules
before it is resumed; do not roll out step 3 while it serves live traffic.
Verification
- Unit:
packages/utils/src/app-coordination-token.test.tscovers default behavior, accept-only, a verifier holding only the slot, promotion with old tokens, fallback removal, the empty-list failure and the short secret. - Per runtime, before moving on: one cross-app sign-in, one app-token
exchange, one signed-access-token flow, and confirm there are no
must be at least 32 charactersorrequireserrors in Worker logs.