Files
ui/_docs/02_document/components/02_auth/description.md
T
Oleksandr Bezdieniezhnykh 510df68bcf [AZ-447] autodev Steps 1-4 baseline: docs, tests, refactor specs
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>
2026-05-11 00:38:49 +03:00

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:

  1. Mount → set loading: true.
  2. api.post('/api/admin/auth/refresh') to ask the server "do I have a valid session?".
  3. On 200 → store user + permissions, loading: false.
  4. On 4xx → user stays null, loading: false. ProtectedRoute then redirects.

PRIORITY finding (B3, copied from state.json): the bootstrap call inside AuthContext.tsx does not pass credentials: '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 /login even 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