Make login OAuth state single-use #193

3 Commits
Author SHA1 Message Date
dev_agentandClaude Opus 5.5 085456b65e Count consumed pending states against the bound
CI / ci (push) Successful in 8m9s
CI / ci (pull_request) Successful in 8m11s
A consumed state left the map at once but stayed in the queue until it
expired, so starting and completing flows grew the queue past the bound.
The bound now counts the queue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:48:57 -04:00
dev_agentandClaude Opus 5.5 0f7f8014f8 Bound pending flow states
CI / ci (push) Successful in 9m31s
The login route is unauthenticated, so its pending states could grow
without limit and every Add scanned them all. Expired states now leave
from the front of an add-ordered queue, and Add refuses a new flow with
ErrTooManyPending once 10000 are pending; login answers 503. Both flows
record the state before setting the cookie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:40:18 -04:00
dev_agentandClaude Opus 5.5 0dccf87b06 Make login state single-use on the server
CI / ci (push) Successful in 9m33s
A saved copy of the signed login cookie verified until it expired, so the
callback accepted it again with a second valid authorization code. The
login now records its state as pending and the callback consumes it,
refusing a replay with the same 400 as a state mismatch.

The pending-state set moves from gcal into auth as PendingStates, so login
and the Google Calendar connect share one mechanism. It is in memory, so a
flow started before a restart fails closed after it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:31:24 -04:00