Review: Fix Stripe SDK v15 webhook crash + add webhook Prometheus metrics
Verdict: NEEDS_REFINEMENT
Template Completeness
- [x] Type -- Bug
- [x] Lineage -- references #343, #346
- [x] Repo -- forgejo_admin/basketball-api
- [x] What Broke -- detailed root cause with error message and SDK version mismatch
- [x] Repro Steps -- 5 clear steps
- [x] Expected Behavior -- clear
- [x] Environment -- cluster, SDK versions, pin info
- [x] Acceptance Criteria -- 5 items
- [x] Related -- present with issue links and project reference
All required bug template sections are present and well-written.
Traceability
- [x] story:WS-S18 -- "As a parent, I want to receive a branded email with jersey ordering link so that I can order without bringing cash"
- [x] story note verified -- found in project-westside-basketball user-stories section (Parent stories list)
- [x] arch:basketball-api label present
- [ ] arch note MISSING -- [SCOPE] Create architecture note arch-basketball-api for component basketball-api
- [x] Forgejo issue -- forgejo_admin/basketball-api#350, open
File Targets
- [x]
src/basketball_api/routes/webhooks.py-- verified: file exists, contains 23 Stripe object .get() calls (issue claims 25, minor discrepancy -- 2 are db.get/dict.get, not Stripe objects). Line 301 confirmed as .get("metadata") call. - [ ]
routes/webhooks.py-- [BODY] Issue uses package-relative path. Repo-root path issrc/basketball_api/routes/webhooks.py. Update for agent clarity. - [x]
pyproject.toml-- verified: line 16 shows"stripe>=11.0"with no upper bound, confirming root cause. - [x]
src/basketball_api/routes/health.py-- verified: existing /metrics endpoint at line 34 exposes only a basic up gauge. Webhook counters would be added here or in a new metrics module. No prometheus_client dependency exists yet in pyproject.toml.
Repo Placement
OK. Issue filed on forgejo_admin/basketball-api, fix is in basketball-api. Single repo scope confirmed.
Dependencies
- #719 (qa column): "Stripe webhook not syncing payment to order status" -- significant scope overlap. Both address webhook handler failures on Stripe data. #719 may be a symptom of the same SDK v15 crash. If so, this ticket supersedes #719 and #719 should be closed as duplicate or marked as resolved-by this ticket.
- #720 (backlog): "Legacy jersey webhook handler missing payment_status guard" -- same arch, same story. Independent bug but related code area. Not a blocker.
- #731/#733 (backlog/in_progress): "Fix 9 jersey/checkout test failures blocking CI deploy" -- AC #5 ("Existing tests pass") depends on these test fixes landing first. If tests are already broken, this ticket's agent cannot verify AC #5.
- Downstream: Issue mentions "pal-e-platform webhook alerting ticket (depends on these metrics)" -- downstream dependency noted but not tracked as a board item link.
Acceptance Criteria
- AC 1 (pin stripe <15): verifiable via grep on pyproject.toml. Clear.
- AC 2 (replace .get() calls): verifiable via grep. Clear.
- AC 3 (live webhook test): requires deployed pod + Stripe test payment. Not automatable by agent in CI -- manual validation needed. Acceptable for a bug fix.
- AC 4 (Prometheus metrics): this is a feature, not a bug fix. Mixing concerns, but scope is small enough. Verifiable via curl /metrics. However, no prometheus_client dependency exists -- AC should mention adding it to pyproject.toml.
- AC 5 (existing tests pass): depends on #731/#733 test fixes landing first. May be unverifiable at dispatch time.
Blast Radius
Low. Stripe .get() usage is isolated to webhooks.py (23 calls). No other files in src/ use .get() on Stripe objects. The /metrics endpoint change is additive. Pin change affects all Stripe usage but <15 preserves current working behavior.
One concern: AC 2 says replace .get() with bracket notation or dict() wrapping for "v15 compat." If the intent is to eventually upgrade to v15, dict() wrapping is the forward-compatible fix. If the intent is to stay on <15, the pin alone suffices and AC 2 is defense-in-depth. The ticket should clarify intent: pin-and-stay vs pin-now-migrate-later.
Decomposition Assessment
2 file targets in 1 repo, 5 acceptance criteria. Borderline on the 5-minute rule. The bug fix (pin + .get() replacement) is mechanical and fast. The metrics addition is a small feature bolted on. A single agent can handle both in one pass. No decomposition needed.
Recommendation
[BODY]Fix file path:routes/webhooks.pytosrc/basketball_api/routes/webhooks.py. Addsrc/basketball_api/routes/health.pyas a file target for metrics work.[BODY]Fix .get() count: 25 to 23 (2 are db.get/dict.get, not Stripe objects).[BODY]Add note that prometheus_client dependency needs adding to pyproject.toml for AC 4.[BODY]Clarify relationship with #719 -- if #719 is a symptom of the same SDK crash, mark as duplicate or add "supersedes #719" to Related.[BODY]Reword AC 5 to "No new test failures introduced" (since #731/#733 indicate pre-existing test failures).[SCOPE]Create architecture note arch-basketball-api for component basketball-api.