This repository has been archived on 2026-07-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
identity-canon/research/commercial-subscription/stripe-customer-billing.md
tegwick 6ea582cd9e Resolve payment credential and CRM pipeline commitment boundaries
Add research on PCI/tokenized payment references vs login Credentials (Payment
Instrument Reference, Payment Mandate) and CRM Opportunity promotion thresholds
(Pipeline Pursuit, binding_trigger). Resolve OpenQuestions for both topics.
Update glossary, conceptual model, terminology, and downstream recommendations.
2026-06-21 23:11:00 +02:00

106 lines
4.7 KiB
Markdown

# Stripe Customer and Subscription Billing
## Source Type
Product API documentation and SaaS architecture practice. Stripe Customer object
and B2B subscription billing integration patterns.
## Domain
Commercial billing, payment methods, subscriptions, and tenant-to-billing linkage
in multi-tenant SaaS.
## Why This Source Matters
Stripe's Customer object is the most widely deployed example of a **billing
customer** that is explicitly not a login account. It demonstrates why
"customer account" must be split into commercial records vs. identity records.
## Key Concepts
- **Customer (Stripe)**: billing entity with email, name, payment methods,
subscriptions, balance, and invoice settings.
- **Subscription**: recurring billing agreement tied to a Customer.
- **Payment method**: card or bank source attached to Customer for charges.
- **Metadata**: key-value pairs linking Stripe Customer to app tenant ID.
- **Delinquent**: billing health flag on Customer from invoice state.
- **Business name / individual name**: Customer may represent company or person.
- **customer_account (Stripe API)**: newer field referencing an Account object
representing a customer — explicit split from legacy Customer.
- **Webhook-driven sync**: Stripe owns payment state; app database owns business
state; webhooks bridge them.
- **Tenant mapping**: standard pattern stores `stripe_customer_id` on tenant record.
## Relevant Terminology
| Term | Source meaning |
| --- | --- |
| Customer | Stripe billing object; not authentication identity. |
| Subscription | Recurring charge agreement. |
| Invoice | Bill document; drives delinquent state. |
| Payment method | Stored payment instrument. |
| Balance | Credit or amount owed on Customer. |
| Metadata | App-defined correlation (e.g., tenant_id). |
| customer_account | Stripe Account representing customer (newer API). |
| Tenant (app) | Application isolation unit linked via metadata. |
## Modeling Assumptions
- **Billing state lives in payment provider**; app caches plan/feature access.
- **One Stripe Customer per tenant** is the common B2B pattern (not per login user).
- **B2B Customer** often has `business_name`; B2C may use `individual_name`.
- **Customer email** is billing contact, not necessarily login email.
- **Commercial identity can exist without Organization** (sole proprietor, individual
plan).
- **CRM "Account"** (Salesforce-style) follows similar commercial-record pattern.
## Identity-Canon Implications
- Stripe **Customer** maps to **Commercial Record** in Record layer — not Account,
not Customer Account, not Organization.
- Link Commercial Record to **Tenant** Scope and/or **Organization** / **Natural
Person** actor via **Commercial Relationship** or Identifier binding.
- Stripe **customer_account** field reinforces separate commercial vs. identity
account split at API level.
- **Subscription state** is Lifecycle State on Commercial Record (downstream).
- Supports S04 when billing is modeled alongside vendor/customer orgs.
## Terminology Conflicts
- **Customer (Stripe) vs. Customer (relationship role)**: same word, different
layers — billing object vs. vendor/customer commercial role.
- **Customer vs. Account**: Stripe uses "customer" and emerging "customer_account"
deliberately separate from login accounts.
- **Customer vs. Tenant**: integration stores stripe ID on tenant; not same entity.
- **CRM Account vs. Account (login)**: Salesforce Account = commercial record.
## Candidate Canonical Mappings
| Stripe / billing concept | Candidate canonical concept |
| --- | --- |
| Customer object | Commercial Record |
| Subscription | Commercial Record lifecycle / entitlement metadata |
| Payment method | Payment Instrument Reference (not Credential) |
| SetupIntent / mandate | Payment Mandate (Commercial Commitment) |
| Metadata.tenant_id | Identifier binding to Tenant Scope |
| business_name | Commercial Record attribute |
| individual_name | Commercial Record attribute (person-backed) |
| customer_account (API) | Commercial Record variant / provider projection |
| Delinquent / balance | Lifecycle State on Commercial Record |
| Webhook event | Evidence Source for billing state change |
## Open Questions
- Does sole-proprietor billing (person-backed Commercial Record without
Organization) need a distinct pattern in scenario tests?
## Resolved (see payment-credential-pci-boundary.md)
- Payment methods → **Payment Instrument Reference**; mandates → **Payment Mandate**.
CHD out of canon; not **Credential**.
## References
- Stripe Customer object — https://docs.stripe.com/api/customers/object
- Stripe Billing — https://docs.stripe.com/billing
- Stripe org customer sharing — https://docs.stripe.com/get-started/account/orgs/sharing/customers-payment-methods