···1717- `stripe_customer_id` (text, unique)
1818- `stripe_subscription_id` (text, unique, nullable)
1919- `plan` (text) — Price ID from `stripe/products.ts`, e.g., `pro_monthly_v1_usd`
2020-- `status` (text) — mirrors Stripe: `trialing`, `active`, `past_due`, `canceled`, `unpaid`
2020+- `status` (text) — mirrors Stripe (`trialing`, `active`, `past_due`, `canceled`, `unpaid`) plus custom `canceling` (set when `cancel_at_period_end` is true, indicates subscription is active but will not renew)
2121- `current_period_end` (timestamp)
2222- `created_at`, `updated_at`
2323···34343535### SKU → Entitlements Mapping
36363737-Entitlements for each Stripe Product are stored in Stripe's product metadata, not locally. Example product metadata:
3737+Entitlements for each product are defined in code (`stripe/products.ts`) alongside the product definitions. The sync script pushes this metadata to Stripe for consistency, but the codebase is the source of truth.
3838+3939+Example from `stripe/products.ts`:
38403941```json
4042{
···4244}
4345```
44464545-This keeps Stripe as the source of truth for what each SKU grants.
4747+The sync script ensures Stripe metadata stays in sync with code definitions.
46484749### Stripe Product Sync
4850