Adds requirements and userstories. also updates diagrams to be mermaid diagrams instead of text variants
This commit is contained in:
@@ -8,54 +8,39 @@ The frontend is a React SPA (to be built) that communicates with the API via RES
|
|||||||
|
|
||||||
## Architecture Diagram
|
## Architecture Diagram
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
+--------------------------------------------------+
|
graph TD
|
||||||
| Client Layer |
|
subgraph ClientLayer["Client Layer"]
|
||||||
| +--------------------------------------------+ |
|
Frontend["React SPA\nVite + TanStack Router + shadcn/ui\nTailwind CSS v4 #ac0000"]
|
||||||
| | React SPA (SlpModularCms.Frontend) | |
|
end
|
||||||
| | Vite + React Router v7 + shadcn/ui | |
|
|
||||||
| | Tailwind CSS v4 (#ac0000 theme) | |
|
subgraph ApiLayer["API Layer"]
|
||||||
| +--------------------------------------------+ |
|
Api["SlpModularCms.Api\nASP.NET Core\nJWT Bearer, CORS, Swagger"]
|
||||||
+---------------------------+----------------------+
|
Identity["Identity Module\nAuthController\nSetupController\nUsersController"]
|
||||||
| HTTP REST / JSON
|
Avail["Availability Module\nAvailabilityController\nPersistentService + CircuitBreaker"]
|
||||||
+---------------------------v----------------------+
|
end
|
||||||
| API Layer |
|
|
||||||
| +--------------------------------------------+ |
|
subgraph CoreLayer["Core Layer"]
|
||||||
| | SlpModularCms.Api (ASP.NET Core) | |
|
Core["SlpModularCms.Core\nApplicationDbContext\nDomain Entities\nIdentity Services\nIModule interface"]
|
||||||
| | - JWT Bearer Auth Middleware | |
|
end
|
||||||
| | - CORS, Swagger/OpenAPI | |
|
|
||||||
| | - Module registration pipeline | |
|
subgraph DataLayer["Data Layer"]
|
||||||
| +--------------------------------------------+ |
|
DB[("SQL Server\nIdentity tables\nRefreshTokens\nInvitations\nGlobalAvailabilityState")]
|
||||||
| |
|
end
|
||||||
| +------------------+ +---------------------+ |
|
|
||||||
| | Identity Module | | Availability Module | |
|
Frontend -->|HTTP REST / JSON| Api
|
||||||
| | - AuthController| | - AvailabilityCtrl | |
|
Api --> Identity
|
||||||
| | - SetupCtrl | | - PersistentService | |
|
Api --> Avail
|
||||||
| | - UsersCtrl | | - CircuitBreaker | |
|
Identity --> Core
|
||||||
| +------------------+ +---------------------+ |
|
Avail --> Core
|
||||||
+---------------------------+----------------------+
|
Core --> DB
|
||||||
|
|
|
||||||
+---------------------------v----------------------+
|
style Frontend fill:#2196F3,stroke:#0D47A1,color:#fff
|
||||||
| Core Layer |
|
style Api fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
| +--------------------------------------------+ |
|
style Identity fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
| | SlpModularCms.Core | |
|
style Avail fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
| | - ApplicationDbContext (EF Core) | |
|
style Core fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
| | - Domain Entities | |
|
style DB fill:#FF5722,stroke:#BF360C,color:#fff
|
||||||
| | - Identity Services (Auth, Setup, Invite) | |
|
|
||||||
| | - IModule interface + ModuleInfo | |
|
|
||||||
| +--------------------------------------------+ |
|
|
||||||
+---------------------------+----------------------+
|
|
||||||
|
|
|
||||||
+---------------------------v----------------------+
|
|
||||||
| Data Layer |
|
|
||||||
| +--------------------------------------------+ |
|
|
||||||
| | SQL Server Database | |
|
|
||||||
| | - ASP.NET Identity tables | |
|
|
||||||
| | - RefreshTokens | |
|
|
||||||
| | - Invitations | |
|
|
||||||
| | - GlobalAvailabilityState | |
|
|
||||||
| +--------------------------------------------+ |
|
|
||||||
+--------------------------------------------------+
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Component Descriptions
|
## Component Descriptions
|
||||||
@@ -92,24 +77,36 @@ The frontend is a React SPA (to be built) that communicates with the API via RES
|
|||||||
|
|
||||||
## Data Flow
|
## Data Flow
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
Login Flow:
|
sequenceDiagram
|
||||||
Browser -> POST /auth/login -> AuthController
|
participant Browser
|
||||||
-> AuthService.AuthenticateAsync()
|
participant AuthController
|
||||||
-> PasswordHasher validates credentials
|
participant AuthService
|
||||||
-> JwtService generates access + refresh tokens
|
participant DB
|
||||||
-> Returns {accessToken, refreshToken}
|
|
||||||
|
|
||||||
Invite Flow:
|
Note over Browser,DB: Login Flow
|
||||||
Admin -> POST /users/invite -> UsersController
|
Browser->>AuthController: POST /auth/login
|
||||||
-> InvitationService.CreateInvitationAsync()
|
AuthController->>AuthService: AuthenticateAsync()
|
||||||
-> Stores Invitation entity with token
|
AuthService->>DB: Validate credentials
|
||||||
-> Returns invite link
|
DB-->>AuthService: User found
|
||||||
|
AuthService-->>AuthController: access + refresh tokens
|
||||||
|
AuthController-->>Browser: 200 OK with tokens
|
||||||
|
|
||||||
New User Setup:
|
Note over Browser,DB: Invite Flow
|
||||||
User -> POST /users/complete-setup -> UsersController
|
Browser->>AuthController: POST /users/invite
|
||||||
-> InvitationService.CompleteInvitationAsync()
|
AuthController->>AuthService: CreateInvitationAsync()
|
||||||
-> Sets password, activates account
|
AuthService->>DB: Store Invitation entity
|
||||||
|
DB-->>AuthService: Stored
|
||||||
|
AuthService-->>AuthController: invite token
|
||||||
|
AuthController-->>Browser: 200 OK with invite link
|
||||||
|
|
||||||
|
Note over Browser,DB: New User Setup
|
||||||
|
Browser->>AuthController: POST /users/complete-setup
|
||||||
|
AuthController->>AuthService: CompleteInvitationAsync()
|
||||||
|
AuthService->>DB: Set password, activate account
|
||||||
|
DB-->>AuthService: Updated
|
||||||
|
AuthService-->>AuthController: success
|
||||||
|
AuthController-->>Browser: 200 OK
|
||||||
```
|
```
|
||||||
|
|
||||||
## Integration Points
|
## Integration Points
|
||||||
|
|||||||
@@ -2,26 +2,28 @@
|
|||||||
|
|
||||||
## Business Context Diagram
|
## Business Context Diagram
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
+--------------------------------------------------+
|
graph TD
|
||||||
| SlpModularCms Platform |
|
subgraph Platform["SlpModularCms Platform"]
|
||||||
| |
|
Identity["Identity Module\n(Auth + Users)"]
|
||||||
| +-----------+ +-----------+ +-----------+ |
|
CMS["CMS Module\n(Content Mgmt)"]
|
||||||
| | Identity | | CMS | |Availability| |
|
Availability["Availability Module\n(System Status)"]
|
||||||
| | Module | | Module | | Module | |
|
Core["Core / Shell\n(Domain entities, DbContext, Module I/F)"]
|
||||||
| | (Auth + | | (Content | | (System | |
|
end
|
||||||
| | Users) | | Mgmt) | | Status) | |
|
|
||||||
| +-----------+ +-----------+ +-----------+ |
|
Identity --> Core
|
||||||
| |
|
CMS --> Core
|
||||||
| +-------------------------------------------+ |
|
Availability --> Core
|
||||||
| | Core / Shell | |
|
|
||||||
| | (Domain entities, DbContext, Module I/F) | |
|
Platform --> AdminFrontend["Admin Frontend\n(React SPA)"]
|
||||||
| +-------------------------------------------+ |
|
Platform --> ExternalClients["External Clients\n(API consumers)"]
|
||||||
+--------------------------------------------------+
|
|
||||||
| |
|
style Identity fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
v v
|
style CMS fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
[Admin Frontend] [External Clients]
|
style Availability fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
(React SPA) (API consumers)
|
style Core fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
|
style AdminFrontend fill:#2196F3,stroke:#0D47A1,color:#fff
|
||||||
|
style ExternalClients fill:#9E9E9E,stroke:#424242,color:#fff
|
||||||
```
|
```
|
||||||
|
|
||||||
## Business Description
|
## Business Description
|
||||||
|
|||||||
@@ -7,60 +7,71 @@
|
|||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
SlpModularCms/
|
graph TD
|
||||||
+-- src/
|
Root["SlpModularCms/"]
|
||||||
| +-- SlpModularCms.Api/ # API host
|
Src["src/"]
|
||||||
| | +-- Extensions/
|
Api["SlpModularCms.Api\n(API host)"]
|
||||||
| | | +-- ServiceCollectionExtensions.cs # DI setup (JWT, Identity, EF, Auth)
|
ApiExt["Extensions/\nServiceCollectionExtensions.cs"]
|
||||||
| | +-- Infrastructure/ # Global exception handler
|
ApiInfra["Infrastructure/\nGlobal exception handler"]
|
||||||
| | +-- Properties/launchSettings.json
|
ApiProg["Program.cs\nApp startup + module loading"]
|
||||||
| | +-- Program.cs # App startup and module loading
|
|
||||||
| | +-- appsettings.json
|
Core["SlpModularCms.Core\n(Shared core)"]
|
||||||
| | +-- appsettings.local.json # Local dev overrides
|
CoreAvail["Availability/\nAvailabilityOptions.cs\nAvailabilityStatus.cs"]
|
||||||
| |
|
CoreData["Data/\nApplicationDbContext.cs"]
|
||||||
| +-- SlpModularCms.Core/ # Shared core
|
CoreIdentity["Identity/\nEntities, Models, Services\nAuthorization/"]
|
||||||
| | +-- Availability/
|
CoreMigrations["Migrations/\nEF Core migrations"]
|
||||||
| | | +-- AvailabilityOptions.cs # Circuit breaker config
|
CoreModules["Modules/\nIModule.cs, ModuleInfo.cs"]
|
||||||
| | | +-- AvailabilityStatus.cs # Enum: Available, Maintenance, Unavailable
|
|
||||||
| | +-- Data/
|
ModIdentity["SlpModularCms.Modules.Identity\n(Identity module)"]
|
||||||
| | | +-- ApplicationDbContext.cs # EF Core DbContext
|
ModIdentityCtrl["Controllers/\nAuthController\nSetupController\nUsersController"]
|
||||||
| | +-- Exceptions/ # Custom exception types
|
|
||||||
| | +-- Identity/
|
ModAvail["SlpModularCms.Modules.Availability\n(Availability module)"]
|
||||||
| | | +-- Authorization/ # Policy handlers
|
ModAvailCtrl["Controllers/\nAvailabilityController"]
|
||||||
| | | +-- Entities/
|
ModAvailSvc["Services/\nPersistentAvailabilityService"]
|
||||||
| | | | +-- ApplicationUser.cs # IdentityUser<Guid> + IsActive + CreatedAt
|
|
||||||
| | | | +-- ApplicationRole.cs # IdentityRole<Guid>
|
Tests1["SlpModularCms.Core.Tests"]
|
||||||
| | | | +-- RefreshToken.cs # Refresh token entity
|
Tests2["SlpModularCms.Modules.Availability.Tests"]
|
||||||
| | | | +-- Invitation.cs # Invite entity with expiry
|
Docs["aidlc-docs/\nAI-DLC workflow documentation"]
|
||||||
| | | | +-- GlobalAvailabilityState.cs # Persisted system status
|
|
||||||
| | | +-- Models/ # DTOs/request-response models
|
Root --> Src
|
||||||
| | | +-- Services/
|
Root --> Docs
|
||||||
| | | +-- AuthService.cs # JWT generation + token validation
|
Src --> Api
|
||||||
| | | +-- InvitationService.cs # Invite creation + completion
|
Src --> Core
|
||||||
| | | +-- SetupService.cs # Initial owner creation
|
Src --> ModIdentity
|
||||||
| | +-- Migrations/ # EF Core migrations
|
Src --> ModAvail
|
||||||
| | +-- Modules/
|
Src --> Tests1
|
||||||
| | +-- IModule.cs # Module interface (Name, Version, RegisterServices, UseModule)
|
Src --> Tests2
|
||||||
| | +-- ModuleInfo.cs # Module metadata record
|
Api --> ApiExt
|
||||||
| |
|
Api --> ApiInfra
|
||||||
| +-- SlpModularCms.Modules.Identity/ # Identity feature module
|
Api --> ApiProg
|
||||||
| | +-- Controllers/
|
Core --> CoreAvail
|
||||||
| | +-- AuthController.cs # /auth/* endpoints
|
Core --> CoreData
|
||||||
| | +-- SetupController.cs # /setup/* endpoints
|
Core --> CoreIdentity
|
||||||
| | +-- UsersController.cs # /users/* endpoints
|
Core --> CoreMigrations
|
||||||
| |
|
Core --> CoreModules
|
||||||
| +-- SlpModularCms.Modules.Availability/ # Availability feature module
|
ModIdentity --> ModIdentityCtrl
|
||||||
| | +-- Controllers/
|
ModAvail --> ModAvailCtrl
|
||||||
| | | +-- AvailabilityController.cs # /availability/* endpoints
|
ModAvail --> ModAvailSvc
|
||||||
| | +-- Middleware/ # Availability check middleware
|
|
||||||
| | +-- Services/
|
style Api fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
| | +-- PersistentAvailabilityService.cs # Reads/writes status to DB + cache
|
style ApiExt fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
| |
|
style ApiInfra fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
| +-- SlpModularCms.Core.Tests/ # Core unit tests
|
style ApiProg fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
| +-- SlpModularCms.Modules.Availability.Tests/ # Availability unit tests
|
style Core fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
|
|
style CoreAvail fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
+-- aidlc-docs/ # AI-DLC workflow documentation
|
style CoreData fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
|
style CoreIdentity fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
|
style CoreMigrations fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
|
style CoreModules fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
|
style ModIdentity fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
|
style ModIdentityCtrl fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
|
style ModAvail fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
|
style ModAvailCtrl fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
|
style ModAvailSvc fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
|
style Tests1 fill:#9E9E9E,stroke:#424242,color:#fff
|
||||||
|
style Tests2 fill:#9E9E9E,stroke:#424242,color:#fff
|
||||||
|
style Docs fill:#CE93D8,stroke:#6A1B9A,color:#000
|
||||||
```
|
```
|
||||||
|
|
||||||
## Key Classes/Modules
|
## Key Classes/Modules
|
||||||
|
|||||||
@@ -2,27 +2,33 @@
|
|||||||
|
|
||||||
## Internal Dependencies
|
## Internal Dependencies
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
SlpModularCms.Api
|
graph TD
|
||||||
+-- SlpModularCms.Core (compile)
|
Api["SlpModularCms.Api"]
|
||||||
+-- SlpModularCms.Modules.Identity (compile)
|
Core["SlpModularCms.Core"]
|
||||||
+-- SlpModularCms.Modules.Availability (compile)
|
ModIdentity["SlpModularCms.Modules.Identity"]
|
||||||
|
ModAvail["SlpModularCms.Modules.Availability"]
|
||||||
|
CoreTests["SlpModularCms.Core.Tests"]
|
||||||
|
AvailTests["SlpModularCms.Modules.Availability.Tests"]
|
||||||
|
Frontend["SlpModularCms.Frontend\n(to be built)"]
|
||||||
|
|
||||||
SlpModularCms.Modules.Identity
|
Api -->|compile| Core
|
||||||
+-- SlpModularCms.Core (compile)
|
Api -->|compile| ModIdentity
|
||||||
|
Api -->|compile| ModAvail
|
||||||
|
ModIdentity -->|compile| Core
|
||||||
|
ModAvail -->|compile| Core
|
||||||
|
CoreTests -->|test| Core
|
||||||
|
AvailTests -->|test| ModAvail
|
||||||
|
AvailTests -->|test| Core
|
||||||
|
Frontend -->|runtime REST| Api
|
||||||
|
|
||||||
SlpModularCms.Modules.Availability
|
style Api fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
+-- SlpModularCms.Core (compile)
|
style Core fill:#FFC107,stroke:#F57F17,color:#000
|
||||||
|
style ModIdentity fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
SlpModularCms.Core.Tests
|
style ModAvail fill:#4CAF50,stroke:#2E7D32,color:#fff
|
||||||
+-- SlpModularCms.Core (test)
|
style CoreTests fill:#9E9E9E,stroke:#424242,color:#fff
|
||||||
|
style AvailTests fill:#9E9E9E,stroke:#424242,color:#fff
|
||||||
SlpModularCms.Modules.Availability.Tests
|
style Frontend fill:#2196F3,stroke:#0D47A1,color:#fff
|
||||||
+-- SlpModularCms.Modules.Availability (test)
|
|
||||||
+-- SlpModularCms.Core (test)
|
|
||||||
|
|
||||||
SlpModularCms.Frontend (to be built)
|
|
||||||
+-- SlpModularCms.Api (runtime via REST HTTP)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Dependency Details
|
### Dependency Details
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
### Frameworks
|
### Frameworks
|
||||||
- React 18.3.1 — UI framework
|
- React 18.3.1 — UI framework
|
||||||
- React Router v7 (7.13.0) — Client-side routing
|
- TanStack Router — Client-side routing (replaces React Router v7 from example app; chosen for full TypeScript safety and modern routing features)
|
||||||
- Tailwind CSS v4 (4.1.12) — Utility-first CSS framework
|
- Tailwind CSS v4 (4.1.12) — Utility-first CSS framework
|
||||||
- shadcn/ui (via Radix UI) — Accessible component primitives
|
- shadcn/ui (via Radix UI) — Accessible component primitives
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
- **Feature Slug**: cms-frontend
|
- **Feature Slug**: cms-frontend
|
||||||
- **Project Type**: Brownfield
|
- **Project Type**: Brownfield
|
||||||
- **Start Date**: 2026-06-16T20:27:00Z
|
- **Start Date**: 2026-06-16T20:27:00Z
|
||||||
- **Current Stage**: INCEPTION - Requirements Analysis (awaiting question answers)
|
- **Current Stage**: INCEPTION - User Stories (awaiting user approval)
|
||||||
- **Branch**: unknown
|
- **Branch**: unknown
|
||||||
|
|
||||||
## Workspace State
|
## Workspace State
|
||||||
@@ -24,13 +24,16 @@
|
|||||||
- **Conversation Language**: Dutch (nl)
|
- **Conversation Language**: Dutch (nl)
|
||||||
|
|
||||||
## Extension Configuration
|
## Extension Configuration
|
||||||
[Will be populated during Requirements Analysis]
|
| Extension | Enabled | Decided At |
|
||||||
|
|---|---|---|
|
||||||
|
| Security Baseline | Yes | Requirements Analysis |
|
||||||
|
| Property-Based Testing | No | Requirements Analysis |
|
||||||
|
|
||||||
## Stage Progress
|
## Stage Progress
|
||||||
- [x] Workspace Detection — Completed 2026-06-16T20:28:00Z
|
- [x] Workspace Detection — Completed 2026-06-16T20:28:00Z
|
||||||
- [x] Reverse Engineering (shared) — Completed 2026-06-16T20:32:00Z — Artifacts: aidlc-docs/_shared/reverse-engineering/
|
- [x] Reverse Engineering (shared) — Completed 2026-06-16T20:32:00Z — Artifacts: aidlc-docs/_shared/reverse-engineering/
|
||||||
- [ ] Requirements Analysis — Not Started
|
- [~] Requirements Analysis — In Progress (requirements.md generated; awaiting approval)
|
||||||
- [ ] User Stories — Not Started
|
- [~] User Stories — In Progress (stories.md + personas.md generated; awaiting approval)
|
||||||
- [ ] Workflow Planning — Not Started
|
- [ ] Workflow Planning — Not Started
|
||||||
- [ ] Construction — Not Started
|
- [ ] Construction — Not Started
|
||||||
- [ ] Build and Test — Not Started
|
- [ ] Build and Test — Not Started
|
||||||
|
|||||||
@@ -12,6 +12,30 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## User Stories — Stage Added
|
||||||
|
|
||||||
|
**Timestamp**: 2026-06-16T20:47:00Z
|
||||||
|
|
||||||
|
**User Input**: "Add user stories"
|
||||||
|
|
||||||
|
**AI Response**: "User Stories stage added. Loading user-stories.md, creating assessment and story generation plan."
|
||||||
|
|
||||||
|
**Context**: User requested User Stories stage before Workflow Planning. Requirements implicitly approved via this request.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Requirements Analysis — Completion
|
||||||
|
|
||||||
|
**Timestamp**: 2026-06-16T20:45:00Z
|
||||||
|
|
||||||
|
**User Input**: "(Questions answered in requirement-verification-questions.md and requirement-clarification-questions.md)"
|
||||||
|
|
||||||
|
**AI Response**: "Generated requirements.md with 12 functional requirements and 11 non-functional requirements. Security baseline enabled. PBT disabled. Auth strategy: access token in memory + refresh token in httpOnly cookie."
|
||||||
|
|
||||||
|
**Context**: Requirements Analysis complete. Awaiting user approval.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Gap Identified — Language Preference
|
## Gap Identified — Language Preference
|
||||||
|
|
||||||
**Timestamp**: 2026-06-16T20:35:00Z
|
**Timestamp**: 2026-06-16T20:35:00Z
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
# Story Generation Plan — CMS Frontend
|
||||||
|
|
||||||
|
## Approach
|
||||||
|
**Persona-Based + Feature-Based Hybrid**: Stories are organized by persona (who) and grouped under the feature/page they relate to (what). This gives clear ownership per role while keeping related stories together for implementation.
|
||||||
|
|
||||||
|
## Planning Checklist
|
||||||
|
- [x] User Stories Assessment completed
|
||||||
|
- [x] Story approach chosen: Persona-Based + Feature-Based Hybrid
|
||||||
|
- [x] Clarification questions generated (see below)
|
||||||
|
- [x] Clarification questions answered
|
||||||
|
- [x] Stories generated (stories.md)
|
||||||
|
- [x] Personas generated (personas.md)
|
||||||
|
- [x] Acceptance criteria verified (INVEST-compliant)
|
||||||
|
- [x] Personas mapped to stories
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Generation Steps
|
||||||
|
|
||||||
|
### Step 1: Generate personas.md
|
||||||
|
Create `aidlc-docs/features/cms-frontend/inception/user-stories/personas.md` with:
|
||||||
|
- [ ] Persona: System Owner
|
||||||
|
- [ ] Persona: CMS Administrator
|
||||||
|
- [ ] Persona: CMS User
|
||||||
|
- [ ] Persona: New Invited User (completing setup)
|
||||||
|
- [ ] Persona: Anonymous Visitor (unauthenticated, e.g. invite link recipient)
|
||||||
|
|
||||||
|
### Step 2: Generate stories.md
|
||||||
|
Create `aidlc-docs/features/cms-frontend/inception/user-stories/stories.md` with stories for:
|
||||||
|
|
||||||
|
**Epic: Authentication & Session**
|
||||||
|
- [ ] US-01 Login with email and password
|
||||||
|
- [ ] US-02 Stay logged in across tab switches (session persistence via refresh token)
|
||||||
|
- [ ] US-03 Logout and end session
|
||||||
|
- [ ] US-04 Access denied redirect when not authenticated
|
||||||
|
- [ ] US-05 Auto token refresh on expiry
|
||||||
|
|
||||||
|
**Epic: System Initialization**
|
||||||
|
- [ ] US-06 Initialize system as first Owner (setup flow)
|
||||||
|
- [ ] US-07 Redirect to setup when system is not initialized
|
||||||
|
|
||||||
|
**Epic: Dashboard**
|
||||||
|
- [ ] US-08 View dashboard after login
|
||||||
|
- [ ] US-09 View system availability status on dashboard
|
||||||
|
|
||||||
|
**Epic: User Management**
|
||||||
|
- [ ] US-10 View list of users (Owner/Admin)
|
||||||
|
- [ ] US-11 Invite a new user by email with role selection (Owner/Admin)
|
||||||
|
- [ ] US-12 Share invite link after invitation is created
|
||||||
|
- [ ] US-13 Complete account setup via invitation link (New Invited User)
|
||||||
|
- [ ] US-14 Handle expired/invalid invitation token gracefully
|
||||||
|
|
||||||
|
**Epic: Profile**
|
||||||
|
- [ ] US-15 View own profile information
|
||||||
|
|
||||||
|
**Epic: System Settings**
|
||||||
|
- [ ] US-16 View system availability status in settings (Owner)
|
||||||
|
- [ ] US-17 Access denied to System Settings for non-Owners
|
||||||
|
|
||||||
|
**Epic: Navigation & Layout**
|
||||||
|
- [ ] US-18 See role-appropriate navigation items in sidebar
|
||||||
|
- [ ] US-19 Toggle dark/light theme
|
||||||
|
|
||||||
|
**Epic: CMS Management (Placeholder)**
|
||||||
|
- [ ] US-20 View CMS management placeholder page
|
||||||
|
|
||||||
|
### Step 3: Validate INVEST criteria
|
||||||
|
- [ ] Each story is Independent (can be implemented standalone)
|
||||||
|
- [ ] Each story is Negotiable (not a contract)
|
||||||
|
- [ ] Each story is Valuable (delivers user benefit)
|
||||||
|
- [ ] Each story is Estimable (dev can size it)
|
||||||
|
- [ ] Each story is Small (fits in one sprint iteration)
|
||||||
|
- [ ] Each story is Testable (acceptance criteria are verifiable)
|
||||||
|
|
||||||
|
### Step 4: Map personas to stories
|
||||||
|
- [ ] Add persona references to each story in stories.md
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Clarification Questions
|
||||||
|
|
||||||
|
Please answer the following questions to improve story quality.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Question 1: Story format preference
|
||||||
|
Which format should be used for user stories?
|
||||||
|
|
||||||
|
A) Standard narrative: "As a [persona], I want to [action], so that [benefit]"
|
||||||
|
B) Job-story format: "When [situation], I want to [motivation], so I can [outcome]"
|
||||||
|
C) Other (please describe after [Answer]: tag below)
|
||||||
|
|
||||||
|
[Answer]: A
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Question 2: Acceptance criteria format
|
||||||
|
How detailed should acceptance criteria be?
|
||||||
|
|
||||||
|
A) Concise bullet points (3–5 bullets per story, focus on happy path + key error states)
|
||||||
|
B) Gherkin-style (Given/When/Then scenarios for each story)
|
||||||
|
C) Detailed checklist covering happy path, error states, edge cases, and security constraints
|
||||||
|
X) Other (please describe after [Answer]: tag below)
|
||||||
|
|
||||||
|
[Answer]: C
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Question 3: Story granularity for auth flows
|
||||||
|
The authentication flow has several sub-steps (login, token refresh, logout, 401 handling). Should these be:
|
||||||
|
|
||||||
|
A) Separate stories — one story per interaction type (login, refresh, logout, redirect)
|
||||||
|
B) One story per user goal — login is one story, "stay logged in" is one story, logout is one story
|
||||||
|
C) A single epic story with sub-tasks broken out in acceptance criteria
|
||||||
|
X) Other (please describe after [Answer]: tag below)
|
||||||
|
|
||||||
|
[Answer]: A
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Question 4: Role names in stories
|
||||||
|
How should roles be referred to in story personas?
|
||||||
|
|
||||||
|
A) Use technical role names from the backend: Owner, Admin, User
|
||||||
|
B) Use business-friendly names: System Owner, CMS Administrator, CMS User
|
||||||
|
C) Use both — technical name + friendly alias (e.g. "Owner (System Owner)")
|
||||||
|
X) Other (please describe after [Answer]: tag below)
|
||||||
|
|
||||||
|
[Answer]: A
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Question 5: Out-of-scope stories
|
||||||
|
Should the stories document include placeholder/future stories for features that are explicitly out of scope in v1 (e.g. profile editing, availability status management, CMS content)?
|
||||||
|
|
||||||
|
A) Yes — include them as clearly marked "Future / Out of Scope" stories
|
||||||
|
B) No — only include stories that are in scope for v1
|
||||||
|
C) Include brief notes only (no full story format) for future features
|
||||||
|
X) Other (please describe after [Answer]: tag below)
|
||||||
|
|
||||||
|
[Answer]: C
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# User Stories Assessment
|
||||||
|
|
||||||
|
## Request Analysis
|
||||||
|
- **Original Request**: Build a React-based CMS admin frontend with Login, Dashboard, User Management, Profile, System Settings, and CMS placeholder pages
|
||||||
|
- **User Impact**: Direct — this is an entirely user-facing application; every requirement is about what users see and do
|
||||||
|
- **Complexity Level**: Moderate — multiple pages, multiple user roles (Owner, Admin, User), distinct user workflows
|
||||||
|
- **Stakeholders**: CMS administrators (Owners, Admins), regular CMS users
|
||||||
|
|
||||||
|
## Assessment Criteria Met
|
||||||
|
- [x] High Priority: New user-facing features — entire frontend is new user interaction surface
|
||||||
|
- [x] High Priority: Multi-persona system — three distinct roles (Owner, Admin, User) with different access levels
|
||||||
|
- [x] High Priority: Complex business requirements — auth flows, invitation flows, role-based navigation, setup initialization
|
||||||
|
- [x] High Priority: New product capabilities — no existing frontend; this is the first admin interface
|
||||||
|
- [x] Benefits: Stories clarify per-role behavior; acceptance criteria define testable boundaries for each feature
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
**Execute User Stories**: Yes
|
||||||
|
|
||||||
|
**Reasoning**: The CMS frontend is a multi-persona, multi-page user-facing application with distinct workflows per role. User stories will:
|
||||||
|
1. Make explicit what each role can and cannot do on each page
|
||||||
|
2. Provide testable acceptance criteria for each interaction
|
||||||
|
3. Clarify the invitation and setup flows which have multiple states (valid/expired/used tokens)
|
||||||
|
4. Define the role-based navigation and access control expectations clearly
|
||||||
|
5. Serve as a specification for future development phases (CMS content modules, profile editing)
|
||||||
|
|
||||||
|
## Expected Outcomes
|
||||||
|
- Clear per-persona stories covering login, dashboard, user management, invitation flow, profile, and settings
|
||||||
|
- Explicit acceptance criteria for edge cases (expired invitations, unauthorized access, system not initialized)
|
||||||
|
- Role-based stories that define Owner vs Admin vs User capabilities without ambiguity
|
||||||
|
- Reusable baseline for future feature extension
|
||||||
+1
-1
@@ -20,4 +20,4 @@ B) Keep localStorage for now (faster to implement, familiar) AND disable the sec
|
|||||||
C) Keep localStorage for now AND keep the security baseline, but acknowledge and document this as an accepted risk / technical debt
|
C) Keep localStorage for now AND keep the security baseline, but acknowledge and document this as an accepted risk / technical debt
|
||||||
X) Other (please describe after [Answer]: tag below)
|
X) Other (please describe after [Answer]: tag below)
|
||||||
|
|
||||||
[Answer]:
|
[Answer]: A
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
# Requirements — CMS Frontend
|
||||||
|
|
||||||
|
## Intent Analysis Summary
|
||||||
|
|
||||||
|
- **User Request**: Build a React-based admin frontend for SlpModularCms, based on an example app (ZIP file) that uses shadcn/ui, Tailwind CSS v4 with primary color `#ac0000`, and React Router v7. First version focuses on Identity management (login, user management, profile, system settings); CMS content management comes later.
|
||||||
|
- **Request Type**: New Feature (new React SPA project added to an existing .NET backend)
|
||||||
|
- **Scope Estimate**: Multiple Components — new frontend project with API integration, auth layer, routing, multiple pages
|
||||||
|
- **Complexity Estimate**: Moderate — established tech stack from example app, clear API contract, well-defined auth flow, some security requirements
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Functional Requirements
|
||||||
|
|
||||||
|
### FR-01: Authentication — Login
|
||||||
|
- The application MUST provide a login page at `/login`
|
||||||
|
- Users authenticate with email + password via `POST /auth/login`
|
||||||
|
- On success: access token stored **in memory** (React state/context), refresh token stored in **httpOnly cookie** (secure, not accessible via JavaScript)
|
||||||
|
- On failure: display clear error message without revealing whether email or password is incorrect
|
||||||
|
- The login page is publicly accessible (unauthenticated)
|
||||||
|
|
||||||
|
### FR-02: Authentication — Session Management
|
||||||
|
- The app MUST automatically refresh the access token using the refresh token cookie via `POST /auth/refresh` when the access token expires or returns a 401
|
||||||
|
- On logout: call `POST /auth/revoke` to invalidate the refresh token; clear in-memory access token; redirect to `/login`
|
||||||
|
- After a page refresh, the app MUST attempt to restore the session by calling `/auth/refresh` using the httpOnly cookie; if it fails, redirect to `/login`
|
||||||
|
|
||||||
|
### FR-03: System Initialization — Setup Flow
|
||||||
|
- On app startup, call `GET /setup/status` to check if the system has been initialized
|
||||||
|
- If NOT initialized: redirect all traffic to `/setup` (initialization page)
|
||||||
|
- The `/setup` page allows creating the first Owner account via `POST /setup/owner` (email + password)
|
||||||
|
- After successful initialization, redirect to `/login`
|
||||||
|
|
||||||
|
### FR-04: Route Security
|
||||||
|
- All routes except `/login`, `/setup`, and `/invite/complete` MUST require authentication
|
||||||
|
- If the user is not authenticated and tries to access a protected route, redirect to `/login`
|
||||||
|
- Role-based guards MUST be applied per page:
|
||||||
|
- System Settings page: Owner only
|
||||||
|
- User Management page: Owner and Admin
|
||||||
|
- Profile page: Any authenticated user
|
||||||
|
- Dashboard: Any authenticated user
|
||||||
|
|
||||||
|
### FR-05: Dashboard
|
||||||
|
- Authenticated users see a dashboard at `/` (or `/dashboard`)
|
||||||
|
- Dashboard shows:
|
||||||
|
- Welcome message with user's name and role
|
||||||
|
- Quick stats/overview widgets (user count, system status indicator)
|
||||||
|
- **System availability status indicator**: Shows current status (Available / Maintenance / Unavailable) with reason, sourced from `GET /availability/status`
|
||||||
|
|
||||||
|
### FR-06: User Management
|
||||||
|
- Accessible at `/users` (Owner and Admin only)
|
||||||
|
- Displays a list of users with name, email, role, and active status
|
||||||
|
- **Invite user**: Dialog/form to invite a new user by email + role selection; calls `POST /users/invite`; shows the generated invite link for sharing
|
||||||
|
- Future extensibility: edit user, deactivate user (backend not yet available)
|
||||||
|
|
||||||
|
### FR-07: User Invitation Completion Flow
|
||||||
|
- Public page at `/invite/complete?token={token}`
|
||||||
|
- On page load: validate the token via `GET /users/validate-invitation?token={token}`
|
||||||
|
- If valid: show a form to set a display name and password; submit via `POST /users/complete-setup`
|
||||||
|
- If invalid/expired: show appropriate error message with no form
|
||||||
|
- On success: show confirmation message and link to `/login`
|
||||||
|
|
||||||
|
### FR-08: Profile / Account Settings
|
||||||
|
- Accessible at `/profile` (any authenticated user)
|
||||||
|
- Displays current user's name, email, and role (read-only for now)
|
||||||
|
- Placeholder for future: change password, update display name
|
||||||
|
|
||||||
|
### FR-09: System Settings
|
||||||
|
- Accessible at `/settings` (Owner only)
|
||||||
|
- First version: read-only overview of system configuration (initialized status, current availability status)
|
||||||
|
- Placeholder structure for future settings categories (modules, CMS config, etc.)
|
||||||
|
- **Note**: The CMS availability master module (for managing multiple client CMS instances) has not been built yet. System Settings only shows the current global availability status from `GET /availability/status`.
|
||||||
|
|
||||||
|
### FR-10: Navigation
|
||||||
|
- Authenticated pages use a sidebar navigation layout (based on example app)
|
||||||
|
- Sidebar shows only navigation items relevant to the user's role:
|
||||||
|
- Dashboard: all authenticated users
|
||||||
|
- User Management: Owner and Admin
|
||||||
|
- System Settings: Owner only
|
||||||
|
- Profile: all authenticated users
|
||||||
|
- Logout button: all authenticated users
|
||||||
|
- Mobile-responsive: sidebar collapses on small screens
|
||||||
|
|
||||||
|
### FR-11: Dark / Light Theme
|
||||||
|
- Users can toggle between dark and light theme via a button in the UI
|
||||||
|
- Preference is persisted in `localStorage` (theme preference only — not auth data)
|
||||||
|
- Default: system preference
|
||||||
|
|
||||||
|
### FR-12: CMS Management (Placeholder)
|
||||||
|
- Page at `/cms` (structure ready, no real data)
|
||||||
|
- Shows navigation structure for future CMS content modules
|
||||||
|
- Clearly marked as "Work in Progress" with a placeholder message
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Non-Functional Requirements
|
||||||
|
|
||||||
|
### NFR-01: Technology Stack
|
||||||
|
- **Framework**: React 18 + TypeScript
|
||||||
|
- **Routing**: TanStack Router (file-based or code-based routing with full TypeScript support)
|
||||||
|
- **UI Components**: shadcn/ui (Radix UI primitives)
|
||||||
|
- **Styling**: Tailwind CSS v4, primary color `#ac0000`
|
||||||
|
- **Build tool**: Vite
|
||||||
|
- **Package manager**: pnpm
|
||||||
|
- **Theme**: next-themes (dark/light mode)
|
||||||
|
- **Icons**: lucide-react
|
||||||
|
- **Forms**: react-hook-form
|
||||||
|
- **Notifications**: sonner (toast)
|
||||||
|
|
||||||
|
> **Note**: The example app in the ZIP uses React Router v7. Route definitions and `<Link>` components must be migrated to TanStack Router equivalents during implementation.
|
||||||
|
|
||||||
|
### NFR-02: Project Location
|
||||||
|
- The React app is placed in `frontend/` at the root of the solution (sibling to `src/` and `SlpModularCms.sln`)
|
||||||
|
|
||||||
|
### NFR-03: API Configuration
|
||||||
|
- API base URL configured via `.env` file using `VITE_API_BASE_URL`
|
||||||
|
- A `.env.example` file is committed to version control as a template
|
||||||
|
- The actual `.env` is added to `.gitignore`
|
||||||
|
- No secrets or sensitive data are hardcoded in source code
|
||||||
|
|
||||||
|
### NFR-04: Authentication Security (SECURITY-12) + Documentation Updates
|
||||||
|
- Access token stored **in memory only** (React context/state) — never in localStorage or sessionStorage
|
||||||
|
- Refresh token sent as **httpOnly cookie** — the backend must set `Set-Cookie: refreshToken=...; HttpOnly; Secure; SameSite=Strict`
|
||||||
|
- **Note**: The backend currently returns the refresh token in the JSON response body. A CORS + cookie configuration update on the backend may be required in a later phase.
|
||||||
|
- Session invalidated on logout (token revoked, cookie cleared)
|
||||||
|
- **Documentation update requirement**: After implementation, verify that the API documentation in `aidlc-docs/features/slp-modular-cms-api/` is still accurate. If the backend requires changes to support httpOnly cookie-based refresh tokens (e.g., CORS policy updates, `Set-Cookie` header changes), update the relevant docs in that feature's directory. Also update `aidlc-docs/_shared/reverse-engineering/api-documentation.md` if any endpoint contracts change.
|
||||||
|
|
||||||
|
### NFR-05: HTTP Security Headers (SECURITY-04) + README Instructions
|
||||||
|
- The app's dev server and production build must serve with security headers
|
||||||
|
- The project root `README.md` MUST include a **Frontend Development** section with at minimum:
|
||||||
|
- Prerequisites (Node.js version, pnpm installation)
|
||||||
|
- How to install dependencies (`pnpm install`)
|
||||||
|
- How to configure the `.env` file (reference `.env.example`)
|
||||||
|
- How to start the dev server (`pnpm dev`)
|
||||||
|
- How to run the production build (`pnpm build`)
|
||||||
|
- When deployed, a web server or reverse proxy (nginx, etc.) MUST set:
|
||||||
|
- `Content-Security-Policy: default-src 'self'`
|
||||||
|
- `Strict-Transport-Security: max-age=31536000; includeSubDomains`
|
||||||
|
- `X-Content-Type-Options: nosniff`
|
||||||
|
- `X-Frame-Options: DENY`
|
||||||
|
- `Referrer-Policy: strict-origin-when-cross-origin`
|
||||||
|
|
||||||
|
### NFR-06: Input Validation (SECURITY-05)
|
||||||
|
- All form inputs are validated client-side using react-hook-form before submission
|
||||||
|
- Validation includes: required fields, email format, password minimum length (8+ chars), max lengths
|
||||||
|
- Server-side validation errors are displayed to the user without exposing internal details
|
||||||
|
|
||||||
|
### NFR-07: Access Control (SECURITY-08)
|
||||||
|
- Frontend enforces role-based access as a UX layer (hide menu items, redirect on unauthorized access)
|
||||||
|
- Backend authorization is the authoritative access control — frontend enforcement is defense-in-depth only
|
||||||
|
- No sensitive operations are performed based solely on client-side role information
|
||||||
|
|
||||||
|
### NFR-08: Error Handling (SECURITY-15, SECURITY-09)
|
||||||
|
- API errors shown to users use generic messages; technical details logged to the browser console only in development
|
||||||
|
- Global error boundary catches unexpected React errors and shows a user-friendly fallback UI
|
||||||
|
- 401 responses trigger token refresh or redirect to login
|
||||||
|
- 403 responses show an "Access Denied" page without internal details
|
||||||
|
- 404 responses show a "Not Found" page
|
||||||
|
|
||||||
|
### NFR-09: Structured Logging (SECURITY-03)
|
||||||
|
- API client logs requests/responses at debug level (not in production builds)
|
||||||
|
- Auth errors, token refresh events, and navigation failures logged at warning level
|
||||||
|
- No passwords, tokens, or PII in any log output
|
||||||
|
|
||||||
|
### NFR-10: Dependency Management (SECURITY-10)
|
||||||
|
- A `pnpm-lock.yaml` lock file is committed to version control
|
||||||
|
- Only packages from official npm registry are used
|
||||||
|
- No unused dependencies included
|
||||||
|
|
||||||
|
### NFR-11: Structured Application Logging (SECURITY-11)
|
||||||
|
- Auth and route guard logic is isolated in dedicated modules (`src/auth/`, `src/router/`)
|
||||||
|
- API communication is centralized in a dedicated API client (`src/api/`)
|
||||||
|
- No auth or security logic scattered across component files
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Baseline Compliance Summary (at Requirements stage)
|
||||||
|
|
||||||
|
| Rule | Status | Notes |
|
||||||
|
|------|--------|-------|
|
||||||
|
| SECURITY-01 (Encryption at Rest/Transit) | N/A | Frontend SPA — no data store; backend handles this |
|
||||||
|
| SECURITY-02 (Access Logging) | N/A | Frontend SPA — infrastructure concern handled at deployment |
|
||||||
|
| SECURITY-03 (Application Logging) | Compliant | NFR-09 addresses structured logging |
|
||||||
|
| SECURITY-04 (HTTP Security Headers) | Compliant | NFR-05 addresses required headers |
|
||||||
|
| SECURITY-05 (Input Validation) | Compliant | NFR-06 addresses client-side validation |
|
||||||
|
| SECURITY-06 (Least Privilege) | N/A | Frontend SPA — no IAM policies |
|
||||||
|
| SECURITY-07 (Network Configuration) | N/A | Frontend SPA — infrastructure concern |
|
||||||
|
| SECURITY-08 (Application Access Control) | Compliant | NFR-07 addresses role-based access |
|
||||||
|
| SECURITY-09 (Hardening) | Compliant | NFR-08 addresses error handling; NFR-03 addresses no hardcoded secrets |
|
||||||
|
| SECURITY-10 (Supply Chain) | Compliant | NFR-10 addresses lock file and trusted sources |
|
||||||
|
| SECURITY-11 (Secure Design) | Compliant | NFR-11 addresses separation of concerns |
|
||||||
|
| SECURITY-12 (Authentication) | Compliant | NFR-04 addresses secure token storage; FR-01/FR-02 address session management |
|
||||||
|
| SECURITY-13 (Data Integrity) | N/A | No external script loading from CDN; SRI not applicable |
|
||||||
|
| SECURITY-14 (Alerting/Monitoring) | N/A | Frontend SPA — infrastructure/backend concern |
|
||||||
|
| SECURITY-15 (Exception Handling) | Compliant | NFR-08 addresses error boundaries and fail-safe defaults |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Constraints and Assumptions
|
||||||
|
|
||||||
|
- The example React app (from ZIP) serves as the design and structural foundation; all pages must match its visual style
|
||||||
|
- The backend API already provides all required endpoints (auth, setup, users, availability)
|
||||||
|
- The backend may need a minor update to support httpOnly cookie-based refresh token delivery (backend change is out of scope for this feature; FR-04 auth can use body-based refresh token temporarily)
|
||||||
|
- CMS content management functionality is explicitly out of scope for the first version
|
||||||
|
- The availability "master module" (multi-CMS management) is not yet built; dashboard only shows current single-instance status
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Open Questions / Future Work
|
||||||
|
|
||||||
|
- Backend CORS + httpOnly cookie support for refresh tokens (currently tokens are returned in response body)
|
||||||
|
- User list endpoint (`GET /users`) — not yet confirmed in API documentation; needs backend verification
|
||||||
|
- Availability master module (managing multiple CMS instances) — placeholder in System Settings for now
|
||||||
|
- Profile editing (change password, display name update) — backend endpoints not yet confirmed
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# Personas — CMS Frontend
|
||||||
|
|
||||||
|
## Persona 1: Owner
|
||||||
|
|
||||||
|
**Role**: Owner (highest privilege)
|
||||||
|
|
||||||
|
**Description**: The person who owns and manages the entire CMS platform. Typically the technical lead or product owner of the organisation. Has full access to all parts of the system.
|
||||||
|
|
||||||
|
**Goals**:
|
||||||
|
- Maintain full control over the platform
|
||||||
|
- Manage users and their roles
|
||||||
|
- Monitor and update system availability
|
||||||
|
- Access all administrative functions
|
||||||
|
|
||||||
|
**Characteristics**:
|
||||||
|
- Technically proficient
|
||||||
|
- Responsible for platform health and security
|
||||||
|
- May also act as CMS content manager
|
||||||
|
- Only persona with access to System Settings
|
||||||
|
|
||||||
|
**Relevant Stories**: US-01 through US-20 (all stories)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Persona 2: Admin
|
||||||
|
|
||||||
|
**Role**: Admin
|
||||||
|
|
||||||
|
**Description**: A trusted team member who manages day-to-day CMS operations. Can invite and manage users but cannot access system-level settings.
|
||||||
|
|
||||||
|
**Goals**:
|
||||||
|
- Invite new users to the platform
|
||||||
|
- Manage CMS content (future)
|
||||||
|
- View and manage the user list
|
||||||
|
|
||||||
|
**Characteristics**:
|
||||||
|
- Regular platform user with elevated permissions
|
||||||
|
- Does not manage system-level configuration
|
||||||
|
- Typically assigned by the Owner
|
||||||
|
|
||||||
|
**Relevant Stories**: US-01, US-02, US-03, US-04, US-05, US-08, US-09, US-10, US-11, US-12, US-15, US-18, US-19, US-20
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Persona 3: User
|
||||||
|
|
||||||
|
**Role**: User (standard access)
|
||||||
|
|
||||||
|
**Description**: A regular user of the CMS platform. Uses the frontend for content tasks. Cannot manage other users or access administrative settings.
|
||||||
|
|
||||||
|
**Goals**:
|
||||||
|
- Access the CMS to perform content-related tasks
|
||||||
|
- View their own profile
|
||||||
|
- Navigate to relevant CMS sections
|
||||||
|
|
||||||
|
**Characteristics**:
|
||||||
|
- Least privileged authenticated persona
|
||||||
|
- Primarily uses Dashboard and CMS Management
|
||||||
|
- Cannot invite users or access system settings
|
||||||
|
|
||||||
|
**Relevant Stories**: US-01, US-02, US-03, US-04, US-05, US-08, US-09, US-15, US-18, US-19, US-20
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Persona 4: New Invited User
|
||||||
|
|
||||||
|
**Role**: Unauthenticated (completing account setup)
|
||||||
|
|
||||||
|
**Description**: A person who has received an email invitation to join the platform. They have not yet created their account. They access the platform via a unique invitation link.
|
||||||
|
|
||||||
|
**Goals**:
|
||||||
|
- Complete account setup using their invitation token
|
||||||
|
- Set a secure password
|
||||||
|
- Gain access to the platform
|
||||||
|
|
||||||
|
**Characteristics**:
|
||||||
|
- Not yet registered; no credentials
|
||||||
|
- Has a limited-time invite token
|
||||||
|
- May receive an expired or already-used token
|
||||||
|
|
||||||
|
**Relevant Stories**: US-13, US-14
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Persona 5: Anonymous Visitor
|
||||||
|
|
||||||
|
**Role**: Unauthenticated (no credentials, no invite)
|
||||||
|
|
||||||
|
**Description**: An unauthenticated person attempting to access the CMS frontend, or a first-time user visiting the system before it has been initialized.
|
||||||
|
|
||||||
|
**Goals**:
|
||||||
|
- Reach the login page to authenticate
|
||||||
|
- Complete initial system setup (if first-ever visitor and no Owner exists)
|
||||||
|
|
||||||
|
**Characteristics**:
|
||||||
|
- No credentials or role
|
||||||
|
- Should be redirected appropriately (to login or setup)
|
||||||
|
- Cannot access any protected resources
|
||||||
|
|
||||||
|
**Relevant Stories**: US-04, US-06, US-07
|
||||||
@@ -0,0 +1,329 @@
|
|||||||
|
# User Stories — CMS Frontend
|
||||||
|
|
||||||
|
**Format**: "As a [persona], I want to [action], so that [benefit]"
|
||||||
|
**Acceptance Criteria**: Detailed checklist — happy path, error states, edge cases, and security constraints
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: Authentication & Session
|
||||||
|
|
||||||
|
### US-01: Login with email and password
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an Owner/Admin/User, I want to log in with my email address and password, so that I can access the CMS platform securely.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] A `/login` page is displayed for unauthenticated users
|
||||||
|
- [ ] The form contains an email field, a password field, and a submit button
|
||||||
|
- [ ] Email field validates format before submission (invalid format shows inline error)
|
||||||
|
- [ ] Password field has a minimum length client-side hint (8 characters)
|
||||||
|
- [ ] On valid credentials: access token is stored in memory, refresh token is set as httpOnly cookie, user is redirected to `/`
|
||||||
|
- [ ] On invalid credentials: a generic error message is shown ("Invalid email or password") — no distinction between wrong email and wrong password
|
||||||
|
- [ ] On network error: a user-friendly error message is shown ("Unable to connect. Please try again.")
|
||||||
|
- [ ] The password field input is masked; a show/hide toggle is present
|
||||||
|
- [ ] The submit button shows a loading state while the request is in progress
|
||||||
|
- [ ] After successful login, the back button does NOT navigate back to the login page
|
||||||
|
- [ ] The page is accessible when the system is initialized and the user is not logged in
|
||||||
|
- [ ] **Security**: No token is stored in localStorage or sessionStorage
|
||||||
|
- [ ] **Security**: The form does not autocomplete passwords in production (autocomplete="new-password" or "current-password" as appropriate)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-02: Stay logged in across tab switches (session persistence via refresh token)
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want my session to be restored when I return to the app after a page refresh or browser restart, so that I do not have to log in repeatedly.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] On app load, the app calls `POST /auth/refresh` using the httpOnly cookie before rendering protected routes
|
||||||
|
- [ ] If the refresh succeeds: the new access token is stored in memory and the user proceeds to their intended route
|
||||||
|
- [ ] If the refresh fails (expired or missing cookie): the user is redirected to `/login`
|
||||||
|
- [ ] During the session restoration check, a loading/spinner state is shown — no flash of the protected content or login page
|
||||||
|
- [ ] A user who has never logged in sees the login page immediately (no loading delay)
|
||||||
|
- [ ] **Security**: The refresh endpoint call uses credentials (cookies) — `credentials: 'include'` in fetch or equivalent
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-03: Logout and end session
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want to log out of the application, so that my session is terminated and no one else can use my account.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] A logout button/menu item is visible in the sidebar for all authenticated users
|
||||||
|
- [ ] Clicking logout calls `POST /auth/revoke` with the current refresh token
|
||||||
|
- [ ] After logout: in-memory access token is cleared, the browser is redirected to `/login`
|
||||||
|
- [ ] If the revoke call fails (network error): the user is still redirected to `/login` and local state is cleared
|
||||||
|
- [ ] After logout, navigating back (browser back button) to a protected page redirects to `/login`
|
||||||
|
- [ ] **Security**: The httpOnly cookie is cleared upon logout (backend sets `Set-Cookie` with expired date)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-04: Redirect to login when not authenticated
|
||||||
|
**Persona**: Anonymous Visitor
|
||||||
|
|
||||||
|
As an unauthenticated visitor, I want to be redirected to the login page when I try to access a protected route, so that I cannot access content I am not authorised to see.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] Navigating to any protected route (e.g. `/`, `/users`, `/settings`) without a valid session redirects to `/login`
|
||||||
|
- [ ] After redirect, the originally requested URL is preserved (e.g. as a `?redirect=/users` query param) so the user can be sent there after login
|
||||||
|
- [ ] No protected page content is rendered, even briefly, before the redirect occurs
|
||||||
|
- [ ] **Security**: The redirect happens client-side as a defence-in-depth measure; the API also enforces authorisation server-side
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-05: Automatic access token refresh on expiry
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want my access token to be refreshed automatically when it expires during an active session, so that I am not abruptly logged out while working.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] When an API call returns a 401 (Unauthorised), the app automatically calls `POST /auth/refresh`
|
||||||
|
- [ ] If the refresh succeeds: the original API call is retried with the new access token
|
||||||
|
- [ ] If the refresh fails (refresh token expired): the user is redirected to `/login` with a notification ("Your session expired. Please log in again.")
|
||||||
|
- [ ] The original user action is not lost if possible (e.g. form data is preserved)
|
||||||
|
- [ ] Only one refresh attempt is made per 401 — infinite retry loops are prevented
|
||||||
|
- [ ] **Security**: The token refresh logic is centralised in the API client, not duplicated across components
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: System Initialization
|
||||||
|
|
||||||
|
### US-06: Initialize system as first Owner
|
||||||
|
**Persona**: Anonymous Visitor
|
||||||
|
|
||||||
|
As the first visitor to a new CMS installation, I want to create an Owner account during system setup, so that the platform is ready for use.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] The `/setup` page contains a form with email and password fields
|
||||||
|
- [ ] The form validates email format and password minimum length (8 characters)
|
||||||
|
- [ ] On submit: `POST /setup/owner` is called with the provided credentials
|
||||||
|
- [ ] On success: the user is redirected to `/login` with a success toast ("System initialized. Please log in.")
|
||||||
|
- [ ] On failure (e.g. system already initialized): an appropriate error message is shown and the user is redirected to `/login`
|
||||||
|
- [ ] **Edge case**: If the user navigates to `/setup` when the system is already initialized, they are redirected to `/login`
|
||||||
|
- [ ] **Security**: The setup page is only reachable when `GET /setup/status` returns `{ initialized: false }`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-07: Redirect to setup when system is not initialized
|
||||||
|
**Persona**: Anonymous Visitor
|
||||||
|
|
||||||
|
As a visitor to an uninitialized CMS, I want to be automatically redirected to the setup page, so that I know the system needs configuration before use.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] On app startup, `GET /setup/status` is called before rendering any page
|
||||||
|
- [ ] If `initialized: false`: all routes redirect to `/setup`
|
||||||
|
- [ ] If `initialized: true`: normal routing applies (login, protected routes, etc.)
|
||||||
|
- [ ] During the status check, a loading state is shown
|
||||||
|
- [ ] **Edge case**: If the `/setup/status` call fails, an error page is shown with a retry option
|
||||||
|
- [ ] **Security**: The `/setup/owner` endpoint is disabled server-side once initialized; the frontend check is defence-in-depth only
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: Dashboard
|
||||||
|
|
||||||
|
### US-08: View dashboard after login
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want to see a dashboard after logging in, so that I get an overview of the system's state and quick access to key functions.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] The `/` (or `/dashboard`) route renders the dashboard page for all authenticated users
|
||||||
|
- [ ] The dashboard displays a welcome message with the user's name and role
|
||||||
|
- [ ] The dashboard displays at least one summary widget (e.g. system status indicator)
|
||||||
|
- [ ] The layout uses the sidebar navigation from the example app design
|
||||||
|
- [ ] **Edge case**: If user data fails to load, a graceful error state is shown
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-09: View system availability status on dashboard
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want to see the current system availability status on the dashboard, so that I am immediately aware of any maintenance or outage.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] The dashboard calls `GET /availability/status` on load
|
||||||
|
- [ ] The status is displayed with a colour-coded indicator: Available (green), Maintenance (yellow), Unavailable (red)
|
||||||
|
- [ ] The status message/reason is shown alongside the indicator if present
|
||||||
|
- [ ] If the API call fails: the indicator shows "Unknown" with a retry option
|
||||||
|
- [ ] The status is refreshed when the user navigates back to the dashboard
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: User Management
|
||||||
|
|
||||||
|
### US-10: View list of users
|
||||||
|
**Persona**: Owner, Admin
|
||||||
|
|
||||||
|
As an Owner or Admin, I want to see a list of all platform users, so that I can manage team membership and access.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] The `/users` page is accessible to Owner and Admin roles only
|
||||||
|
- [ ] The page displays a table/list with each user's name, email, role, and active status
|
||||||
|
- [ ] If the user list is empty, an empty state message is shown
|
||||||
|
- [ ] If the API call fails, an error state is shown with a retry option
|
||||||
|
- [ ] **Security**: Navigating to `/users` as a User role redirects to an "Access Denied" page or back to `/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-11: Invite a new user
|
||||||
|
**Persona**: Owner, Admin
|
||||||
|
|
||||||
|
As an Owner or Admin, I want to invite a new user by providing their email address and selecting their role, so that they can join the platform.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] An "Invite User" button is visible on the `/users` page for Owner and Admin roles
|
||||||
|
- [ ] Clicking the button opens a dialog/modal with an email field and a role selector (Admin, User)
|
||||||
|
- [ ] The email field validates format before submission
|
||||||
|
- [ ] The role selector does NOT allow selecting Owner (Admins cannot create other Owners; Owner-role invites are also restricted unless the inviter is an Owner — consider showing Owner option only when logged in as Owner)
|
||||||
|
- [ ] On submit: `POST /users/invite` is called
|
||||||
|
- [ ] On success: the dialog remains open and transitions to the "share link" step (US-12)
|
||||||
|
- [ ] On failure (e.g. email already registered): an appropriate inline error is shown
|
||||||
|
- [ ] **Security**: The invite action is only available to Owner and Admin; role selection is validated server-side
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-12: Share invite link after invitation is created
|
||||||
|
**Persona**: Owner, Admin
|
||||||
|
|
||||||
|
As an Owner or Admin, I want to see and copy the generated invite link after creating an invitation, so that I can share it with the invited person.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] After a successful invitation (US-11), the dialog shows the generated invite link
|
||||||
|
- [ ] A "Copy to clipboard" button is present; clicking it copies the link and shows a success toast
|
||||||
|
- [ ] The link is displayed as readable text (not just a button)
|
||||||
|
- [ ] A "Done" button closes the dialog
|
||||||
|
- [ ] **Edge case**: If the clipboard API is unavailable (e.g. non-HTTPS context), a fallback allows manual selection of the text
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-13: Complete account setup via invitation link
|
||||||
|
**Persona**: New Invited User
|
||||||
|
|
||||||
|
As a person who received an invitation link, I want to complete my account setup by setting a password, so that I can log in to the platform.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] Navigating to `/invite/complete?token={token}` triggers `GET /users/validate-invitation?token={token}`
|
||||||
|
- [ ] If the token is valid: a form is shown with a display name field and a password field (with confirmation)
|
||||||
|
- [ ] Password must meet minimum requirements (8+ characters); a strength indicator is shown
|
||||||
|
- [ ] Password confirmation must match; mismatch shows an inline error
|
||||||
|
- [ ] On submit: `POST /users/complete-setup` is called with the token, display name, and password
|
||||||
|
- [ ] On success: a confirmation message is shown ("Your account is ready. You can now log in.") with a link to `/login`
|
||||||
|
- [ ] The form shows a loading state during submission
|
||||||
|
- [ ] **Security**: The token is sent to the backend for server-side validation; client-side token inspection is never used for access decisions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-14: Handle expired or invalid invitation token
|
||||||
|
**Persona**: New Invited User
|
||||||
|
|
||||||
|
As a person with an expired or already-used invitation link, I want to see a clear error message, so that I understand why I cannot proceed and know what to do next.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] If `GET /users/validate-invitation` returns an error (expired, used, or invalid token): no setup form is shown
|
||||||
|
- [ ] An error message is displayed: "This invitation link is invalid or has expired. Please contact your administrator for a new invite."
|
||||||
|
- [ ] A link to `/login` is provided for users who already completed setup
|
||||||
|
- [ ] **Edge case**: If the token query parameter is missing from the URL, the same error state is shown
|
||||||
|
- [ ] **Security**: No partial form data is shown when token validation fails
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: Profile
|
||||||
|
|
||||||
|
### US-15: View own profile information
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want to see my profile information, so that I can verify my account details.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] The `/profile` page is accessible to all authenticated users
|
||||||
|
- [ ] The page displays the user's display name, email address, and role
|
||||||
|
- [ ] All fields are read-only in v1
|
||||||
|
- [ ] A placeholder/note indicates that profile editing will be available in a future version
|
||||||
|
- [ ] **Edge case**: If the user data cannot be loaded, an error state is shown
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: System Settings
|
||||||
|
|
||||||
|
### US-16: View system availability status in settings
|
||||||
|
**Persona**: Owner
|
||||||
|
|
||||||
|
As an Owner, I want to view the current system availability status in the System Settings page, so that I have a central place for system-level information.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] The `/settings` page is accessible to Owner only
|
||||||
|
- [ ] The page displays the current system status (Available / Maintenance / Unavailable) and reason from `GET /availability/status`
|
||||||
|
- [ ] The initialized status of the system is also shown (always "Initialized" when this page is reachable)
|
||||||
|
- [ ] Placeholder sections for future settings categories are visible (e.g. "Module Settings", "CMS Configuration")
|
||||||
|
- [ ] **Edge case**: If the availability API call fails, the status shows "Unknown" with a retry option
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-17: Access denied for System Settings for non-Owners
|
||||||
|
**Persona**: Admin, User
|
||||||
|
|
||||||
|
As an Admin or User, I want to be prevented from accessing the System Settings page, so that system-level configuration is protected.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] Navigating to `/settings` as an Admin or User redirects to an "Access Denied" page or to `/`
|
||||||
|
- [ ] The System Settings item is NOT shown in the sidebar for Admin or User roles
|
||||||
|
- [ ] **Security**: The redirect is enforced client-side as defence-in-depth; the backend also enforces authorisation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: Navigation & Layout
|
||||||
|
|
||||||
|
### US-18: See role-appropriate navigation items in sidebar
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want to see only the navigation items relevant to my role in the sidebar, so that the interface is uncluttered and I am not confused by inaccessible sections.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] Dashboard: visible to all authenticated users
|
||||||
|
- [ ] User Management: visible to Owner and Admin only
|
||||||
|
- [ ] System Settings: visible to Owner only
|
||||||
|
- [ ] CMS Management: visible to all authenticated users
|
||||||
|
- [ ] Profile: visible to all authenticated users
|
||||||
|
- [ ] Logout: visible to all authenticated users
|
||||||
|
- [ ] The sidebar is responsive: collapses to an icon-only view or a hamburger menu on small screens
|
||||||
|
- [ ] The currently active route is highlighted in the sidebar
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### US-19: Toggle dark/light theme
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want to switch between dark and light themes, so that I can use the interface comfortably in different lighting conditions.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] A theme toggle button is present in the UI (sidebar footer or top bar)
|
||||||
|
- [ ] Clicking the toggle switches between light and dark mode immediately
|
||||||
|
- [ ] The chosen theme is persisted in `localStorage` under a well-named key (e.g. `cms-theme`)
|
||||||
|
- [ ] On app load, the persisted theme preference is applied before the first render (no flash)
|
||||||
|
- [ ] If no preference is stored, the system (OS) preference is used as default
|
||||||
|
- [ ] **Security**: Only theme preference is stored in localStorage — no auth data
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Epic: CMS Management (Placeholder)
|
||||||
|
|
||||||
|
### US-20: View CMS management placeholder page
|
||||||
|
**Persona**: Owner, Admin, User
|
||||||
|
|
||||||
|
As an authenticated user, I want to navigate to the CMS Management section, so that I know where CMS content features will be available in the future.
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- [ ] The `/cms` route renders a CMS Management page for all authenticated users
|
||||||
|
- [ ] The page displays a clear "Work in Progress" or "Coming Soon" message
|
||||||
|
- [ ] A brief description explains that CMS content modules will appear here
|
||||||
|
- [ ] The page uses the same layout as other pages (sidebar, header)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Features (Brief Notes — Out of Scope for v1)
|
||||||
|
|
||||||
|
- **Profile editing** (`/profile`): Change display name and password — backend endpoints not yet confirmed
|
||||||
|
- **Availability status management** (`/settings`): Allow Owner to set status to Available/Maintenance/Unavailable — requires CMS availability master module
|
||||||
|
- **User deactivation/editing** (`/users`): Deactivate or edit existing users — backend endpoints not yet confirmed
|
||||||
|
- **CMS content modules**: Actual content management pages — dependent on backend CMS modules being built
|
||||||
Reference in New Issue
Block a user