11 KiB
Entitlements -- Interfaces
Module: entitlements
This document records the cross-module interface surface of the entitlements module: what other modules depend on (provided interfaces), what this module depends on (consumed interfaces), and the behavioral contracts that govern these boundaries.
Provided Interfaces (Other Modules Depend on Us)
pool_id (entitlements.resource_pools.pool_id)
Consumed by: organization module
FK column: organization.role_assignments.scope_pool_id
Cardinality: 0..* role assignments per pool
Semantics: Pool-scoped role assignments allow administrators to grant permissions scoped to a specific resource pool. This is the mechanism for pool administration delegation. The organization module references pool_id to scope role assignments; it does not interpret or depend on pool contents (entitlements, quotas, provisions).
Stability guarantee: pool_id is a UUIDv7 primary key. Pools are never physically deleted (ON DELETE RESTRICT as universal default, Decision 33). A pool may transition to archived status, but the row and its pool_id persist indefinitely.
entitlement_set_id (entitlements.entitlement_sets.set_id)
Consumed by: billing module
FK column: billing.products.entitlement_set_id
Cardinality: 0..* products per entitlement set
Semantics: 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 entitlement_set_id so that the provision-creation path can resolve and denormalize it onto pool_provisions.
Stability guarantee: set_id is a UUIDv7 primary key. Entitlement sets are never physically deleted. A set may be deactivated (is_active = false), but the row and its set_id persist indefinitely. Existing products and grants referencing a deactivated set remain valid.
usage_events (entitlements.usage_events table)
Consumed by: billing module FK references:
billing.credit_transactions.usage_event_id->entitlements.usage_events.event_id-- real-time credit deductions (prepaid topology)billing.pending_charge_usage_events.event_id->entitlements.usage_events.event_id-- billing attribution linkage
Cardinality: 0..* credit transactions per usage event; 0..* pending charge links per usage event Semantics: Usage events are append-only universal consumption records. The billing module references individual events to link them to the financial transactions they produce -- either real-time credit deductions (Topology B, prepaid) or pending charges that roll up into invoice line items (Topology A, postpaid). The billing module never modifies usage events; it creates its own records that reference them.
Stability guarantee: Usage event rows are append-only; no field is updated after creation. event_id is a UUIDv7 primary key that persists indefinitely. The billing_account_id on the event is denormalized at creation time and never changes, even if the pool's on-demand configuration subsequently changes. For quota-resolved events, billing_account_id may be NULL.
Consumed Interfaces (We Depend on Other Modules)
From organization module (schema: organization)
| FK Column | References | Purpose |
|---|---|---|
resource_pools.org_id |
organization.organizations.org_id |
Governance scope: which organization governs this pool |
pool_assignments.workspace_id |
organization.workspaces.workspace_id |
Capability delivery: which workspace receives capabilities from this pool |
usage_events.workspace_id |
organization.workspaces.workspace_id |
Usage attribution: which workspace generated this consumption |
Why the dependency exists: Resource pools exist to provide capabilities to workspaces within organizations. The organization provides the governance container (which org controls this pool) and the resource container (which workspace receives capabilities). Without these references, the pool abstraction has no consumers and no governance scope.
From billing module (schema: billing)
| FK Column | References | Purpose |
|---|---|---|
pool_provisions.billing_account_id |
billing.billing_accounts.billing_account_id |
Financial source identification |
pool_provisions.subscription_id |
billing.subscriptions.subscription_id |
Subscription as provision source (exclusive arc) |
pool_provisions.purchase_id |
billing.purchases.purchase_id |
Purchase as provision source (exclusive arc) |
grants.product_id |
billing.products.product_id |
Optional product reference for audit clarity on grants |
grants.granted_to_billing_account_id |
billing.billing_accounts.billing_account_id |
Billing account as grant recipient |
pool_ondemand_config.billing_account_id |
billing.billing_accounts.billing_account_id |
On-demand charge routing (payer designation) |
pool_ondemand_config.rate_plan_id |
billing.prices.price_id |
On-demand pricing rate |
pool_provision_ladders.plan_ladder_id |
billing.plan_ladders.plan_ladder_id |
Catalog-shape registration: records which plan ladder rung a provision occupies; carries the exclusion constraint enforcing tier exclusivity per (pool, ladder) |
usage_events.billing_account_id |
billing.billing_accounts.billing_account_id |
Resolved payer at event time |
Why the dependency exists: Resource pools bridge the financial world and the resource world. The billing module provides the financial sources (billing accounts, subscriptions, purchases) and the product catalog (products, prices) that the pool system consumes. Pool provisions normalize these diverse access sources into a uniform interface for materialization. Grants (Decision 106), entitlement sets, and entitlement set rules now live within the entitlements module. The pool_provisions.entitlement_set_id and entitlement_set_rules.set_id references are intra-module. The billing module's products.entitlement_set_id is a consumed interface from entitlements (reverse direction from the prior product_entitlement_rules.product_id pattern). The pool_provision_ladders junction is the sole point at which entitlements directly references billing's plan ladder catalog: it crosses the module boundary to record catalog-shape facts (which ladder rung a provision occupies) while keeping the commercial facts (the provision itself) within the entitlements module.
entitlement_sets and entitlement_set_rules (intra-module)
entitlement_sets and entitlement_set_rules (formerly product_entitlement_rules, Decision 107) are intra-module tables. The entitlement set abstraction decouples capability specification from commercial packaging: products reference a set via products.entitlement_set_id (a consumed interface from entitlements into billing), and grants may reference a set directly via grants.entitlement_set_id for ad hoc capability conferral.
entitlement_set_rules.resource_key is an intra-module FK referencing resource_keys. entitlement_set_rules.set_id is an intra-module FK referencing entitlement_sets.
The materialization pipeline reads rules keyed by set_id (resolved from pool_provisions.entitlement_set_id):
- For
rule_type = 'boolean': creates or updatesboolean_entitlementsrows. - For
rule_type = 'limit'or'quota': creates or updatesnumeric_entitlementsandnumeric_entitlement_contributionsrows. - For
rule_type = 'credit': createscredit_grantsin the billing module withsource_provision_idprovenance (cross-module write, Decision 100). - The pipeline never writes to
entitlement_set_rules.
resource_keys as Shared Namespace
Consumed from: shared (Decision 103)
Table: resource_keys
Access pattern: FK reference from both entitlement and on-demand systems
The resource_keys table enforces a shared namespace between the entitlement system and the on-demand billing system. Both entitlement_set_rules.resource_key and pool_ondemand_config.resource_key FK into resource_keys.resource_key. This ensures that a typo (e.g., api-calls vs. api_calls) produces an FK violation rather than a silent mismatch between a quota and its corresponding on-demand config.
Interface Contracts
Organization Module Guarantees
organizations.org_idremains stable through the organization's lifecycle. Organizations are never physically deleted.workspaces.workspace_idremains stable through the workspace's lifecycle. Workspaces are never physically deleted. A workspace may be suspended or archived, but the row persists.
Billing Module Guarantees
products.product_idremains stable when a product is deactivated (is_active = false). Products are catalog entries that persist indefinitely for historical reference.billing_accounts.billing_account_idremains stable when a billing account is suspended or closed. The row persists for financial audit purposes.subscriptions.subscription_idandpurchases.purchase_idremain stable through their lifecycle transitions. These are referenced by pool provisions and must persist for provision provenance.prices.price_idremains stable when a price is deactivated. Referenced bypool_ondemand_config.rate_plan_idfor on-demand pricing.
Entitlements Module Guarantees (to Consumers)
resource_pools.pool_idremains stable indefinitely. Pools transition through status states (active,suspended,archived) but are never physically deleted.usage_eventsrows are append-only. No field is updated after creation.event_idpersists indefinitely.- The materialization pipeline is idempotent: calling
materialize_pool_entitlements(pool_id)multiple times with the same pool state produces the same result. - Entitlement state (
boolean_entitlements.is_enabled) is a pure function of active provisions and their entitlement set rules. No administrative override mechanism exists (Decision 51).
Behavioral Expectations
- Provision lifecycle: When a billing source (subscription or purchase) changes status, the billing module or application code is responsible for updating the corresponding
pool_provisionsstatus and invoking the materialization pipeline. When a grant changes status, the entitlements module manages this internally. The entitlements module does not poll billing sources. - On-demand config payer resolution: When a usage event is recorded, the payer is resolved from
pool_ondemand_config.billing_account_idat event creation time. This is a point-in-time snapshot; subsequent changes to the on-demand config do not retroactively change event attribution. For quota-resolved events,billing_account_idmay be NULL. - Cross-organization provisioning:
pool_provisions.billing_account_idis unconstrained relative to the pool'sorg_id(Decision 53). The entitlements module does not enforce cross-org governance; that is deferred application logic.