Defines a subscription integration that separates provider objects, internal service periods, money movements, and entitlement state so retries, prorations, cancellations, and reconciliation remain auditable.
Package status: reference context ready for human review. The contract and test scenarios are complete, but no claim is made that an adopting implementation has passed them.
Decision
Maintain an internal subscription projection from verified provider events, but record money movements and service entitlement as separate immutable facts. Provider status is input evidence, not the only business ledger.
Scope
- Customer mapping, plan/price versions, subscription lifecycle, invoices, payments, credits/refunds, service periods, entitlements, cancellations, event ordering, and reconciliation.
- Recurring provider-billed subscriptions.
- Accounting-oriented identities and lifecycle integration, not formal financial statements.
Outside this block
- Tax/accounting advice or a general ledger implementation.
- Assuming provider subscription status alone determines product access.
Contract
- Provider account, customer, subscription, invoice, payment, refund, and event IDs map to distinct internal entities.
- Plan and price versions are immutable for historical periods; changes create new references.
- A service period has explicit start/end and entitlement outcome independent of the provider object's mutable current status.
- Cancellation distinguishes stop-renewal, end-of-period, and immediate termination; user-visible dates come from confirmed internal state.
- Events are de-duplicated and applied with provider object version/time rules; stale events cannot reverse a newer accepted transition.
- Reconciliation compares invoices, captured/refunded amounts, subscription periods, and entitlements, surfacing rather than auto-erasing differences.
Implementation guidance
- Use an event inbox keyed by provider account plus event ID and a transition table with accepted object state/version.
- Write money amounts in integer minor units with explicit currency and type.
- Create entitlement commands from accepted service-period facts through an outbox.
- Keep manual adjustments as new reasoned entries with actor and evidence, not edits to provider history.
Failure handling and safeguards
- If events arrive out of order, retain them and apply only transitions valid after current state.
- If payment succeeds but entitlement projection fails, replay the outbox without changing money records.
- If provider and internal amounts disagree, open a reconciliation case; do not silently overwrite either side.
Verification and operations
- Measure event lag/duplicates/stale order, invoice-to-payment mismatch, paid-without-entitlement, entitlement-without-supported-period, cancellation timing, refunds, and reconciliation age.
- Run daily money and service-period reconciliation plus targeted probes after pricing changes.
- Restrict and audit manual adjustment capability.
The executable-looking examples in this package are fixtures and acceptance contracts. Run
python tools/validate.py from the collection root to check package structure and metadata; then
implement and execute the scenarios in the target repository.
Adoption assumptions
- Names and numeric values in
example.yamlare an adoption profile, not universal defaults. - The adopting team must map actors, data classes, error vocabulary, and ownership to its system.