Skip to content

improvement(checkout): enforce team/enterprise-only org subscription, block double-covered personal checkouts#5715

Merged
icecrasher321 merged 4 commits into
stagingfrom
improvement/billing-checkout
Jul 17, 2026
Merged

improvement(checkout): enforce team/enterprise-only org subscription, block double-covered personal checkouts#5715
icecrasher321 merged 4 commits into
stagingfrom
improvement/billing-checkout

Conversation

@icecrasher321

Copy link
Copy Markdown
Collaborator

Summary

Enforce team/enterprise-only org subscription, block double-covered personal checkouts and drop renewal-triggered workspace detach

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…, block double-covered personal checkouts, and drop renewal-triggered workspace detach
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 17, 2026 1:48am

Request Review

@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Changes touch auth middleware, Stripe adapter writes, checkout authorization, and webhook subscription lifecycle paths where incorrect gating could block legitimate billing or allow double billing.

Overview
Tightens billing invariants so organization subscriptions only ever hold Team or Enterprise plans, and users already covered by a paid org cannot start a personal checkout.

Checkout and auth hooks now block personal /subscription/upgrade when org coverage applies (assertPersonalCheckoutAllowed), and org checkouts reject non–team/enterprise plans, duplicate org subs, and unresolved Enterprise issuance via explicit APIErrors instead of silent false. The Better Auth DB adapter is wrapped with guardSubscriptionPlanWrites so Stripe plugin writes cannot persist a personal plan on an org-referenced row before webhooks run; syncSubscriptionPlan applies the same rule in callbacks and returns the effective DB plan for downstream webhook logic.

On personal Pro completion, pauseProSubscriptionForOrgCoverage closes the race where checkout finishes after the user joined a paid org—pausing renewal and skipping handleSubscriptionCreated when covered so usage is not reset incorrectly. Team subs still re-home onto the admin’s org under lock in ensureOrganizationForTeamSubscription.

handleOrganizationPlanDowngrade is removed from subscription update handling so plan/price changes no longer detach workspaces; dormancy/detach is documented as subscription deletion only, with bulk recordAuditBatch on workspace detach.

Reviewed by Cursor Bugbot for commit 37eb50d. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR tightens checkout and subscription handling for personal and organization plans. The main changes are:

  • Restricts organization subscriptions to Team and Enterprise plans.
  • Blocks personal checkout when an organization already covers the user.
  • Pauses personal Pro subscriptions created during an organization-coverage race.
  • Removes workspace detachment from plan-downgrade updates.
  • Adds batched audit records for workspace detachment.

Confidence Score: 5/5

This looks safe to merge.

  • The updated write guard preserves the intended organization plan in both adapter and callback paths.
  • Downstream subscription processing uses the persisted plan instead of the rejected Stripe plan.
  • No distinct blocking issue remains within the scope of this follow-up.

Important Files Changed

Filename Overview
apps/sim/lib/auth/auth.ts Integrates personal checkout checks, guarded subscription writes, effective-plan handling, and checkout-race cleanup.
apps/sim/lib/auth/stripe-adapter-guard.ts Prevents non-organization plans from being stored on organization-referenced subscriptions.
apps/sim/lib/billing/authorization.ts Adds plan and duplicate-coverage checks for personal and organization checkout requests.
apps/sim/lib/billing/core/subscription.ts Returns the persisted effective plan after synchronization and adds organization coverage lookup.
apps/sim/lib/billing/organization.ts Strengthens Team and Enterprise subscription re-homing with locked membership and plan checks.
apps/sim/lib/billing/organizations/membership.ts Adds transactional pausing for personal Pro subscriptions created while organization coverage exists.
packages/audit/src/log.ts Adds chunked batch insertion for audit records.

Reviews (4): Last reviewed commit: "fix(billing): compute org coverage indep..." | Re-trigger Greptile

Comment thread apps/sim/lib/billing/core/subscription.ts
Comment thread apps/sim/lib/auth/auth.ts
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

@icecrasher321

Copy link
Copy Markdown
Collaborator Author

@greptile

Comment thread apps/sim/lib/auth/auth.ts
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

@icecrasher321

Copy link
Copy Markdown
Collaborator Author

@greptile

Comment thread apps/sim/lib/billing/core/subscription.ts
Comment thread apps/sim/lib/billing/organizations/membership.ts Outdated
Comment thread apps/sim/lib/auth/stripe-adapter-guard.ts
…lookup and fail closed on unverifiable plan writes
@icecrasher321

Copy link
Copy Markdown
Collaborator Author

bugbot run

@icecrasher321

Copy link
Copy Markdown
Collaborator Author

@greptile

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 37eb50d. Configure here.

@icecrasher321
icecrasher321 merged commit 442eaba into staging Jul 17, 2026
20 checks passed
@waleedlatif1
waleedlatif1 deleted the improvement/billing-checkout branch July 17, 2026 15:09
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