Starts after: Stage 7 complete.
Tasks
-
Admin live contest dashboard (/internal/contests/admin/[contestId])
- Bracket view (SVG, colour-coded by status: pending / active / completed).
- Room controls: start, walkover (required note).
- Advancement preview: "Compute Advancement" button shows who advances before confirming.
- Audit log viewer (walkovers, manual overrides, time extensions).
- Ability to extend the time limit on an active room if CF is responding slowly.
-
Active room screen polish
- All UI states:
- Sync button: Ready → Syncing... (spinner) → AC ✓ / WA ✗, 60s cooldown progress ring.
- Blitz: "Solved by [Team Name]" slide-in banner, problem progress dots.
- Arena: card flip animation on claim, lock icon + claimant team name, colour states (open / claimed-me / claimed-opponent).
- Activity feed (right sidebar on desktop, collapsible on mobile).
- Knockout sidebar widget: current round + bracket position context.
- Timer turns red at <2 min.
- Opponent team sync status visible at all times.
- Mobile playability: 1-column Arena grid, collapsible sidebar.
-
Edge case UX
- "CF API slow" warning appears after >20s without a sync result.
sync.queued SSE event drives a queue position badge on the Sync button.
- Insufficient problems error shown clearly in the admin creation wizard before any room stub is created.
-
Full regression pass
- Every SSE event type in
SSE_EVENTS.md: verified end-to-end.
- Every Redis key pattern: verify creation and cleanup timing for both standalone and knockout contests.
- Every MongoDB document shape: compare against the Platform Architecture schemas above.
- Full end-to-end coverage: Blitz 1v1, Arena 1v1, Blitz 3v3, Arena 3v3, knockout tournament with blitz rooms, knockout tournament with arena rooms.
-
Performance checks
- 20 concurrent active rooms → verify
cf_sync_queue depth stays manageable (~0.7 req/s, within the 2/s limiter).
- Alert at queue depth >50.
- Redis memory usage within expected bounds for N active rooms.
Cross-Cutting Concerns (Every Stage)
Redis is the source of truth during live rooms. MongoDB is the ledger. Never query MongoDB for live room state. Never write to MongoDB outside of a reconciliation_queue job.
All CF API calls go through BullMQ (cf_sync_queue). No inline CF fetches in route handlers or anywhere else.
Server computes all room state. Client only renders. No state computation on the client side. This is the anti-cheating constraint.
Every admin action writes to the audit log. Walkovers, time extensions, manual advancements — all timestamped and stored.
Schemas are additive, never destructive. New fields are nullable. Old rooms must still resolve correctly after schema changes.
Event names use dot notation, all lowercase. room.advance, not room:advance or roomAdvance. Enforced by SSE_EVENTS.md.
Summary Table
| Stage |
What |
Prereq |
Owner |
Est. |
| S1 |
Infrastructure, schemas, Redis, BullMQ, SSE gateway, presence |
None |
— |
3–4d |
| S2 |
CF Sync Engine, Validation Matrix |
S1 |
— |
3–4d |
| S3 |
Blitz Room Engine (1v1), Reconciliation Worker |
S2 |
— |
5–6d |
| S4 |
Arena Mechanics, Lua claim script |
S3 |
— |
4–5d |
| S5 |
Team Mode (3v3) |
S4 |
— |
3–4d |
| S6A |
Tournament Schemas, Admin Wizard, Registration |
S4 |
— |
3–4d |
| S6B |
Knockout (Bracket) Engine |
S6A |
— |
4–5d |
| S6C |
Reconciliation Hook & Full Tournament Integration |
S5 + S6B |
— |
3–4d |
| S7 |
Player-Facing UI, Match History |
S6C |
— |
3–4d |
| S8 |
Admin Dashboard, Polish, Final QA |
S7 |
— |
4–5d |
Total estimated effort (sequential, single developer): ~37–47 working days.
With two parallel tracks (S5 ∥ S6A–6B): Savings of ~6–8 days.
Appendix: Integration Checkpoints
| Checkpoint |
After Stage |
What to run |
| Internal playtesting |
S3 |
Two devs run a real Blitz 1v1 with actual CF accounts |
| Arena simultaneous-AC stress test |
S4 |
10 concurrent sync requests for same problem — Lua always awards earliest CF timestamp |
| 3v3 team match test |
S5 |
6 real CF accounts, two teams of 3, verify team scoring and attribution |
| 4-player knockout internal test |
S6B |
Bracket generation, bye handling, bracket SVG renders correctly at every stage |
| 8-player knockout stress test |
S6C |
Full 3-round bracket, all real CF accounts, all Redis keys cleaned up after each room and after contest end |
| Regression pass |
S8 |
Every SSE event in SSE_EVENTS.md, every Redis key creation and cleanup, every MongoDB document shape |
Starts after: Stage 7 complete.
Tasks
Admin live contest dashboard (
/internal/contests/admin/[contestId])Active room screen polish
Edge case UX
sync.queuedSSE event drives a queue position badge on the Sync button.Full regression pass
SSE_EVENTS.md: verified end-to-end.Performance checks
cf_sync_queuedepth stays manageable (~0.7 req/s, within the 2/s limiter).Cross-Cutting Concerns (Every Stage)
Redis is the source of truth during live rooms. MongoDB is the ledger. Never query MongoDB for live room state. Never write to MongoDB outside of a
reconciliation_queuejob.All CF API calls go through BullMQ (
cf_sync_queue). No inline CF fetches in route handlers or anywhere else.Server computes all room state. Client only renders. No state computation on the client side. This is the anti-cheating constraint.
Every admin action writes to the audit log. Walkovers, time extensions, manual advancements — all timestamped and stored.
Schemas are additive, never destructive. New fields are nullable. Old rooms must still resolve correctly after schema changes.
Event names use dot notation, all lowercase.
room.advance, notroom:advanceorroomAdvance. Enforced bySSE_EVENTS.md.Summary Table
Total estimated effort (sequential, single developer): ~37–47 working days.
With two parallel tracks (S5 ∥ S6A–6B): Savings of ~6–8 days.
Appendix: Integration Checkpoints
SSE_EVENTS.md, every Redis key creation and cleanup, every MongoDB document shape