Skip to main content

Compliance coverage matrix

Every regulatory and security control implemented in the platform, grouped by legal envelope. Each row lists the citation, the module(s) that carry the control, the audit review doc that specifies it, and the code + test paths that enforce it. Both the agent-mediated and ZFA-direct channels are covered on every row unless explicitly noted.

Legend:

  • Statute column cites the primary source (Ugandan law, IRA/URA regulation, or industry standard).
  • Module is the InsureLink module that owns enforcement.
  • Review links to the audit doc that specifies scope, gaps, and acceptance criteria.
  • Locked in by points at the tests / invariants that would fail if the control regressed.

Uganda Data Protection & Privacy Act 2019 (+ Regulations 2021)

DPPA citeControlModuleReviewLocked in by
§8 lawful, fair, transparent processingEvery processing activity has a documented purpose in the DPIA folder; PII reads emit an audit event.Notifications, AuditNotifications review · Audit / SIEM reviewaudit-egress-snapshot.spec, pii-permission-scope.spec
§11 storage-limitationDocuments retention cascade physically unlinks blobs when the retention window closes; sanctions/fraud rows purged on schedule; warehouse exports carry a hard TTL.Documents, Sanctions, BordereauDocuments review · Sanctions/Fraud review · Bordereau reviewdocument-storage.spec (retention path), sanctions-fraud retention job spec
§13(1) prior consentReferral consent captured at referral creation (moved from client_accepted to create). Public inquiry captures consent as first field. Portal captures consent on first login.Referrals, Client Portal, Client InquiriesReferrals review · Client Portal reviewdata-transfer-consent.spec, referral consent invariant
§13(3) purpose-scoped consentNotificationPreferences is per-category; the DPPA §16 cross-border kind (sms_kenya, whatsapp_us, sanctions_offshore, email_smtp) is a separate DataTransferConsent row per subject.Notification Preferences, Notifications DispatchNotifications reviewdata-transfer-consent.spec, notification-preferences.spec
§13 consent-withdrawal pathPortal DSAR objection endpoint; unsubscribe token on every notification body; withdrawal downgrades DataTransferConsent.withdrawnAt.Client Portal, Notifications, DSARClient Portal review · DSAR reviewunsubscribe-token.spec, dsar-request-lifecycle.spec
§16 cross-border transferAfrica's Talking (KE), WhatsApp Cloud (US), SMTP (varies), sanctions provider (UK/US) all gated by a per-subject DataTransferConsent row of the matching kind. Absent consent → dispatch dropped, audit event notification.blocked.no_transfer_consent. DPIA per provider in /docs/compliance/dpia/.Notifications, SanctionsNotifications review · Sanctions reviewdata-transfer-consent.spec (block path), webhook-signature-parity.spec
§17 data-subject rights (access, rectify, erase, object, restrict, port)DsarRequest entity with 30-day SLA tracker, subject-portal + DPO-verified submission surfaces, structured export pack, tombstone erasure with dsarErasedAt stamp.DSAR, Client PortalDSAR reviewdsar-request-lifecycle.spec, sar-scope.spec
§21 security safeguardsPII fields ciphered (PiiCipher) with HMAC search hash; documents AES-256-GCM at rest; app-layer encryption on webhook bodies; MFA gate on privileged roles; refresh-token reuse detection.Auth, Documents, Notifications, Common SecurityAuth review · Documents reviewpii-cipher.spec, secrets-cipher.spec, document-storage.spec
§21 accountability — PII read visibilityEvery bulk-PII decrypt requires a permission from the whitelisted set and emits an audit.pii_bulk_read event. Presigned-URL fetches emit document.download with subject id + IP.Common Security, DocumentsDocuments reviewpii-permission-scope.spec, document-storage.spec (download audit)
§33 72-h breach notificationComplianceBreach entity, automated 72-h countdown, IRA/UPDPO notify-subjects endpoint, escalation event when SLA breached.Compliance BreachesComplaints / SARs / Breaches reviewcomplaints-sars-breaches spec (72-h timer)
§33(1) records of processingDPIA folder maintained per third-party processor (Africa's Talking, WhatsApp, SMTP, sanctions).NotificationsNotifications reviewLiving docs at /docs/compliance/dpia/

Uganda Anti-Money Laundering Act 2013 (as amended 2017)

AML citeControlModuleReviewLocked in by
§3 customer due diligenceAgent KYC required-doc policy per agent-type; client KYC field-completeness gate before payout.Agent KYC, KYC/IdentityKYC/AML reviewagent-kyc verify path, id-patterns.spec (NIN/TIN)
§6 pre-transaction sanctions screeningEvery payout / commission / policy-issue calls SanctionsProviderRegistry. Refuses to boot in prod on console fallback. Circuit-breaker on the external provider. Inbound-collection payer screen shipped in Collections Phase 1 (see Collections review gap 1).Sanctions, Payments, CollectionsSanctions/Fraud review · Collections reviewprod-startup-gate.spec, sanctions integration spec
§12–14 record retention7-year retention on transaction + KYC records; document retention job enforces the floor.Documents, AuditDocuments review · Audit reviewDocument retention job spec
§17 STR (suspicious-transaction reporting)RegulatorRequest entity + POST /reports/regulator/fia/sweep + GET /reports/regulator/fia/goaml.xml for FIA goAML XML export. Tipping-off banner in compliance UI.Reports, ComplianceComplaints / SARs / Breaches reviewFIA XML export snapshot
FIA CTR (Cash Threshold Reporting) ≥ UGX 20MFiaThresholdService.sweep() walks payment + claimPayment above FIA_CTR_THRESHOLD_UGX; goAML XML export at GET /reports/regulator/fia/goaml.xml. Inbound collection CTR coverage shipped in Collections Phase 1 (see Collections review gap 4).Regulator Reports, CollectionsCollections review · Complaints reviewfia-threshold sweep spec

Uganda Insurance Act 2017 & IRA regulations

Statute citeControlModuleReviewLocked in by
§60–75 policy lifecycle8-state policy machine (issued → active → endorsed → cancelled → reinstated → renewed), IRA-schema policy schedule PDF, product-approval reference on every quote.PoliciesPolicies reviewpolicies state-transition tests
§88–95 claims handlingClaims workflow with acknowledgement SLA, reserve booking, IRA-compliant decision-reason enum, disbursement audit trail.ClaimsClaims reviewClaims state-transition spec, claim.disburse permission gate
§102 IRA quarterly returnPOST /reports/regulator/ira/quarterly builds + snapshots the quarterly return, GET .../:id/xml emits the IRA-schema XML.ReportsBordereau/Warehouse reviewRegulator report snapshot spec
§112 commission capsCommission preview endpoint validates against per-product / per-insurer cap; over-cap triggers commission.cap.exceeded audit event and requires super-admin override.CommissionsCommissions/Wallets reviewcommission-calculator.spec
§128 monthly bordereauBordereau warehouse export runs on schedule, produces the IRA-schema file, records checksum + retention timestamp.BordereauBordereau reviewBordereau export + retention spec
IRA IT Controls Guidance — segregation of dutiesClaim pay requires a different actor than claim approve; withdrawal approve cannot be the same actor as the requester.Claims, WalletsAuth review · Commissions reviewendpoint-coverage.spec, policy.guard.spec
IRA market-conduct — cooling-offConsumer Protection §37 cooling-off period exposed on policy schedule + client portal; cancellation inside the window bypasses cancellation-fee.Policies, Client PortalPolicies reviewPolicy cancel path spec

Uganda tax law (URA)

CiteControlModuleReviewLocked in by
Income Tax Act §80 — 6% WHT on commissionsURA_WHT deduction row (versioned, beneficiaryTypes=["agent","zfa_house"]) applies to every commission approval. IRP5-equivalent export at GET /reports/regulator/ura/irp5/:agentId/:year.CommissionsCommissions reviewdeduction-stacking.spec (WHT invariant), IRP5 export snapshot
URA monthly remittance by 15thPOST /reports/regulator/ura/remittance/compute computes the amount; POST .../:id/submitted records submission.ReportsCommissions reviewRegulator remittance report spec
7-year record retention (tax)Documents retention floor honours the max of AML §14 and URA §41 → effectively 7 years.DocumentsDocuments reviewDocument retention job spec

Uganda payments & telecoms

CiteControlModuleReviewLocked in by
National Payment Systems Act 2020 (payouts)Payout-provider registry gates prod-boot on real-provider config; webhook HMAC verified per-provider; idempotency key on every dispatch.Payment ProvidersPayment gateway reviewproviders.spec, webhook-verifier.spec, idempotency.service.spec
National Payment Systems Act 2020 (collections)Four inbound rails (MTN MoMo, Airtel, Flutterwave, Pesapal, direct bank). Per-provider webhook signature strategies (HMAC-timestamp, Airtel body-hash, Pesapal GetTransactionStatus follow-up). Idempotent webhook ingest via (provider, eventId) unique. Prod-boot gate on collection providers shipped in Collections Phase 1; initiate-side idempotency + rate-limit remain Phase 2 (Collections review gaps 3, 6, 7).Collections, Payment ProvidersCollections reviewwebhook-signature-parity.spec, provider-webhook-sig.spec
BOU cybersecurity guidelines — MFA on privileged accountsMFA required for ZFA staff / super-admin / finance; hardware-passkey enrolment path; recovery-code hashing.AuthAuth reviewauth-security-runbook procedures; policy-guard spec
BOU cybersecurity — 90-day log retention floorAudit chain + SIEM cursor retention >= 90 days; expired sweep on schedule.Audit / SIEMAudit / SIEM reviewaudit-chain.spec, audit-egress-snapshot.spec
Uganda Communications Act 2013 §5 + UCC GuidelinesNotification unsubscribe token on every SMS/email/WhatsApp; opt-out honoured on next dispatch attempt.NotificationsNotifications reviewunsubscribe-token.spec
Computer Misuse Act 2011Every state-changing endpoint hits audit.record(); hash-chained AuditEvent; regulator-scope filter prevents cross-tenant peek.AuditAudit reviewaudit-chain.spec, regulator-scope.spec

Uganda Consumer Protection Act 2011

CiteControlModuleReviewLocked in by
§8–13 unfair practices — clear pricingDeductions preview endpoint returns net-of-deductions gross so agents / clients see the actual take-home before commitment.Commissions, Client PortalCommissions review · Client Portal reviewdeduction-stacking.spec (preview parity)
§8–13 unfair practices — unsubscribeEvery SMS/email/WhatsApp carries an HMAC-signed unsubscribe token; single click opts out at category granularity.NotificationsNotifications reviewunsubscribe-token.spec
§37–39 cooling-offPolicy schedule exposes cooling-off period, portal cancellation endpoint honours the window fee-free.Policies, Client PortalPolicies reviewPolicy cancel spec
Complaints handling3-state complaint machine (opened → acknowledged → resolved), SLA timer, IRA §102 escalation event.ComplaintsComplaints reviewComplaints SLA spec

OWASP Top 10 & ASVS L2

OWASP citeControlModuleReviewLocked in by
A01 broken access controlObject-authorization service scopes every referral / policy / claim / wallet fetch by (a) agent, (b) sponsor, (c) ZFA-direct handler, (d) portal client, (e) insurer.Common PoliciesAuth review · Referrals reviewobject-authorization.spec, endpoint-coverage.spec
A02 cryptographic failuresPII/documents/secrets each keyed separately (PII_HASH_KEY, SECRETS_KEY, DOCUMENT_KEY), AES-256-GCM, HMAC-SHA256 for search hashes, Argon2id for passwords.Common Security, DocumentsAuth review · Documents reviewpii-cipher.spec, secrets-cipher.spec, document-storage.spec
A03 injectionEvery DB call is parametric via Prisma; DTO validation with class-validator; no raw string concatenation into queries.(platform-wide)Auth reviewRepository-wide grep audit; DTO validation tests per controller
A05 security misconfigurationprod-startup-gate refuses boot on console fallback for sanctions + notification providers; boot fails loudly rather than silently degrading.Sanctions, NotificationsSanctions review · Notifications reviewprod-startup-gate.spec
A07 identification & authentication failuresRefresh-token reuse detection, session revocation across devices, MFA on privileged accounts, passkey enrolment, magic-link + OTP for portal.Auth, Client PortalAuth review · Client Portal reviewauth refresh-rotate spec, MFA spec
A08 software / data integrityWebhook HMAC signature verification uses timing-safe comparison; audit chain uses SHA-256 forward-hash. Bordereau + Sanctions webhook parity spec locks the pattern.Common Security, Audit, BordereauAudit reviewwebhook-signature-parity.spec, audit-chain.spec
A09 logging & monitoring failuresEvery state change → audit.record(); every audit → Track-3 structured log line → SIEM push (with circuit-breaker on collector). Metrics + tracing on every job.Audit, SIEM, ObservabilityAudit reviewaudit-egress-snapshot.spec, siem-export.spec, metrics-timing.spec
A10 SSRFSIEM export host allowlist (SIEM_TARGET_HOSTS), sanctions provider URL allowlist, webhook URL egress denylist.SIEM, SanctionsAudit review · Sanctions reviewsiem-export.spec (host-check invariant)

Cross-cutting invariants

Three spec files enforce that the whole platform respects patterns established in the module audits. If ANY module regresses one of these, CI turns red:

InvariantEnforced byWhat it locks in
PII permission whitelistpii-permission-scope.specOnly the enumerated permissions may return bulk PII from a controller. Adding a permission to the whitelist requires a corresponding legitimate-use entry — accidental widening is caught in review.
Webhook signature paritywebhook-signature-parity.specEvery inbound HMAC verification uses timing-safe compare, the correct header, and rejects on malformed / stale timestamps. Bordereau, Sanctions, and Payment webhooks all pass the same shape.
Prod startup gate parityprod-startup-gate.specSanctions + Notifications + Warehouse each refuse to boot in production when their real-provider config is missing, unless a matching escape-hatch env var (SANCTIONS_ALLOW_CONSOLE_IN_PROD, NOTIFICATION_ALLOW_CONSOLE_IN_PROD, WAREHOUSE_ALLOW_...) is set. Prevents silent degradation to console-fallback in prod.

Channel parity

Every control above applies on both the agent-mediated and ZFA-direct channels. Verifications you can run to prove parity:

Control areaAgent-mediated pathZFA-direct pathSame code path?
Referral state machinePOST /referralsPOST /admin/zfa-direct/inquiries/:id/convert-to-referralYes — one ReferralsService.transition()
POP verifyAgent uploadsPortal / staff uploads via /client-portal/referrals/:id/popYes — one PopService.verify()
ConsentAgent-collected at referral createClient-signed at inquiry / portal loginSame DataTransferConsentService
DSARSubject via DPO or portalSubject via portalSame DsarRequestService
Sanctions screenPre-payoutPre-payoutSame SanctionsProviderRegistry
Commission WHTApplied on agent wallet creditApplied on house wallet creditSame deductions engine, different beneficiaryTypes

The only intentional differences are:

  1. Commission payee: agent wallet vs house wallet — enforced by beneficiaryTypes on each deduction row.
  2. Consent capture surface: agent-facing DTO vs public / portal form — same table, different UI.
  3. Object-authorization scope: agent scopes by agentId; ZFA-direct scopes by zfaDirectHandlerId; portal client scopes by clientId.

Where to go next