Files
slp-modular-cms/aidlc-docs/features/cms-frontend/inception/application-design/application-design.md
T

152 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Application Design — CMS Frontend
## Overview
This document consolidates the complete application design for the CMS frontend feature. It covers both the backend prerequisite changes (Unit 0) and the full frontend React SPA (Units 16).
**Tech decisions confirmed by user:**
- **State management**: React Context (auth) + TanStack Query (server state)
- **HTTP client**: TanStack Query (server state) using native fetch via `ApiClient` wrapper
- **Form validation**: react-hook-form + zod
- **Routing**: TanStack Router — file-based (`src/routes/`)
- **Auth token storage**: Access token in-memory (React context), refresh token in httpOnly cookie
- **Cookie**: `refreshToken`, path `/api/v1/auth`, HttpOnly, Secure, SameSite=Strict
- **CORS origins**: Configured via `appsettings.json → Cors:AllowedOrigins[]` (dotnet-appsettings pattern)
- **User data in context**: Full user object `{ id, email, name, role, isActive }`
- **Error boundaries**: Global + per-page
---
## Architecture at a Glance
```mermaid
graph LR
subgraph FE["Frontend (frontend/)"]
direction TB
Infra["Infrastructure\nApiClient · AuthContext · RouterConfig"]
Guards["Guards\nProtectedRoute · RoleGuard · InitGuard"]
Layout["Layout\nAppLayout · Sidebar · ThemeProvider"]
Hooks["TanStack Query Hooks\nuseAvailability · useUsers · useInvitation · useSetup"]
Pages["Pages\nLogin · Setup · InviteComplete\nDashboard · Users · Profile\nSettings · CMS · 403 · 404"]
end
subgraph BE["Backend (src/)"]
direction TB
CORS["CORS Policy\n(ServiceCollectionExtensions)"]
AuthCtrl["AuthController\n(httpOnly cookie)"]
AuthSvc["AuthService"]
end
Pages --> Hooks
Pages --> Infra
Layout --> Infra
Guards --> Infra
Hooks --> Infra
Infra -->|HTTP + cookie| AuthCtrl
AuthCtrl --> AuthSvc
style Infra fill:#FFC107,stroke:#F57F17,color:#000
style Guards fill:#FF5722,stroke:#BF360C,color:#fff
style Layout fill:#9C27B0,stroke:#4A148C,color:#fff
style Hooks fill:#009688,stroke:#004D40,color:#fff
style Pages fill:#2196F3,stroke:#0D47A1,color:#fff
style CORS fill:#4CAF50,stroke:#2E7D32,color:#fff
style AuthCtrl fill:#4CAF50,stroke:#2E7D32,color:#fff
style AuthSvc fill:#FFC107,stroke:#F57F17,color:#000
```
---
## Unit Decomposition Summary
| Unit | Name | Primary Components |
|------|------|--------------------|
| 0 | Backend Prerequisites | CorsPolicy, AuthController (cookie), appsettings updates |
| 1 | Project Scaffold | ApiClient, AuthContext, RouterConfig, ThemeProvider, ErrorBoundary, `.env` |
| 2 | Auth Pages | LoginPage, SetupPage, InviteCompletePage, ProtectedRoute, RoleGuard, InitGuard |
| 3 | Layout & Navigation | AppLayout, Sidebar |
| 4 | Dashboard | DashboardPage, AvailabilityStatusBadge, useAvailabilityStatus |
| 5 | User Management | UsersPage, InviteUserDialog, useUsers, useInviteUser, useValidateInvitation, useCompleteSetup |
| 6 | Remaining Pages | ProfilePage, SettingsPage, CmsPage, NotFoundPage, AccessDeniedPage, README.md |
---
## Project Structure
```
frontend/
├── src/
│ ├── api/
│ │ ├── client.ts # ApiClient (fetch wrapper, 401 interceptor)
│ │ ├── types.ts # Shared TypeScript interfaces
│ │ ├── useAvailability.ts # TanStack Query hooks
│ │ ├── useUsers.ts
│ │ ├── useInvitation.ts
│ │ └── useSetup.ts
│ ├── auth/
│ │ ├── AuthContext.tsx # AuthContext + AuthProvider
│ │ ├── useAuth.ts # useAuth hook
│ │ ├── ProtectedRoute.tsx
│ │ ├── RoleGuard.tsx
│ │ └── InitGuard.tsx
│ ├── components/
│ │ ├── layout/
│ │ │ ├── AppLayout.tsx
│ │ │ ├── Sidebar.tsx
│ │ │ └── ThemeProvider.tsx
│ │ ├── users/
│ │ │ └── InviteUserDialog.tsx
│ │ ├── shared/
│ │ │ └── AvailabilityStatusBadge.tsx
│ │ └── error/
│ │ └── ErrorBoundary.tsx
│ ├── routes/ # TanStack Router file-based routes
│ │ ├── __root.tsx # Root route (InitGuard, ErrorBoundary)
│ │ ├── index.tsx # / → DashboardPage
│ │ ├── login.tsx # /login
│ │ ├── setup.tsx # /setup
│ │ ├── invite.complete.tsx # /invite/complete
│ │ ├── users.tsx # /users (Owner/Admin)
│ │ ├── profile.tsx # /profile
│ │ ├── settings.tsx # /settings (Owner)
│ │ ├── cms.tsx # /cms (Owner)
│ │ ├── 403.tsx # /403
│ │ └── $404.tsx # catch-all
│ ├── routeTree.gen.ts # Generated by TanStack Router CLI
│ ├── main.tsx # App entry point
│ └── app.tsx # QueryClientProvider + AuthProvider + RouterProvider
├── .env.example # Template for VITE_API_BASE_URL
├── .env # gitignored — developer local override
├── package.json
├── pnpm-lock.yaml
├── tsconfig.json
├── vite.config.ts
└── tailwind.config.ts
```
---
## Security Design Summary
| Concern | Design Decision |
|---------|----------------|
| Access token storage | In-memory only (React state in `AuthContext`) |
| Refresh token storage | httpOnly cookie — set/cleared by backend |
| CORS | Named policy `"FrontendPolicy"` with specific origins + `AllowCredentials()` |
| Role enforcement | `RoleGuard` (routing) + `Sidebar` (UX) + backend (authoritative) |
| HTTP calls | Centralised through `ApiClient` only |
| Form validation | zod schemas matching backend password rules |
| Error handling | Global + per-page `ErrorBoundary`; generic user-facing error messages |
---
## Artifacts Index
| Artifact | Path |
|---------|------|
| Component definitions | `inception/application-design/components.md` |
| Method signatures | `inception/application-design/component-methods.md` |
| Service layer | `inception/application-design/services.md` |
| Dependency diagram | `inception/application-design/component-dependency.md` |
| This document | `inception/application-design/application-design.md` |