◀ Billing Lifecycle

Billing Lifecycle Maturity Scorecard

Evidence-based maturity assessment — what IS

65.8%
Overall Score 65.8%
0 = Missing
1 = Planned
2 = Partial
3 = Production
4 = Hardened
5 = Institutional

Execution Foundation

100%

Billing execution table, 6-state machine, triple-layer idempotency, immutability trigger, lifecycle event store

6 capabilities Target: 100%

Workflow Event Integration

100%

Authoritative workflow writes, BillingWorkflowConfig, WorkflowWriteContext, transition coverage, read compliance

5 capabilities Target: 100%

Webhook and Async Settlement

63%

Provider-agnostic webhook handler, async settlement flow, signature verification, reconciliation worker

5 capabilities Target: 100%

Financial Controls and Compliance

0%

Payment instrument entity, 3D Secure, risk assessment, PCI-DSS compliance, settlement reconciliation reports

5 capabilities Target: 100%
Capability Score Weight Status Evidence Hint
Billing Executions Schema
billing_executions table with tenant_id, entity_contract_id, plan_contract_id, amount, currency, Citus-ready indexes
0 1 2 3 4 5
15 Institutional Migration: 20260327_create_billing_executions.sql
6-State Execution Machine
created -> pending -> processing -> completed|failed. Pending settlement: processing -> pending. Cancel: created|pending -> canceled
0 1 2 3 4 5
20 Institutional Migration: 20260401_billing_status_machine_upgrade.sql with CHECK constraint
Triple-Layer Idempotency
App-level check + DB ON CONFLICT (idempotency_key partial unique) + WHERE status guard. Pending included in duplicate detection.
0 1 2 3 4 5
20 Institutional SubscriptionBillingService::executePayment — 3 layers verified
DB Immutability Enforcement
Trigger: terminal row protection (completed/failed/canceled), valid-only transitions, processing->pending allowed for async
0 1 2 3 4 5
15 Institutional Migration: 20260401_billing_immutability_trigger.sql
Append-Only Lifecycle Event Store
BillingExecutionEventRepository — every state transition records type, old_status, new_status, metadata, user_id, correlation_id
0 1 2 3 4 5
15 Institutional
Transactional Outbox Pattern
Dual-write: execution state + outbox event in same DB transaction. Events carry payment_rail, payment_provider, idempotency_key.
0 1 2 3 4 5
15 Institutional
Capability Score Weight Status Evidence Hint
Authoritative Workflow Write Path
recordWorkflowEventTransactional() writes to billing.contract_term_datetimes inside DB transaction. AUTHORITATIVE_WRITE_ENABLED=true.
0 1 2 3 4 5
25 Institutional PostgreSQLBillingExecutionRepository::recordWorkflowEventTransactional — fail-closed, asserts active transaction
BillingWorkflowConfig Canonical Key
Centralized config: workflow key wf:billing.execution, 8 phase codes, target table, default source. Single source of truth.
0 1 2 3 4 5
15 Institutional BillingWorkflowConfig.php — 8 phase codes, wf:billing.execution key
Stateless Context Propagation
WorkflowWriteContext VO: serviceDefault(), webhook(provider), user(userId), system(). Passed explicitly at every call site.
0 1 2 3 4 5
20 Institutional
Full Transition Coverage
All 9 repository transition methods emit workflow events: markPending, markProcessing, markCompleted, markFailed, markCanceled, confirmFromPending, rejectFromPending, settleFromProcessing, reconcile
0 1 2 3 4 5
25 Institutional BillingWorkflowComplianceProvider verifies all 9 transitions
Historical Event Backfill
Backfill migration creates contract_term_datetimes rows for all existing executions with deterministic SHA-256 transition IDs
0 1 2 3 4 5
15 Institutional Migration: 20260401_billing_workflow_event_backfill.sql
Capability Score Weight Status Evidence Hint
Provider-Agnostic Webhook Handler
/api/v1/billing/webhook/{provider} — idempotent, extracts event_type/reference_id, dispatches confirmation/rejection
0 1 2 3 4 5
25 Hardened WebhookAction.php — returns 200 for terminal, 409 for non-pending
Webhook Signature Verification
Per-provider HMAC-SHA256 verification of webhook payload. Skeleton in place; needs provider-specific signing keys.
0 1 2 3 4 5
20 Partial WebhookAction has verifySignature placeholder — needs per-provider HMAC implementation
Pending Reconciliation Worker
Polls findPendingForReconciliation(), calls checkStatus() per rail, transitions pending->completed or pending->failed
0 1 2 3 4 5
25 Hardened bin/billing/billing-reconciliation-worker.php — idempotent, timeout-based, dry-run support
Transient Failure Retry Strategy
Exponential backoff for isRetryable() failures. Max retries per rail, dead-letter after exhaustion.
0 1 2 3 4 5
15 Missing
Billing Structured Observability
billing.execution.result + billing.rail.execution structured log events with duration_ms, rail, provider, correlation_id
0 1 2 3 4 5
15 Institutional
Capability Score Weight Status Evidence Hint
Payment Instrument Entity (Contract Pattern)
Model payment methods as contract pattern entities with tokenized storage via contract_term_attrs
0 1 2 3 4 5
25 Missing
3D Secure Authentication Flow
3DS challenge flow for card payments: enroll check, challenge redirect, result verification
0 1 2 3 4 5
20 Missing
Risk Assessment and Velocity Check
Pre-execution risk scoring: velocity limits, amount thresholds, fraud signals, device fingerprinting
0 1 2 3 4 5
20 Missing
Settlement Reconciliation Reports
Daily/weekly reconciliation between internal records and provider settlement files. Discrepancy flagging.
0 1 2 3 4 5
20 Missing
Financial Compliance Audit Trail
PCI-DSS Level 1 evidence: all cardholder data access logged, tokenization enforced, audit trail for regulatory inquiry
0 1 2 3 4 5
15 Missing