Paradaux

PAR-202

0

Stripe billing — plans, checkout, webhooks, PAYG AI

CanceledNormalUnassignedTesksFeature

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):

  • Plan model on tenant (plan id, seat allowance, AI token allowance); seed a free tier.
  • Stripe: customer + subscription per workspace, Checkout for plan purchase, billing portal, webhook handling (subscription state → plan/seat_limit), test vs live mode via config/secrets.
  • PAYG AI: meter usage_event (ai_tokens) and report/charge overage (Stripe usage records or invoice items).
  • Cloud-only; self-hosted bypasses billing.

Note: keep secrets out of the repo; verify webhook signatures; this is workspace-level billing.

Resources

Comments

tesks · Jun 16, 2026, 10:00 AM

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_id slot), 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; BillingProvider interface with DisabledBillingProvider active by default; StripeBillingProvider (raw Stripe REST, no SDK) + StripeWebhookController (full signature verify + event→state mapping) gated on tesks.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) set plan.stripe_price_id for paid plans; 3) point a Stripe webhook at /billing/webhook; 4) add the checkout/portal entry points to the UI (PAR-203). Checklist also in StripeBillingProvider's javadoc.

Marking Pending Release (the scaffolding ships; activation is config, not code).

tesks · Jun 16, 2026, 8:11 PM

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.

tesks · Jun 16, 2026, 8:14 PM

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.

Activity

  • tesks changed status to Status → Canceled
  • tesks commented
  • tesks commented
  • ParadauxIO linked a commit — Commit 8880281 — Implement billing scaffolding (Stripe wired but inert) (PAR-202)
  • tesks changed status to Status → Pending Release
  • tesks commented
  • tesks changed status to Status → In Progress
  • tesks created the issue