mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 15:11:10 +00:00
[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>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user