Review: Fix fresh-pending reuse shows stale Stripe amount

review-1006-2026-04-13 Review

review ready

Verdict: READY

Scope is tight, file targets verified against origin/main, traceability complete. Fits a single agent pass (<5 min).

Template Completeness

  • [x] Type (Bug)
  • [x] Lineage (regression from #473)
  • [x] Repo
  • [x] What Broke
  • [x] Repro Steps
  • [x] Expected Behavior
  • [x] Environment
  • [x] File Targets
  • [x] Acceptance Criteria
  • [x] Test Expectations
  • [x] Related

Traceability

  • [x] story:WS-S11 — "As an admin, I want to create Stripe checkout sessions for jerseys/fees so that payments are automated" (verified in project-westside-basketball user-stories)
  • [x] arch:basketball-api label present
  • [ ] arch note MISSING — no arch-basketball-api note returned by semantic search. [SCOPE] Create arch-basketball-api note (pre-existing gap across all basketball-api tickets, not unique to this one — recommend tracking as a board item rather than blocking this fix)
  • [x] Forgejo issue 479 — open, URL valid

File Targets

  • [x] src/basketball_api/routes/checkout.py — verified on origin/main. The "fresh-pending reuse" branch is at lines 358-374 (ticket says 360-380 — close enough, line count matches intent). Confirmed: stripe.checkout.Session.retrieve followed by unconditional RedirectResponse without amount comparison. Fix surface is ~5 lines as claimed.
  • [x] tests/test_first_payment.py — verified. Existing tests referenced in acceptance criteria all present: test_first_payment_paid_still_blocked (line 171), test_first_payment_stale_pending_replaced (line 201), test_first_payment_fresh_pending_returns_redirect (line 263). Adding new test fits existing fixture pattern.

Repo Placement

OK. Fix is localized to basketball-api. Email rendering (basketball-api/services/email.py) is explicitly excluded and correct — email always uses fresh fee. No cross-repo work needed.

Dependencies

Depends on #473/#474 (already merged on main). No open blockers. Ticket does not block anything else.

Acceptance Criteria

Five criteria, all verifiable via pytest. Each maps to a specific test (existing or new). Run command provided: pytest tests/test_first_payment.py -v. Testable and complete.

Blast Radius

Grepped for similar "retrieve existing Stripe session and redirect" patterns in checkout.py. The pattern exists only in first_payment_checkout (single match at lines 365-368). Jersey and tournament checkout flows do not reuse sessions — they create new each time. No sibling services need the same fix.
Note: Stripe Checkout Sessions are immutable after creation — ticket correctly identifies that the fix path must cancel + create new, not "update amount."

Decomposition Assessment

2 file targets, 1 repo, 5 AC, estimated ~5 line code change + 1 new test. Well under the 5-minute rule. No decomposition needed.

Recommendation

  • [SCOPE] Create arch-basketball-api architecture note. Pre-existing gap affecting all basketball-api tickets — track separately, do NOT block this fix.
No other action needed. Ready to move backlog → todo.