feat(billing): Phase 16 — Stripe billing integration
Implements the full Phase 16 Stripe billing stack per docs/PHASE16-STRIPE-BILLING-PLAN.md §7 build order.
## What changed
### Step 1 — billing-constants.mjs - Rename `starter` → `plus` (backward-compat alias kept); add `growth` tier (68M tokens, $17/mo) - `pro` monthly token allowance set to `null` (unlimited) - Add `NOTE_CAP_BY_TIER`: free=200, plus=2 000, growth=5 000, pro=null - Add `PACK_TOKENS`: small=20M, medium=60M, large=150M - Add `addonTokensFromPackPriceId()` returning token grant per pack price ID - Add `isSubscriptionPriceId()`, `isPackPriceId()`, `priceIdFromTierShorthand()` helpers - Add `STRIPE_PRICE_GROWTH` env lookup in `tierFromEnvPriceId()`
### Steps 2+3 — server.mjs - `POST /api/v1/billing/checkout`: validates price_id / tier / pack_size, determines mode (subscription vs payment), creates Stripe Checkout Session, returns { url } - `POST /api/v1/billing/portal`: looks up or creates Stripe Customer, creates Billing Portal Session, returns { url }
### Step 4 — billing-stripe.mjs - `checkout.session.completed` payment handler now credits `pack_indexing_tokens_balance` from Stripe price metadata `indexing_tokens` (authoritative) with env-var fallback - Adds `createCheckoutSession()` and `createPortalSession()` exports
### Step 5 — billing-store.mjs - `resetMonthlyTokensIfNeeded(userId)`: resets `monthly_indexing_tokens_used` + advances `period_start/period_end` by one calendar month when period has expired - Called at top of `handleBillingSummary` and `runBillingGate`
### Step 6 — billing-middleware.mjs - Storage cap gate on note CREATE: fetches live note count via `getNoteCount` callback, checks against `NOTE_CAP_BY_TIER[tier]`, returns 402 STORAGE_QUOTA_EXCEEDED when over cap (only when BILLING_ENFORCE=true; shadow-logs when disabled) - `runBillingGate` accepts optional `opts.getNoteCount` async callback - server.mjs wires `getNoteCountForUser` (fetches canister total, fails open)
### Step 7 — Hub UI (hub.js + hub.css + index.html) - Plan badge with tier-coloured pill (free/plus/growth/pro) - Upgrade → button (Free/beta users, Stripe configured) - Manage billing → button (active subscription holders) - Token usage progress bar with warn/over colour states - Note cap display (N max from billing summary) - Pack rollover balance display - Token pack purchase cards (Small $10 / Medium $25 / Large $50) — visible on paid plans - Born Free Communities blurb with bornfree.io link - Period + renewal date display
### billing-http.mjs - Wires `resetMonthlyTokensIfNeeded` before loading summary - Adds `note_cap` and `has_active_subscription` fields to summary response
BILLING_ENFORCE remains false (shadow log mode). Keys/price IDs are set via Netlify env vars.
0 comments
muse hub commit comment sha256:29f0377812c07ce287028a495e3553c0209beddb7050b915a3b1628cfeacdfb3 --body "your comment"
No comments yet. Be the first to start the discussion.