Adds application design (awaiting approval)

This commit is contained in:
2026-06-17 20:15:54 +02:00
parent c7154e288f
commit 9e49489f7e
12 changed files with 1171 additions and 22 deletions
@@ -0,0 +1,143 @@
# Component Dependencies — CMS Frontend
## Dependency Overview
```mermaid
graph TD
subgraph Backend["Backend (Unit 0)"]
CorsPolicy["CorsPolicy\n(ServiceCollectionExtensions)"]
AuthCtrl["AuthController\n(updated)"]
AuthSvc["AuthService\n(no changes)"]
AuthCtrl --> AuthSvc
end
subgraph Infrastructure["Frontend Infrastructure Layer"]
ApiClient["ApiClient\n(fetch wrapper)"]
AuthContext["AuthContext\n(session state)"]
Router["RouterConfig\n(TanStack Router)"]
AuthContext --> ApiClient
end
subgraph Guards["Auth Guards"]
ProtectedRoute["ProtectedRoute"]
RoleGuard["RoleGuard"]
InitGuard["InitGuard"]
ProtectedRoute --> AuthContext
RoleGuard --> AuthContext
InitGuard --> ApiClient
end
subgraph Layout["Layout Components"]
AppLayout["AppLayout"]
Sidebar["Sidebar"]
ThemeProvider["ThemeProvider"]
AppLayout --> Sidebar
Sidebar --> AuthContext
end
subgraph QueryHooks["TanStack Query Hooks"]
useAvailability["useAvailabilityStatus"]
useUsers["useUsers + useInviteUser"]
useInvitation["useValidateInvitation\nuseCompleteSetup"]
useSetup["useSetupStatus\nuseCreateOwner"]
useAvailability --> ApiClient
useUsers --> ApiClient
useInvitation --> ApiClient
useSetup --> ApiClient
end
subgraph Pages["Page Components"]
LoginPage["LoginPage"]
SetupPage["SetupPage"]
InviteCompletePage["InviteCompletePage"]
DashboardPage["DashboardPage"]
UsersPage["UsersPage"]
ProfilePage["ProfilePage"]
SettingsPage["SettingsPage"]
CmsPage["CmsPage"]
LoginPage --> AuthContext
SetupPage --> useSetup
InviteCompletePage --> useInvitation
DashboardPage --> useAvailability
UsersPage --> useUsers
ProfilePage --> AuthContext
SettingsPage --> useAvailability
end
Router --> Guards
Router --> AppLayout
AppLayout --> Pages
style CorsPolicy fill:#4CAF50,stroke:#2E7D32,color:#fff
style AuthCtrl fill:#4CAF50,stroke:#2E7D32,color:#fff
style AuthSvc fill:#FFC107,stroke:#F57F17,color:#000
style ApiClient fill:#FFC107,stroke:#F57F17,color:#000
style AuthContext fill:#FFC107,stroke:#F57F17,color:#000
style Router fill:#FFC107,stroke:#F57F17,color:#000
style ProtectedRoute fill:#FF5722,stroke:#BF360C,color:#fff
style RoleGuard fill:#FF5722,stroke:#BF360C,color:#fff
style InitGuard fill:#FF5722,stroke:#BF360C,color:#fff
style AppLayout fill:#9C27B0,stroke:#4A148C,color:#fff
style Sidebar fill:#9C27B0,stroke:#4A148C,color:#fff
style ThemeProvider fill:#9C27B0,stroke:#4A148C,color:#fff
style useAvailability fill:#009688,stroke:#004D40,color:#fff
style useUsers fill:#009688,stroke:#004D40,color:#fff
style useInvitation fill:#009688,stroke:#004D40,color:#fff
style useSetup fill:#009688,stroke:#004D40,color:#fff
style LoginPage fill:#2196F3,stroke:#0D47A1,color:#fff
style SetupPage fill:#2196F3,stroke:#0D47A1,color:#fff
style InviteCompletePage fill:#2196F3,stroke:#0D47A1,color:#fff
style DashboardPage fill:#2196F3,stroke:#0D47A1,color:#fff
style UsersPage fill:#2196F3,stroke:#0D47A1,color:#fff
style ProfilePage fill:#2196F3,stroke:#0D47A1,color:#fff
style SettingsPage fill:#2196F3,stroke:#0D47A1,color:#fff
style CmsPage fill:#2196F3,stroke:#0D47A1,color:#fff
```
---
## Dependency Matrix
| Component | Depends On | Used By |
|-----------|-----------|---------|
| **ApiClient** | `import.meta.env.VITE_API_BASE_URL`, `AuthContext.accessToken` | All TanStack Query hooks, `InitGuard` |
| **AuthContext** | `ApiClient` (for login/logout/refresh calls) | `ProtectedRoute`, `RoleGuard`, `Sidebar`, `ProfilePage`, `LoginPage` |
| **RouterConfig** | `ProtectedRoute`, `RoleGuard`, `InitGuard`, `AppLayout` | App root |
| **ProtectedRoute** | `AuthContext` | Router (wraps authenticated routes) |
| **RoleGuard** | `AuthContext` | Router (wraps role-restricted routes) |
| **InitGuard** | `useSetupStatus``ApiClient` | Router (root-level check) |
| **AppLayout** | `Sidebar`, `ThemeProvider` | Authenticated routes |
| **Sidebar** | `AuthContext` | `AppLayout` |
| **useAvailabilityStatus** | `ApiClient` | `DashboardPage`, `SettingsPage` |
| **useUsers / useInviteUser** | `ApiClient` | `UsersPage` |
| **useValidateInvitation / useCompleteSetup** | `ApiClient` | `InviteCompletePage` |
| **useSetupStatus / useCreateOwner** | `ApiClient` | `InitGuard`, `SetupPage` |
| **DashboardPage** | `useAvailabilityStatus`, `AuthContext` | Router |
| **UsersPage** | `useUsers`, `useInviteUser`, `InviteUserDialog` | Router |
| **ProfilePage** | `AuthContext` (user data from context — no API call) | Router |
| **SettingsPage** | `useAvailabilityStatus` | Router |
| **InviteCompletePage** | `useValidateInvitation`, `useCompleteSetup` | Router |
| **LoginPage** | `AuthContext.login()` | Router |
| **SetupPage** | `useCreateOwner` | Router |
---
## Communication Patterns
| Pattern | Where Used |
|---------|-----------|
| **React Context** | Auth state shared from `AuthContext` to guards, sidebar, profile, login page |
| **TanStack Query** | Server state (availability, users, invitation, setup) — cached, auto-refetch |
| **Cookie (httpOnly)** | Browser ↔ Backend: refresh token — set by backend, never read by JS |
| **In-memory state** | Access token held in `AuthContext` — cleared on page refresh (intentional) |
| **LocalStorage** | Theme preference only (`cms-theme`) — no auth data |
---
## Key Dependency Rules (Security Baseline)
- `ApiClient` is the **only** module that makes HTTP calls — no direct `fetch` in pages/components
- `accessToken` is accessed **only** through `AuthContext` — never passed as prop or stored elsewhere
- `refreshToken` is **never accessible to JavaScript** — httpOnly cookie only
- Role checks happen in `RoleGuard` (routing) and `Sidebar` (UX) — backend is authoritative