Adds application design (awaiting approval)
This commit is contained in:
+143
@@ -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
|
||||
Reference in New Issue
Block a user