Skip to main content

Billing Service — Security Model

Status: populated Owner: Platform Engineering + Security Last updated: 2026-04-18 Companion: 13 Security

1. Authentication

Kong enforces JWT or API key authentication on all REST endpoints. This service re-validates X-Tenant-Id against JWT tenant_id claim (defense in depth).

NATS consumer: cluster-internal; no external access. NATS TLS + auth credentials injected via Vault sidecar.

2. Authorization (RBAC)

ScopeActionRole
billing:readUsage query, invoice list/downloadaccount.admin, account.viewer
billing:adminPricing CRUD, operator cost CRUDplatform.billing_admin
platform.financeVoid invoiceplatform.finance (separate from billing_admin)
Cross-account readAny account's billing dataplatform.admin (audit-logged)

3. Tenant Isolation

  • tenant_id column on all tables with RLS policy.
  • Query always includes WHERE tenant_id = $1 AND RLS enforced at PG level.
  • Integration test test/integration/tenant-isolation.spec.ts verifies cross-tenant read returns empty/404.

4. Financial Data Controls

  • Pricing table changes are audit-logged: created_by, created_at, version history via effectiveTo.
  • Invoice void requires platform.finance role + mandatory reason field; voided records retained with voided_by, voided_at.
  • All PATCH to pricing creates a new versioned row rather than mutating existing data (append-only pattern).
  • NATS ingestion uses ON CONFLICT DO NOTHING — no retroactive billing changes via replay.

5. Encryption

ClassMechanism
In-flightTLS 1.2+ (Kong + internal mTLS)
At rest (PG)Transparent disk encryption (EBS/GCP PD)
S3 objects (PDFs)SSE-S3 or SSE-KMS on bucket
SecretsVault → env at pod start

6. Threat Model

ThreatControl
Tampered billing event (inflated segment count)Source of truth is dlr-processor; operator logs cross-reference; segment_count validated range 1–10
Price manipulation via pricing APIplatform.billing_admin role required; all changes audit-logged
Unauthorized invoice downloadS3 presigned URLs scoped to authenticated account; TTL 15 min
Unauthorized invoice voidplatform.finance role; audit trail retained even after void
NATS message injectionCluster-internal NATS; TLS + Vault credentials; schema validation on ingest
SQL injectionPrisma parameterization; billing_admin endpoint guarded by input validation

7. GDPR / Data Retention

  • billing_events retained for regulatory accounting period (7 years minimum); not subject to short-term GDPR erasure.
  • On tenant_erased.v1 event: customer-facing PII (accountId FK retained for audit; tenantId anonymized per legal guidance).
  • Invoice PDFs in S3: retention policy set to 7 years on bucket lifecycle.