Split the 1,896-line crates/relay/src/auth/mod.rs into focused modules:
-
jwt.rs (149 lines): JWT validation - AccessTokenClaims, AuthScope, TokenType, peek_jwt_typ, verify_access_token (HS256/ES256), parse_scope. Pattern: Functional Core.
-
bearer.rs (37 lines): Bearer token extraction. Pattern: Functional Core.
-
dpop.rs (459 lines): DPoP proof validation + nonce management - DPopHeader, DPopClaims, DpopNonceStore, DpopTokenEndpointError, issue_nonce, validate_and_consume_nonce, cleanup_expired_nonces, validate_dpop_for_token_endpoint, validate_dpop, dpop_alg_from_str, jwk_thumbprint. Pattern: Mixed (nonce store combines pure validation with async I/O).
-
signing_key.rs (139 lines): OAuth signing key lifecycle - OAuthSigningKey, load_or_create_oauth_signing_key, decode_oauth_signing_key, build_encoding_key. Pattern: Imperative Shell.
-
extractors.rs (114 lines): Axum FromRequestParts implementations - AuthenticatedUser with full DPoP/Bearer validation logic. Pattern: Imperative Shell.
-
mod.rs (1,032 lines): Module declarations, re-exports, and test suite. Tests use 'use super::*' to access internal helpers.
All code refactored exactly as-is with no logic changes. Public API unchanged. Tests passing: 61 auth tests, 144 total.