Files
GameList/TECH.md
Frank Tovar ae85c369ba
Some checks failed
CI / build-and-test (push) Has been cancelled
Add TECH kickoff blueprint from current architecture
2026-02-24 20:35:53 +01:00

12 KiB

TECH - Kickoff Blueprint from Pick'n'Play

This document extracts the implementation patterns, conventions, and guardrails from the current codebase so a new webapp can start with proven structure and avoid known pitfalls.

Scope covered:

  • Backend (Program.cs, Endpoints/*, Infrastructure/*, Data/*, Domain/*, Contracts/*)
  • Frontend (wwwroot/*)
  • Tooling and CI (scripts/*, .github/workflows/ci.yml, npm tooling)
  • Tests (GameList.Tests/*)
  • Review carryover (REVIEW.md unresolved topics)

1) Stack and baseline choices

  • ASP.NET Core Minimal API on .NET 10.
  • EF Core + SQLite in current project (single-node deployment).
  • Cookie authentication (HttpOnly, SameSite=Strict, secure in production).
  • Static frontend (HTML/CSS/JS modules), no frontend framework.
  • OpenAPI generated from backend and consumed by generated JS client.
  • xUnit integration-heavy test suite with in-memory SQLite 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 legacy compatibility retained.

2.5 Data and invariants

  • Strong DB model with explicit constraints:
    • Unique normalized username
    • Unique owner partial index
    • Unique vote key (PlayerId, SuggestionId)
    • Seeded singleton app state row
  • DB-level guardrails (trigger) complement app-level checks:
    • Suggestion limit enforced in DB (suggestion_limit_exceeded) to survive concurrent writes.
  • 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 Workflow and permission model

  • Phases (Suggest, Vote, Results) drive endpoint access and UX behavior.
  • Effective phase can be derived from persisted phase + global resultsOpen.
  • Reconciliation helper functions centralize phase alignment rules.
  • Admin abilities are intentionally constrained per operation (e.g., only specific transitions allowed).

Keep centralization of workflow rules. Avoid spreading phase/permission checks inline.

2.7 Frontend architecture

  • ES module 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.8 Frontend safety and rendering hygiene

  • Safe rendering helpers:
    • escapeHtml for template interpolation
    • safeUrl for links/media
  • Sensitive modal content set via textContent, not interpolated HTML.
  • Trusted output patterns covered by regression tests.

Maintain this as a non-negotiable standard for any user-supplied content path.

2.9 Testing strategy patterns

  • Full-stack integration tests via WebApplicationFactory.
  • Real migrations applied to in-memory SQLite 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.10 Tooling and contract discipline

  • OpenAPI generated during build (openapi/GameList.json).
  • JS 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 currently implemented

Use this as a reusable "starter scope menu" for the new app:

  • Auth:
    • register/login/logout
    • owner bootstrap via admin key
    • immutable display name post-registration
    • 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
    • phase next/prev
    • SSE state invalidation
    • etag conditional state reads
  • Suggestions:
    • create/update/delete/mine/all
    • phase gating + admin override behavior
    • suggestion cap + joker path
    • link metadata exposure
    • screenshot URL and reachability validation
  • Votes:
    • vote upsert
    • finalize/unfinalize
    • linked suggestion vote fan-out
    • conflict handling on concurrent insert/update
  • Results:
    • gated by phase + admin-open flag
    • ordered leaderboard with aggregates and voter metadata
    • per-user own vote context
  • Admin:
    • results open/close toggle with phase realignment
    • vote status panel
    • joker grant
    • player phase correction
    • admin role grant/revoke (owner protected)
    • player delete with cascades and password confirmation
    • link/unlink suggestions with vote reset and unfinalize behavior
    • reset/factory reset with password confirmation

4) REVIEW.md unresolved topics -> new-project design defaults

This section translates outstanding review risks into early decisions for the new app.

4.1 Data store scalability

Review concern:

  • SQLite bottlenecks under higher write concurrency and multi-node scaling.

New-project default:

  • Start with PostgreSQL (or SQL Server) for production profile.
  • Keep provider abstraction and provider-specific migration strategy from day one.
  • Keep SQLite only as local dev/test convenience if needed.

4.2 Workflow extensibility

Review concern:

  • Workflow transitions are hard-coded in many places.

New-project default:

  • Define transitions in a single state-machine table/model.
  • Drive backend authorization and frontend navigation from same transition metadata.
  • Add tests that validate the transition table itself.

4.3 Authorization model growth

Review concern:

  • Role booleans (IsAdmin, IsOwner) limit future permission expansion.

New-project default:

  • Use role/permission tables or claims-based capabilities.
  • Keep owner as a protected capability, not a special-case boolean spread across code.
  • Use policy-based authorization with explicit capability names.

4.4 Frontend maintainability

Review concern:

  • String-template-heavy UI + global mutable state can become fragile.

New-project default:

  • Move to TypeScript (or strict JSDoc typing) early.
  • Keep module boundaries by feature.
  • Keep explicit escaping/safe-url guards and DOM textContent standards.
  • If not using framework, introduce a small typed view-model layer.

4.5 In-memory cache bounds

Review concern:

  • Unbounded dictionaries may grow under high-cardinality traffic.

New-project default:

  • Replace unbounded maps with bounded MemoryCache (size + TTL + eviction).
  • For distributed deployments, use Redis with cardinality and TTL controls.

4.6 Linking/results query scaling

Review concern:

  • Link and result workflows currently pull full sets into memory.

New-project default:

  • Persist link-group ids and compute aggregates in SQL.
  • Add pagination/windowing for large result sets.
  • Benchmark query plans on realistic volumes.

4.7 External URL validation latency

Review concern:

  • Reachability validation happens synchronously on write path.

New-project default:

  • Accept user URL quickly, validate asynchronously (job queue/background worker), store validation status.
  • Optionally proxy or prefetch media through controlled media service.

5) Topics from REVIEW that are already fixed and should be carried forward

  • Polling amplification has been reduced through SSE + etag conditional reads.
  • CSRF protection is explicit (same-origin validation for authenticated mutating requests).
  • Password hashing is versioned and modernized (Argon2id current, transparent upgrades).
  • CSP is tightened compared to prior permissive baseline (no inline style allowance, no insecure image origins).
  • API drift risk reduced with OpenAPI generation + generated frontend client.

These are not optional add-ons; they should be baseline in the new app.

6) New-project starter checklist

  • Bootstrap:
    • choose production DB provider first
    • define transition/state-machine model before endpoint coding
    • define permission/capability model before admin features
  • 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.