Parent epic: #868
Depends on: #869 , #870 , #871 , #873 , #875
Context
AWCMS-Mini needs reusable SaaS subscription billing orchestration, but it must not become a tenant general ledger, AR/AP, tax engine, or payment provider implementation. Commercial records need exact amounts, immutable issued documents, idempotent period generation, and deterministic lifecycle requests.
Objective
Implement a provider-neutral subscription_billing capability for subscription terms, renewals, invoices, line items, credits, refunds-as-commercial-requests, dunning schedules, and lifecycle/entitlement coordination.
Scope
Add admitted module/extension descriptor, permissions, jobs, events, lifecycle descriptors, and admin navigation.
Add schema for:
subscriptions and immutable plan-version binding;
billing periods and anchors;
invoice drafts, issued invoices, line items, totals, due dates, and status history;
credit notes/adjustments linked to original invoice lines;
renewal, upgrade, downgrade, cancellation, proration-policy metadata, and scheduled changes;
payment allocation references without accounting-ledger semantics;
dunning attempts/schedules and lifecycle requests.
Implement state machines for subscription and invoice lifecycles.
Generate invoice drafts idempotently from catalog price components and usage aggregates.
Support review/issue/void/credit operations; issued invoices are immutable.
Use exact decimal/minor-unit arithmetic with currency consistency and explicit rounding policy.
Integrate with entitlements and lifecycle through commands/events, not direct cross-module table writes.
Request payment sessions through feat(payment-gateway): add provider-neutral checkout, signed webhook inbox, retries, and reconciliation #877 adapter contract; no provider call in invoice transaction.
Add scheduled renewal/invoice/dunning jobs with leases, bounded batches, retries, and reconciliation.
Add OpenAPI/AsyncAPI, admin UI, tenant-facing invoice read/download metadata, audit, metrics, and reporting projections.
Out of scope
General ledger, double-entry accounting, tax determination, statutory e-invoicing, withholding, AR/AP subledger, cash/bank reconciliation, or tenant business invoices.
Provider webhook processing (feat(payment-gateway): add provider-neutral checkout, signed webhook inbox, retries, and reconciliation #877 ).
Hardcoded pricing for a specific product/application.
Silently deleting or mutating issued documents.
Security and integrity requirements
Platform billing permissions are separate from tenant administration.
Tenant users can read only authorized tenant commercial records and cannot change issued invoices.
Invoice generation is idempotent per subscription/period/version.
Amount/currency/rounding constraints prevent overflow and mixed-currency totals.
Upgrade/downgrade/cancel changes are concurrency-safe and preserve historical terms.
Payment status is updated only through validated adapter/reconciliation outcomes.
Lifecycle suspension requests are reasoned and auditable; billing does not directly bypass feat(tenant-lifecycle): enforce trial, active, grace, suspended, canceled, restore, and downgrade semantics #873 policy.
Sensitive billing contact/provider references are minimized and masked.
Acceptance criteria
A subscription binds to an immutable published offer version.
Renewal creates at most one invoice for a billing period under concurrent workers.
Usage-based lines reconcile to feat(usage-metering): add idempotent usage events, aggregation, quotas, corrections, and reconciliation #875 aggregates and record their source window/version.
Issued invoices cannot be edited; correction uses credit/void semantics.
Upgrade/downgrade scheduling is deterministic and preserves old period evidence.
Dunning can request lifecycle transitions through feat(tenant-lifecycle): enforce trial, active, grace, suspended, canceled, restore, and downgrade semantics #873 without direct state mutation.
Payment allocation references do not create accounting tables or claims.
Tenant A cannot view/change tenant B subscriptions or invoices.
LAN/offline/manual-payment mode works without an online gateway.
API/UI/events/audit/reporting/docs are synchronized.
Testing
Unit tests for subscription/invoice state machines, period boundaries, proration policy, rounding, credits, and dunning.
PostgreSQL integration tests for RLS, uniqueness, immutable issued records, idempotent concurrent generation, and event same-commit behavior.
Usage-to-invoice reconciliation tests.
Worker restart/lease tests and failure injection.
Cross-tenant and authorization-negative tests.
E2E plan assignment → subscription → invoice issue → manual payment reference/dunning.
Mutation tests for duplicate invoice generation, float use, or issued-invoice edit.
Documentation
ERD/data dictionary, state diagrams, monetary/rounding policy, OpenAPI/AsyncAPI, billing operator and tenant guides, manual-payment SOP, dunning/lifecycle matrix, retention/backup impact, module README, and changeset.
Dependencies
Consumes payment outcomes from #877 and feeds control-plane reporting #880 .
Parent epic: #868
Depends on: #869, #870, #871, #873, #875
Context
AWCMS-Mini needs reusable SaaS subscription billing orchestration, but it must not become a tenant general ledger, AR/AP, tax engine, or payment provider implementation. Commercial records need exact amounts, immutable issued documents, idempotent period generation, and deterministic lifecycle requests.
Objective
Implement a provider-neutral
subscription_billingcapability for subscription terms, renewals, invoices, line items, credits, refunds-as-commercial-requests, dunning schedules, and lifecycle/entitlement coordination.Scope
Out of scope
Security and integrity requirements
Acceptance criteria
Testing
Documentation
Dependencies
Consumes payment outcomes from #877 and feeds control-plane reporting #880.