Skip to content

C4 Level 1 — System Context

Generated from a canonical source

This page is a read-only projection of docs/architecture/c4-context.md. Edit the canonical file, then run npm --prefix tools/project-knowledge-derive run derive.

Structural diagram. Not yet engineering-confirmed (see sign_off above) — treat as a candidate representation to be corrected against the as-built system, not as ratified fact.

GitHub does not render the experimental C4Context mermaid block, so this uses a plain flowchart (same convention as the ERD, which uses erDiagram for the same reason).

flowchart TB
    MerchantAdmin["Merchant Admin<br/>(person)"]
    Subscriber["Subscriber<br/>(person)"]
    Developer["Developer<br/>(person)"]
    SupportOps["Support / Ops<br/>(person)"]

    Platform["bc-subscriptions platform<br/>(system in focus)<br/>Subscription agreements, charge history,<br/>plan config, eligibility, dunning,<br/>entitlement, allotment, actors,<br/>delivery instances, event/audit log"]

    BC["BigCommerce platform<br/>(external system)<br/>Catalog, pricing, price lists,<br/>customer profile, customer groups,<br/>orders, order status/fulfillment"]

    Processor["Payment processor<br/>(external system)<br/>BC Payments vault (Braintree) / Stripe<br/>Payment method tokens, settlement, payout"]

    Email["Email delivery<br/>(external system)<br/>Resend (transactional notifications)"]

    Sentry["Sentry<br/>(external system)<br/>Error tracking / observability"]

    MerchantAdmin -->|"configures plans, eligibility, dunning"| Platform
    Subscriber -->|"self-serves subscriptions via portal"| Platform
    Developer -->|"integrates via SDK/API/webhooks"| Platform
    SupportOps -->|"reconciles charges, resolves failed renewals"| Platform

    Platform -->|"read-through: catalog, pricing, price lists, customer profile, customer groups"| BC
    Platform -->|"webhook-consume: order status, fulfillment state"| BC
    Platform -->|"pointer-reference: bc_order_id, plan-config metafield"| BC

    Platform -->|"pointer-reference: payment_method_ref (vault token)"| Processor
    Platform -->|"read: settlement + payout (reconciliation)"| Processor

    Platform -->|"sends transactional notifications"| Email
    Platform -->|"emits errors / traces"| Sentry

Provenance table

Element Type Cited source
bc-subscriptions platform (system in focus) System ARCHITECTURE.md §0 (lines 38–58, five-deployable Cloudflare stack: admin, portal, Catalyst storefront, API/webhooks, D1/KV/Queues — R2 is listed in §0 prose but bound by no product-runtime Worker, so it is omitted here per the fabrication guard)
Subscription agreement, charge history, plan config, eligibility, dunning, event/audit log Platform capability labels ARCHITECTURE.md §3 rows: "Subscription agreement," "Charge history," "Plan configuration," "Eligibility rules," "Dunning policies," "Event / audit log" — all marked "We are the SoR"
Entitlement, AllotmentGrant, actors, DeliveryInstance Platform capability labels ARCHITECTURE.md §3 rows: "Entitlement state," "AllotmentGrant," "Multi-actor membership (actors[])," "DeliveryInstance" — all marked "We are the SoR"
Merchant Admin (actor) Human actor BRD.md §3 (line 74, persona list) + PRD.md §5.1 (lines 83–88, primary buyer + daily user)
Subscriber (actor) Human actor BRD.md §3 (line 75) + PRD.md §5.2 (lines 90–94, end consumer, portal self-service)
Developer (actor) Human actor BRD.md §3 (line 76) + PRD.md §5.3 (lines 96–99, headless SDK / webhooks / API)
Support / Ops (actor) Human actor BRD.md §3 (line 77) + PRD.md §5.4 (lines 101–104, reconciles failed renewals, one screen for dunning state)
"configures plans, eligibility, dunning" (edge) Relationship PRD.md §5.1 persona description (merchant runs the store, owns plan/catalog setup) + ARCHITECTURE.md §3 rows "Plan configuration"/"Eligibility rules"/"Dunning policies" (we are SoR, merchant-configured)
"self-serves subscriptions via portal" (edge) Relationship PRD.md §5.2 (skip/swap/pause/update payment/reschedule "from one portal")
"integrates via SDK/API/webhooks" (edge) Relationship PRD.md §5.3 ("headless SDK, webhooks, stable API")
"reconciles charges, resolves failed renewals" (edge) Relationship PRD.md §5.4 ("reconciles failed renewals... payment method health, dunning state")
BigCommerce platform (external system) External system ARCHITECTURE.md §3 rows: "Product catalog," "Pricing (base)," "Price Lists," "Customer profile," "Customer group membership," "Orders," "Order status + fulfillment state" — all marked SoR = BigCommerce
"read-through: catalog, pricing, price lists, customer profile, customer groups" (edge) Relationship ARCHITECTURE.md §3 "Our Copy?" column: "Read-through; never cached beyond 5 min" (catalog), "Read-through" (pricing, price lists), "Read; mirror only what we need" (customer profile), "Read at runtime" (customer group membership)
"webhook-consume: order status, fulfillment state" (edge) Relationship ARCHITECTURE.md §3 row "Order status + fulfillment state" → "Our Copy?": "Read via webhook"
"pointer-reference: bc_order_id, plan-config metafield" (edge) Relationship ARCHITECTURE.md §3 row "Orders" → "Our Copy?": "We store a bc_order_id pointer only"; row "Plan configuration" → "(pointer stored as BC metafield for discoverability)"
Payment processor (external system) External system ARCHITECTURE.md §3 row "Payment method tokens (vault)" — "Processor (BC Payments → Braintree, or Stripe)"; apps/api/src/adapters/bc-payments.ts and apps/api/src/adapters/stripe.ts (real, non-stub ProcessorAdapter implementations)
"pointer-reference: payment_method_ref (vault token)" (edge) Relationship ARCHITECTURE.md §3 row "Payment method tokens (vault)" → "Our Copy?": "We store payment_method_ref only"
"read: settlement + payout (reconciliation)" (edge) Relationship ARCHITECTURE.md §3 row "Payment settlement + payout" → "Our Copy?": "Read for reconciliation"
Email delivery (external system) External system ARCHITECTURE.md §2.7 "Shared Architectural Decisions" (line 162): "Email: Resend (SendGrid as swap candidate)" — this subsection sits before, and is distinct from, the rejected-approach comparison content starting at §5
Sentry (external system) External system ARCHITECTURE.md §0 as-built table (line 57): "Observability (Phase 1) — Workers Analytics + Sentry"
"sends transactional notifications" (edge) Relationship ARCHITECTURE.md §3 row "Customer profile" → "Our Copy?": "mirror only what we need (name, email for notifications)"; §2.7 line 162 (Resend as the email provider)
"emits errors / traces" (edge) Relationship ARCHITECTURE.md §0 (line 57), Sentry as as-built observability sink

Systems of Record summary

Per ARCHITECTURE.md §3 (line 204): "we are a system of systems, not a commerce platform. We own the subscription, charge, and rule data models; everything else we read-through, webhook-consume, or pointer-reference."

  • We own: subscription agreement, charge history, plan configuration, eligibility rules, dunning policies, event/audit log, subscriber portal auth session, app install credentials, entitlement state, allotment grants, multi-actor membership (actors[]), delivery instances.
  • BigCommerce owns: product catalog/variants, base pricing, price lists, customer profile, customer group membership, orders, order status/fulfillment state.
  • The processor owns: payment method tokens (vault) and settlement/payout — via BC Payments (Braintree) or Stripe, per apps/api/src/adapters/bc-payments.ts and apps/api/src/adapters/stripe.ts. (A third adapter, apps/api/src/adapters/authnet.ts, exists as a Phase-1 stub whose charge() always throws — excluded from this diagram as not yet a live external dependency.)

Actor roles vs. product personas — do not conflate

The edges above are drawn from the four product personas (BRD.md §3, PRD.md §5): Merchant Admin, Subscriber, Developer, Support/Ops. These are the human actors of this context diagram.

Separately, PRD-COMPANION.md §D19 (line 466, ADR-0023) defines a per-subscription domain concept: a multi-actor role enum (owner / payer / beneficiary / manager / org_admin) attached to the actors[] table (ARCHITECTURE.md §3, "Multi-actor membership on subscription"). A single Subscriber persona can hold one or more of these roles on a given subscription (e.g., "payer" and "beneficiary"), and a Merchant-side actor (e.g., a CS rep) can hold "manager." This role enum is internal domain modeling, not a fifth persona — it does not appear as a separate box or actor in this context diagram.