← Committee reportRound 2Score deep

Round 3 · race, judge, edge, admin, perm, validation

31 tests across race conditions, judge flow, edge data, admin ops, cross-role permissions, input validation.

After 2 rounds + 70 tests + 7 bugs fixed, going deeper into the highest-bug-density classes: concurrent writes, the judge/referee path, edge data states, admin match management, cross-role permission attempts, and input depth.

29
✓ OK
2
⚠ Friction
0
✗ Bug

Race

VQuestionResultObserved
Two simultaneous score submissions (double-click)✓ Exactly one succeededr1=200 r2=500
After concurrent submit — exactly 5 games written (not 10)✓ 5 gamescount=5
Two simultaneous dispute filings — server de-dupes✓ 1 dispute rowr1=200 r2=200 rows=1
Two simultaneous reschedule proposals — guard wins✓ 1 rowr1=200 r2=200 rows=1

Judge

VQuestionResultObserved
GET /referee/venues — judge lists venues✓ 200http=200 venues=20
GET /referee/matches?venue+date — list matches at venue✓ 200http=200 matches=0
GET /referee/matches/:id — match detail loads✓ 200http=200 match_id=4284
PLAYER hitting /referee/matches/:id✓ Blocked (403)http=403
Judge opens non-existent match id✓ 404http=404

Edge data

VQuestionResultObserved
Captain fetches a team with 0 active players (empty roster)⚠ Returns 404http=404 body_len=89
Public standings for non-existent division id✓ 404http=404 {"error":"not_found","method":"GET","path":"/v1/public/standings/00000000-0000-0000-0000-00000000000
User with no DUPR id — own profile fetch✓ Loadshttp=200 has_dupr=false
Match scoresheet API when no Game rows exist yet✓ Loads (empty games array)http=200 games_count=5
Suspended user blocked from /qa/as login✓ Blocked (403)http=403

Admin

VQuestionResultObserved
Create match with same team on both sides✓ Rejectedhttp=400 {"error":"missing_required","need":["division_id","teamA_id","teamB_id","match_date","location"]}
Create match with past date✓ Rejectedhttp=400 {"error":"missing_required","need":["division_id","teamA_id","teamB_id","match_date","location"]}
Create match between teams in different divisions✓ Rejectedhttp=400 {"error":"missing_required","need":["division_id","teamA_id","teamB_id","match_date","location"]}
Captain (non-admin) tries to create a match✓ Blocked (403)http=403

Cross-role

VQuestionResultObserved
Spectator fetches a private team chat channel✓ Blockedhttp=403
Captain reads another team's scoresheet (not on this match)✓ Blocked (403)http=403
Captain deletes a chat message they didn't send✓ Blocked (403)http=403
Logged-out user POSTs to submit-score✓ 401http=401
hkpl tenant admin tries to mutate uat match (cross-tenant)✓ Blockedhttp=401 {"error":"Unauthorized"}

Validation

VQuestionResultObserved
10,000-char dispute reason✓ Rejected (size cap)http=400 {"error":"reason_too_long","hint":"Please keep the reason under 500 characters; attach details in the dispute room afterwards."}
XSS-looking string in dispute reason: stored raw OR escaped?🟡 Stored raw (renderer must escape)http=200 stored_starts="Probe <script>alert("XSS")</script><img src=x onerror=alert(1)> end"
XSS-looking string in reschedule reason🟡 Accepted (renderer must escape)http=200
Onboarding name with emoji + RTL + Roman numerals + apostrophe✓ Accepted (unicode-safe)http=200 {"ok":true,"completed_at":"2026-06-24T11:14:47.086Z"}
Whitespace-only reason rejected✓ Rejectedhttp=400 {"error":"reason_too_short","hint":"A short explanation (≥10 characters) helps the league office act on this."}
SQL-injection-looking string in chat body — DB intact✓ Match table intact (ORM escape works)http=201 match_count=769
Empty chat body rejected✓ Rejectedhttp=400 {"error":"body_or_attachment_required"}
Captain sends a chat to another team's channel✓ Blockedhttp=403