# 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).
