# Session Auth Protocol (Frontend <-> Backend) This protocol defines login, refresh, and logout contract for Eryao Flutter app. Protocol verification status: - Last audited against backend source: `backend/src/v1/auth/router.py`, `backend/src/v1/auth/schemas.py`, `backend/src/v1/router.py` - Frontend mapping source: `apps/lib/features/auth/data/apis/auth_api.dart` - Current status: aligned ## Base URL - Runtime injected by Flutter `--dart-define=BACKEND_URL=...` - Fallback: - Android emulator: `http://10.0.2.2:5775` - Others: `http://localhost:5775` ## Transport - Content type: `application/json` - Error format: RFC7807 with extension fields `code`, `params` ## Route audit (current backend) From `backend/src/v1/auth/router.py`: - `POST /auth/otp/send` (204) - `POST /auth/email-session` (200, `SessionResponse`) - `POST /auth/sessions/refresh` (200, `SessionResponse`) - `DELETE /auth/sessions` (204) Gateway error codes from `backend/src/v1/auth/gateway.py`: - `AUTH_SERVICE_UNAVAILABLE` - `AUTH_TOO_MANY_REQUESTS` - `AUTH_VERIFICATION_CODE_INVALID` - `AUTH_REFRESH_TOKEN_INVALID` - `AUTH_REFRESH_TOKEN_MISSING` ## Frontend route mapping - Send OTP: `POST /api/v1/auth/otp/send` - Login with OTP: `POST /api/v1/auth/email-session` - Refresh session: `POST /api/v1/auth/sessions/refresh` - Logout: `DELETE /api/v1/auth/sessions` ## Payload contract ### Send OTP Request: ```json { "email": "user@example.com" } ``` Validation (backend): - `email` must match `SUPABASE_EMAIL_PATTERN` Response: `204 No Content` ### Create session Request: ```json { "email": "user@example.com", "token": "123456" } ``` Validation (backend): - `email` must match `SUPABASE_EMAIL_PATTERN` - `token` must be exactly 6 chars Response: ```json { "access_token": "...", "refresh_token": "...", "expires_in": 3600, "token_type": "bearer", "user": { "id": "uuid", "email": "user@example.com" } } ``` ### Refresh session Request: ```json { "refresh_token": "..." } ``` Validation (backend): - `refresh_token` min length: 1 Response: same as create session. ### Logout Request: ```json { "refresh_token": "..." } ``` Validation (backend): - `refresh_token` min length: 1 Response: `204 No Content` ## Global auth state requirements - Auth must be managed by single global `AuthBloc` instance. - App startup must attempt refresh if refresh token exists. - On refresh failure (`401` + `AUTH_REFRESH_TOKEN_INVALID`), clear local session and route to login. - Login success must persist access token + refresh token + display email. - Logout must call backend route then clear local session. - For protected requests, when backend returns `401`, frontend network layer must trigger global auth invalidation callback (single chain), not feature-level token clearing. ## Login identity mode - Current app version supports **email OTP login only**. - Phone registration/login is removed from frontend flow.