feat(billing): add Stripe subscriptions and paywall middleware

↗ view on GitHub · z · 2026-05-13 · ba00445b

Batch 5 - gate AI chat endpoints behind an active subscription
(or active 14-day trial) and record token usage against the
subscription's monthly limit.

Database:
- backend/migrations/001_add_subscriptions.sql: idempotent
  (CREATE IF NOT EXISTS), RLS-enabled, auto-provisions a trial
  row on every new auth.users insert via trigger.
- backend/schema.sql: mirror of the migration appended.

Backend:
- backend/src/lib/stripe.ts: Stripe SDK wiring.
- backend/src/lib/billing/usage.ts: recordTokenUsage() fire-and-
  forget bookkeeping after stream completion (never blocks the
  hot path, never throws).
- backend/src/routes/billing.ts: checkout/portal/webhook endpoints.
  Handles checkout.session.completed and
  customer.subscription.{created,updated,deleted}.
- backend/src/middleware/requireActiveSubscription.ts: paywall.
- backend/src/index.ts: mount raw-body parser ahead of express.json
  for the Stripe webhook signature check; gate POST /chat,
  /projects/:id/chat, /tabular-review/:id/chat, and
  /tabular-review/:id/generate with requireAuth + paywall.
- backend/.env.example: STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET,
  and STRIPE_PRICE_{STARTER,PROFESSIONAL,ENTERPRISE}.
- backend/package.json: stripe@^22.1.1 + vitest test runner.
- routes/{chat,projectChat,tabular}.ts: void recordTokenUsage(...)
  after each successful stream.

Frontend:
- frontend/src/lib/billing.ts: tier metadata + helpers.
- frontend/src/app/lib/mikeApi.ts: HTTP 402 interceptor redirects
  the browser to /pricing?reason=... on paywall rejection.

Tests:
- 6 middleware tests + 4 webhook tests (10 new tests total).

Agent ID: aa83ddc67d4dfac03 (general-purpose).
Repository hosman20/mike-2.0
Author z <z@zs-MacBook-Pro.local>
Authored
Parents 07a46ceb
Stats 17 files changed , +2831 , -521
Part of Stripe subscriptions, paywall middleware, and billing UI

Capture this commit into my fork

Download a Markdown prompt that tells Claude how to port this exact commit into your working tree. Run it via claude -p < capture-commit-ba00445b.md from inside the repo you want the change in.

⬇ Download capture-commit-ba00445b.md