Files
RpgRoller/TECH.md

7.2 KiB

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<T> + 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.