Stripe checkout, pricing, subscription, Pro plan, webhook, and entitlement runbook for cmux billing work. Use when editing or debugging billing, pricing, Stripe Checkout, subscription recording, Pro plan status, webhooks, entitlement metadata, or pricing dev/prod tooling.
cmux-billing is an internal runbook skill for the cmux project that documents how the product's billing, pricing, subscription, and entitlement systems work. It is meant to be read before editing or debugging anything related to Stripe Checkout, the Pro plan, webhooks, subscription recording, entitlement metadata, or the dev/prod pricing tooling, so that changes respect the existing architecture instead of breaking it.
The document maps the billing endpoints and their responsibilities: `/api/billing/checkout` creates Stripe Checkout Sessions and falls back to a legacy purchase path, `/api/billing/portal` opens a Stripe customer portal, `/api/billing/subscription` cancels or resumes subscriptions, and a shared idempotent recorder attaches purchases without cross-granting on unverified emails. It explains the entitlement model (the cmuxPlan metadata field, a manual override, and how Pro status is resolved by OR-ing legacy products with active Stripe subscription rows), and describes the signature-verified, insert-first idempotent webhook handler. It also gives a dev workflow (dev scripts, per-branch Postgres ports, dogfooding with anonymous buyers and a reset script), test-mode product and price identifiers, feature-flag gating, a production runbook for provisioning live keys and running DB migrations, and a list of common gotchas around mocking, DrizzleQueryError handling, and next-intl routing.
It targets cmux engineers working on billing code. Use cases include adding or fixing a checkout flow, debugging webhook idempotency, adjusting Pro entitlement resolution, and safely running staging-then-production migrations. The credential handling it describes (STRIPE_SECRET_KEY, operator keys, Vercel envs, signature verification) follows standard official Stripe tooling with no exfiltration.
It is a reference runbook to read before changing cmux billing, pricing, Stripe Checkout, Pro entitlement, webhook, or subscription code, so edits align with the existing architecture and idempotency guarantees.
The cmuxPlan field in Stack clientReadOnlyMetadata is the only entitlement the VM code reads, with a cmuxVmPlan manual override taking precedence. Pro status is resolved by OR-ing legacy Stack products with active Stripe subscription rows.
The webhook endpoint is signature-verified and insert-first idempotent through a stripe_webhook_events table, is safe for foreign events in a shared Stripe account, and gates cmux handling on a metadata.app === "cmux" check. It returns 2xx only after durable writes and 500 to force Stripe retries.
Checkout activates only when STRIPE_SECRET_KEY is set; live provisioning runs a provision script with an operator key and adds two Vercel environment variables. This is standard official Stripe/Vercel credential handling, and the shared recorder never cross-grants based on an unverified email.
Process-global module mocks must carry every real export, tests must not depend on DATABASE_URL, drizzle wraps pg errors in DrizzleQueryError (read error.cause for code/constraint), and pages outside app/[locale] need a proxy.ts bypass and their own layout to avoid 404s.
Quick Setup:
.claude/skills/Repository
manaflow-ai/cmux