Write HIPAA crosswalk and owner actions
Epic ask (verbatim): "Research the gap to get Jaah HIIPA compliant and fix everything that does not require human and does not break what is working now by imposing limits" (HIIPA = HIPAA). Full PRD/architecture: the epic's settled `prd` (Task 5917) and `architecture` (Task 5918) — the crosswalk half of architecture child **C9**. Lands LAST (D-A10) so every row points at a live file.
Operator decisions (verbatim): D1 "Business Associate — Jaah can sign BAAs and lawfully host/process customers' PHI"; D3 "Prod and dev"; D4 "HIPAA crosswalk on the SOC 2 programme (`docs/compliance/`), pointers to existing controls, gaps as risk-register rows". BA B1: obligations covered = Security Rule (§164.308–.316), Breach Notification as a BA (§164.410), and BA contract/use limits (§164.502(e), §164.504(e)); patient-rights duties appear only as pass-through rows. B8: human-only actions are listed as owner actions, never built.
## Requirements (verbatim)
### R1 — HIPAA crosswalk
A new `docs/compliance/hipaa-crosswalk.md`, routed from `docs/compliance/README.md` (Registers table) and therefore reachable from the hub.
- **AC1.1** Every Security Rule standard AND implementation specification in §164.308(a)(1)–(8), (b); §164.310(a)–(d); §164.312(a)–(e); §164.314(a); §164.316(a)–(b) has its own row, marked Required/Addressable, with status **live** (pointer to the operating file/SOC 2 control — never restated prose), **in build** (the task/epic building it), **gap** (risk-register id), or **owner action** (R2 id). Rows for §164.410 (BA breach notice) and §164.502(e)/§164.504(e) (BA contract terms) exist too.
- verify: diff the crosswalk's citations against the Security Standards Matrix (45 CFR Part 164 Subpart C, Appendix A) — every standard and implementation specification there appears exactly once; no row lacks a status.
- **AC1.2** Every row's pointer resolves; the doc reaches from the hub.
- verify: `python3 tools/check_context.py` exits 0.
- **AC1.3** States both environments (dev and prod) as in-boundary (D3) and states Jaah's role as Business Associate (D1); a reader with no context understands, in the first screen, what is live, what is a gap and what needs the owner.
- verify: read the top section; count of live/in-build/gap/owner-action rows shown in a summary table that matches the row statuses (a script/grep count equals the table).
- **AC1.4** Every gap row has a matching risk-register row (`docs/compliance/risk-register.md`, new `R-HIPAA-*` ids) with score, treatment, owner role.
- verify: each `R-HIPAA-` id in the crosswalk greps to exactly one row in risk-register.md.
### R2 — Owner-action list
In the crosswalk, a section listing every human-only step, each with an id, the role, and the evidence-store folder it files to. At minimum: execute AWS BAA (AWS Artifact) and confirm only HIPAA-eligible services hold PHI; Anthropic BAA for API accounts (and zero-data-retention decision); OpenAI, Google Workspace/Cloud, Slack (Enterprise) BAAs or keep them warned; designate HIPAA Security Official and Privacy Official; HIPAA workforce training and sanctions record; legal review + adoption of the customer BAA template (R3); sign the HIPAA risk analysis; annual HIPAA evaluation (§164.308(a)(8)).
- **AC2.1** Each item names role, not person (instance data stays in `portfolio/projects/jaah.md`), and an evidence folder that exists in `tools/evidence_store.py`'s allowlist (add a `baa` folder there if needed).
- verify: `python3 tools/evidence_store.py --help`/unit test lists the folder; `check_context.py` instance-data check passes.
### R6 (part)
- **AC6.4 Encryption at rest is complete.** Every store that may hold PHI is encrypted at rest in both envs (RDS, EFS, S3 transcripts/attachments/artifacts, EBS for ECS hosts and cloud nodes); any found unencrypted is fixed. The crosswalk row cites each.
- verify: `terraform plan`/config inspection per store; the crosswalk §164.312(a)(2)(iv) row lists each with its file:line.
## Approach (architecture C9)
- `tools/evidence_store.py:29-32` `CONTROLS` += `"baa"`, `"hipaa"` (training/risk-analysis/evaluation records) + unit test.
- Crosswalk routed from the `docs/compliance/README.md` Registers table; summary table on the first screen (role BA, dev+prod in boundary); one row per Appendix A standard/spec (+§164.410, §164.502(e)/504(e)); live rows point at the files the earlier children shipped (`apps/api/app/hipaa.py`, idle/MFA/PHI-audit/warnings code, `docs/compliance/public/baa.md`, updated policies, terraform); status "in build" only for anything still unmerged.
- `R-HIPAA-*` rows in `risk-register.md` (existing column format); `HIPAA-OA-*` owner actions naming role + evidence folder (`baa`/`hipaa`/existing).
- §164.312(a)(2)(iv) row cites every store: RDS `infra/jaah/terraform/modules/rds/main.tf:121`, EFS `shared-storage.tf:15`, transcripts/attachments/artifacts `session-transcripts.tf:37-46` (SSE-S3), archive/evidence KMS, cloud-node EBS `apps/api/app/aws/ec2.py:310-314`, account default `org/modules/account-baseline/main.tf:84-92`, ECS Fargate ephemeral storage (cite the module's platform version). Verify each line still says what it claims; fix any store found unencrypted.
- Gap rows to name: Object-Lock-less dev archive (E2), pre-existing archive objects still on 400 d, no PHI detection in task text (deferred). Check for any `mfa_exempt` operator row (`mfa.py:420`) and record operator-workforce MFA as an `R-HIPAA-*` gap if one exists.
- Add a small count script/test so the summary table equals the row statuses.
Credentials & reach: worktree only (docs, `check_context.py`, evidence_store unit test) — **verified**. Main terraform plan for AC6.4 — **deferred** (promotion to master is a human gate; cite the shared tf source instead).
Out of scope: N4 "No BAA is signed, no vendor contacted, no person named in reusable docs (instance data → `portfolio/projects/jaah.md` only)." N8 "Do not duplicate SOC 2 policy prose into the crosswalk — pointer only (single-home)." N9 "Do not alter the SOC 2 readiness checklist's existing G-/H- items' meaning; HIPAA ids are new (`R-HIPAA-*`, `HIPAA-OA-*`)." N3 nothing published, no policy past `draft`. Do NOT change product code except to fix an unencrypted store found under AC6.4.
Done means:
- AC1.1 — a script/test compares the crosswalk's citations to the Appendix A list (embedded in the test) and asserts each standard and implementation specification appears exactly once with R/A and a status; §164.410 and §164.502(e)/504(e) rows present.
- AC1.2 — `python3 tools/check_context.py` exits 0; crosswalk routed from `docs/compliance/README.md`.
- AC1.3 — first screen states BA role and dev+prod boundary; the count script's live/in-build/gap/owner-action numbers equal the summary table.
- AC1.4 — each `R-HIPAA-` id greps to exactly one risk-register row with score, treatment, owner role.
- AC2.1 — evidence_store unit test lists `baa` and `hipaa`; every `HIPAA-OA-*` names a role and an allowlisted folder; all R2 minimum items present; check_context instance-data check passes.
- AC6.4 — the §164.312(a)(2)(iv) row lists every store with a resolving file:line; any unencrypted store fixed (or none found, stated).
- Quality — a reader with no context can tell from the first screen exactly which steps remain for Jaah to act as a Business Associate.
- `./dc check full` green; PR merged to develop and Jaah Deploy green on dev.
Outcome
HIPAA crosswalk (46 live/10 gap/14 owner action), 7 R-HIPAA risks, HIPAA-OA-1..10, baa/hipaa evidence folders; no unencrypted store. Full gate green, #5179 merged, Jaah Deploy green on dev. Also unblocked develop's vendor census.
Artifacts
Activity
- Draft
- Ready
- Runner started
- Runner ended (done)