Skip to main content

Population Health Service — Security Model

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

1. RBAC / ABAC Matrix

PermissionRolesABAC Conditions
population_health:dashboard:readclinician, nurse, analyst, facility_admin, moph_viewerScoped to authorized nodeId hierarchy
population_health:cohort:readclinician, analyst, facility_admin, moph_viewerisShared=true OR ownerId=caller
population_health:cohort:writeanalyst, facility_admin, moph_adminNode scope match
population_health:cohort:deletefacility_admin, moph_adminOwns cohort OR has admin role
population_health:registry:readclinician, nurse, analystNode scope; requires phi:read to see patientId
population_health:risk:writeanalyst, facility_adminNode scope
population_health:risk:overridesenior_clinician, moph_adminRequires explicit override permission flag
population_health:outreach:writecare_coordinator, analyst, facility_adminTeam assignment scope
population_health:quality:readclinician, analyst, moph_viewer, donor_viewerProgram-scoped: donor_viewer only sees donor indicator pack
population_health:hmis:exportmoph_integration, platform_adminPlatform-level; not tenant-scoped
population_health:export:writeresearcher + secondary_use:approvedPurpose must be in approved list; IRB reference required for identifiable
phi:readclinician, senior_analystRequired supplement to see patient IDs in list responses

2. Aggregate-Only Policy

For any user without phi:read permission, list responses (registries, cohort membership, outreach items) must suppress patientId and return only aggregate counts and de-identified row data. This is enforced in the application layer (mapper) — not by SQL alone.

Export TypeConsent Requirement
Aggregate counts (no patientId)No individual consent required
De-identified cohort dataset (k≥5)Consent checked at cohort level; suppression if k<5
Identifiable patient-level exportExplicit patient consent + approved IRB purpose required
HMIS aggregate push to DHIS2Aggregate only; no patient-level identifiers ever included

4. Encryption Classes

DataClassMechanism
definition_json (cohort DSL)StandardAES-256 at rest via PostgreSQL tablespace encryption
patient_id in registry/risk tablesPHI-StandardPostgreSQL column-level encryption via pgcrypto for non-aggregate tables
De-identified export filesStandardEncrypted at rest in object storage; presigned URL (24h TTL)
DHIS2 API credentialsSecretStored in KMS (AWS KMS / HashiCorp Vault); never in application DB
Jira/override reason textStandardAt-rest encryption

5. Audit Events

All audit events are published via AuditPort → NATS → audit-service.

Audit EventTrigger
COHORT_CREATEDCohort definition created
COHORT_UPDATEDCohort definition version created
COHORT_ARCHIVEDCohort soft-deleted
RISK_OVERRIDE_APPLIEDManual tier override recorded
OUTREACH_STATUS_CHANGEDFSM transition on outreach item
EXPORT_REQUESTEDSecondary-use export job created
EXPORT_RELEASEDDe-identified dataset released
EXPORT_BLOCKEDExport blocked due to consent or k-threshold violation
HMIS_EXPORT_COMPLETEDDHIS2 push succeeded
HMIS_EXPORT_FAILEDDHIS2 push failed after max retries
CROSS_TENANT_VIOLATIONAttempt to access cross-tenant data
PHI_ACCESSPatient-level data returned (when phi:read used)

6. GDPR / Data Protection Participation

RightHandling
Right to erasurePatient patientId removed from all registry, risk, outreach tables on patient deletion request; audit trail preserved with pseudonym
Right to portabilityNot applicable for aggregate analytics data
Data minimizationCohort jobs fetch only the clinical fields required by the DSL predicates
Purpose limitationExport purpose is recorded and checked against approved list before release
Data residencyAll PostgreSQL data remains in MoPH-designated region; DHIS2 is MoPH-operated

7. Data Residency (Afghanistan)

  • All production data stored in Afghanistan MoPH data center or designated sovereign cloud region.
  • DHIS2 is MoPH-operated; no health data leaves Afghan sovereignty except for donor reporting with explicit MoPH sign-off.
  • Research exports require MoPH Data Governance Committee approval before release to external parties.

8. Tenant Isolation

  • PostgreSQL RLS policies enforce tenant_id = current_setting('app.tenant_id') on all tables.
  • nodeId hierarchy is additionally enforced at the application layer (not SQL alone).
  • Cross-tenant API requests return 403 CROSS_TENANT_SCOPE_VIOLATION and are logged as security events.