# PHI boundary checklist — subnet, KMS, audit, BAA scope

Complete before first production PHI ingest. Check each box; any unchecked item blocks go-live.

## Account & contract

- [ ] AWS BAA executed for account(s) holding PHI
- [ ] HIPAA-eligible services only in PHI boundary (verify [AWS HIPAA page](https://aws.amazon.com/compliance/hipaa-eligible-services-reference/))
- [ ] Separate OU/account for non-PHI dev workloads (no shared IAM roles across boundary)

## Network

- [ ] PHI subnets have no direct internet ingress; NAT or VPC endpoints only
- [ ] Interface VPC endpoints for HealthLake, HealthImaging, S3, KMS, CloudWatch Logs
- [ ] Security groups: least privilege; no `0.0.0.0/0` on application ports
- [ ] Flow Logs enabled on PHI VPC subnets → S3 with Object Lock or Glacier retention

## Encryption

- [ ] CMK per data class (clinical FHIR vs imaging vs analytics de-ID)
- [ ] KMS key policy denies `kms:Decrypt` from non-PHI roles
- [ ] S3 buckets: SSE-KMS, block public access, versioning on audit buckets

## Identity & access

- [ ] IAM Identity Center or federation; no long-lived access keys on PHI paths
- [ ] Break-glass role with MFA + CloudTrail data event on HealthLake `SearchWithGet`
- [ ] SMART on FHIR scopes mapped to least-privilege IAM via application proxy

## Audit & retention

- [ ] CloudTrail organization trail; log file validation on
- [ ] HealthLake CloudWatch metrics + API error alarms
- [ ] Retention policy documented (state law vs HIPAA minimum 6 years)

## BAA scope worksheet

| Data class | AWS service | Account ID | Retention (years) | Owner |
|------------|-------------|------------|-------------------|-------|
| FHIR clinical | HealthLake | | | |
| DICOM imaging | HealthImaging | | | |
| De-ID research | S3 + Glue | | | |
| App logs (may contain PHI) | CloudWatch Logs | | | |

## Failure modes to rehearse

1. **Cross-account snapshot copy** without KMS grant → decrypt failures at restore
2. **Bedrock prompt** including raw PHI without guardrails → log leakage; use de-ID export path
3. **CCDA transform agent** mis-template → wrong Patient linkage; validate with Inferno + manual sample set before bulk import
