Files
member-console/design/billing/interfaces.md

9.9 KiB

Billing Module Interfaces

This document inventories the cross-module dependencies of the billing module, both inbound (other modules consuming billing entities) and outbound (billing entities referencing other modules). It also records behavioral contracts that cross module boundaries.


Provided Interfaces (other modules depend on us)

The billing module's primary structural output to other modules is mediated through pool provisions -- the universal interface through which access mechanisms communicate billing intent to the resource layer. Note: grants was moved from billing to entitlements (Decision 106); two of the three provision source types (subscriptions and purchases) remain in billing. The following tables and columns are consumed by other modules.

Consumed by entitlements module (schema: entitlements)

Billing Table Column(s) Consumer Semantics
billing.subscriptions subscription_id entitlements.pool_provisions Exclusive arc: identifies a provision's subscription source.
billing.purchases purchase_id entitlements.pool_provisions Exclusive arc: identifies a provision's purchase source.
billing.products product_id entitlements.grants Optional product reference on grants for audit clarity (Decision 106).
billing.billing_accounts billing_account_id entitlements.pool_provisions, entitlements.pool_ondemand_config, entitlements.grants Financial identity. Also consumed by entitlements.grants.granted_to_billing_account_id (Decision 106).
billing.prices price_id entitlements.pool_ondemand_config On-demand pricing rate plan reference.
billing.plan_ladders plan_ladder_id entitlements.pool_provision_ladders Catalog-shape reference: each junction row in pool_provision_ladders identifies which ladder the provision occupies.
entitlements.resource_keys resource_key Materialization pipeline, on-demand config Shared namespace reference table (Decision 103). Both entitlement and on-demand systems FK into it.

The credit rule type (Decision 100) produces a cross-module write: the entitlements materialization pipeline creates credit_grants in billing with source_provision_id provenance. This is the one case where the billing module receives writes from the entitlements pipeline rather than from its own internal processes.

Note: product_entitlement_rules (now entitlement_set_rules) and the new entitlement_sets table reside in the entitlements module. Products now consume entitlement_sets.set_id via products.entitlement_set_id — the dependency direction is reversed from the prior pattern where product_entitlement_rules.product_id consumed from billing. Pool provisions no longer reference products.product_id directly; they resolve to entitlement_set_id at creation time.

Consumed by cooperative module (schema: cooperative)

Billing Table Column(s) Consumer Semantics
billing.billing_accounts billing_account_id cooperative.patrons One-to-one cooperative identity overlay on a billing account.
billing.payments payment_id cooperative.patronage_events (via source_payment_id) Patronage attribution source reference (Decision 108).
billing.invoices invoice_id cooperative.patronage_events (via source_invoice_id) Patronage attribution source reference (Decision 108).
billing.products product_id cooperative.patronage_events Product-level patronage attribution (Decision 108).

The cooperative module observes billing execution without participating in it. patrons and patronage_events were moved from billing to the cooperative module (Decision 108). These references were previously internal; they are now cross-module consumed interfaces.


Consumed Interfaces (we depend on other modules)

From identity module (schema: identity): persons

The billing module references identity.persons.person_id in ten or more actor attribution columns across multiple tables. These are governance-sensitive references recording which human exercised discretion in a state transition.

Billing Table FK Column(s) Purpose
billing_accounts suspended_by, closed_by Lifecycle action attribution.
subscription_changes changed_by_person_id Subscription modification actor. NULL if system-driven.
coupons created_by_person_id Coupon creation governance.
promotion_codes created_by_person_id Code creation governance.
discounts applied_by_person_id, removed_by_person_id Discount application and manual removal attribution.
pending_charges created_by_person_id, voided_by_person_id Manual charge creation and voiding attribution.
credit_grants created_by_person_id, voided_by_person_id Credit grant authorization and voiding attribution.
credit_transactions created_by_person_id Manual adjustment attribution.

The pattern is consistent: governance-sensitive transitions that a human initiates carry a person FK; system-driven transitions carry only timestamps. Persons are not billing actors -- a person does not subscribe or receive invoices.

From organization module (schema: organization): organizations

Billing Table FK Column(s) Purpose
billing_accounts org_id Organizational ownership of billing accounts. References organization.organizations. An organization may have multiple billing accounts.
coupons org_id Organization that created a coupon. References organization.organizations. NULL for platform-level coupons.

The billing module does not reach into the organization module beyond the org_id foreign key. It does not know about workspaces, workspace members, or role assignments. The entitlements module mediates between billing and organizational resources.

From entitlements module (schema: entitlements): usage_events

Billing Table FK Column(s) Purpose
pending_charge_usage_events event_id References entitlements.usage_events. Links individual usage events to the pending charge that bills for them. Provides full traceability from consumption to billing.
credit_transactions usage_event_id References entitlements.usage_events. Links real-time credit deductions (Topology B) to the usage event that triggered them.

Usage events have a dual role crossing the entitlements/billing boundary. The entitlements path (usage_events -> numeric_entitlement_usage) handles consumption enforcement. The billing path (usage_events -> pending_charge_usage_events -> pending_charges) handles billing attribution. These two paths are structurally independent.

From entitlements module (schema: entitlements): entitlement_sets

Billing Table FK Column(s) Purpose
products entitlement_set_id References entitlements.entitlement_sets. Declares which entitlement set a product confers. Resolved at provision-creation time.

Products reference an entitlement set to declare what capabilities a purchase or subscription confers. The billing module does not interpret set contents (rules, resource keys); it carries the FK for the provision-creation path to resolve. This is the reverse of the prior pattern where product_entitlement_rules.product_id consumed from billing — the dependency now flows from billing into entitlements.


Interface Contracts

Product stability guarantee

The billing module guarantees that products.product_id remains stable when a product is deactivated (is_active = false). Deactivation gates new purchases and subscriptions but does not invalidate existing references. Grants that reference an inactive product remain valid and are not disrupted.

Entitlement set rules (formerly product_entitlement_rules — Decision 107, now entitlement set abstraction)

product_entitlement_rules was previously owned by the billing module (Decision 97). Decision 107 (Document 29) reassigned it to the entitlements module. It has since been re-parented as entitlement_set_rules, belonging to entitlement_sets rather than directly to products. Products now reference an entitlement set via products.entitlement_set_id (a consumed interface from entitlements). The dependency direction is reversed: billing consumes from entitlements, rather than entitlements consuming product_id from billing for rule ownership. The materialization pipeline reads rules keyed by entitlement_set_id (resolved from pool_provisions), not by product_id.

Billing account financial anchor

All financial objects in the billing module (subscriptions, invoices, credit grants, pool provisions) reference billing_accounts.billing_account_id directly. No financial object references organizations.org_id for financial purposes. The billing account is the financial root; the organization is the administrative container. This separation enables cross-organizational billing -- where a billing account in one organization funds a pool in another -- without structural coupling between the billing and organization modules.

Patronage observation contract

The patronage layer (patrons, patronage_events) — now in the cooperative module (Decision 108) — observes billing execution but does not participate in it. Payment processing, invoice finalization, and subscription lifecycle transitions proceed without consulting patronage state. Patronage events are written as a consequence of settled payments via Temporal workflows. If the cooperative module is unavailable, billing execution continues normally; patronage events are reconciled when it recovers. This decoupling ensures that cooperative accounting complexity does not affect billing reliability.