Files
gridpilot.gg/plans/league-admin-mvp-plan.md
2025-12-28 12:04:12 +01:00

8.0 KiB
Raw Blame History

League Admin MVP Plan (Admin Acquisition)

Goal

Finish all league-management tools needed to attract and retain league admins by making three workflows fully functional, permission-correct, and data-backed:

  • Schedule builder + publishing
  • Roster + join requests + roles
  • Results import + standings recompute

This plan prioritizes fixing auth/permissions and API contracts first, because they block all three workflows.


What we observed (current state)

Website gaps (data + correctness)

  • Schedule UI assumes a rich race object but contract is effectively unknown[] and uses Date methods; this is unsafe and likely to break on real API responses.
  • Standings page uses real standings + memberships, but fills missing stats fields with placeholders (avgFinish, penaltyPoints, bonusPoints, racesStarted).
  • League settings page checks admin via a membership cache, which can falsely deny access if cache isnt hydrated.
  • Stewarding data fetch is N+1: for each race, fetch protests + penalties, which wont scale.
  • Wallet page is explicitly demo/prototype: hardcoded season/account and static breakdown data; also not admin-gated.

API gaps (permissions + contract + admin tooling)

  • Actor identity is inconsistent:
    • Some operations take a performer/admin ID from request data.
    • Some operations hardcode an admin ID.
    • Some areas infer identity from session.
  • Swagger/OpenAPI generation exists in code, but the committed OpenAPI artifact is stale/empty, so it cannot serve as a reliable contract source right now.
  • League schedule endpoint exists, but it does not appear to deliver a typed, UI-ready schedule contract that the website expects.
  • League admin tooling endpoints exist in fragments (join requests, memberships, config, wallet, protests), but are missing end-to-end admin workflows (schedule editing/publishing, results import flows, etc.) and consistent authorization.

Definition of Done (MVP-wide)

  1. Every admin action is authorized server-side based on the authenticated session identity (no client-supplied performer IDs; no hardcoded admin IDs).
  2. Website uses stable, generated types for API DTOs; no unknown[] schedule data.
  3. Admin can:
    • Create and publish a season schedule (add/edit/remove races).
    • Manage roster and join requests (approve/reject, roles, remove members; enforce capacity).
    • Import results and see standings update per season.
  4. Performance guardrails:
    • No N+1 requests for league stewarding over races; provide aggregate endpoint(s).
  5. Quality gates pass in implementation phase: lint, typecheck, tests.

Gap matrix (workflow → missing pieces)

1) Auth/Permissions (cross-cutting)

Missing / must improve:

  • A single canonical “actor” model (session userId vs driverId mapping).
  • Consistent admin/owner authorization checks for all league write operations.
  • Removal of performer IDs from all public contracts.

Dependencies:

  • Session endpoint exists; need to decide how driver identity is represented in session and how its resolved.

Deliverable:

  • A short doc describing actor model and permission rules, then code changes that enforce them.

2) Schedule builder + publishing

Missing / must improve:

  • Contract: schedule DTO must be typed and use ISO strings for dates; website parses to Date in view models.
  • Admin endpoints: create/update/delete schedule races, associate to season, publish/unpublish.
  • UI: schedule admin interface for managing races.
  • Driver registration status: schedule should reflect registration per driver without relying on ad-hoc “isRegistered” fields.

Deliverable:

  • Season-aware schedule read endpoint + schedule write endpoints + website schedule editor.

3) Roster + join requests + roles

Missing / must improve:

  • Join requests list exists, but approval/rejection must be permission-correct and actor-derived.
  • Role changes and member removal must be actor-derived.
  • UI: admin roster page (requests inbox + members list + role controls + remove).
  • Capacity/status enforcement at the API layer.

Deliverable:

  • A single roster admin experience that matches API rules.

4) Results import + standings recompute

Missing / must improve:

  • Results import UX in website (admin flow) and stable API contract(s) for import + recompute.
  • Standings should be season-aware and include fields the UI currently fakes or omits.
  • Ensure penalties/protests can affect standings where applicable.

Deliverable:

  • Admin results import page + standings page backed by season-aware API.

5) Stewarding

Missing / must improve:

  • Aggregate league stewarding endpoint (races + protests + penalties) to avoid N+1 behavior.
  • Confirm admin-only access and correct actor inference for review/apply penalty.

Deliverable:

  • Single endpoint powering stewarding page, plus minimal UI updates.

6) Wallet (scope decision required)

Recommendation:

  • Keep wallet “demo-only” for MVP, but make it permission-correct and remove hardcoded season/account IDs.
  • Replace static breakdown sections with values derived from the wallet endpoint, or hide them behind a “coming soon” section.

Deliverable:

  • Admin-only wallet access + remove hardcoded values + clearly labeled non-MVP parts.

Proposed execution plan (implementation-ready)

Phase 0 — Contract & identity foundation (must be first)

  • Define the actor model:
    • What the session contains (userId, driverId, roles).
    • How userId maps to driverId (1:1 or indirect).
    • What “league admin” means and where its validated.
  • Update all league write endpoints to infer actor from session and enforce permissions.
  • Remove any hardcoded actor IDs in services.
  • Make OpenAPI generation reliable and used as contract source.

Acceptance criteria:

  • No API route accepts performer/admin IDs for authorization.
  • OpenAPI doc contains real paths and is regeneratable in CI/local.

Phase 1 — Normalize DTOs + website type safety

  • Fix website type generation flow so generated DTOs exist and match API.
  • Fix schedule DTO contract:
    • Race schedule entries use ISO strings.
    • Website parses and derives isPast/isUpcoming deterministically.
    • Registration state is returned explicitly or derived via a separate endpoint.

Acceptance criteria:

  • No schedule-related unknown casts remain.
  • Schedule page renders with real API data and correct date handling.

Phase 2 — Admin schedule management

  • Implement schedule CRUD endpoints for admins (season-scoped).
  • Build schedule editor UI (create/edit/delete/publish).
  • Ensure driver registration still works.

Acceptance criteria:

  • Admin can publish a schedule and members see it immediately.

Phase 3 — Roster and join requests

  • Ensure join request approve/reject is actor-derived and permission-checked.
  • Provide endpoints for roster listing, role changes, and member removal.
  • Build roster admin UI.

Acceptance criteria:

  • Admin can manage roster end-to-end without passing performer IDs.

Phase 4 — Results import and standings

  • Implement results import endpoints and recompute trigger behavior (manual + after import).
  • Make standings season-aware and include additional fields needed by the UI (or simplify UI to match real data).
  • Build results import UI and update standings UI accordingly.

Acceptance criteria:

  • Import updates standings deterministically and is visible in UI.

Phase 5 — Stewarding performance + wallet cleanup

  • Replace N+1 stewarding fetch with aggregate endpoint; update UI to use it.
  • Wallet: admin-only gating; remove hardcoded season/account; hide or compute static sections.

Acceptance criteria:

  • Stewarding loads in bounded requests.
  • Wallet page does not contain hardcoded season/account IDs.

Phase 6 — Quality gates

  • Run lint, typecheck, and tests until clean for all changes introduced.

Key decisions / assumptions (explicit)

  • “Admin acquisition” MVP includes all three workflows and therefore requires solid permissions and contracts first.
  • Wallet is not a blocker for admin acquisition but must not mislead; keep demo-only unless you want it fully MVP.