Files
slp-modular-cms/aidlc-docs/features/cms-frontend/construction/plans/unit-2-functional-design-plan.md
T

8.2 KiB

Functional Design Plan — Unit 2: Authentication Pages

Status: Complete — awaiting approval

Plan Context

  • Unit: Unit 2 — Authentication Pages
  • Depends on: Unit 1 (ApiClient, AuthContext, router.tsx, shadcn primitives, MSW handlers)
  • Stories Covered: US-01, US-02, US-03, US-04, US-05, US-06, US-07, US-13, US-14
  • Stages to Execute: Functional Design → Code Generation (NFR + Infrastructure skipped for this unit)

Unit 1 Context (Already Delivered)

Unit 1 already provided the following that Unit 2 builds on:

  • src/contexts/AuthProvider.tsx + src/contexts/auth-context.tsuser, accessToken (memory), login, logout, refresh
  • src/lib/api-client.ts — fetch wrapper with 401 intercept + refresh retry
  • src/router.tsx_authenticated layout route with beforeLoad guard (redirects to /login); public routes: /login, /setup; protected routes: /dashboard, /users, /cms
  • src/pages/LoginPage.tsx — fully implemented with react-hook-form + zod, MSW-tested, data-testid attributes
  • src/mocks/authHandlers (login, refresh, revoke), setupHandlers (setup status at /Setup/status), userHandlers
  • Tailwind v4 + shadcn primitives (Button, Input, Label, Card, DropdownMenu, Toaster)
  • Deviations: code-based routing in router.tsx; pages in src/pages/; locales in src/i18n/locales/

Functional Design Steps

  • Step 1: Analyze unit stories and responsibilities
  • Step 2: Identify open questions (this document)
  • Step 3: Collect answers from user
  • Step 4: Generate functional design artifacts — COMPLETED

Questions

Answer each question by filling in the [Answer]: tag below it.


Q1 — SetupPage: Fields to collect

The SetupPage is shown when the system is not yet initialized (initialized: false from GET /Setup/status). The backend POST /Setup endpoint creates the first Owner account.

Which fields should the SetupPage form collect?

A) Email + Password + Confirm Password (name comes from the email prefix or can be set later in Profile) B) Name + Email + Password + Confirm Password C) Name + Email + Password + Confirm Password + a "language/locale" preference D) Other


Q2 — SetupPage: Action after successful setup

When POST /Setup succeeds and the first Owner account is created, what should happen?

A) Automatically log in the user (call AuthContext.login()) and redirect to /dashboard B) Show a success message and redirect to /login so the user can log in manually C) Show a success message on the same page with a "Go to login" button D) Other


Q3 — InviteCompletePage: Fields to collect

The InviteCompletePage is reached via a link like /invite/complete?token=xxx. The backend validates the token and completes account setup.

Which fields should the form collect?

A) Name + Password + Confirm Password (email is known from the invitation and shown read-only) B) Password + Confirm Password only (name can be set later in Profile) C) Name + Password + Confirm Password + email shown read-only as informational D) Other


Q4 — InviteCompletePage: Token validation timing

When should the invitation token be validated?

A) On page mount (GET request to validate token), then show form only if valid — show error page directly if invalid/expired B) On form submit only — show validation errors after the user tries to submit C) On page mount with a loading state, then switch to form (valid) or error state (invalid/expired) D) Other


Q5 — InviteCompletePage: Action after successful completion

When POST /Invitation/complete succeeds, what should happen?

A) Automatically log in the user and redirect to /dashboard B) Show a success message and redirect to /login C) Show a success message with a "Go to login" button D) Other


Q6 — InitGuard: Caching strategy

The InitGuard checks GET /Setup/status and redirects to /setup if initialized: false. It must run before every route renders (in the root route).

How should setup status be cached?

A) Cache for the session (once loaded, never re-fetch — a setup operation redirects back to login anyway) B) Refresh every time the app is loaded/refreshed (staleTime: 0 — always re-fetch on mount) C) Short stale time, e.g., 60 seconds (balance between freshness and extra requests) D) Other


Q7 — InitGuard: Routes that bypass the guard

Which routes should bypass the InitGuard (i.e., be accessible even when initialized: false)?

A) Only /setup bypasses the guard (all other routes redirect to /setup if not initialized) B) /setup and /invite/complete bypass the guard C) /setup, /invite/complete, and /login bypass the guard D) Other


Q8 — RoleGuard: Role model

The application has user roles. The backend returns a role field on the authenticated user.

What roles exist in the system?

A) Two roles: Owner and User B) Three roles: Owner, Admin, and User C) The roles match what's already defined in the backend (check ApplicationUser or UserRole enum in the existing code) D) Other

Answer: D, This should already be defined in the back-end, but it should be Owner, Admin and User


Q9 — RoleGuard: Which routes are role-restricted?

Which routes require a specific minimum role?

A) Only /settings and /cms require Owner role; /users requires Owner or Admin; /dashboard and /profile are accessible to all authenticated users B) /users, /settings, and /cms all require Owner role; /dashboard and /profile for all roles C) /cms requires Owner; /settings requires Owner; /users is open to all authenticated users D) Other


Q10 — RoleGuard: Unauthorized behavior

When an authenticated user tries to access a route they don't have the role for, what should happen?

A) Redirect to /403 (Access Denied page — already in Unit 6 scope but can be a simple inline message for now) B) Redirect to /dashboard with a toast notification C) Show an inline "Access Denied" message on the page itself (no separate route needed) D) Other


Q11 — Password validation rules

The backend enforces specific password rules. Unit 1 already has Zod schemas.

Where should the shared password Zod schema live?

A) In src/lib/validation.ts — a shared module imported by both LoginPage and the new pages B) In each page file separately (duplicated for isolation) C) In src/lib/schemas/auth.ts — a dedicated auth schemas file D) Other


Q12 — i18n: Translation keys for Unit 2

Unit 1 already added login namespace keys. For Unit 2 pages, how should translation keys be organized?

A) Add setup and inviteComplete keys to the existing translation.json files (single namespace per locale) B) Separate namespace files: setup.json and inviteComplete.json lazy-loaded per page C) Extend existing translation.json with a setup section and inviteComplete section D) Other


Q13 — MSW handler scope for Unit 2

Unit 1 has setupHandlers for GET /Setup/status. Unit 2 needs handlers for POST /Setup (create owner) and invitation endpoints.

Where should the new handlers be added?

A) Extend existing setupHandlers in src/mocks/setup/ with POST /Setup and add invitationHandlers in src/mocks/invitation/ B) Add everything to the existing setupHandlers file C) New file src/mocks/invitation/ for invitation handlers; POST /Setup goes into existing setup handlers D) Other


Q14 — Error handling in forms

For form submission errors (network errors, validation errors from the backend), what is the preferred pattern?

A) Show errors in a dismissible banner above the form (consistent with LoginPage's existing pattern) B) Show errors inline next to the relevant field C) Show errors in a toast notification (using Sonner, already installed) D) Other

Answer: D, a combination of A and B. Isn't that also used on the login page. Inline for real live checking, but after submission a banner can be shown. I am not seeing that on the login page now. It should be consistent throughout the app though