1. The system in one picture¶
Generated from a canonical source
This page is a read-only projection of docs/solution-review/01-system-in-one-picture.md.
Edit the canonical file, then run npm --prefix tools/project-knowledge-derive run derive.
What is being built, and for whom¶
bc-subscriptions is a subscription-management engine built natively on the BigCommerce platform. It owns the parts a commerce platform does not: the subscription agreement, the recurring-charge history, plan configuration, eligibility rules, dunning policy, entitlement state, and an event/audit log. Everything a store already knows — the product catalog, base pricing, customer profiles, orders, checkout — stays in BigCommerce and is read through, consumed by webhook, or referenced by pointer. The design principle is "a system of systems, not a second commerce platform."
It reaches merchants today as a BigCommerce Marketplace app: OAuth install
per merchant, an admin UI that loads inside BigCommerce's control panel, all
platform reads and writes over public v3 REST and Storefront APIs, webhooks in
both directions. That shape is a deliberate destination, not scaffolding — the
app is "marketplace-first, native-ready" per ADR-0029 (marketplace destination,
not waypoint; graduation to native is an option, not a commitment). The same
work also stands as a reference implementation of the capability restated in
BigCommerce-native terms, so a decision to build it first-party later has a
bounded lift rather than a rewrite. Deep dive:
../decisions/0029-marketplace-first-native-ready.md.
Context: the system and the outside world¶
flowchart TB
Merchant["Merchant staff<br/>(person)"]
Subscriber["Subscriber<br/>(person)"]
Support["Support / Ops<br/>(person)"]
Platform["bc-subscriptions<br/>(system in focus)<br/>Subscriptions, charges, plans,<br/>eligibility, dunning, events"]
BC["BigCommerce platform<br/>Catalog, pricing, customers,<br/>orders, checkout, webhooks"]
Processor["Payment processor<br/>BC Payments vault / Stripe<br/>Tokens, settlement"]
Email["Email delivery<br/>Transactional notifications"]
Merchant -->|"configures plans, dunning"| Platform
Subscriber -->|"self-serves via portal"| Platform
Support -->|"reconciles failed renewals"| Platform
Platform -->|"read-through: catalog / pricing / customers;<br/>webhook-consume: orders"| BC
Platform -->|"pointer-reference: vault token"| Processor
Platform -->|"sends notifications"| Email
bc-subscriptions is the system of record for subscription, charge, and rule
data. BigCommerce owns catalog, pricing, customers, orders, and hosted
checkout. The payment processor owns the card vault and settlement — the app
holds only a token reference, never card data (see
04-money-movement.md). Adapted from
../architecture/c4-context.md.
Runtime: the deployed pieces¶
flowchart TD
Merchant((Merchant / Staff))
Subscriber((Subscriber))
Admin["Admin UI (apps/admin)<br/>Vite + React + BigDesign<br/>CF Pages"]
API["subs-api<br/>OAuth, webhooks, REST, scheduler<br/>CF Workers"]
Portal["subs-storefront-svelte<br/>Subscriber portal + cart/checkout<br/>CF Workers + Pages"]
Widget["Storefront widget (apps/storefront-catalyst)<br/>Subscribe affordance / intent capture<br/>CF Pages"]
EmailC["subs-email-consumer<br/>Transactional email<br/>CF Workers (queue consumer)"]
Assistant["subs-assistant<br/>Ask-the-substrate chat<br/>CF Workers"]
DB[("subs-api-d1<br/>D1 (SQLite)")]
Q{{"EVENTS_QUEUE<br/>Queue: subs-events"}}
Merchant -->|"BC control-panel iframe"| Admin
Subscriber -->|"hosted portal"| Portal
Subscriber -->|"storefront widget / PDP"| Widget
Admin -->|"REST, signed JWT"| API
Portal -->|"service binding"| API
Widget -->|"REST"| API
API --> DB
API -->|"produces"| Q
API -->|"assistant handoff token"| Assistant
Q -->|"consumes"| EmailC
| Component | What it does | Runtime |
|---|---|---|
subs-api |
OAuth install handshake, inbound webhook receiver, merchant + portal REST API, and the billing scheduler on a scheduled() cron |
Cloudflare Workers |
subs-storefront-svelte |
Subscriber self-service portal and the storefront cart/checkout integration | Cloudflare Workers + Pages assets |
subs-email-consumer |
Consumes EVENTS_QUEUE and sends transactional email |
Cloudflare Workers (queue consumer) |
subs-assistant |
"Ask the substrate" chat over the project corpus; the API worker mints its handoff token | Cloudflare Workers |
Admin UI (apps/admin) |
Merchant admin SPA loaded inside BigCommerce's control panel | Vite + React + BigCommerce BigDesign, Cloudflare Pages (not a Worker) |
Storefront widget (apps/storefront-catalyst) |
Subscribe affordance and subscription-intent capture on the merchant storefront | Catalyst / Stencil, Cloudflare Pages |
subs-api-d1 |
System-of-record datastore: subscriptions, charges, plans, payment-method references, events | Cloudflare D1 (SQLite) |
EVENTS_QUEUE |
Event fan-out substrate feeding email and (designed) merchant webhooks | Cloudflare Queues |
The runtime view is adapted from
../architecture/c4-container.md, which is
mechanically generated from the deploy configs. Note one intentional
divergence: subs-assistant is a real product worker
(apps/assistant/wrangler.jsonc) but does not appear in the generated
container diagram, which parsed only wrangler.toml files.
Three UI surfaces, three host constraints¶
The product presents on three independently deployable surfaces. ADR-0005 (three-surface UI architecture) established the principle: each surface is its own deployment artifact and they communicate by contract only, never by shared bundle. A fourth artifact, the internal design prototype, is a reviewer-only reference, not a production surface.
| Surface | Who uses it | Auth model | BigCommerce embedding constraint |
|---|---|---|---|
| Merchant admin | Merchant staff | BigCommerce signed-JWT app-load (/api/load) over the store's OAuth grant |
Loads inside the control-panel iframe. An App Extension panel is limited to PANEL / LINK on the Products, Orders, and Customers pages — there is no cart or category context available to it |
| Subscriber portal | Signed-in subscribers | Portal session (magic-link / SSO handoff); subscribing requires a signed-in BigCommerce customer per ADR-0090 | Hosted by the app on Cloudflare, outside the storefront. The subscriber crosses a domain boundary from the merchant storefront into the portal |
| Storefront widget | Shoppers on the merchant storefront | Per-merchant Storefront API token / anonymous cart | Composed into the merchant's Catalyst/Stencil storefront. Because App Extensions have no cart context, subscribe intent cannot be captured from an admin extension — the widget lives in the storefront, where the cart is, and writes intent to cart metafields |
The last row is the load-bearing one for the rest of this package: the widget
exists specifically because the platform's admin-extension surface cannot see a
cart. Intent captured there flows into the money and event mechanics described
in 04-money-movement.md and
05-event-backbone.md. Deep dive:
../decisions/0005-three-surface-ui-architecture.md.
The runtime bet¶
Phase 1 runs entirely on Cloudflare: Workers for compute, D1 (SQLite) for the
datastore, Queues for event fan-out, KV for caches, cron triggers for the
billing scheduler. Phase 2 is a planned migration to Google Cloud — all web
surfaces to Cloud Run (containerized), the datastore to Cloud SQL (PostgreSQL
15). The migration shape is ratified in ADR-0030 (the Cloudflare → GCP phasing
authority, per ARCHITECTURE.md §0) with the managed-SQL engine chosen in
ADR-0054. Nothing in Phase 1 forecloses the move: tenant isolation is enforced
by mandatory store_hash scoping on every query, and the observability sink is
abstracted for a Phase-2 cutover. Deep dives:
../decisions/0030-bigeng-pattern-alignment.md,
../decisions/0054-cloud-sql-engine.md.
Words you'll hear¶
One line each; the full list is at
../methodology/glossary.md.
| Term | In one line |
|---|---|
| Stored instrument | A vaulted, tokenized card held by BigCommerce or Stripe; the app persists only the token, never the card. |
| Charge rail | The single gateway-agnostic path all recurring charges take — payments.bigcommerce.com against a stored instrument (ADR-0037). |
| PAT | Payment Access Token — a one-hour BigCommerce token, minted per order, that authorizes a stored-instrument charge. |
| MIT / MREC | Merchant-Initiated Transaction; MREC is its recurring-renewal subtype, the flag every off-session renewal carries. |
| Vault | The processor-hosted store of tokenized cards; "vault-at-checkout" is how a card first gets tokenized. |
| Off-session | A charge run with no shopper present — every renewal — as opposed to the cardholder-initiated first purchase. |
| Dunning | The retry-and-notify policy applied when a renewal charge fails, before a subscription is cancelled. |
| App Extension | A BigCommerce control-panel embedding slot (PANEL/LINK) on Products/Orders/Customers — no cart or category context. |
| Metafield | Arbitrary key/value data attached to a BigCommerce entity; subscribe intent rides a cart metafield the storefront widget writes. |
| Intent capture | Recording, at add-to-cart time, that a line is meant to be a subscription — the seed the order-created webhook turns into a subscription. |