Relationships
#2534 serve: without a remote datastore the token GC is not serialized against token rotate/re-mint
Opened by stack72 · 9/25/2026
Description
The server token GC (swamp-club#2413) collects each token as one unit under serve's sync gate. Inside the unit it re-reads the token's token-main, re-checks eligibility, then deletes the secret, the OAuth access token and the records. Serve's access.token.mint, access.token.rotate and access.token.revoke handlers, and the OAuth login mint, hold the same gate. With a remote datastore, a token write in the same process therefore lands either before the GC's re-read or after its unit.
Serve only creates the gate when a sync service exists. In src/cli/commands/serve.ts it is created as syncService ? createSyncGate() : undefined. On the default filesystem datastore, withSyncGate(undefined, fn) just calls fn(), so nothing serializes the GC against token writes.
Race (filesystem datastore)
- Token
ciexpired two hours ago, and the grace period is one hour. - A sweep re-reads
ci, finds it eligible, and moves on to resolve its definition. - An operator's
access.token.rotate ciwrites a new secret toserver-token-ciand an activetoken-mainon the same definition. - The GC deletes
server-token-ci(the new secret), then the definition and data. - The rotate has already returned a credential that never authenticates, and
ciis gone fromaccess token list.
The window is a few milliseconds per collected token per sweep, and the failure is fail-closed (no unauthorized access), but the rotated token is lost and has to be minted again. design/primitives/serve.md documents this gap.
Expected
Token writes and the GC's collection unit are serialized in every deployment. That could be a process-local lock for token mutations, which the GC, the token handlers and the OAuth mint share whether or not a sync service exists. Or the sync gate could always be created for these units. Creating it unconditionally for every gated request would also serialize the other handlers on filesystem serve, which may or may not be wanted.
Open
No activity in this phase yet.
Sign in to post a ripple.