Subscriptions
Reconcile web and store purchases into one account-bound entitlement snapshot.
Unified entitlement is account-bound. A host maintains one authoritative subscription snapshot per Better Auth user; clients read isEntitled rather than reimplementing entitlement math.
Purchase paths
| Surface | Provider path | Shared result |
|---|---|---|
| Web host | Creem or Stripe webhook | Updates the host subscription snapshot |
| Swift / Expo iOS | RevenueCat + App Store | RevenueCat webhook updates the same snapshot |
| Kotlin / Expo Android | RevenueCat + Google Play | RevenueCat webhook updates the same snapshot |
| Electron / Tauri | Host checkout | Opens validated provider checkout and refreshes the snapshot |
Before starting a purchase, refresh the authoritative snapshot and block a second channel while entitlement is active. Webhooks must verify signatures or authorization, map explicit product IDs, and protect against duplicate or out-of-order events.
Management UI follows the active provider: use the host portal for Web purchases, RevenueCat or store management for mobile purchases, and a clear unavailable state when no portal exists.
Do not mix Supabase subscription state with a Unified Better Auth session. Backend, RevenueCat identity, purchase guard, and entitlement cache change together.
