Review: Remove opt-out from jersey ordering options (#263)

review-718-remove-opt-out Doc

review ready

Verdict: APPROVED

Issue forgejo_admin/basketball-api#263 -- "Remove opt-out from jersey ordering options"
Board item #718 on board-westside-basketball, column: backlog -> todo

Template Completeness

Field Present Notes
Type Yes Bug
Lineage Yes Standalone, discovered during jersey ordering validation 2026-03-30
Repo Yes <code>forgejo_admin/basketball-api</code>
What Broke Yes Specific: opt-out still offered, player Zion Odejinmi (id=113) already selected it
Repro Steps Yes 3 concrete steps with observable outcome
Expected Behavior Yes Only reversible ($90) and jersey+warmup ($130) should appear
Environment Yes prod namespace, commit <code>4cd0e1b5</code>, affected player identified
Acceptance Criteria Yes 4 checkboxes, all concrete and verifiable
Related Yes <code>project-westside-basketball</code>, <code>story:WS-S18</code>
All 9 template fields present and complete. No gaps.

File Target Verification

  • src/basketball_api/routes/jersey.py -- JERSEY_OPTIONS list at lines 25-41 contains opt_out entry (lines 37-40). GET /jersey/options at line 137 returns all options unfiltered. POST /jersey/checkout at lines 202, 269-276 has opt_out handling path. All confirmed in codebase.
  • src/basketball_api/routes/checkout.py -- POST /checkout/create-session at lines 168-192 handles opt_out via ProductType.opt_out check. Confirmed.
  • src/basketball_api/models.py -- JerseyOption.opt_out at line 83, ProductType.opt_out at line 120. Enum values exist. Note: these enum values should NOT be removed from the model (data preservation for existing records), only from the API surface.
  • tests/test_jersey.py -- 6 opt_out test cases that will need updating
  • tests/test_checkout.py -- 3 opt_out test cases that will need updating
All file targets verified. Agent will find exactly what it needs.

Traceability

  • Board item #718 labels: type:bug,arch:basketball-api,story:WS-S18 -- correct
  • Issue body references: story:WS-S18 -- matches board item
  • Story WS-S18 is defined in project-westside-basketball under Parent stories
Traceability triangle complete.

Dependency Check

  • #260 (QA nits from jersey PRs) -- related but not blocking, different scope
  • #262 (extract _resolve_player helper) -- refactor, independent
  • #264 (Stripe webhook sync) -- independent bug
  • No blockers identified. This bug can be fixed independently.

Decomposition Assessment

3 discrete changes required:
  • Remove opt_out from JERSEY_OPTIONS list in jersey.py + add validation to reject opt_out in POST /jersey/checkout
  • Add rejection in checkout.py /create-session for opt_out ProductType
  • Update tests in test_jersey.py and test_checkout.py (convert opt_out tests to rejection tests)
Exactly 3 changes. Well within single-agent scope. Estimated ~5 min.

Important Implementation Note

The enum values JerseyOption.opt_out and ProductType.opt_out must NOT be removed from models.py. Existing database records (e.g., Zion id=113) reference these values. The acceptance criteria explicitly state "Existing opt-out records are not deleted (data preservation)." The fix is API-surface only: remove from the options list, reject in validation.

Recommendation

APPROVED for todo. Ready for agent dispatch. Clean scope, verified file targets, no blockers.