# TECH - Kickoff Blueprint ## 0) Current scaffold status - Root solution: `RpgRoller.sln` - Backend/full-stack project: `RpgRoller` (Minimal API + static `wwwroot` frontend) - Frontend source: `RpgRoller/frontend` (TypeScript) - Test project: `RpgRoller.Tests` (xUnit + `WebApplicationFactory` integration tests) - OpenAPI source: `openapi/RpgRoller.json` - Generated client source: `RpgRoller/frontend/generated/api-client.ts` - Generated client output: `RpgRoller/wwwroot/generated/api-client.js` - Local CI parity entrypoint: `scripts/ci-local.ps1` ## 1) Stack and baseline choices - ASP.NET Core Minimal API on .NET 10. - EF Core + Database in current project (single-node deployment). - Cookie authentication (`HttpOnly`, `SameSite=Strict`, secure in production). - A minimal frontend framework supporting mixing 3D graphics with 2D elements, or a modern framework-less alternative (HTMl/CSS/TypeScript). - OpenAPI generated from backend and consumed by generated client. - xUnit integration-heavy test suite with in-memory Database and coverage gates. ## 2) Architecture patterns to keep ### 2.1 API shape and layering - Route mapping in thin endpoint modules (`MapXEndpoints` per feature area). - Domain logic in workflow services (`*WorkflowService`) instead of endpoint lambdas. - Service responses normalized via `ServiceResult` + `ServiceError`, then mapped to HTTP at the edge. - Consistent `ProblemDetails` payloads with `error` extension for machine-usable errors. - Endpoint-level concerns handled by endpoint filters (`AdminOnlyFilter`, `PhaseRequirementFilter`, `PhaseOrJokerFilter`). Keep this split: - Endpoint adapters: auth, deserialization, HTTP mapping only. - Workflow services: validation, query/update rules, transactions. - Helpers: shared utility and security-sensitive routines. ### 2.2 Middleware pipeline discipline - Security and behavior depend on middleware ordering; keep explicit ordering. - Important current order: 1. Forwarded headers 2. Rate limiter 3. HSTS + HTTPS redirect (prod) 4. Security headers writer 5. Base path 6. Global exception handling 7. Authentication 8. Ensure player still exists 9. CSRF origin/referer checks 10. Authorization 11. State change notifier middleware 12. Static files 13. Endpoint mapping ### 2.3 State synchronization - Event-driven invalidation with SSE (`/api/events/state`) plus heartbeats. - Conditional reads for state (`ETag` + `If-None-Match`) to return `304`. - In-process notifier (`StateChangeNotifier`) with monotonic version and etag stamp. - Mutation middleware (`StateChangeNotificationMiddleware`) emits invalidation only for successful mutating API calls. This pattern is a strong baseline for low to medium scale and should be the default in the new app. ### 2.4 Security baseline - Cookie auth with short/medium session sliding expiration plus absolute lifetime cap. - Explicit same-origin CSRF checks for authenticated mutating API calls. - Rate limiting on auth-sensitive and admin-sensitive surfaces with custom `429` payload. - Security headers on all responses (`CSP`, `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Permissions-Policy`). - Forwarded headers restricted to configured trusted proxies/networks only. - Owner/admin protection rules enforced in business logic and DB constraints. - Destructive admin operations require password re-confirmation. - Password hashing is versioned and supports transparent upgrade on successful auth. - Current hash defaults to Argon2id, with forward compatibility retained via versioning. ### 2.5 Data and invariants - Strong DB models - DB-level guardrails (trigger) to complement app-level checks - EF patterns: - `AsNoTracking()` for read-only queries - `ExecuteUpdateAsync` / `ExecuteDeleteAsync` for efficient bulk operations - Explicit transactions for multi-step destructive/admin operations - Conflict handling around unique constraints ### 2.6 Frontend architecture - modules split by concern: - API wrapper - Data loaders - UI composition - Feature-specific renderers/handlers - Shared utils and runtime dependency injection - Single runtime state object with deliberate clear/reset logic. - Refresh scheduler: - Serialized refreshes (no overlap) - Adaptive polling backoff - SSE-triggered immediate refresh for state mutations - Visibility-aware refresh suppression - API client is generated from OpenAPI operation ids, not handwritten endpoints. - Internationalization: - translation file validation at startup - language-specific FAQ markdown loading with fallback to default language ### 2.7 Testing strategy patterns - Full-stack integration tests via `WebApplicationFactory`. - Real migrations applied to in-memory Database during test host startup. - HTTP side effects mocked deterministically (`StubHttpMessageHandler` and `IHttpClientFactory` replacement). - Coverage-focused tests for: - auth/security rules - middleware behavior - filter behavior - link/vote/result edge cases - OpenAPI operation id stability - CI-local parity script (`scripts/ci-local.ps1`) mirrors pipeline flow. ### 2.8 Tooling and contract discipline - OpenAPI generated during build (`openapi/RpgRoller.json`). - Client generated from OpenAPI with required operation-id checks. - Separate lint + format + tests + coverage threshold checks. - Build configured with warnings as errors in CI/local script. ## 3) Concrete feature set Use this as a reusable "starter scope menu" for the new app: - Auth: - register/login/logout - owner bootstrap via admin key - auth options endpoint for registration UX - Identity/session: - cookie claim identity with admin claim - stale/deleted-account cookie invalidation - absolute session lifetime enforcement - State: - `/api/state`, `/api/me` - SSE state invalidation - etag conditional state reads ## 4) New-project starter checklist - Security: - cookie or token strategy finalized with CSRF model - rate limiting partitions and thresholds defined - strict CSP and security headers in first commit - versioned password hashing with migration strategy - trusted proxy/host settings explicit - Contract: - OpenAPI generation enabled in build - generated client wired into frontend - operation-id stability tested - Data integrity: - enforce critical invariants both app-side and DB-side - transaction boundaries for multi-entity admin actions - Frontend: - module boundaries and state refresh model defined - escaping/url-safe helpers mandatory - i18n structure and fallback behavior in place - Testing: - integration test host with real migrations - deterministic stubs for network dependencies - coverage gate enforced in local + CI scripts ## 7) Keep/avoid quick reference Keep: - Thin endpoints + workflow services. - Shared service result abstraction. - Explicit middleware order. - SSE + ETag state sync. - Generated API client from OpenAPI. - DB-enforced invariants. - Regression tests for security-sensitive UI rendering. Avoid: - Hard-coded workflow transitions scattered in backend/frontend. - Boolean-only role model for long-term products. - Unbounded in-memory caches. - Synchronous external network checks on hot write paths. - Manual API contract duplication between docs/frontend/backend.