Review: Jersey email: E2E validation + production send to boys

review-666-2026-03-29 Review

review ready

Verdict: READY

Re-review. Previous verdict was NEEDS_REFINEMENT (3 findings). All 3 findings addressed in updated issue body.

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — Decomposed from basketball-api#243
  • [x] Repo — westside-landing + basketball-api
  • [x] User Story — Marcus (admin) validates jersey email flow
  • [x] Context — Adequate background on ConfigMap hotfix, Kings+Queens gear photos
  • [x] File Targets — "No code changes" (ops/validation ticket, acceptable)
  • [x] Dependency Gate — NEW: Added per review finding. Documents both blocking dependencies with rationale.
  • [x] Acceptance Criteria — 6 items, all now include procedures
  • [x] Test Expectations — Playwright screenshots + manual validation
  • [x] Constraints — Stripe live, Marcus approval gate, sequential deployment order
  • [x] Checklist — Present
  • [x] Related — Present with blocking annotations
All required template sections present. Dependency Gate is a valuable addition beyond template requirements.

Traceability

  • [x] story:WS-S7 label — Jersey ordering flow
  • [x] story:WS-S18 label — Jersey deadline/ordering UX
  • [x] arch:basketball-api label — Send trigger endpoint
  • [x] arch:westside-app label — Jersey page UI validation
  • [x] Forgejo issue — westside-landing#182, open
Traceability triangle complete.

File Targets

No code changes — ops/validation ticket. No file targets to verify. Acceptable for this issue type.
Verified infrastructure exists:
  • [x] ~/westside-app/src/routes/(app)/jersey/+page.svelte — jersey page exists, currently shows "March 28" (confirms #180 dependency is real)
  • [x] ~/basketball-api/src/basketball_api/routes/admin.py:847POST /email/jersey-reminder exists, currently lacks division and exclude_ordered params (confirms #243 dependency is real)
  • [x] ~/basketball-api/src/basketball_api/routes/admin.py:56POST /admin/generate-tokens exists and works as described in AC #5

Repo Placement

Issue filed on westside-landing but touches both westside-landing (UI validation) and basketball-api (send trigger). The issue correctly identifies both repos. Since no code changes are needed (ops/validation only), single-issue placement is acceptable.

Dependencies

  • westside-landing#180 (Fix stale jersey deadline: March 28 → April 10) — OPEN, board item #659 in needs_approval. PR #189 and PR #190 both open (same fix, duplicate PRs). Issue body references "PR #189" while board item references pr:190 — minor discrepancy, not blocking.
  • basketball-api#243 (Division filter + exclude_ordered params) — OPEN, board item #660 in in_progress. Confirmed: current endpoint sends to ALL parents with tokens. Without this, production send would email boys AND girls.
Dependency Gate section in issue body clearly documents both dependencies and the rationale. This ticket cannot move to next_up until both dependencies are merged and deployed.

Acceptance Criteria

  • AC #1 (Dependencies deployed) — Gate check. Clear.
  • AC #2 (E2E walk-through) — Verifiable via Playwright/Chrome DevTools. Clear.
  • AC #3 (Stripe verified) — Verifiable via pod env and Stripe dashboard. Clear.
  • AC #4 (Test send to Marcus) — Uses test_email param on existing endpoint. Clear.
  • AC #5 (Token generation for Max Jordan) — FIXED: Now documents the procedure: POST /admin/generate-tokens. Verified endpoint exists at admin.py:56 and auto-generates tokens for paid parents missing them. Clear.
  • AC #6 (Production send to ~35 boys) — Blocked by #243 until division filter is deployed. Clear once dependency resolved.
6 ACs total. All are clear and verifiable. AC #5 procedure resolved from previous review.

Blast Radius

  • Jersey cancel page (cancel/+page.svelte:37) still shows "March 28" — will also need updating, but that's #180's scope, not this ticket's.
  • No risk to girls-side email flow — ticket targets boys only via division filter (once #243 lands).
  • Stripe is LIVE — constraints correctly flag no test transactions without approval.
  • send_jersey_reminder_email loops per-parent — no bulk blast per call, but admin endpoint iterates all matching parents. Marcus approval gate is the correct mitigation.
  • Email sends are irreversible. Sequential gate (validate → test send → Marcus approves → production send) is well documented.

Decomposition Assessment

6 ACs across 2 repos with 2 open dependencies and a human approval gate. Exceeds the 5-AC threshold numerically. However, this is an ops/validation ticket — the work is inherently sequential and human-gated. Automated agent decomposition is not applicable. The dependency gate section correctly frames the sequencing. No sub-board needed.

Previous Findings Resolution

  • [BODY] Token generation procedure — RESOLVED. AC #5 now documents: POST /admin/generate-tokens with explanation that it auto-generates tokens for paid parents missing them.
  • [BODY] Dependency gate section — RESOLVED. New ### Dependency Gate section added with both dependencies, PR references, and rationale for why #243 is critical (prevents emailing all parents).
  • [SCOPE] #180 scope clarification — RESOLVED. Dependency Gate section specifies "#180 — deadline text fix on jersey page." Verified: jersey page at +page.svelte:276 still shows "March 28", confirming the fix is needed on the jersey page itself.

Recommendation

No action needed. All previous findings addressed. Scope is solid for an ops/validation ticket. Ready to move backlog → todo now, and todo → next_up once both dependencies (#180 and #243) are merged and deployed.
Minor note: Issue body references "PR #189 in review" for #180, but both PR #189 and #190 exist with the same title. Board item #659 tracks pr:190. Not blocking — the executing agent will see which PR merges.