# 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.tsx` — `withUser` helper now uses POST refresh + GET `/users/me`; all `http.get('/api/admin/auth/refresh', …)` mocks swapped to POST. - `src/components/Header.test.tsx` — `wireAuthAndFlights` 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.ts` — `afterEach` 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.get` → `http.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 violation** — `tests/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).