Update API and spec for linked voting

This commit is contained in:
2026-02-05 10:58:40 +01:00
parent 5d432c9d17
commit 6305985dad
2 changed files with 45 additions and 46 deletions

49
API.md
View File

@@ -1,38 +1,39 @@
# API Contract (Auth-enabled) # API Contract (auth-enabled)
All endpoints are JSON. Most routes require the HttpOnly cookie `player`, which is issued after successful register/login. Legacy player rows are given `legacy-xxxxxxxx` usernames during migration; they must register/login to get a valid auth cookie. All endpoints are JSON. Most routes require the HttpOnly `player` cookie issued after register/login. Admin access is granted via authenticated admin user or `X-Admin-Key`/`key` matching `ADMIN_PASSWORD`.
## Auth ## Auth
POST /api/auth/register POST /api/auth/register — accepts optional `adminKey` to set `IsAdmin=true`
POST /api/auth/login POST /api/auth/login
POST /api/auth/logout POST /api/auth/logout
- Register accepts optional `adminKey`; when it matches `ADMIN_PASSWORD`, the account is marked `IsAdmin=true` and can use admin APIs. If an `adminKey` is supplied but wrong (or ADMIN_PASSWORD unset), registration returns 400. ## State (requires auth)
GET /api/state — returns currentPhase (for caller), votesFinal, resultsOpen, updatedAt, counts (players/suggestions/votes)
## State GET /api/me — id, displayName, username, isAdmin, currentPhase, votesFinal
GET /api/state (public)
## Player (requires auth) ## Player (requires auth)
GET /api/me (returns id, displayName, username, isAdmin) POST /api/me/name — set display name (max 16 chars)
POST /api/me/name POST /api/me/phase/next — advance caller to next phase (Suggest→Vote→Results; Results gated by resultsOpen)
POST /api/me/phase/prev — admin-only move caller backward (Results→Vote→Suggest)
## Suggestions (requires auth + phase gating) ## Suggestions (requires auth + phase gating)
GET /api/suggestions/mine GET /api/suggestions/mine — own suggestions (Suggest phase)
POST /api/suggestions POST /api/suggestions — create (name required ≤100; max 5 per player; validates screenshot URL)
DELETE /api/suggestions/{id} PUT /api/suggestions/{id} — update (non-admin: own suggestion; title locked after Suggest)
PUT /api/suggestions/{id} (non-admin: own suggestion, Suggest phase only; admin: any time, any suggestion) DELETE /api/suggestions/{id} — delete (non-admin only in Suggest; admin any time)
GET /api/suggestions/all GET /api/suggestions/all — all suggestions (from Vote onward), includes author, link metadata
## Votes (requires auth + phase gating) ## Votes (requires auth + Vote phase)
GET /api/votes/mine GET /api/votes/mine
POST /api/votes POST /api/votes — upsert vote; if suggestion is in a linked group, applies the same score to all linked siblings
POST /api/votes/finalize — `{ final: bool }` toggles callers finalized status (blocks further vote edits when true)
## Results (requires auth + phase gating) ## Results (requires auth + Results phase + resultsOpen)
GET /api/results GET /api/results — leaderboard with totals, counts, averages, callers vote, media/links, link metadata
## Admin (requires admin account or admin key) ## Admin (admin auth or admin key)
POST /api/admin/phase POST /api/admin/results — `{ resultsOpen: bool }` locks/unlocks results and aligns player phases
POST /api/admin/reset GET /api/admin/vote-status — readiness overview (who finalized)
POST /api/admin/factory-reset POST /api/admin/link-suggestions — `{ sourceSuggestionId, targetSuggestionId }`; merges vote groups during Vote, clears votes in the linked group, unfinalizes affected players
POST /api/admin/reset — clear suggestions/votes; keep players; reset phases/vote-final flags
Admin APIs accept either an authenticated admin user (cookie) or, for compatibility, `X-Admin-Key`/`key` matching `ADMIN_PASSWORD`. POST /api/admin/factory-reset — wipe players, suggestions, votes, state

42
SPEC.md
View File

@@ -1,36 +1,34 @@
# Pick'n'Play — Product Spec (MVP) # Pick'n'Play — Product Spec (current)
## Goal ## Goal
A micro web app for a closed Discord group (48 players) to decide what co-op game to play using a phased process: Help a small Discord group (48 players) pick a co-op game via phased flow:
1. Suggest (blind) 1. Suggest (blind)
2. Reveal (discuss) 2. Vote (blind, 010 sliders)
3. Vote (blind scoring 010) 3. Results (leaderboard)
4. Results (leaderboard)
## MVP Scope ## Scope
- Single shared instance - Single shared instance
- Username/password login (cookie holds auth token after register/login) - Username/password login (cookie auth)
- Organizer-controlled phase switching (admin accounts flagged via admin key at registration) - Admins flagged via admin key at registration
- Per-user phase tracking; admins can move themselves backward, everyone can move forward (subject to admin “results open” toggle)
## Suggest Phase ## Suggest Phase
- Up to 3 suggestions per player - Up to **5 suggestions** per player
- Name required - Name required; optional genre, description, screenshot URL, YouTube URL, external game link, min/max players
- Optional genre, description, screenshot URL, YouTube URL - Players see only their own suggestions until voting
- Players see only their own suggestions - Screenshots validated as reachable images
## Reveal Phase
- All suggestions visible
- Suggester name shown
- Suggestions locked
## Vote Phase ## Vote Phase
- All suggestions visible with authors
- Score each suggestion 010 - Score each suggestion 010
- Players see only their own votes - Players see only their own votes; can finalize/unfinalize their ballot
- **Linked games**: admins can link duplicates; linked games share a vote group. Moving a slider on one updates all linked siblings.
- Linking two games clears votes for the linked group and unfinalizes affected players
## Results Phase ## Results Phase
- Totals, vote count, optional averages - Visible only after admin enables results; players auto-advance when opened
- Sorted by total descending - Leaderboard sorted by average score; shows totals, counts, players own vote, and links/media
## Non-functional ## Non-functional
- Desktop + mobile usable - Desktop + mobile friendly
- IIS-hosted - Runs on IIS; SQLite via EF Core