Review: Admin queue view for Marcus

review-814-2026-04-03 Doc

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — Standalone
  • [x] Repo — forgejo_admin/twitch-2k-wager
  • [x] User Story — As Marcus (operator), wants to see paid challengers + gamertags
  • [x] Context — adequate operator motivation, ADMIN_SECRET auth decision stated
  • [x] File Targets — 3 new files specified
  • [x] Acceptance Criteria — 7 items
  • [x] Test Expectations — 3 items
  • [x] Constraints — present (auth pattern, dark theme, minimal)
  • [x] Checklist — present
  • [x] Related — references #12, story note, arch note

Traceability

  • [x] story:game-status label — present on board item
  • [x] story note exists — story-twitch-2k-wager-game-status (id 1159) found in pal-e-docs
  • [ ] story mismatch — [SCOPE] The story story-twitch-2k-wager-game-status is written from the Challenger perspective ("As a challenger, I want to see on the website that my payment was received"). This ticket is from the Operator (Marcus) perspective ("As Marcus, I want to see a list of people who have paid"). These are different user roles with different needs. Recommend creating story-twitch-2k-wager-operator-queue and re-labeling the board item story:operator-queue.
  • [x] arch:dataflow-twitch-2k-wager label — present on board item
  • [x] arch note verified — arch-dataflow-twitch-2k-wager (id 1155) exists. Diagram includes "Operator declares winner" flow which directly aligns with this ticket.
  • [x] Forgejo issue — forgejo_admin/twitch-2k-wager#40, open

File Targets

  • [x] src/routes/admin/+page.svelte — NEW file. Parent src/routes/ exists. No existing admin/ directory. Correct placement for SvelteKit page route.
  • [x] src/routes/admin/+page.server.ts — NEW file. Server load function to fetch games from DB. Correct SvelteKit pattern.
  • [x] src/routes/admin/+layout.server.ts — NEW file. Auth guard for admin routes. Correct SvelteKit pattern.
  • [ ] MISSING target[BODY] src/lib/db.ts must be added to File Targets. The admin page needs a new query function (e.g. listAllGamesWithChallengers()) that joins the game and challenger tables. Current DB functions are insufficient: listQueuedGames() returns only queued games with no challenger join; listGamesByChallenger() filters to a single challenger. The admin page needs all games (across all statuses) with challenger info.

Repo Placement

OK. Issue filed on forgejo_admin/twitch-2k-wager, all file targets are in this repo. Single-repo change. No cross-repo concerns.

Dependencies

  • [x] #12 (Stripe Connect payout + admin result) — validation column, Forgejo issue closed. The admin page calls /api/admin/result which exists at src/routes/api/admin/result/+server.ts. Satisfied.
  • [x] #9 (Postgres schema + db.ts) — done column. DB layer and types exist. Satisfied.
  • [x] #13 (Game status UI + email receipts) — validation column. Challenger-facing, independent from admin view. No dependency.
No unresolved dependencies that block execution.

Acceptance Criteria

  • [x] "/admin?key=ADMIN_SECRET shows the queue" — testable, clear
  • [ ] "Each game shows: gamertag, email, tier amount, pot amount, status, timestamp" — [BODY] gamertag data gap. The Challenger type (src/lib/types.ts) has twitch_username and email but no gamertag field. The frontend (+page.svelte, play/+page.svelte) collects gamertag input but the checkout API (/api/checkout/+server.ts) calls upsertChallenger(twitchId, twitchUsername, email) — gamertag is never persisted. Either: (a) clarify that twitch_username serves as the display identifier (update AC wording), or (b) add a gamertag column (separate prerequisite ticket touching schema + checkout API).
  • [x] "Challenger Wins / Marcus Wins buttons on each active game" — testable, clear
  • [x] "Clicking a result button calls /api/admin/result" — testable, existing endpoint
  • [x] "Completed games show result + payout status" — testable
  • [x] "Auto-refreshes (poll every 5s)" — testable
  • [x] "Mobile-friendly" — testable visually

Blast Radius

  • Auth pattern divergence: The existing admin result endpoint (src/routes/api/admin/result/+server.ts) authenticates via Authorization: Bearer ADMIN_SECRET header. This ticket proposes query-param auth (?key=ADMIN_SECRET) for the admin page. Two different auth mechanisms for the same admin surface. The agent needs guidance on how the page JS should authenticate calls to /api/admin/result — either include a Bearer header from client-side JS, or have the layout guard set a cookie that the API also accepts. [BODY] Add a note in Constraints clarifying how admin page authenticates API calls.
  • No external blast radius. Admin page is internal operator tooling. No downstream consumers affected.
  • Rollback is straightforward — delete the 3 new files and the DB function.

Decomposition Assessment

3 new file targets + 1 DB function modification, all in 1 repo. 7 AC items but they describe a single cohesive page. Estimated agent time: 3-4 minutes for a standard SvelteKit CRUD page with server load + auth guard + polling.
No decomposition needed — fits the three-thing limit (3 new routes + 1 db function = one coherent feature) and five-minute rule. No independent subtasks worth parallelizing.
Prerequisite: the gamertag data gap must be resolved before dispatching. If it requires a schema migration, that becomes a separate prerequisite ticket.

Recommendation

  • [SCOPE] Create user story story-twitch-2k-wager-operator-queue ("As an operator, I want to see paid challengers and their gamertags so I can invite them and declare results"). Add to project-twitch-2k-wager user-stories table. Update board item #814 label from story:game-status to story:operator-queue.
  • [BODY] Add src/lib/db.ts to File Targets: "Add listAllGamesWithChallengers() function joining game + challenger tables for the admin view."
  • [BODY] Resolve gamertag data gap: clarify in AC whether twitch_username is the display identifier (rename "gamertag" to "twitch username" in AC), or scope a prerequisite ticket to add a gamertag column to the challenger table and update the checkout flow.
  • [BODY] Add to Constraints: "Admin page JS must include Authorization: Bearer ADMIN_SECRET header when calling /api/admin/result, matching the existing endpoint's auth pattern. The layout guard validates the query param on initial page load and stores the secret client-side for subsequent API calls."