The external/payment half of monetisation (PAR-193), split out because it needs design sign-off + Stripe credentials and is outward-facing (real payment surface). Built on the metering foundation already shipped (usage_event + tenant.seat_limit).
Scope (design-first, needs decisions on tiers + what's metered/charged):
tenant (plan id, seat allowance, AI token allowance); seed a free tier.usage_event (ai_tokens) and report/charge overage (Stripe usage records or invoice items).Note: keep secrets out of the repo; verify webhook signatures; this is workspace-level billing.
Verification: scaffolding only — keeping open (consistent with the ticket's "design-first, needs Stripe credentials"). Present: plan table + free/pro/enterprise seed and tenant.plan_id/stripe_customer_id/... (V25); BillingService (plans, seat limit, token allowance/overage); a StripeWebhookController + StripeBillingProvider. Not done: no Stripe SDK (com.stripe:stripe-java) — raw HTTP stubs only; no billing API surface or plan-selection/checkout UI in tesks-ui; webhook only flips subscription state; no upsell journey. Real Stripe integration + UI still required.
Closing as won't-do-now / revisit later (not Done). Stripe billing isn't on the roadmap for the next ~6 months, and by the time it is, the app's architecture is likely to be materially different — so this should get a fresh design pass rather than being implemented against today's assumptions. The metering foundation (usage_event, seat_limit, plan schema) stays in place. Billing won't be forgotten when the time comes; re-open/re-scope then.
Implemented + inert (tesks
8880281) — drop-in for later, no live Stripe yet, per the brief.Settled & built: plan model (free/pro/enterprise seeded, with seat + AI-token allowances + a
stripe_price_idslot),tenant.plan_id+ Stripe customer/subscription/status columns;BillingService(effective seat limit = tenant override else plan; token allowance/period-usage/overage;applySubscription/applyByCustomer); seat enforcement now plan-aware;BillingProviderinterface withDisabledBillingProvideractive by default;StripeBillingProvider(raw Stripe REST, no SDK) +StripeWebhookController(full signature verify + event→state mapping) gated ontesks.billing.enabled=true. 7 tests; suite 131 green.To go live (2-min wiring, ~2 months): 1) set
tesks.billing.enabled=true+stripe-secret-key+stripe-webhook-secret; 2) setplan.stripe_price_idfor paid plans; 3) point a Stripe webhook at/billing/webhook; 4) add the checkout/portal entry points to the UI (PAR-203). Checklist also inStripeBillingProvider's javadoc.Marking Pending Release (the scaffolding ships; activation is config, not code).