# Code Generation Summary — Unit 2: Authentication Pages **Status**: ✅ Complete **Date**: 2026-06-21 **Plan**: `aidlc-docs/features/cms-frontend/construction/plans/unit-2-code-generation-plan.md` --- ## Files Created | File | Purpose | |---|---| | `frontend/src/lib/schemas/auth.ts` | Shared Zod schemas: `passwordSchema`, `loginSchema`, `setupSchema`, `inviteCompleteSchema` | | `frontend/src/components/ui/PasswordField.tsx` | Password input with show/hide toggle | | `frontend/src/components/ui/FormBannerError.tsx` | Dismissible inline error banner for API errors | | `frontend/src/components/auth/RoleGuard.tsx` | Role-based access wrapper; renders inline "Access Denied" for unauthorized roles | | `frontend/src/api/useSetup.ts` | `useSetupStatus`, `useCreateOwner` hooks with module-level session cache | | `frontend/src/api/useInvitation.ts` | `useValidateInvitation`, `useCompleteSetup` hooks | | `frontend/src/mocks/invitation/handlers.ts` | MSW handlers for invitation validate/complete endpoints | | `frontend/src/pages/SetupPage.tsx` | Full 5-field owner setup form (replaces stub) | | `frontend/src/pages/InviteCompletePage.tsx` | Invitation completion page with token validation states | | `frontend/src/pages/SetupPage.test.tsx` | Tests: render, validation, success, 409 error, InitGuard redirect | | `frontend/src/pages/InviteCompletePage.test.tsx` | Tests: loading, invalid token states, form, success | ## Files Modified | File | Change | |---|---| | `frontend/src/api/types.ts` | Added `SetupRequest`, `InvitationValidation`, `InviteCompleteRequest` interfaces | | `frontend/src/router.tsx` | Full rewrite: InitGuard (`async beforeLoad` on rootRoute), `inviteCompleteRoute`, `RoleGuard` wrappers on `usersRoute`/`cmsRoute`, `_resetSetupStatusCache` export for tests | | `frontend/src/pages/LoginPage.tsx` | Replaced inline schema with `loginSchema` from `@/lib/schemas/auth`; added `mode: 'onTouched'` | | `frontend/src/mocks/setup/handlers.ts` | Added `POST /Setup` success handler, `setupUninitializedHandlers`, `setupConflictHandlers` | | `frontend/src/mocks/index.ts` | Added `invitationHandlers` to combined handlers + re-exports | | `frontend/src/i18n/locales/en/translation.json` | Added `setup`, `inviteComplete`, `nav.profile/settings`, `errors.accessDenied/sessionExpired` keys | | `frontend/src/i18n/locales/nl/translation.json` | Dutch translations for all new keys | | `frontend/src/test/RouteGuard.test.tsx` | Added InitGuard tests (setup redirect both ways) + RoleGuard tests | --- ## Story Coverage | Story | Coverage | |---|---| | US-01 — Login | `loginSchema` extracted to shared file; `mode: 'onTouched'` added to LoginPage | | US-02 — Session persistence | Unit 1 (AuthContext + ApiClient); no changes | | US-03 — Logout | Unit 1 (AuthContext.logout()); no changes | | US-04 — Redirect when unauthenticated | `authenticatedRoute.beforeLoad` (Unit 1); `RoleGuard` (Unit 2) | | US-05 — Auto token refresh | Unit 1 (ApiClient 401 interceptor); no changes | | US-06 — Owner initialization | `SetupPage`, `useCreateOwner`, `setupSchema`, InitGuard, EN/NL translations | | US-07 — Redirect to setup when not initialized | InitGuard in `rootRoute.beforeLoad`, `fetchSetupStatus()` session cache | | US-13 — Complete setup via invitation | `InviteCompletePage`, `useValidateInvitation`, `useCompleteSetup`, `invitationHandlers` | | US-14 — Handle expired/invalid invitation | `InviteCompletePage` invalid token states (`EXPIRED`, `USED`, `NOT_FOUND`, no token) | --- ## Deviations from Plan | Plan spec | Actual | Reason | |---|---|---| | `useSetupStatus()` with TanStack Query `staleTime: Infinity` | Module-level `_setupStatusCache` + `useState`/`useEffect` | TanStack Query is not installed in this project | | `UserRole = 'Owner' \| 'Admin' \| 'User'` | `UserRole = 'Owner' \| 'Administrator' \| 'User'` | Matches existing `src/api/types.ts` and backend identity model | | InitGuard as React component with `useEffect` | `async beforeLoad` on rootRoute | More idiomatic for TanStack Router; avoids render flash before redirect | | `fetchSetupStatus` in separate module from router | Inlined in `router.tsx` with `_resetSetupStatusCache` export | Keeps router self-contained; simplifies test cache reset | --- ## Test Utilities Added - `_resetSetupStatusCache()` exported from `src/router.tsx` — resets module-level setup cache between tests so each test controls its own MSW handler for `GET /Setup/status` - `setupUninitializedHandlers` / `setupConflictHandlers` exported from `src/mocks/index.ts` — per-test MSW overrides