Changes backend in preparation for frontend work
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# Code Generation Plan — Unit 0: Backend Prerequisites
|
||||
|
||||
This plan defines all concrete steps to implement Unit 0 (backend prerequisites) safely in the brownfield .NET solution. Follow the numbered steps in order and check them off during execution.
|
||||
|
||||
## Unit Context
|
||||
- Unit: Unit 0 — Backend Prerequisites
|
||||
- Type: .NET backend changes (API + Core + Module Identity)
|
||||
- Stories (traceability):
|
||||
- US-02 (partial) — Auth: secure refresh-token via httpOnly cookie
|
||||
- US-06 (partial) — Session lifecycle: refresh & revoke
|
||||
- US-07 (partial) — Error handling & API consistency
|
||||
- Dependencies: None (prerequisite unit for all frontend integration)
|
||||
- Related NFRs: NFR-U0-01..07 (security cookie, CORS, rate limiting, reliability, ProblemDetails, maintainability, tests)
|
||||
|
||||
## Code Locations (brownfield)
|
||||
- Application Code:
|
||||
- src/SlpModularCms.Api/Program.cs
|
||||
- src/SlpModularCms.Api/Extensions/ServiceCollectionExtensions.cs
|
||||
- src/SlpModularCms.Modules.Identity/Controllers/AuthController.cs
|
||||
- src/SlpModularCms.Core/Exceptions/GlobalExceptionHandler.cs
|
||||
- src/SlpModularCms.Core/Exceptions/ApiErrorResponse.cs (to be removed/replaced)
|
||||
- src/SlpModularCms.Core/Identity/Models/TokenResponse.cs
|
||||
- src/SlpModularCms.Core/Identity/Models/IdentityRequests.cs (contains RefreshTokenRequest)
|
||||
- src/SlpModularCms.Core/Identity/Services/IAuthService.cs
|
||||
- src/SlpModularCms.Core/Identity/Services/AuthService.cs
|
||||
- Configuration:
|
||||
- src/SlpModularCms.Api/appsettings.json
|
||||
- src/SlpModularCms.Api/appsettings.Development.json
|
||||
- Tests:
|
||||
- src/SlpModularCms.Core.Tests/Identity/* (extend where feasible)
|
||||
- NEW: src/SlpModularCms.Modules.Identity.Tests/ (controller tests) [optional, recommended]
|
||||
|
||||
## PART 1 — Planning Checklist
|
||||
- [x] Read all Unit 0 design artifacts (business-rules.md, nfr-requirements.md, nfr-design/*)
|
||||
- [x] Validate repository state and file presence against paths above
|
||||
- [x] Confirm appsettings three-file pattern (dotnet-appsettings skill) and add missing sections
|
||||
|
||||
## PART 2 — Generation Steps (execute in order)
|
||||
|
||||
### Step 1 — API Routing & CORS
|
||||
- [x] Update route on AuthController to `[Route("api/v1/auth")]` (currently `[Route("[controller]")]`)
|
||||
- [x] Add `AddCmsCors()` in ServiceCollectionExtensions to read `Cors:AllowedOrigins` and configure explicit allowlist + `AllowCredentials()`
|
||||
- [x] Register CORS BEFORE `UseAuthentication`/`UseAuthorization` in Program.cs pipeline
|
||||
- [x] Add `Cors` section to appsettings.json and appsettings.Development.json per logical-components.md
|
||||
|
||||
### Step 2 — Rate Limiting (Global Middleware)
|
||||
- [x] Add `AddCmsRateLimiting()` to register Fixed window (login: 5/min) and Sliding window (refresh: 20/min)
|
||||
- [x] Register `UseRateLimiter()` in Program.cs before CORS (per design ordering)
|
||||
- [x] Ensure 429 responses include standard headers (Retry-After) where applicable
|
||||
|
||||
### Step 3 — Refresh Token in httpOnly Cookie
|
||||
- [x] Modify `AuthController.Login` to set `refreshToken` cookie (`HttpOnly`, `Secure=request.IsHttps` in prod, `SameSite=Strict`, Path=/api/v1/auth)
|
||||
- [x] Modify `AuthController.Refresh` to read refresh token from `Request.Cookies["refreshToken"]` (remove body model)
|
||||
- [x] Modify `AuthController.Revoke` to clear the cookie using same Path and expire to Epoch
|
||||
|
||||
### Step 4 — Remove Request Body Model for Refresh
|
||||
- [x] Delete `RefreshTokenRequest` from `IdentityRequests.cs`
|
||||
- [x] Update method signatures & usages accordingly
|
||||
|
||||
### Step 5 — Service Contract Adjustments (AuthService/IAuthService)
|
||||
- [x] Change refresh flow contract to accept ONLY the refresh token (no access token in body)
|
||||
- [x] Implement repository lookup by refresh token and user, with rotation semantics intact
|
||||
- [x] Ensure reuse-detection logic (mark used, revoke all on reuse) remains functional
|
||||
|
||||
### Step 6 — Response Model & Payload Alignment
|
||||
- [x] Update `TokenResponse` to remove `RefreshToken` from the response body
|
||||
- [x] Extend response body to include: `accessToken`, `expiresAt`, and `user` object: `{ id, email, name, role, isActive }`
|
||||
- [x] Compute `name` as `DisplayName ?? Email` (see BR-U0-07)
|
||||
- [x] Ensure controllers only return allowed fields; NEVER return the refresh token
|
||||
|
||||
### Step 7 — Revoke Endpoint Authorization Policy
|
||||
- [x] Implement per BR-U0-05: remove `[Authorize]` from `POST /api/v1/auth/revoke` to allow idempotent logout even if access token expired
|
||||
|
||||
### Step 8 — ProblemDetails Migration (RFC 9457)
|
||||
- [x] Replace custom `ApiErrorResponse` with standardized `ProblemDetails` in `GlobalExceptionHandler`
|
||||
- [x] Map known exceptions to appropriate status codes (Unauthorized, 429, etc.)
|
||||
- [x] Remove/retire `ApiErrorResponse` usages
|
||||
|
||||
### Step 9 — Configuration (dotnet-appsettings)
|
||||
- [x] Add/verify `Cors` and `RateLimiting` sections in `appsettings.json` and `appsettings.Development.json`
|
||||
- [x] Do NOT store secrets; follow three-file pattern; add README notes for `appsettings.local.json` overrides
|
||||
|
||||
### Step 10 — Tests
|
||||
- [x] Update/extend unit tests to cover:
|
||||
- Cookie set on successful login/refresh
|
||||
- Cookie cleared on revoke
|
||||
- 401 when cookie missing on refresh
|
||||
- Rate limit behavior (mock/stub)
|
||||
- [x] Optionally add `SlpModularCms.Modules.Identity.Tests` for controller-level tests; otherwise, add minimal WebApplicationFactory-based tests in an existing test project
|
||||
|
||||
### Step 11 — Documentation & README
|
||||
- [x] Update backend README with local dev instructions (CORS origin, HTTPS dev certs, cookie behavior)
|
||||
- [x] Update cross-feature docs if affected (e.g., slp-modular-cms-api endpoints, auth flow)
|
||||
|
||||
### Step 12 — Build & Smoke Verification
|
||||
- [x] Build solution
|
||||
- [x] Manual smoke test of auth endpoints: login → cookie present; refresh → cookie rotates; revoke → cookie cleared; CORS preflight succeeds
|
||||
|
||||
## Story Traceability Matrix
|
||||
- US-02 (partial): Steps 3–6
|
||||
- US-06 (partial): Steps 3–7, 12
|
||||
- US-07 (partial): Steps 8–12
|
||||
|
||||
## Definition of Done (Unit 0)
|
||||
- [ ] No refresh token in any response body
|
||||
- [ ] Refresh token exclusively in httpOnly cookie
|
||||
- [ ] CORS allowlist enforced and credentials enabled
|
||||
- [ ] Global rate limiting active with configured windows
|
||||
- [ ] ProblemDetails standardized for all auth-related errors
|
||||
- [ ] Tests updated/added per NFR-U0-07
|
||||
- [ ] README updated with local dev guidance
|
||||
@@ -2,7 +2,13 @@
|
||||
|
||||
Welkom bij de NFR Design fase voor Unit 0. In deze fase vertalen we de NFR-eisen naar een concreet technisch ontwerp.
|
||||
|
||||
Beantwoord de onderstaande vragen om het plan te valideren:
|
||||
- [x] Analyseer antwoorden in `unit-0-nfr-design-plan.md`
|
||||
- [x] Genereer NFR Design artefacten voor Unit 0
|
||||
- [x] `nfr-design-patterns.md`
|
||||
- [x] `logical-components.md`
|
||||
- [x] Valideer artefacten tegen `common/content-validation.md` en `common/mermaid-diagram-standards.md`
|
||||
- [x] Update `audit.md` en `aidlc-state.md`
|
||||
- [x] Presenteer voltooiingsbericht en vraag om goedkeuring voor de volgende stap (Code Generation)
|
||||
|
||||
## Vraag 1: CORS Implementation Details
|
||||
A) Custom `CorsPolicy`
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# Functional Design Plan — Unit 1: Project Scaffold & Infrastructure
|
||||
|
||||
## Unit Context
|
||||
- Unit: Unit 1 — Project Scaffold & Infrastructure
|
||||
- Type: Frontend (Vite + React + TypeScript)
|
||||
- Depends on: Unit 0 (CORS + cookie-based auth ready)
|
||||
- Goals:
|
||||
- Initialize frontend workspace with TanStack Router, shadcn/ui, Tailwind v4
|
||||
- Set primary color to `#ac0000`
|
||||
- Provide `ApiClient` and `AuthContext` foundations aligned with cookie-based auth (httpOnly refresh cookie, access token in memory)
|
||||
|
||||
## Plan Checklist
|
||||
- [ ] Confirm scaffold strategy and tools via questions below
|
||||
- [ ] Generate folder structure (`src/api`, `src/auth`, `src/components`, `src/routes`)
|
||||
- [ ] Install and configure dependencies (TanStack Router, @tanstack/react-query, Tailwind v4, shadcn/ui)
|
||||
- [ ] Configure Tailwind theme with primary color `#ac0000`
|
||||
- [ ] Initialize TanStack Router with root route and placeholders
|
||||
- [ ] Create `AuthContext` (in-memory access token + user) and `useAuth` hook
|
||||
- [ ] Create `ApiClient` (fetch wrapper) with `credentials: 'include'` and 401 handling
|
||||
- [ ] Add `.env.example` with `VITE_API_BASE_URL`
|
||||
- [ ] README: local dev instructions
|
||||
|
||||
---
|
||||
|
||||
Please answer the following questions by filling in the letter after each `[Answer]:` tag.
|
||||
|
||||
## Question 1: Package manager
|
||||
A) pnpm (recommended)
|
||||
B) npm
|
||||
C) yarn
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Question 2: Router choice
|
||||
A) TanStack Router (required by NFR-01)
|
||||
B) React Router
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Question 3: UI foundation
|
||||
A) Tailwind v4 + shadcn/ui (recommended)
|
||||
B) Tailwind v4 only (no shadcn/ui)
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Question 4: Primary color integration (`#ac0000`)
|
||||
A) Tailwind theme config (extend colors + use via utility classes)
|
||||
B) CSS variables (root-level var, consumed by components)
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Question 5: HTTP client layer
|
||||
A) Fetch wrapper (`ApiClient`) with `credentials: 'include'` + JSON helpers (recommended)
|
||||
B) Axios instance with `withCredentials: true`
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Question 6: API base URL source
|
||||
A) `import.meta.env.VITE_API_BASE_URL` (from `.env`)
|
||||
B) Derive from `window.location.origin` + `/api`
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Question 7: Session bootstrap behavior
|
||||
A) On app mount, attempt silent refresh (uses httpOnly cookie) to hydrate `AuthContext` (recommended)
|
||||
B) Do not auto-refresh on mount; rely on login flow and 401 handling
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
|
||||
## Question 8: Linting/formatting baseline
|
||||
A) ESLint (recommended) + Prettier with sensible defaults
|
||||
B) ESLint only
|
||||
C) None for now
|
||||
X) Other (please describe after the [Answer]: tag below)
|
||||
|
||||
[Answer]:
|
||||
@@ -0,0 +1,62 @@
|
||||
# Logical Components — Unit 0: Backend Prerequisites
|
||||
|
||||
The following logical components and configuration structures are defined to support the NFR implementation.
|
||||
|
||||
## 1. Middleware Ordering (Pipeline Design)
|
||||
The order of middleware registration is critical for security and performance. The pipeline is configured in `Program.cs`.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Start((Start)) --> Exc[GlobalExceptionHandler]
|
||||
Exc --> RL[Rate Limiter]
|
||||
RL --> CORS[CORS Middleware]
|
||||
CORS --> Auth[Authentication]
|
||||
Auth --> Map[Endpoint Mapping]
|
||||
Map --> End((End))
|
||||
|
||||
classDef infra fill:#cbd5e0,stroke:#1a202c,stroke-width:2px,color:#1a202c;
|
||||
classDef security fill:#feb2b2,stroke:#742a2a,stroke-width:2px,color:#742a2a;
|
||||
classDef core fill:#9ae6b4,stroke:#22543d,stroke-width:2px,color:#22543d;
|
||||
class Start,End,Map infra;
|
||||
class Exc,RL,CORS,Auth security;
|
||||
```
|
||||
|
||||
Text alternative: Sequence of middleware in the ASP.NET Core pipeline (colored nodes indicate role).
|
||||
|
||||
## 2. Configuration Structure (appsettings.json)
|
||||
Following the `dotnet-appsettings` skill pattern, the configuration for NFRs is centralized.
|
||||
|
||||
### CORS Configuration
|
||||
```json
|
||||
"Cors": {
|
||||
"AllowedOrigins": [
|
||||
"https://localhost:5173"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Rate Limiting Configuration
|
||||
```json
|
||||
"RateLimiting": {
|
||||
"Login": {
|
||||
"PermitLimit": 5,
|
||||
"WindowSeconds": 60
|
||||
},
|
||||
"Refresh": {
|
||||
"PermitLimit": 20,
|
||||
"WindowSeconds": 60
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Extension Methods
|
||||
To keep `Program.cs` clean, logical components are encapsulated in `ServiceCollectionExtensions.cs`.
|
||||
|
||||
| Component | Responsibility |
|
||||
|-----------|----------------|
|
||||
| `AddCmsCors()` | Configures the CORS policy based on settings. |
|
||||
| `AddCmsRateLimiting()` | Defines the Fixed and Sliding window policies for auth. |
|
||||
| `AddCmsExceptionHandling()` | Registers the `GlobalExceptionHandler` and ProblemDetails. |
|
||||
|
||||
## 4. ProblemDetails Integration
|
||||
The `GlobalExceptionHandler` will be modified to fully replace the custom `ApiErrorResponse` with standard `ProblemDetails` as the return type. No backward compatibility for the old error format is required.
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# NFR Design Patterns — Unit 0: Backend Prerequisites
|
||||
|
||||
Non-functional requirements are addressed using the following design patterns and implementation strategies.
|
||||
|
||||
## Resilience & Protection Patterns
|
||||
|
||||
### 1. Global Rate Limiting Pipeline
|
||||
To protect the authentication endpoints from brute-force and DoS attacks, a global rate limiting pipeline is implemented using the built-in ASP.NET Core `Microsoft.AspNetCore.RateLimiting` middleware.
|
||||
|
||||
- **Fixed Window Pattern (Login)**:
|
||||
- Scoped to `POST /api/v1/auth/login`.
|
||||
- Limit: 5 requests per 1 minute.
|
||||
- Partitioned by Client IP Address.
|
||||
- **Sliding Window Pattern (Refresh)**:
|
||||
- Scoped to `POST /api/v1/auth/refresh`.
|
||||
- Limit: 20 requests per 1 minute.
|
||||
- Partitioned by Client IP Address.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Client[Client Request] --> RL[Rate Limiter Middleware]
|
||||
RL -- Limit Exceeded --> 429[429 Too Many Requests]
|
||||
RL -- Within Limit --> Pipeline[Authentication Pipeline]
|
||||
|
||||
classDef client fill:#fef3c7,stroke:#92400e,stroke-width:2px,color:#92400e;
|
||||
classDef security fill:#feb2b2,stroke:#742a2a,stroke-width:2px,color:#742a2a;
|
||||
classDef success fill:#c6f6d5,stroke:#22543d,stroke-width:2px,color:#22543d;
|
||||
class Client client;
|
||||
class RL,429 security;
|
||||
class Pipeline success;
|
||||
```
|
||||
|
||||
Text alternative: Flow showing Rate Limiter Middleware intercepting requests and either returning 429 or passing to the pipeline (colored nodes indicate role).
|
||||
|
||||
## Security Patterns
|
||||
|
||||
### 2. Cross-Origin Resource Sharing (CORS) Policy
|
||||
CORS is configured via a strongly-typed `ServiceCollectionExtensions` method to ensure consistent application of security rules.
|
||||
|
||||
- **Pattern**: Explicit Origin Allowlist.
|
||||
- **Logic**: Origin is validated against `Cors:AllowedOrigins` in `appsettings.json`.
|
||||
- **Requirement**: `AllowCredentials()` is mandatory to support the `httpOnly` Refresh Token cookie cross-origin.
|
||||
|
||||
### 3. Secure Cookie Pattern (Refresh Token)
|
||||
The Refresh Token is stored using a multi-layered security approach:
|
||||
- **HttpOnly**: Prevents access via JavaScript (XSS protection).
|
||||
- **Secure**: Ensures the cookie is only transmitted over HTTPS (In production).
|
||||
- **SameSite=Strict**: Prevents the browser from sending the cookie with cross-site requests (CSRF protection).
|
||||
- **Scoped Path**: Path is restricted to `/api/v1/auth` to minimize exposure.
|
||||
|
||||
## Performance & Reliability Patterns
|
||||
|
||||
### 4. Standardized RFC 9457 Error Handling
|
||||
Existing `GlobalExceptionHandler` is extended to return `ProblemDetails` conform RFC 9457. This ensures client-side libraries can predictably parse error responses.
|
||||
|
||||
- **Mapping**: Specific exceptions (e.g. `UnauthorizedAccessException`, `RateLimitRejectedException`) are mapped to their corresponding HTTP status codes.
|
||||
- **Safety**: Stack traces are only included in `Development` environment.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Client #fef3c7
|
||||
participant M as Middleware/Controller #c6f6d5
|
||||
participant H as GlobalExceptionHandler #feb2b2
|
||||
|
||||
C->>M: Request
|
||||
M-->>M: Error Occurs
|
||||
M->>H: Catch Exception
|
||||
H->>C: ProblemDetails (JSON)
|
||||
```
|
||||
|
||||
Text alternative: Sequence diagram showing how exceptions are caught by the GlobalExceptionHandler and returned as ProblemDetails to the client (colored participants indicate role).
|
||||
Reference in New Issue
Block a user