[PR #8476] Implement grouped Stripe subscription targeting #8000

Open
opened 2026-03-13 13:56:16 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8476
Author: @hasdfa
Created: 3/7/2026
Status: 🔄 Open

Base: canaryHead: tunis


📝 Commits (10+)

  • c510ad9 Implement grouped Stripe subscription targeting
  • 6d54766 Fix Stripe subscription success subscription lookup
  • e6d185f Clean up Stripe webhook subscription create payload
  • ec5da6d Handle stale Stripe subscription IDs in routes
  • 5342a0a Clean up stale Stripe restore subscriptions
  • 1a95b2e Fix Stripe CI regression tests
  • afbe760 Fix Stripe test spell lint
  • fc39d14 Merge branch 'canary' into tunis
  • 1919ee6 Merge branch 'canary' into tunis
  • 2c4605d Merge branch 'canary' into tunis

📊 Changes

10 files changed (+1611 additions, -281 deletions)

View changed files

📝 docs/content/docs/plugins/stripe.mdx (+42 -3)
📝 packages/stripe/src/error-codes.ts (+6 -0)
📝 packages/stripe/src/hooks.ts (+169 -64)
📝 packages/stripe/src/metadata.ts (+3 -0)
📝 packages/stripe/src/routes.ts (+256 -107)
📝 packages/stripe/src/schema.ts (+5 -0)
📝 packages/stripe/src/types.ts (+1 -1)
📝 packages/stripe/src/utils.ts (+16 -0)
📝 packages/stripe/test/stripe-organization.test.ts (+9 -17)
📝 packages/stripe/test/stripe.test.ts (+1104 -89)

📄 Description

Summary

  • implement real Stripe subscription group support with persisted subscription.group
  • scope list/cancel/restore and upgrade targeting by referenceId + group while keeping omitted group unscoped
  • normalize missing groups to "default" for matching and add compatibility tests for legacy rows and grouped webhook behavior

Details

This proposal turns the existing Stripe group field from dead metadata into an actual subscription lane.

Key behavior:

  • one active or trialing subscription per referenceId + group in plugin-managed flows
  • plans without a configured group are treated as default for matching
  • omitting group in list/cancel/restore remains unscoped across all groups
  • explicit group: "default" targets legacy rows with no stored group
  • grouped webhook reconciliation updates only the matching lane

Verification

  • pnpm test --run test/stripe.test.ts in packages/stripe
  • result: 106 passed (106)

Summary by cubic

Adds first-class subscription groups to the stripe plugin and tightens targeting across APIs, webhooks, and the success redirect. Also hardens cancel/restore by pruning stale local rows when Stripe returns missing or non-active subscriptions and returning clear errors.

  • New Features

    • upgrade/list/cancel/restore accept optional group; omit to search all groups, or pass "default" to target legacy/no-group rows.
    • Enforces one active/trialing subscription per referenceId + group; throws AMBIGUOUS_SUBSCRIPTION_GROUP/AMBIGUOUS_SUBSCRIPTION_TARGET and SUBSCRIPTION_GROUP_MISMATCH when a subscriptionId points to another group.
    • Webhooks resolve by subscriptionId or group and update only that lane; internal metadata now includes group; missing grouped rows can be created.
    • Success handler updates only the Checkout Session’s subscription via its subscription ID; avoids touching other active grouped lanes.
    • Cancel/restore resolve the exact target with group-aware checks; Stripe resource_missing or non-active lookups map to SUBSCRIPTION_NOT_FOUND and delete stale local rows.
    • list supports group filtering and returns only active/trialing subscriptions.
  • Migration

    • If multiple groups can be active, pass group or subscriptionId to cancel/restore/upgrade to avoid ambiguity errors.
    • If you manage the DB schema manually, add a nullable group_name column to the subscription table.

Written for commit 00a21fab3a. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/8476 **Author:** [@hasdfa](https://github.com/hasdfa) **Created:** 3/7/2026 **Status:** 🔄 Open **Base:** `canary` ← **Head:** `tunis` --- ### 📝 Commits (10+) - [`c510ad9`](https://github.com/better-auth/better-auth/commit/c510ad9087a8b87ca860461473a98d9cf85daf89) Implement grouped Stripe subscription targeting - [`6d54766`](https://github.com/better-auth/better-auth/commit/6d54766116a81e11e217f300c4d3c74ed84101e8) Fix Stripe subscription success subscription lookup - [`e6d185f`](https://github.com/better-auth/better-auth/commit/e6d185f7fe3ca4ac70f4eca0b79dcb07456d7ba0) Clean up Stripe webhook subscription create payload - [`ec5da6d`](https://github.com/better-auth/better-auth/commit/ec5da6d67855e9aa2b89e7182d7fae3ba47e0010) Handle stale Stripe subscription IDs in routes - [`5342a0a`](https://github.com/better-auth/better-auth/commit/5342a0a6c8f178685a7345f250daa4f6a8c3cf37) Clean up stale Stripe restore subscriptions - [`1a95b2e`](https://github.com/better-auth/better-auth/commit/1a95b2ebf37061ca8e347b218ed3eb058586c552) Fix Stripe CI regression tests - [`afbe760`](https://github.com/better-auth/better-auth/commit/afbe7602471e8ca2bd76d6de61ff95671385bc76) Fix Stripe test spell lint - [`fc39d14`](https://github.com/better-auth/better-auth/commit/fc39d14226acb6bb31dc7bea5ed850ed975b6593) Merge branch 'canary' into tunis - [`1919ee6`](https://github.com/better-auth/better-auth/commit/1919ee6fe5f664655f5431b5d4bb66996f2ee1cf) Merge branch 'canary' into tunis - [`2c4605d`](https://github.com/better-auth/better-auth/commit/2c4605dcbfb15df6fce3915b418399fc8476fc1f) Merge branch 'canary' into tunis ### 📊 Changes **10 files changed** (+1611 additions, -281 deletions) <details> <summary>View changed files</summary> 📝 `docs/content/docs/plugins/stripe.mdx` (+42 -3) 📝 `packages/stripe/src/error-codes.ts` (+6 -0) 📝 `packages/stripe/src/hooks.ts` (+169 -64) 📝 `packages/stripe/src/metadata.ts` (+3 -0) 📝 `packages/stripe/src/routes.ts` (+256 -107) 📝 `packages/stripe/src/schema.ts` (+5 -0) 📝 `packages/stripe/src/types.ts` (+1 -1) 📝 `packages/stripe/src/utils.ts` (+16 -0) 📝 `packages/stripe/test/stripe-organization.test.ts` (+9 -17) 📝 `packages/stripe/test/stripe.test.ts` (+1104 -89) </details> ### 📄 Description ## Summary - implement real Stripe subscription group support with persisted subscription.group - scope list/cancel/restore and upgrade targeting by referenceId + group while keeping omitted group unscoped - normalize missing groups to "default" for matching and add compatibility tests for legacy rows and grouped webhook behavior ## Details This proposal turns the existing Stripe group field from dead metadata into an actual subscription lane. Key behavior: - one active or trialing subscription per referenceId + group in plugin-managed flows - plans without a configured group are treated as default for matching - omitting group in list/cancel/restore remains unscoped across all groups - explicit group: "default" targets legacy rows with no stored group - grouped webhook reconciliation updates only the matching lane ## Verification - pnpm test --run test/stripe.test.ts in packages/stripe - result: 106 passed (106) <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds first-class subscription groups to the `stripe` plugin and tightens targeting across APIs, webhooks, and the success redirect. Also hardens cancel/restore by pruning stale local rows when Stripe returns missing or non-active subscriptions and returning clear errors. - **New Features** - `upgrade`/`list`/`cancel`/`restore` accept optional `group`; omit to search all groups, or pass `"default"` to target legacy/no-group rows. - Enforces one active/trialing subscription per `referenceId + group`; throws `AMBIGUOUS_SUBSCRIPTION_GROUP`/`AMBIGUOUS_SUBSCRIPTION_TARGET` and `SUBSCRIPTION_GROUP_MISMATCH` when a `subscriptionId` points to another group. - Webhooks resolve by `subscriptionId` or `group` and update only that lane; internal metadata now includes `group`; missing grouped rows can be created. - Success handler updates only the Checkout Session’s subscription via its `subscription` ID; avoids touching other active grouped lanes. - Cancel/restore resolve the exact target with group-aware checks; Stripe `resource_missing` or non-active lookups map to `SUBSCRIPTION_NOT_FOUND` and delete stale local rows. - `list` supports `group` filtering and returns only active/trialing subscriptions. - **Migration** - If multiple groups can be active, pass `group` or `subscriptionId` to `cancel`/`restore`/`upgrade` to avoid ambiguity errors. - If you manage the DB schema manually, add a nullable `group_name` column to the subscription table. <sup>Written for commit 00a21fab3abf9f4368afc3eb69f2d30a73d2b974. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-03-13 13:56:16 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8000