Skip to content

fix: preserve active Pro entitlement on stale Stripe webhooks - #2336

Open
richiemcilroy wants to merge 2 commits into
mainfrom
codex/fix-stale-pro-webhooks
Open

richiemcilroy wants to merge 2 commits into
mainfrom
codex/fix-stale-pro-webhooks

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Sep 22, 2026

Copy link
Copy Markdown
Member

Summary

  • Keep an entitled Pro subscription on the user record when an earlier checkout expires or is deleted.
  • Prefer active or trialing Pro subscriptions over past-due ones and preserve the combined entitled seat quota.
  • Read every Stripe subscription page before choosing the effective subscription.

Incident

An abandoned checkout's customer.subscription.updated event arrived after a paid checkout and overwrote the user's active Pro status with incomplete_expired. Two affected production accounts have been reconciled separately.

Verification

  • Biome check on both touched files
  • bun run test __tests__/unit/signed-baa-webhook.test.ts --silent --reporter=dot (36 passed)

Comment on lines +778 to +782
const currentSubscription = effectiveProSubscription(
subscription,
subscriptions.data,
);
const inviteQuota = proInviteQuota(subscriptions.data);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Pagination can revoke entitlement

If a customer has more than 100 subscription attempts, their entitled Pro subscription can be on a later Stripe page. This code only selects from the first 100 records, so a stale canceled or expired webhook can fall back to its own subscription and overwrite the user's active entitlement. Fetch all subscription pages before choosing the effective subscription and calculating the combined quota. The deleted-event path at lines 911–926 has the same problem.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/api/webhooks/stripe/route.ts
Line: 778-782

Comment:
**Pagination can revoke entitlement**

If a customer has more than 100 subscription attempts, their entitled Pro subscription can be on a later Stripe page. This code only selects from the first 100 records, so a stale canceled or expired webhook can fall back to its own subscription and overwrite the user's active entitlement. Fetch all subscription pages before choosing the effective subscription and calculating the combined quota. The deleted-event path at lines 911–926 has the same problem.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

This branch was successfully deployed

1 active deployment
Preview cf29d33d Deployed Sep 22, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant