Captures the full output of autodev existing-code Phase A through Step 4 (Code Testability Revision) for the Azaion UI workspace: - Step 1 Document: _docs/02_document/ (FINAL_report, architecture, glossary, components/, modules/, diagrams/, system-flows, module-layout) plus _docs/00_problem/ + _docs/01_solution/ + _docs/legacy/ + _docs/how_to_test + README. - Step 2 Architecture Baseline: architecture_compliance_baseline.md. - Step 3 Test Spec: _docs/02_document/tests/ (environment, test-data, blackbox/performance/resilience/security/ resource-limit tests, traceability-matrix), enum_spec_snapshot, expected_results/results_report.md (98 rows), plus the run-tests.sh + run-performance-tests.sh runners. - Step 4 Code Testability Revision: 01-testability-refactoring/ run dir (list-of-changes C01-C07, deferred_to_refactor, analysis/research_findings + refactoring_roadmap) and the 7 child task specs AZ-448..AZ-454 under _docs/02_tasks/todo/ plus _dependencies_table.md. - _docs/_autodev_state.md pins the cursor at Step 4 / refactor Phase 4 entry so /autodev resumes cleanly. Epic AZ-447 (UI testability gates) tracks the 7 child tasks that will land in subsequent commits. Co-authored-by: Cursor <cursoragent@cursor.com>
4.0 KiB
02 — Auth
1. High-Level Overview
Purpose: Authentication state, login/logout/refresh plumbing, and the <ProtectedRoute> gate that wraps every non-public route.
Architectural Pattern: React Context provider + route-guard component.
Upstream dependencies: 00_foundation (types), 01_api-transport.
Downstream consumers: 04_login, 10_app-shell, every authenticated page (indirectly via the route gate).
2. Internal Interfaces
src/auth/AuthContext.tsx
| Export | Signature | Notes |
|---|---|---|
AuthProvider({ children }) |
React component | Wraps the app below BrowserRouter. Bootstraps via GET /api/admin/auth/refresh on mount. |
useAuth(): AuthContextValue |
hook | Read-only access to { user, permissions, login, logout, refresh, loading }. |
AuthContextValue (output DTO):
user: User | null
permissions: Permission[] ← from server, used by route guards & UI
loading: boolean ← true during initial bootstrap and active refresh
login(c): Promise<User> ← POST /api/admin/auth/login
logout(): Promise<void> ← POST /api/admin/auth/logout
refresh(): Promise<void> ← POST /api/admin/auth/refresh
src/auth/ProtectedRoute.tsx
| Export | Signature | Notes |
|---|---|---|
ProtectedRoute({ children, requirePermission? }) |
React component | Renders children if authenticated; otherwise navigates to /login. Optional requirePermission is checked against useAuth().permissions and renders a 403 placeholder on miss. |
3. External API Specification
Consumes only — does not expose. Endpoint set (from _docs/02_document/modules/src__auth__AuthContext.md):
| Method | Path | Auth | When |
|---|---|---|---|
| POST | /api/admin/auth/login |
public | Login form submit |
| POST | /api/admin/auth/refresh |
cookie | Bootstrap + on 401 retry |
| POST | /api/admin/auth/logout |
cookie | Header → Logout |
| GET | /api/admin/auth/me |
cookie | (post-login profile fetch, if implemented) |
5. Implementation Details
State Management: Single React context. Token lives in an HTTP-only cookie (server-managed); the React state holds only the parsed user + permissions. No localStorage.
Bootstrap sequence:
- Mount → set
loading: true. api.post('/api/admin/auth/refresh')to ask the server "do I have a valid session?".- On 200 → store user + permissions,
loading: false. - On 4xx → user stays
null,loading: false.ProtectedRoutethen redirects.
PRIORITY finding (B3, copied from state.json): the bootstrap call inside
AuthContext.tsxdoes not passcredentials: 'include'consistently — the cookie is therefore not sent on the very first request and bootstrap silently fails on a fresh page load. Confirmed real bug; Step 4 fix.
Spinner UX: ProtectedRoute renders a centered spinner during loading. The spinner has no role="status" / no accessible label / no timeout. (Findings B4, joint with Step 4 client.ts timeout flag.)
7. Caveats & Edge Cases
- Bootstrap missing
credentials: 'include'→ users land on/logineven with a valid cookie session. PRIORITY Step 4. - Spinner accessibility — Step 4.
- Token-rotation interaction with SSE — see
01_api-transport. Auth refresh works for fetch but breaks every active EventSource. - No idle-timeout / inactivity logout — server-side concern; UI tolerates whatever the server enforces.
8. Dependency Graph
Must be implemented after: 00_foundation, 01_api-transport.
Can be implemented in parallel with: nothing inside this workspace's gate path.
Blocks: 03_shared-ui (Header reads useAuth), 04_login, 10_app-shell, indirectly every authenticated page.
Module Inventory
| Path | Module Doc |
|---|---|
src/auth/AuthContext.tsx |
_docs/02_document/modules/src__auth__AuthContext.md |
src/auth/ProtectedRoute.tsx |
_docs/02_document/modules/src__auth__ProtectedRoute.md |