feat(billing): add Stripe subscriptions and paywall middleware
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.