Files
cgalo5758 71818de0bd Add setup checklist and empty-state guidance
Implement the ux-first-run change: a state-derived setup checklist on
/operator/setup with a landing region that recedes once required steps
are done, and empty states that distinguish blocked from empty across
operator and member surfaces. Also add production deployment and
environment reference docs, plus a config-key completeness test.
2026-08-23 03:06:11 -05:00
..

Stripe Integration (internal)

This package implements the Stripe provider integration. For self-hosting setup instructions, see docs/stripe.md.

Data flow

Operator creates product/price in MC
  → Row inserted into billing schema
  → Outbox entry enqueued (integration.outbox)
  → Temporal outbox poller picks up entry
  → Stripe API call (creates Stripe object)
  → Mapping row written (stripe.*_mappings)

Stripe sends webhook
  → POST /webhooks/stripe
  → Inserted into integration.webhook_events
  → Temporal webhook processor picks up event
  → Mapping row created/updated/confirmed
  → Core billing tables updated (subscriptions, invoices, payments)

Mapping tables

Each billing entity has a corresponding mapping table in the stripe schema:

MC table Mapping table Stripe ID column
billing.products stripe.product_mappings stripe_product_id
billing.prices stripe.price_mappings stripe_price_id
billing.accounts stripe.customer_mappings stripe_customer_id
billing.subscriptions stripe.subscription_mappings stripe_subscription_id
billing.invoices stripe.invoice_mappings stripe_invoice_id
billing.payments stripe.payment_mappings stripe_payment_intent_id

Each mapping row has a sync_status: pending, synced, or deleted.

No Stripe IDs appear on core billing tables (Decision 113). The mapping tables are the only join point.

Provider config

Stripe declares its configuration via ConfigSpec() (stripe-api-key, stripe-webhook-secret, stripe-mode); credentials live in environment variables, never in the database. Non-secret keys are operator-overridable app-wide via core.integration_config_overrides (see docs/building-an-integration.md §6). The former stripe.provider_configs singleton was dropped in migration 00002 — it was never read or written by any code.

Temporal workflows

Two long-running workflows in internal/integrations/stripe/workflows/:

  • stripe-outbox-poller (outbox.go) — Polls integration.outbox for pending entries, executes them (Stripe API calls), writes mapping rows. Uses ContinueAsNew.
  • stripe-webhook-processor (webhook.go) — Polls integration.webhook_events, dispatches to per-event-type handlers.

Both start automatically on member-console start.

Outbox actions

Action type Trigger Executor
create_stripe_customer Billing account creation executeCreateStripeCustomer
create_stripe_product Migration seed / operator UI executeCreateStripeProduct
create_stripe_price Migration seed / operator UI executeCreateStripePrice

Key files

  • migrations/ — Schema and mapping table DDL, seed outbox entries
  • queries/ — sqlc queries for mapping table CRUD
  • ensure_customer.go — Stripe Customer creation payload
  • internal/integrations/stripe/workflows/outbox.go — Outbox poller and executors
  • internal/integrations/stripe/workflows/webhook.go — Webhook event dispatcher and handlers
  • internal/server/stripe_webhook.go — HTTP handler for POST /webhooks/stripe