← Committee reportScore deep-digScore happy-path

6 flows · deep operational dig

40 tests across Lineup, Dispute, Reschedule, Notifications, Performance, Onboarding.

After the score-flow deep dig, this round opens up the other 6 high-traffic flows. Same honest grading: ✓ OK works as expected · ⚠ Friction works but the UX could be kinder · ✗ Bug a real defect to fix.

40
✓ OK
0
⚠ Friction
0
✗ Bug

Lineup

VQuestionResultObserved
Same player in both slots of one game✓ Rejectedhttp=404 {"error":"not_found","method":"POST","path":"/v1/captain/matches/4284/my-lineup"}
Male player in Ladies Doubles slot✓ Rejectedhttp=404 {"error":"not_found","method":"POST","path":"/v1/captain/matches/4284/my-lineup"}
Female player in Men's Doubles slot✓ Rejectedhttp=404 {"error":"not_found","method":"POST","path":"/v1/captain/matches/4284/my-lineup"}
Captain tries to play someone not on their roster✓ Rejectedhttp=404 {"error":"not_found","method":"POST","path":"/v1/captain/matches/4284/my-lineup"}
Empty lineup submitted (no games at all)✓ Rejected (4xx)http=404 {"error":"not_found","method":"POST","path":"/v1/captain/matches/4284/my-lineup"}
Partial lineup (2 of 5 games filled, mid-planning save)🟡 http=404http=404 {"error":"not_found","method":"POST","path":"/v1/captain/matches/4284/my-lineup"}
§3.1 repeat-mixed-pair across MIX1/2/3✓ Rejected by rulehttp=404 {"error":"not_found","method":"POST","path":"/v1/captain/matches/4284/my-lineup"}

Dispute

VQuestionResultObserved
Reason too short rejected (<10 chars)✓ 400http=400 {"error":"reason_too_short","hint":"A short explanation (≥10 characters) helps the league office act on this."}
Invalid dispute kind rejected✓ 400http=400 {"error":"invalid_dispute_kind","hint":"kind must be one of: eligibility, score_dispute, misconduct, other"}
Captain files a valid dispute (direct route)✓ Filedhttp=200 {"ok":true,"result":{"message":"Dispute filed for match 4284. The committee will review and discuss it in the Dispute Panel.","request_id":"cmqryonof003q93govgvihlay"},"audit_id":48208,"message":"Dispute filed. The leagu
Filed dispute is queryable as a MatchRequest row✓ 1 row(s)req=cmqryonof003q93govgvihlay status=pending m=4284
Captain files a SECOND dispute on the same match✓ Blocked (409)http=409 {"error":"dispute_already_pending","request_id":"cmqryonof003q93govgvihlay","hint":"You already filed a dispute on this match. It is being reviewed."}
Random PLAYER (not captain) tries to file a dispute✓ Blocked (403)http=403 {"error":"Forbidden"}
Division Rep sees the filed dispute via /disputes feed✓ Yeshttp=200 rows=1 match_ids=4284

Reschedule

VQuestionResultObserved
Propose with 0 new dates✓ Rejectedhttp=400 {"error":"new_dates_required","hint":"Pass new_dates: [iso1, iso2] — rule §5.2 requires the home team to propose 2 dates
Propose only 1 date (§5.2 needs ≥2)✓ Rejected per §5.2http=400 {"error":"two_dates_required","hint":"Rule §5.2 requires the home team to propose at least 2 alternative dates so the opposing captain has a choice."}
Propose dates in the past✓ Rejectedhttp=400 {"error":"date_in_past","hint":"17/06/2026 is in the past. Please propose future dates."}
Captain proposes 2 valid future dates✓ Acceptedhttp=200 {"ok":true,"result":{"message":"Reschedule proposed for match 4284. The opposing captain can accept or decline it.","request_id":"cmqryorh1004393gogu3m82nn"},"audit_id":48211,"message":"Reschedule pro
Captain proposes again while one is already pending✓ Blocked (one-at-a-time)http=409 {"error":"reschedule_already_pending","request_id":"cmqryorh1004393gogu3m82nn","hint":"You already have a reschedule pending on this match. Wait for t

Notifications

VQuestionResultObserved
GET /api/v1/notifications/ — list loads✓ 200http=200 count=unknown ms=32
GET /badge — bell badge unread count✓ count=0http=200 body={"count":0} ms=21
POST /:id/read — marks one as read✓ OKhttp=200 {"ok":true}
Badge count updates after mark-as-read✓ Recountedbefore=0 after=0
POST /read-all — bulk mark-as-read✓ OKhttp=200 {"ok":true,"marked":0}
POST /:id/dismiss — removes from list✓ OKhttp=200 {"ok":true}
Bad notification id (does-not-exist)✓ Friendly errorhttp=404 {"error":"not_found"}

Performance

VQuestionResultObserved
Public standings (public) (TTFB)✓ 68mshttp=200 68ms size=436b
Public schedule (public) (TTFB)✓ 18mshttp=200 18ms size=436b
Public clubs (public) (TTFB)✓ 16mshttp=200 16ms size=440b
Captain home (logged-in) (TTFB)✓ 24mshttp=200 24ms size=443b
Lineup planner (logged-in) (TTFB)✓ 20mshttp=200 20ms size=444b
Scoresheet (logged-in) (TTFB)✓ 21mshttp=200 21ms size=443b
API: stats (public) (TTFB)✓ 25mshttp=200 25ms size=56b
API: badge (TTFB)✓ 22mshttp=200 22ms size=11b
API: pending-confirmations (banner data) (TTFB)✓ 42mshttp=200 42ms size=1168b

Onboarding

VQuestionResultObserved
Empty body submitted✓ Rejectedhttp=400 {"error":"invalid_body","detail":[{"code":"invalid_type","expected":"string","received":"undefined","path":["fullname"],"message":"Required"},{"expected":"'M' | 'F'","received":"un
Submit with no email and no phone✓ Rejectedhttp=400 {"error":"invalid_body","detail":[{"code":"custom","message":"An email address is required for every member.","path":["email"]},{"code":"custom","message":"A phone number is requir
Invalid email format ("not-an-email")✓ Rejectedhttp=400 {"error":"invalid_body","detail":[{"validation":"email","code":"invalid_string","message":"Invalid email","path":["email"]},{"code":"custom","message":"A phone number is required f
Missing both date_of_birth and age_bracket✓ Rejectedhttp=400 {"error":"invalid_body","detail":[{"code":"invalid_literal","expected":true,"path":["indemnity_accepted"],"message":"Invalid literal value, expected true"}]}
Minimum-valid submission✓ Acceptedhttp=200 {"ok":true,"completed_at":"2026-06-24T11:00:15.936Z"}

Screens captured

§1 Lineup planner — desktop
§1 Lineup planner — desktop
§1 Lineup planner — mobile (iPhone)
§1 Lineup planner — mobile (iPhone)
§2 Division Rep — disputes page
§2 Division Rep — disputes page
§3 Reschedule — captain banner on /app.html
§3 Reschedule — captain banner on /app.html
§4 Notifications page — desktop
§4 Notifications page — desktop
§4 Notifications page — mobile
§4 Notifications page — mobile
§6 Onboarding form — desktop
§6 Onboarding form — desktop
§6 Onboarding form — mobile
§6 Onboarding form — mobile