Files
turnstone/tests
Patrick Buckley 1e84f62619 fix(mcp): round-3 review fixes — revocation generation for catalog publishers
Round 3 identified the class behind the remaining bugs: catalog
PUBLISHERS never re-validate revocation state, so anything that read a
token or suspended before a drop could republish (resurrect) a revoked
catalog that retention then keeps forever. One primitive closes the
class:

- PoolEntryState.catalog_gen, bumped by _evict_session_drop_catalog.
  The three list_changed refreshes snapshot it before their awaits and
  discard results if it moved; dispatch and priming snapshot it before
  their token reads, and _connect_one_pool refuses to connect (raising
  _PoolGrantRevokedError, a non-breaker failure) when the generation
  moved past the caller's snapshot — the bearer in hand predates a
  disconnect.
- _connect_one_pool stages all three discovery results locally and
  publishes them together in the final wiring block: a mid-discovery
  failure now leaves the retained catalog exactly as it was instead of
  a torn half-update diverging from the per-user maps.
- Priming converges dead grants too: _prime_one schedules the same
  catalog drop the dispatchers use, so a NEW session's prime clears
  ghosts left by a disconnect made on another node.
- obo re-login is the obo restore moment: a successful credential
  capture at the OIDC callback now schedules prime_user_pools, so a
  previously dropped obo catalog returns to LIVE sessions (obo has no
  consent flow to heal through).
- ChatSession construction re-runs its tool rebuild when the change
  marker advanced during its authoritative read — the mirror race
  where a fresher listener update was clobbered by the constructor's
  staler snapshot.
- evict_user_session's drop task is now tracked (_spawn_background) so
  shutdown cancels it instead of abandoning a parked task.

Dedup/altitude from the round: _schedule_dead_grant_drop is the single
drop block (was three byte-identical copies); _pool_lookup_verdict is
the single lookup classification — rendering and _lookup_grant_dead
both derive from it, with literal code strings kept so the consent-url
sibling audit still sees the sites (expected count 7 -> 5 after the
collapse); PoolEntryState.drop_session() pairs session/bound_token
clearing structurally (owner-death was missing the bearer clear).
2026-07-13 21:13:42 -07:00
..