Skip to main content

Audit Service — Security Model

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 13 security-compliance-tenancy

1. RBAC matrix

RoleRead entriesRead disclosuresRequest exportAdmin operations
SUPER_ADMINAll tenantsAll tenantsYesYes
TENANT_ADMINOwn tenant onlyOwn tenant onlyNo (export = super admin)No
COMPLIANCE_OFFICEROwn tenant (assigned)Own tenantRead export statusNo
PATIENTOwn disclosures only (via portal)Own onlyNoNo
SERVICE_ACCOUNTNoNoNoNo — services produce events; never query audit

Scopes enforced by Keycloak JWT claims; RLS enforcement at DB is secondary defence.

2. Data access controls

ControlMechanism
Tenant isolationtenant_id column + JWT-extracted tenantId; Tenant Admins' queries auto-scoped
DB role immutabilityaudit_app role: INSERT on audit_entries; SELECT on audit_entries + audit_exports; UPDATE on audit_exports only (status transitions); UPDATE/DELETE on audit_entries revoked
Query window limitLive queries limited to 90-day ranges; wider ranges require async export
Export file accessSigned URLs with 1-hour TTL; only the requesting user's userId receives the URL
Admin operationsRequire SUPER_ADMIN scope; Keycloak RS256 JWT validation

3. Encryption

DataClassMechanism
audit_entries at restSensitive (may contain PHI in metadata)AES-256 via PostgreSQL TDE (operator level)
audit_exports export filesSensitiveServer-side encryption on object storage (SSE-S3)
chain_hashIntegritySHA-256 hex; stored as plain text (hash, not encrypted)
TransitConfidentialTLS 1.3 on all connections (Kong, NATS, Postgres, object storage)

4. Audit of the audit service (meta-audit)

The audit service audits its own operations:

OperationMeta-audit entry
Bulk export requestedAuditEntry { eventType: BULK_EXPORT, actorId: <requester> }
Chain integrity failureLogged + audit.dlq.alert.v1 emitted; NOT stored as AuditEntry (DB may be compromised)
DLQ alertaudit.dlq.alert.v1 event to platform-admin-service

5. GDPR and data retention

RequirementImplementation
7-year retention floorrecorded_at partitions retained; automated archival policy prevents premature deletion
GDPR Art. 17 erasureClinical audit records retained (legal basis: public health, MoPH obligation); PII in metadata.actorId and metadata.resourceId obfuscated on erasure request
Accounting of disclosuresGET /api/v1/audit/disclosures?patientId= returns patient-visible access log (HIPAA analogue)
Data residencyAll data co-located with primary Postgres; no cross-border transfer without DPIA

6. Threat model

ThreatLikelihoodImpactMitigation
Insider modifies audit recordsLowCriticalDB role UPDATE/DELETE revoked; chain-hash detects tampering; DBA access logged
Cross-tenant queryLowCriticalRLS + JWT claim enforcement; integration test mandatory
Export data exfiltrationLowHighSigned URLs; 1-hour TTL; export itself creates AuditEntry; rate-limited
NATS event spoofing (fake audit events)LowHighmTLS on NATS connections; service accounts authenticated via Keycloak; wildcard consumer validates envelope schema
DDoS on query APIMediumMediumKong rate limiting (60 req/min per user); 90-day window limit prevents expensive full-scan queries
Supply chain (compromised event from source service)LowMediumEvent envelope schema validation at ingestion; malformed events to DLQ

7. Compliance references

StandardApplicabilityImplementation
HIPAA Security Rule (analogue)FullAccess audit, tamper detection, minimum-necessary access
GDPR Art. 5(1)(e)PartialRetention policy; right to erasure balanced against public health obligation
Afghanistan MoPH data governanceFullData residency; 7-year retention; MoPH export on request
ISO 27001 A.12.4PartialEvent logging, log protection (chain hash), log administrator access (meta-audit)