123 lines
3.4 KiB
JSON
123 lines
3.4 KiB
JSON
{
|
|
"schemaVersion": "1.0",
|
|
"id": "billing",
|
|
"title": "Billing and Subscriptions",
|
|
"classification": "core",
|
|
"status": "proposed",
|
|
"owner": "core-pruning",
|
|
"description": "Minimal Stripe-backed subscription, pricing settings, subscription settings, and webhook handling.",
|
|
"rationale": [
|
|
"A SaaS boilerplate usually needs billing as a default capability.",
|
|
"The retained surface should be minimal and separate from marketing pricing presentation."
|
|
],
|
|
"codeAreas": [
|
|
"apps/web/app/routes/subscribe.$tenant*",
|
|
"apps/web/app/routes/app.$tenant/settings/subscription.tsx",
|
|
"apps/web/app/routes/admin/settings/pricing*",
|
|
"apps/api/src/app.ts",
|
|
"/v1/billing/stripe/webhooks",
|
|
"apps/web/app/application/pricing (admin billing-plan metadata, not public marketing pricing)",
|
|
"apps/web/app/components/core/pricing (admin billing-plan configuration)",
|
|
"apps/web/app/components/core/settings/subscription",
|
|
"stripe"
|
|
],
|
|
"dependencies": [
|
|
"auth-tenancy",
|
|
"transactional-mail"
|
|
],
|
|
"consumers": [
|
|
"core",
|
|
"admin-app-shell"
|
|
],
|
|
"integration": {
|
|
"ownership": "hybrid",
|
|
"surfaces": {
|
|
"adminRoutes": [
|
|
"apps/web/app/routes/admin/settings/pricing*"
|
|
],
|
|
"tenantRoutes": [
|
|
"apps/web/app/routes/app.$tenant/settings/subscription.tsx",
|
|
"apps/web/app/routes/subscribe.$tenant*"
|
|
],
|
|
"publicRoutes": [],
|
|
"apiRoutes": [
|
|
"apps/api/src/app.ts",
|
|
"/v1/billing/stripe/webhooks"
|
|
]
|
|
},
|
|
"configuration": {
|
|
"admin": [
|
|
"Plans, prices, billing policy"
|
|
],
|
|
"tenant": [
|
|
"Subscription selection and billing portal actions"
|
|
],
|
|
"environment": [
|
|
"STRIPE_SK",
|
|
"STRIPE_WEBHOOK_SIGNING_SECRET",
|
|
"STRIPE_ACCOUNT_COUNTRY"
|
|
],
|
|
"secrets": [
|
|
"Stripe keys are platform/admin-owned, never tenant-owned."
|
|
]
|
|
},
|
|
"workers": {
|
|
"required": false,
|
|
"queues": [],
|
|
"jobs": [],
|
|
"notes": [
|
|
"Webhook handling is request-driven unless later converted to queue processing."
|
|
]
|
|
},
|
|
"externalProviders": [
|
|
"stripe"
|
|
],
|
|
"permissions": [
|
|
"admin.pricing.*",
|
|
"app.settings.subscription.*"
|
|
],
|
|
"auditEvents": [
|
|
"billing.plan.updated",
|
|
"billing.subscription.updated",
|
|
"billing.webhook.received"
|
|
],
|
|
"billingImpacts": [
|
|
"Owns subscription and pricing foundation."
|
|
],
|
|
"uat": [
|
|
"Admin can configure pricing.",
|
|
"Tenant can view/update subscription.",
|
|
"Stripe webhook updates subscription state."
|
|
]
|
|
},
|
|
"boundaries": {
|
|
"mustKeep": [
|
|
"Stripe subscription and webhook foundation",
|
|
"Admin pricing configuration",
|
|
"Tenant subscription settings"
|
|
],
|
|
"mayMoveToPlugin": [
|
|
"Portal-oriented pricing flows not required by the app shell",
|
|
"Provider-specific billing extensions beyond Stripe",
|
|
"Advanced billing analytics beyond subscription state"
|
|
],
|
|
"mustNotTouch": [
|
|
"Tenant subscription checkout and success routes",
|
|
"Navigation changes owned by parallel workers"
|
|
]
|
|
},
|
|
"pruning": {
|
|
"phase": "1",
|
|
"action": "keep",
|
|
"notes": [
|
|
"Keep billing as core. Public marketing pricing was pruned; admin pricing and tenant subscription flows remain."
|
|
]
|
|
},
|
|
"validation": {
|
|
"source": [
|
|
"docs/feature-inventory.md"
|
|
],
|
|
"lastReviewed": "2026-05-05"
|
|
}
|
|
}
|