The plan documented both behaviors but neither was exercised:
- Concurrent rotation: two clients presenting the same refresh token whose
GetTokenByJTI lookups both complete before either revoke must both
succeed with distinct new pairs. Uses a barrierStore that gates the
first Revoke so the test is deterministic instead of relying on the
scheduler.
- Revoke failure: if RevokeTokenByJTI errors after the new pair is
persisted, /auth/refresh returns 500 and the OLD JTI stays valid so
the client can retry without losing access.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>