Repository navigation
Conversation
The peer and dev ranges in packages/stripe and the login example's dependency go from ^22.6.1 to ^23.1.0, the newest stable release (published 2026-10-29, outside the one-day minimum release age). The peer range admits v23 only: STRIPE_API_VERSION is the installed SDK's pinned version, so a range spanning both majors would let a consumer's install choose between two API versions and two type surfaces. Stripe 23 removes `payment_method_types` from Checkout session creation; Checkout now sends `allowed_payment_method_types: ['card']`, which filters the account's dynamically eligible methods down to cards. The request snapshot and the trial test's expected parameters follow. Validated: pnpm typecheck, pnpm test:unit, and the billing, billing-http and billing-workers integration tests (54 passing), all against StripeDev. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Subscriptions StripeDev creates now carry the fields the endive API versions define and that were missing or new: each item's `current_period_start` (advanced with `current_period_end` on renewal and failed payment) and `current_trial: null`, `trial_settings` with `end_behavior.billing_cycle_anchor: null` and the requested `missing_payment_method`, and `pending_update: null`. `transition(id, 'pause')` and `'resume'` model the new pause endpoint and the portal's `subscription_pause` flow: pausing sets `status: 'paused'` with `status_details.paused`, resuming returns to `active` with a new period starting now; each emits `customer.subscription.updated` and then `.paused` or `.resumed`. Checkout session creation refuses `payment_method_types`, which the endive versions removed, and records `allowed_payment_method_types` on the session. A new billing test pins what a paused subscription means to pgstencil: no access, another checkout refused, not chosen by reconcileStale, and access back after resuming. Removing 'paused' from SUBSCRIBED fails it. Validated: pnpm typecheck, pnpm format:check, pnpm test:unit and the three billing integration suites against StripeDev. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Stripe 23 makes `webhooks.signature.verifyHeader[Async]` apply the 300-second default when no tolerance is passed (it used to skip the check) and lets 0 really skip it. `verifyWebhook` passes 300 to `constructEventAsync` explicitly, with the injected clock as `receivedAt`, so its behavior is unchanged: v22 and v23 both check the `t=` of the Stripe-Signature header, the time Stripe signed that delivery attempt, against the clock, rejecting only an age over 300 s. A new test pins that: a delivery is accepted exactly 300 s after it was signed and refused one second later; the same event re-signed five hours later, as a Stripe retry is, verifies and is a ledger no-op (one row, one attempt). The test fails with the tolerance set to 299 or to 0. Validated: pnpm typecheck, pnpm format:check, the billing integration suite (28 passing) against StripeDev. Co-Authored-By: Claude Opus 5.5 <[email protected]>
BILLING.md names the pinned version (2026-10-28.endive for stripe 23.1) and how to create a webhook endpoint at it, explains that the 300-second tolerance reads each delivery's signed timestamp, says what `paused` means for access now that Stripe's pause endpoint and the portal's subscription_pause flow reach it, states which stale owners reconcileStale never chooses, documents the StripeDev pause and resume transitions and what StripeDev does not model, and adds "Moving to a new Stripe API version", marked as not yet exercised end to end. Checkout's card restriction is now `allowed_payment_method_types`. packages/stripe/README.md and PACKAGES.md tell applications that every `stripe` minor release moves the API version webhooks must match, so they pin it with `~`. Validated: pnpm check (format, typecheck, 31 script tests, 208 Vitest tests) passes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…rts what changed reconcileStale finds only owners holding a current subscription without access, so an event missed during a Stripe API version move (a cancellation, a portal-scheduled cancellation, a refund) is never repaired by it. reconcileAll keyset-pages every account with a customer, resyncs each under its owner lock, and returns the owners whose subscription rows changed with the rows before and after, plus each failure, without stopping. A dry run rolls each owner's transaction back, so it reports what would change and writes nothing. Its report is the measurement a cut-over needs: each changed owner is one event that was lost. BILLING.md's migration step 5 now names it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
nedtwigg
marked this pull request as ready for review
November 10, 2026 21:02
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves
@pgstencil/stripefromstripe22 to 23 (API2026-08-26.dahlia→2026-10-28.endive) and adds a reconcile that covers every owner, so a consumer can prove an API version move lost nothing.Draft until the sandbox rehearsal is done. Everything here ran against StripeDev; nothing has reached api.stripe.com. This PR raises no package version, so merging it releases nothing.
What changes for a consumer
stripe ^23.1.0. Everystripeminor moves the pinned API version (23.0 pins2026-09-30.endive, 23.1 pins2026-10-28.endive), so the docs now tell consumers to pinstripewith~and treat any move as the endpoint procedure inBILLING.md→ "Moving to a new Stripe API version".allowed_payment_method_types: ['card']. v23 removespayment_method_types. The new parameter filters the methods Stripe would offer instead of listing them. This also changes Checkout's idempotent parameters, so a creation retried across the deploy is refused.pausedis a reachable status, through the pause endpoint or the portal's opt-in pause flow. It denies access and blocks another checkout.reconcileStaledoes not pick up a paused owner.reconcileAll({ dryRun?, pageSize? })pages every account with a customer, resyncs each under its owner lock, and returns the owners whose subscription rows changed, with the rows before and after, plus each failure, without stopping. A dry run rolls each owner's transaction back.reconcileStalefinds only owners holding a current subscription without access, so it never repairs a cancellation or refund missed during a cut-over.No migration is added or changed. No field pgstencil reads changed type between the two API versions.
Cut-over behavior, from the code
ON CONFLICT DO NOTHINGand processing stops if it was already handled. A delivery that fails verification records nothing, so it cannot block the other endpoint's copy.api_versioncheck. Each release handles its own endpoint's deliveries and answers 400 to the other's.Verification
pnpm checkpasses on the branch (format, typecheck, script tests, 209 Vitest tests).reconcileAll's tests fail with the resync removed and with the dry-run rollback removed.pnpm packages:packproduces clean archives; Dormouse Hosted is being built and tested against them on a rehearsal branch.Not verified, and how to verify it
All of these need a Stripe sandbox:
allowed_payment_method_typessucceeds, alone and with automatic tax.2026-10-28.endiveis accepted and its events verify.reconcileAllthat reports no changed owner.StripeDev remains partial: it has no invoices, payments, or refunds, and does not serve the pause endpoint.
🤖 Generated with Claude Code