[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>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-11 00:38:49 +03:00
parent da0a5aa187
commit 510df68bcf
84 changed files with 13065 additions and 0 deletions
@@ -0,0 +1,84 @@
# 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` |