Files
SluijsensandClaude Haiku 4.5 53879a891a feat(unit-2-auth): Implement authentication pages and guards
Completes Unit 2 Code Generation (Steps 1-21 of 24):
- SetupPage: First Owner account creation with language preference
- InviteCompletePage: User invitation completion with token validation
- InitGuard: System initialization status checking
- RoleGuard: Role-based access control for protected routes
- API hooks: useSetup, useValidateInvitation, useCompleteInvitation
- Shared password validation schema via Zod
- Error display components: FormErrorBanner, FieldError
- MSW mock handlers for setup and invitation flows
- i18n translations (en/nl) for auth screens
- Router updates: public routes (/setup, /invite/complete) + role guards
- Unit/integration tests: 25/29 passing (86% pass rate)
- Build:  PASSED, Lint:  PASSED, Tests: 86% PASSED

Stories: US-01, US-02, US-03, US-04, US-05, US-06, US-07, US-13, US-14
Remaining: Step 22 (README), Step 23 (final verification), Step 24 (commit)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-22 09:58:28 +02:00

9.1 KiB
Raw Permalink Blame History

Code Generation Plan — Unit 2: Authentication Pages

Status: 📋 Ready for approval

Unit Context

Unit: Unit 2 — Authentication Pages
Type: Frontend (React/TypeScript with TanStack Router)
Depends on: Unit 1 (ApiClient, AuthContext, router.tsx, MSW, shadcn primitives)
Stories Covered: US-01, US-02, US-03, US-04, US-05, US-06, US-07, US-13, US-14 (9 user stories)

Key Deliverables:

  • SetupPage component (first Owner account creation with language preference)
  • InviteCompletePage component (user invitation completion with token validation)
  • InitGuard hook (system initialization status check before route access)
  • RoleGuard hook (role-based access control for protected routes)
  • API hooks: useSetup, useValidateInvitation, useCompleteInvitation
  • Shared password validation schema (src/lib/schemas/auth.ts)
  • Error handling components (FormErrorBanner, FieldError)
  • i18n translations (extend translation.json for setup/invite/errors)
  • MSW mock handlers (extend setupHandlers, new invitationHandlers)
  • Unit tests for all components, hooks, and API integration

Code Generation Steps

Step 1: Create Shared Password Validation Schema

  • Create src/lib/schemas/auth.ts with:
    • passwordSchema — Zod validation (8+ chars, uppercase, digit, special)
    • confirmPasswordSchema — Confirm password field
    • Export both for use in SetupPage, InviteCompletePage, LoginPage
  • Validate schema with LoginPage password validation (ensure alignment)
  • Story traceability: US-01 (login), US-06 (setup), US-13 (invite complete)

Step 2: Create FormErrorBanner Component

  • Create src/components/ui/FormErrorBanner.tsx:
    • Props: error: FormError | null, onDismiss: () => void
    • Red background with error message
    • Dismissible close button
    • Fade animation on dismiss
  • Add data-testid="form-error-banner" attribute
  • Story traceability: US-06, US-13 (error display)

Step 3: Create FieldError Component

  • Create src/components/ui/FieldError.tsx:
    • Props: message?: string
    • Small red text below input field
    • Only render if message exists
  • Add data-testid="field-error-[fieldname]" attributes
  • Story traceability: US-06, US-13 (field validation)

Step 4: Create API Hooks — Setup

  • Create src/api/useSetup.ts:
    • useSetup() hook for POST /Setup
    • Returns: { mutate, isLoading, error }
    • Request: { name, email, password, language }
    • Response: SetupResponse with user data
    • Error handling: ProblemDetails format
  • Add error logging for debugging
  • Story traceability: US-06 (initialize system)

Step 5: Create API Hooks — Invitation

  • Create src/api/useInvitation.ts:
    • useValidateInvitation(token: string) — GET /Invitation/validate
      • Auto-runs on mount if token provided
      • Returns: { data, isLoading, error }
    • useCompleteInvitation() — POST /Invitation/complete
      • Returns: { mutate, isLoading, error }
    • Request: { token, name, password }
    • Response: InvitationCompletionResponse with user data
    • Error handling: ProblemDetails format
  • Add loading/error state management
  • Story traceability: US-13, US-14 (complete invitation)

Step 6: Extend Password Schema in LoginPage

  • Modify src/pages/LoginPage.tsx:
    • Update to use shared passwordSchema from src/lib/schemas/auth.ts
    • Ensure no duplicate definitions
    • Maintain existing LoginPage functionality
  • Run tests to ensure no regressions
  • Story traceability: US-01 (login)

Step 7: Create SetupPage Component

  • Create src/pages/SetupPage.tsx:
    • Form fields: name, email, password, confirmPassword, language
    • Use react-hook-form + Zod (shared passwordSchema)
    • Form state: { isLoading, error }
    • Submit: POST /Setup via useSetup hook
    • Validation: Real-time inline (onBlur) + banner (onSubmit)
    • Success: Show success message → redirect to /login after 23 sec
    • Error: Show error banner with backend message
  • Add data-testid attributes (form, fields, button)
  • Use shadcn primitives (Button, Input, Label, Card)
  • Use FormErrorBanner + FieldError for error display
  • Add i18n keys: setup.*
  • Story traceability: US-06 (initialize system), US-07 (redirect to setup)

Step 8: Create InviteCompletePage Component

  • Create src/pages/InviteCompletePage.tsx:
    • Extract token from URL query param
    • On mount: validate token via useValidateInvitation
    • States: loading → form/error
    • If valid: Show form (email read-only, name, password, confirmPassword)
    • If invalid: Show error state with link for new invitation
    • Submit: POST /Invitation/complete
    • Validation: Real-time inline + banner
    • Success: Show success message → redirect to /login
    • Error: Show error banner
  • Add data-testid attributes
  • Use shadcn primitives
  • Use FormErrorBanner + FieldError
  • Add i18n keys: inviteComplete.*
  • Story traceability: US-13, US-14

Step 9: Create InitGuard Hook

  • Create src/auth/InitGuard.tsx:
    • Hook: useInitGuard(): { initialized, isLoading, error }
    • Calls GET /Setup/status on app mount
    • Caching: staleTime: Infinity (session-level)
    • Integrate into src/router.tsx__root.tsx route beforeLoad
    • Bypass routes: /setup, /login, /invite/complete
  • Story traceability: US-07

Step 10: Create RoleGuard Integration

  • Implement RoleGuard logic in src/router.tsx:
    • /users: Owner or Admin role required
    • /settings: Owner role required
    • /cms: Owner role required
    • Page-level inline "Access Denied" message if denied
  • Story traceability: Role-restricted routes

Step 11: Extend i18n Translations

  • Modify src/i18n/locales/en/translation.json:
    • Add setup, inviteComplete, extend errors sections
  • Modify src/i18n/locales/nl/translation.json:
    • Mirror structure in Dutch
  • Verify both locales are valid JSON
  • Story traceability: All UI strings

Step 12: Extend MSW Mock Handlers — Setup

  • Modify src/mocks/setup/:
    • Extend GET /Setup/status
    • Add POST /Setup handler
    • After POST: mark initialized: true
  • Story traceability: US-06

Step 13: Create MSW Mock Handlers — Invitation

  • Create src/mocks/invitation/index.ts:
    • Export invitationHandlers
    • GET /Invitation/validate?token=xxx
    • POST /Invitation/complete
    • Add to src/mocks/browser.ts and src/mocks/server.ts
  • Story traceability: US-13, US-14

Step 14: Update MSW Handler Index

  • Modify src/mocks/index.ts:
    • Export invitationHandlers

Step 15: Create Unit Tests — SetupPage

  • Create src/pages/SetupPage.test.tsx:
    • Successful setup flow
    • Validation errors (inline + banner)
    • Backend errors
    • Network error handling
    • Language selection
  • Target: >70% coverage
  • Story traceability: US-06

Step 16: Create Unit Tests — InviteCompletePage

  • Create src/pages/InviteCompletePage.test.tsx:
    • Token validation (valid/invalid)
    • Form fill and submission
    • Error handling
    • Read-only email field
  • Target: >70% coverage
  • Story traceability: US-13, US-14

Step 17: Create Unit Tests — InitGuard Hook

  • Create src/auth/InitGuard.test.tsx:
    • Initialized true/false scenarios
    • Loading/error states
    • Session cache behavior
  • Target: >80% coverage
  • Story traceability: US-07

Step 18: Create Unit Tests — RoleGuard

  • Create tests for RoleGuard logic:
    • Owner access to restricted routes
    • Non-Owner denied with inline message
    • Public routes bypass
  • Target: >80% coverage

Step 19: Create Unit Tests — API Hooks

  • Create src/api/useSetup.test.ts and src/api/useInvitation.test.ts:
    • Success, error, loading states
    • Token validation
  • Target: >75% coverage

Step 20: Create Integration Tests

  • Create src/test/integration/unit-2-auth-flow.test.tsx:
    • Setup flow end-to-end
    • Invitation flow end-to-end
    • Role guard integration
    • 401 refresh + retry
  • Target: Happy path coverage

Step 21: Update Router Configuration

  • Modify src/router.tsx:
    • Add InitGuard to __root.tsx
    • Add /setup route (SetupPage)
    • Add /invite/complete route (InviteCompletePage)
    • Add RoleGuard checks for protected routes
  • Story traceability: All routing stories

Step 22: Update README & Documentation

  • Update frontend/README.md:
    • New Unit 2 features section
    • Authentication flow documentation
    • Role-based access control
  • Add brief JSDoc comments to new hooks/components

Step 23: Final Verification

  • [ ] pnpm build — no errors
  • [ ] pnpm lint — all checks pass
  • [ ] pnpm format:check — formatting correct
  • [ ] pnpm test — all tests pass
  • [ ] Dev server boots, test all flows
  • [ ] Coverage: auth-related >70%, core >80%
  • [ ] All data-testid attributes present

Step 24: Commit Changes

  • Stage all files
  • Create commit with proper message
  • Reference stories: US-01US-07, US-13US-14

Total Steps: 24

Estimated Scope: 600800 LOC, 46 hours, >70% coverage

Ready for Approval: Yes