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

170 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.