feat: implement POST /xrpc/com.atproto.server.refreshSession
Exchanges a refresh JWT for a new access + refresh token pair with
full token rotation and replay detection.
- Verify HS256 refresh JWT (signature, expiry, audience, scope)
- Look up token in refresh_tokens table; reject if not found/expired
- Detect replay: next_jti IS NOT NULL triggers full session revocation
(deletes session + all its refresh tokens atomically)
- On first use: atomically insert new token and set next_jti on old one
- Return { accessJwt, refreshJwt, handle, did }
Refactors issue_access_jwt and issue_refresh_jwt out of create_session
into auth/jwt.rs so both routes can share them without violating the
no-cross-route-imports rule. Also promotes extract_bearer_token to
pub(crate) so route handlers can call it directly.
10 tests covering all 4 ACs: valid rotation, scope/claim checks, DB
state after rotation, replay rejection, session revocation on replay,
expired/invalid/wrong-scope token errors, missing auth header.