HIPAA Compliance Overview
Part of the hipaa module
HIPAA is one of the optional modules -- present in the full profile, absent from the core one. A core deployment does not serve these routes. See Modules and profiles for what each profile includes and how to run the full one.
Summary
The hipaa module keeps Business Associate Agreement (BAA) records and a PHI access log, encrypts and decrypts single values with a key you configure, and reports a readiness status.
Components
1. PHI Encryption (modules/backend/app/core/phi_encryption.py)
Symmetric encryption for Protected Health Information (PHI) using Fernet (AES-128-CBC + HMAC-SHA256).
Key generation:
from modules.backend.app.core.phi_encryption import PHIEncryption
key = PHIEncryption.generate_key() # Store this in AWS Secrets Manager
Usage:
enc = PHIEncryption() # Reads key from settings.PHI_ENCRYPTION_KEY
ciphertext = enc.encrypt("John Smith DOB 1990-01-01")
plaintext = enc.decrypt(ciphertext)
Properties:
- Each encrypt() call uses a random IV — same plaintext produces different ciphertexts
- HMAC authentication prevents tampered ciphertext from decrypting
- decrypt() raises ValueError on any integrity failure
- Encryption uses one key, PHI_ENCRYPTION_KEY. A value encrypted under another key does not decrypt: /decrypt answers 400, so keep every key you have used.
2. PHI Audit Log (modules/backend/app/models/phi_audit_log.py)
Entries in experimentation.phi_audit_logs are written by two routes: POST /audit-logs, which records the access you send, and POST /decrypt, which records a READ by the calling user. Each entry has:
- Who accessed (user_id FK to users)
- What was accessed (resource_type, resource_id)
- What action (READ / WRITE / DELETE / EXPORT)
- Which fields (phi_fields_accessed — HIPAA minimum-necessary principle)
- Why (purpose: treatment / operations / research)
- Network context (ip_address, user_agent)
- Retention marker (retention_years = 6, per HIPAA §164.530(j))
3. BAA Configuration (modules/backend/app/models/baa_config.py)
Business Associate Agreements are tracked in experimentation.baa_configs. Each record stores:
- Covered entity contact (organization_name, signatory_name, signatory_email)
- Agreement period (effective_date, expiry_date)
- Data residency region (e.g., us-east-1)
- PHI categories covered (demographics, diagnosis, treatment, billing)
- A hash of the signed BAA document, as you send it (signed_document_hash)
4. API Endpoints (modules/backend/app/api/v1/endpoints/hipaa.py)
All endpoints at /api/v1/hipaa require ADMIN role (except /encrypt which also allows DEVELOPER).
| Method | Path | Description |
|---|---|---|
| POST | /baa |
Create BAA configuration |
| GET | /baa |
List BAA configurations |
| GET | /baa/{id} |
Get specific BAA |
| DELETE | /baa/{id} |
Deactivate BAA (soft delete) |
| GET | /audit-logs |
Paginated PHI audit log |
| POST | /audit-logs |
Manually log PHI access |
| GET | /report |
HIPAA compliance report |
| POST | /encrypt |
Encrypt a PHI value |
| POST | /decrypt |
Decrypt a PHI value |
| GET | /data-residency |
Data residency configuration |
| GET | /status |
HIPAA readiness status |
Configuration
| Setting | What it does |
|---|---|
PHI_ENCRYPTION_KEY |
The key /encrypt and /decrypt use. Without it they answer 503. |
HIPAA_ENABLED |
Returned as hipaa_enabled by /data-residency. The routes work the same either way. |
HIPAA_ALLOWED_REGIONS |
Returned by /data-residency beside the deployment's region (default ["us-east-1","us-west-2"]). |
HIPAA_AUDIT_LOG_RETENTION_YEARS |
Written into each new audit log entry as retention_years (default 6). |
Readiness Status
GET /api/v1/hipaa/status returns:
{
"has_active_baa": true,
"phi_encryption_configured": true,
"audit_logging_enabled": true,
"data_residency_configured": true,
"overall_hipaa_ready": true
}
overall_hipaa_ready is true when an active BAA exists, PHI_ENCRYPTION_KEY is set and HIPAA_ALLOWED_REGIONS is not empty. It reports configuration; it does not inspect stored data or logs.
Security Notes
- Audit logs are append-only — no DELETE endpoint is exposed
- BAA deactivation is a soft delete — records are preserved for audit history