Revert PR #490 code changes — Stripe Checkout Session expires_at is capped at 24h #493

Closed
opened 2026-04-17 21:43:33 +00:00 by forgejo_admin · 0 comments

Type

Bug

Lineage

Emergency follow-up to PR #490 (issue #488). Deployed 2026-04-17, broke prod checkout for ~60 min. Reverted at the deployment overlay in pal-e-deployments #131. basketball-api main still contains the broken code — any future merge to main will rebuild broken image and the update-kustomize-tag step will overwrite the revert in pal-e-deployments.

Repo

forgejo_admin/basketball-api

User Story

As an engineer, basketball-api main builds an image that works in prod. Right now it doesn't — the next merge to main will re-break checkout.

What Broke

PR #490 merged code that calls stripe.checkout.Session.create(..., expires_at = int(time.time()) + 30 * 24 * 3600, ...) at 8 call sites. Stripe's real cap for Checkout Session expires_at is 24 hours, not 30 days. Every call hits:

InvalidRequestError: The expires_at timestamp must be less than 24 hours
from Checkout Session creation.

The unit tests passed because they mocked stripe.checkout.Session.create; mocks don't enforce Stripe's server-side constraint.

Repro Steps

  1. git checkout main on basketball-api (current HEAD contains the #490 squash)
  2. Build + deploy to any environment with a real Stripe key
  3. Call any of the 8 checkout flows
  4. Observe 400 from Stripe

Expected Behavior

basketball-api main builds an image whose checkout flows work in prod. Since Stripe's 24h cap cannot be raised via expires_at, the correct architecture is not a TTL extension — it's one of:

  • Stripe Payment Links (don't expire; separate API)
  • Lazy-mint /pay/{token} (our backend mints fresh session on click)

Both options are scoped under spike #489.

Environment

  • basketball-api main @ current HEAD (squash of PR #490, commit message "fix: set 30-day expires_at on all Stripe Checkout Sessions (#488) (#490)")
  • Deployment layer reverted to pre-merge SHA a4047d2c629... via pal-e-deployments #131

Acceptance Criteria

  • basketball-api main no longer contains the 30-day expires_at code
  • No CHECKOUT_SESSION_TTL_SECONDS constant set to a value Stripe rejects
  • A smoke test against real Stripe (not mocked) is part of CI OR the test suite includes a bounds assertion matching Stripe's documented max
  • basketball-api#488 closure is revisited — the original bug (24h expiry breaks email-blast economics) is real but the fix approach is wrong; #488 may need reopening with new title/scope, OR superseded by spike #489's chosen architecture
  • forgejo_admin/basketball-api #488 — original ticket (closed by #490's squash merge — closure is misleading, root problem unsolved)
  • forgejo_admin/basketball-api #489 — architecture spike (Payment Links vs lazy-mint); now load-bearing
  • forgejo_admin/pal-e-deployments #130, #131 — deployment revert that restored prod
  • Memory: feedback_retrieve_before_theorize.md — the missing sanity check
### Type Bug ### Lineage Emergency follow-up to PR #490 (issue #488). Deployed 2026-04-17, broke prod checkout for ~60 min. Reverted at the deployment overlay in pal-e-deployments #131. **basketball-api main still contains the broken code** — any future merge to main will rebuild broken image and the update-kustomize-tag step will overwrite the revert in pal-e-deployments. ### Repo `forgejo_admin/basketball-api` ### User Story As an engineer, basketball-api main builds an image that works in prod. Right now it doesn't — the next merge to main will re-break checkout. ### What Broke PR #490 merged code that calls `stripe.checkout.Session.create(..., expires_at = int(time.time()) + 30 * 24 * 3600, ...)` at 8 call sites. Stripe's real cap for Checkout Session `expires_at` is 24 hours, not 30 days. Every call hits: ``` InvalidRequestError: The expires_at timestamp must be less than 24 hours from Checkout Session creation. ``` The unit tests passed because they mocked `stripe.checkout.Session.create`; mocks don't enforce Stripe's server-side constraint. ### Repro Steps 1. `git checkout main` on basketball-api (current HEAD contains the #490 squash) 2. Build + deploy to any environment with a real Stripe key 3. Call any of the 8 checkout flows 4. Observe 400 from Stripe ### Expected Behavior basketball-api main builds an image whose checkout flows work in prod. Since Stripe's 24h cap cannot be raised via `expires_at`, the correct architecture is not a TTL extension — it's one of: - Stripe Payment Links (don't expire; separate API) - Lazy-mint `/pay/{token}` (our backend mints fresh session on click) Both options are scoped under spike #489. ### Environment - basketball-api main @ current HEAD (squash of PR #490, commit message "fix: set 30-day expires_at on all Stripe Checkout Sessions (#488) (#490)") - Deployment layer reverted to pre-merge SHA `a4047d2c629...` via pal-e-deployments #131 ### Acceptance Criteria - [ ] basketball-api main no longer contains the 30-day `expires_at` code - [ ] No `CHECKOUT_SESSION_TTL_SECONDS` constant set to a value Stripe rejects - [ ] A smoke test against real Stripe (not mocked) is part of CI OR the test suite includes a bounds assertion matching Stripe's documented max - [ ] basketball-api#488 closure is revisited — the original bug (24h expiry breaks email-blast economics) is real but the fix approach is wrong; `#488` may need reopening with new title/scope, OR superseded by spike #489's chosen architecture ### Related - `forgejo_admin/basketball-api #488` — original ticket (closed by #490's squash merge — closure is misleading, root problem unsolved) - `forgejo_admin/basketball-api #489` — architecture spike (Payment Links vs lazy-mint); now load-bearing - `forgejo_admin/pal-e-deployments #130, #131` — deployment revert that restored prod - Memory: `feedback_retrieve_before_theorize.md` — the missing sanity check
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/basketball-api#493
No description provided.