Files
ui/_docs/03_implementation/batch_13_cycle3_report.md
T
Oleksandr Bezdieniezhnykh 70fb452805 [AZ-510] Auth bootstrap: POST refresh + chained /users/me
Replace the broken `GET /api/admin/auth/refresh` (no `credentials:'include'`)
mount-time bootstrap with `POST /api/admin/auth/refresh` (with credentials)
chained to `GET /api/admin/users/me`. Returning users with a valid HttpOnly
refresh cookie no longer flash through `/login`. Closes Finding B3 / Vision P3.

- Add module-scoped `bootstrapInflight` guard (StrictMode double-mount safety)
  + test-only reset hook exported via the `src/auth` barrel; `tests/setup.ts`
  resets it in `afterEach` to prevent pending-promise leakage between tests.
- Defensive `hasPermission` against legacy `/users/me` payloads omitting
  `permissions`; default MSW handler now seeds `permissions` explicitly.
- Add `endpoints.admin.usersMe()` builder (STC-ARCH-02 forbids the literal).
- Bulk-swap 15 test files from `http.get` -> `http.post` for the refresh
  override so intentional bootstrap-fail tests still fail correctly.
- Update auth component description; mark B3 closed.
- Code review verdict PASS; static + fast suites green (231 / 13 skipped).

Batch report: _docs/03_implementation/batch_13_cycle3_report.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 02:59:31 +03:00

5.3 KiB

Batch 13 — AZ-510 (Auth bootstrap refresh consolidation)

Date: 2026-05-13 Cycle: 3 — autodev Step 10 (Implement), batch 1 of 3 (fixes-first order: AZ-510 → AZ-511 → AZ-512) Tickets: AZ-510 (Epic AZ-509) Verdict: PASS


Task Results

Task Status Files Modified Tests AC Coverage Issues
AZ-510_auth_bootstrap_consolidation Done 25 files 231 passed / 13 skipped (full fast suite) 6/6 ACs covered None

AC Test Coverage: 6/6 covered

  • AC-1 → AuthContext.test.tsx FT-P-01 (POST + credentials:'include' + no GET refresh)
  • AC-2 → FT-P-01 (chain to /users/me, bearer set, loading false)
  • AC-3 → ProtectedRoute.test.tsx (failed bootstrap → spinner → /login once); also exercised by NFT-SEC-01's intermediate state
  • AC-4 → AuthContext.test.tsx "AC-4 (AZ-510)" test (new, lines 108-138)
  • AC-5 → ProtectedRoute.test.tsx admin-route success cases (no /login on success bootstrap)
  • AC-6 → AuthContext.test.tsx NFT-SEC-01 + FT-P-03 (401-retry path unchanged); plus existing src/api/client.test.ts retry tests

Code Review Verdict: PASS

  • Report: _docs/03_implementation/reviews/batch_13_review.md
  • 0 findings (Critical / High / Medium / Low)
  • Resolved baseline finding B3 (Auth bootstrap missing credentials:'include' — Vision P3 violation)

Auto-Fix Attempts: 0

No auto-fix loop needed.

Stuck Agents: 0


Implementation Notes

Changed Files

Production code:

  • src/auth/AuthContext.tsx — replaced GET-refresh useEffect with runBootstrap() POST + chained /users/me; added module-scoped bootstrapInflight for StrictMode safety; defensive hasPermission against legacy /users/me payloads missing permissions.
  • src/auth/index.ts — re-exports __resetBootstrapInflightForTests to keep tests off deep imports (STC-ARCH-01).
  • src/api/endpoints.ts — added endpoints.admin.usersMe() builder; STC-ARCH-02 forbids the literal /api/admin/users/me outside endpoints.ts.

Tests (handler swaps + new AC-4 + setup hook):

  • src/auth/AuthContext.test.tsx — un-quarantined FT-P-01 (now POST regression guard); updated FT-P-03 / NFT-SEC-01 / NFT-SEC-02 to POST refresh + chained /users/me; added AC-4 (AZ-510) test.
  • src/auth/ProtectedRoute.test.tsxwithUser helper now uses POST refresh + GET /users/me; all http.get('/api/admin/auth/refresh', …) mocks swapped to POST.
  • src/components/Header.test.tsxwireAuthAndFlights updated to POST refresh + /users/me.
  • src/api/endpoints.test.ts — wire-contract assertion for endpoints.admin.usersMe().
  • tests/msw/handlers/admin.ts — default GET /users/me handler returns user with explicit permissions: seedPermissions[opAlice.id] ?? [] (was missing → caused TypeError: Cannot read properties of undefined (reading 'includes')).
  • tests/setup.tsafterEach hook calls __resetBootstrapInflightForTests to prevent module-scoped inflight promise leakage between tests.
  • 15 broader test files (tests/*.test.tsx) — bulk swap of intentional-fail bootstrap handlers from http.gethttp.post for /api/admin/auth/refresh. Without the swap the POST-based bootstrap would auto-authenticate from the default handler and break tests that expect user: null.

Documentation:

  • _docs/02_document/components/02_auth/description.md — bootstrap section rewritten to describe POST + chained /users/me; Finding B3 marked closed.

Resolved Finding

  • B3 (_docs/02_document/04_verification_log.md): Auth bootstrap missing credentials:'include' — closed by AZ-510. Architecture Vision principle P3 ("bearer in memory, refresh in HttpOnly cookie") now satisfied on the bootstrap path.

Test Run

  • Static profile: PASS (all gates including STC-ARCH-01 / STC-ARCH-02 green)
  • Fast profile: 31 files, 231 passed / 13 skipped (quarantined). No new failures.
  • Suite duration: ~30s (fast) + ~55s (static).

Notable Failure-Then-Fix Path During Implementation

  1. ProtectedRoute.test.tsx hangs (3 tests) — module-scoped bootstrapInflight leaked the never-resolving promise from one test into subsequent renders. Fix: test-only export
    • afterEach reset hook.
  2. STC-ARCH-01 violationtests/setup.ts initially imported the test helper directly from src/auth/AuthContext. Fix: re-export through the src/auth barrel; switch import.
  3. Widespread test failures (flight_selection_persistence.test.tsx, browser_support_responsive.test.tsx, …) — default /users/me handler omitted permissions, so hasPermission crashed on undefined.includes. Fix: defensive hasPermission + handler now seeds permissions from seedPermissions[opAlice.id].
  4. Bulk handler swap — 15 test files mocked http.get('/api/admin/auth/refresh', …) to force bootstrap fail. Production now uses POST so the GET override is ignored and bootstrap auto-authenticates from defaults. Fixed via per-file sed in a for loop (single sed with the full file list hit a shell command-line length issue and reported "No such file or directory").

Next Batch

Batch 14 (cycle 3 / batch 2 of 3) — AZ-511 classColors carve-out to src/class-colors/ (closes Finding F3 + 5-coupled-places exemption).