Diagrams — Module FT21: HIPAA and BAA Elimination

Module: FT21 — HIPAA and BAA Elimination Diagram count: 5 Tool: Mermaid (primary). Each diagram validated in Mermaid Live Editor.


Diagram 1 — The BAA Chain (and its elimination via local)

Type: Comparison / structural Purpose: The single diagram that anchors the module. The BAA is a contractual instrument that flows HIPAA obligations down a chain of vendors. It exists because a third party touches the data. Local eliminates the third party — and the BAA disappears with it. Reading the diagram: Left = the API path (covered entity → vendor → subprocessors, each link a BAA, each link a liability surface). Right = the local path (covered entity runs the model on its own GPUs; no third party touches PHI; no BAA needed for the LLM).

flowchart LR
  subgraph API["THE API PATH — BAA chain required"]
    direction LR
    CE1["Covered Entity\n(hospital / health system)"]
    BA1["Business Associate\n(API vendor)"]
    SUB1["Subprocessor\n(infra / hosting)"]
    CE1 -->|"BAA"| BA1
    BA1 -->|"BAA"| SUB1
    PHI1["PHI flows out\nthrough every link"]
    CE1 -.-> PHI1
    PHI1 -.-> BA1
    PHI1 -.-> SUB1
  end
  subgraph LOCAL["THE LOCAL PATH — no business associate"]
    direction LR
    CE2["Covered Entity"]
    GPU["On-prem GPUs\nopen-weights model\n(vLLM / TGI / Ollama)"]
    CE2 -->|"owns + operates"| GPU
    NOPHI["No PHI egress\nNo third party\nNo BAA for the LLM"]
    GPU -.-> NOPHI
  end

  API -.->|"structural alternative"| LOCAL

  style CE1 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style BA1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style SUB1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style PHI1 fill:#08080c,stroke:rgba(240,128,128,0.5),stroke-dasharray:4 2,color:#f08080
  style CE2 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style GPU fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style NOPHI fill:#08080c,stroke:rgba(94,234,212,0.5),stroke-dasharray:4 2,color:#5eead4
  style API fill:#08080c,stroke:rgba(255,255,255,0.08),color:#9494a0
  style LOCAL fill:#08080c,stroke:rgba(94,234,212,0.2),color:#e4e4e8

Diagram 2 — The API-BAA Coverage Gaps

Type: Coverage matrix / risk surface Purpose: The teaching point "you can't get a BAA that covers everything." The BAA covers the vendor relationship; coverage of individual surfaces is endpoint-specific. Image inputs, stateful assistants, batch pipelines, embeddings are frequently outside zero-retention even under a signed BAA. Reading the diagram: Top = the signed BAA (looks comprehensive). Below = the actual surface coverage. Green = covered by ZDR; red = uncovered or unclear. A real clinical workflow almost always touches at least one red surface.

flowchart TD
  BAA["Signed BAA + Zero-Data-Retention\n(the contract)"]
  BAA --> S1["Chat completions (text)\nCOVERED by ZDR"]
  BAA --> S2["Embeddings endpoint\nCHECK eligibility per endpoint"]
  BAA --> S3["Image / vision inputs\nFREQUENTLY EXCLUDED"]
  BAA --> S4["Assistants / Threads\n(stateful) UNCLEAR / narrower"]
  BAA --> S5["Batch API\nCHECK eligibility"]
  BAA --> S6["Fine-tuning endpoint\noften NOT ZDR-eligible"]
  BAA --> S7["Subprocessors\nflow-down not always complete"]

  GAP["THE TEACHING POINT:\nyou can't get a BAA that covers everything\nA real workflow almost always touches >=1 uncovered surface"]
  S3 -.-> GAP
  S4 -.-> GAP
  S6 -.-> GAP

  style BAA fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style S1 fill:#14141f,stroke:#82e0aa,color:#e4e4e8
  style S2 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style S3 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style S4 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style S5 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style S6 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style S7 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style GAP fill:#08080c,stroke:rgba(240,128,128,0.6),stroke-dasharray:4 2,color:#f08080

Diagram 3 — The Four Ways to Run an LLM on PHI

Type: Gradient / posture ranking Purpose: The taxonomy of deployment shapes, ranked weakest-to-strongest by data-exposure posture. The local/self-hosted path (Options 3 and 4) is the destination. Reading the diagram: Left = weakest posture (PHI leaves, multi-tenant). Right = strongest posture (PHI never leaves the building). Every step rightward moves the boundary from contractual (a BAA) to physical (a cable not plugged in).

flowchart LR
  O1["1. Cloud endpoints\nunder BAA\n(multi-tenant)"]
  O2["2. Dedicated capacity\n(single-tenant)"]
  O3["3. Self-hosted\nopen weights\n(your VPC)"]
  O4["4. On-prem GPUs\n(your metal)"]

  O1 -->|"stronger"| O2
  O2 -->|"stronger"| O3
  O3 -->|"stronger"| O4

  O1 -.- E1["PHI leaves ->\nvendor infra\nBAA required"]
  O2 -.- E2["PHI leaves ->\nsingle-tenant\nBAA required"]
  O3 -.- E3["PHI may stay\nin your VPC\nBAA often avoidable"]
  O4 -.- E4["PHI never leaves\nthe premises\nNO BAA for the LLM"]

  WEAK["WEAKEST POSTURE\n(contractual boundary)"]
  STRONG["STRONGEST POSTURE\n(physical boundary)"]
  O1 -.- WEAK
  O4 -.- STRONG

  style O1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style O2 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style O3 fill:#14141f,stroke:rgba(94,234,212,0.6),color:#e4e4e8
  style O4 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style E1 fill:#08080c,stroke:rgba(240,128,128,0.3),color:#f08080
  style E2 fill:#08080c,stroke:rgba(240,168,104,0.3),color:#f0a868
  style E3 fill:#08080c,stroke:rgba(94,234,212,0.3),color:#5eead4
  style E4 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#5eead4
  style WEAK fill:#08080c,stroke:rgba(255,255,255,0.06),color:#9494a0
  style STRONG fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4

Diagram 4 — The Local Architecture (data stays on-prem)

Type: Architecture / data-flow Purpose: The target architecture for a PHI workload. Every component that touches PHI lives inside the trust boundary. The only thing that crosses the boundary is the de-identified model artifact (downloaded once) and the audit log (if shipped to a SIEM under BAA). Reading the diagram: The dashed box is the on-prem trust boundary. PHI enters, is de-identified for fine-tuning, the model is trained/served inside the boundary, responses leave to clinicians inside the boundary. No PHI crosses the boundary outbound.

flowchart LR
  subgraph BOUND["ON-PREM TRUST BOUNDARY (your building, your network)"]
    direction TB
    SRC["Clinical data sources\nEHR, notes, imaging metadata"]
    DEID["De-identification pipeline\nPresidio / Tonic / custom\n(Safe Harbor or Expert Det.)"]
    CORP["De-identified fine-tuning corpus"]
    TRAIN["Training / fine-tuning\n(open-weights base + LoRA)"]
    SERVE["Serving stack\nvLLM / TGI / Ollama\n(from FT20)"]
    CLIN["Clinician UI\n(RBAC, MFA)"]
    AUDIT["Audit log store\n(every prompt / response / access)"]
    ENC["Encryption at rest\n(disk) + in transit (TLS)"]

    SRC --> DEID
    DEID --> CORP
    CORP --> TRAIN
    TRAIN --> SERVE
    CLIN -->|"prompt (PHI)"| SERVE
    SERVE -->|"response"| CLIN
    SERVE -.->|"every call"| AUDIT
    ENC -.-> SERVE
    ENC -.-> AUDIT
  end

  MODEL_IN["Open-weights model\n(downloaded once, no PHI)"]
  SIEM["SIEM / log warehouse\n(under BAA if external)"]

  MODEL_IN -->|"crosses boundary once\n(no PHI)"| TRAIN
  AUDIT -.->|"shipped under BAA"| SIEM

  style BOUND fill:#08080c,stroke:rgba(94,234,212,0.4),stroke-dasharray:6 3,color:#5eead4
  style SRC fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style DEID fill:#14141f,stroke:#5eead4,color:#e4e4e8
  style CORP fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style TRAIN fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style SERVE fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style CLIN fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style AUDIT fill:#14141f,stroke:#5eead4,color:#e4e4e8
  style ENC fill:#14141f,stroke:rgba(255,255,255,0.12),color:#9494a0
  style MODEL_IN fill:#08080c,stroke:rgba(94,234,212,0.3),color:#9494a0
  style SIEM fill:#08080c,stroke:rgba(255,255,255,0.08),color:#9494a0

Diagram 5 — The Fine-Tuning Data Risk and De-Identification

Type: Risk flow / defense-in-depth Purpose: Why fine-tuning on raw PHI is dangerous (memorization → extraction) and why de-identification is defense-in-depth even under local. The model is one control in a stack, not the only control. Reading the diagram: Top = the wrong path (train on raw PHI → model memorizes → PHI extractable). Bottom = the right path (de-identify → train → evaluate for memorization → serve under audit). Each control compensates for the failure modes of the others.

flowchart TD
  subgraph BAD["THE WRONG PATH — train on raw PHI"]
    direction LR
    RAW["Raw PHI\ncorpus\n(names, MRNs, dates)"]
    FT1["Fine-tune\non raw PHI"]
    MEM["Model MEMORIZES\nidentifiers\n(Carlini et al.)"]
    EXTRACT["PHI EXTRACTABLE\nvia prompting\n(insider / adversary)"]

    RAW --> FT1
    FT1 --> MEM
    MEM --> EXTRACT
  end

  subgraph GOOD["THE RIGHT PATH — defense-in-depth"]
    direction LR
    RAW2["Raw PHI\ncorpus"]
    DEID2["De-identify\n(Presidio / Tonic)\nSafe Harbor or Expert Det."]
    CORP2["PHI-scarce corpus"]
    FT2["Fine-tune\non de-identified data"]
    EVAL["Evaluate for memorization\n(canary, membership inference,\nextraction attacks)"]
    DPSGD["DP-SGD if high-sensitivity\n(behavioral health, HIV, SUD)"]
    SERVE2["Serve under audit\n+ access controls\n+ local boundary"]

    RAW2 --> DEID2
    DEID2 --> CORP2
    CORP2 --> FT2
    FT2 --> EVAL
    EVAL --> DPSGD
    DPSGD --> SERVE2
  end

  PRINCIPLE["DEFENSE-IN-DEPTH:\nde-identify because the model might memorize\naudit because de-identification might miss something\nrun local because the API might leak\nno single control is trusted alone"]
  GOOD -.-> PRINCIPLE

  style RAW fill:#14141f,stroke:#f08080,color:#e4e4e8
  style FT1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style MEM fill:#14141f,stroke:#f08080,color:#e4e4e8
  style EXTRACT fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  style RAW2 fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style DEID2 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style CORP2 fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style FT2 fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style EVAL fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style DPSGD fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style SERVE2 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style PRINCIPLE fill:#08080c,stroke:rgba(94,234,212,0.5),stroke-dasharray:4 2,color:#5eead4
  style BAD fill:#08080c,stroke:rgba(240,128,128,0.2),color:#9494a0
  style GOOD fill:#08080c,stroke:rgba(94,234,212,0.2),color:#9494a0

Validation notes

# Diagrams — Module FT21: HIPAA and BAA Elimination

**Module**: FT21 — HIPAA and BAA Elimination
**Diagram count**: 5
**Tool**: Mermaid (primary). Each diagram validated in [Mermaid Live Editor](https://mermaid.live).

---

## Diagram 1 — The BAA Chain (and its elimination via local)

**Type**: Comparison / structural
**Purpose**: The single diagram that anchors the module. The BAA is a contractual instrument that flows HIPAA obligations down a chain of vendors. It exists *because* a third party touches the data. Local eliminates the third party — and the BAA disappears with it.
**Reading the diagram**: Left = the API path (covered entity → vendor → subprocessors, each link a BAA, each link a liability surface). Right = the local path (covered entity runs the model on its own GPUs; no third party touches PHI; no BAA needed for the LLM).

```mermaid
flowchart LR
  subgraph API["THE API PATH — BAA chain required"]
    direction LR
    CE1["Covered Entity\n(hospital / health system)"]
    BA1["Business Associate\n(API vendor)"]
    SUB1["Subprocessor\n(infra / hosting)"]
    CE1 -->|"BAA"| BA1
    BA1 -->|"BAA"| SUB1
    PHI1["PHI flows out\nthrough every link"]
    CE1 -.-> PHI1
    PHI1 -.-> BA1
    PHI1 -.-> SUB1
  end
  subgraph LOCAL["THE LOCAL PATH — no business associate"]
    direction LR
    CE2["Covered Entity"]
    GPU["On-prem GPUs\nopen-weights model\n(vLLM / TGI / Ollama)"]
    CE2 -->|"owns + operates"| GPU
    NOPHI["No PHI egress\nNo third party\nNo BAA for the LLM"]
    GPU -.-> NOPHI
  end

  API -.->|"structural alternative"| LOCAL

  style CE1 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style BA1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style SUB1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style PHI1 fill:#08080c,stroke:rgba(240,128,128,0.5),stroke-dasharray:4 2,color:#f08080
  style CE2 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style GPU fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style NOPHI fill:#08080c,stroke:rgba(94,234,212,0.5),stroke-dasharray:4 2,color:#5eead4
  style API fill:#08080c,stroke:rgba(255,255,255,0.08),color:#9494a0
  style LOCAL fill:#08080c,stroke:rgba(94,234,212,0.2),color:#e4e4e8
```

---

## Diagram 2 — The API-BAA Coverage Gaps

**Type**: Coverage matrix / risk surface
**Purpose**: The teaching point "you can't get a BAA that covers everything." The BAA covers the *vendor relationship*; coverage of individual *surfaces* is endpoint-specific. Image inputs, stateful assistants, batch pipelines, embeddings are frequently outside zero-retention even under a signed BAA.
**Reading the diagram**: Top = the signed BAA (looks comprehensive). Below = the actual surface coverage. Green = covered by ZDR; red = uncovered or unclear. A real clinical workflow almost always touches at least one red surface.

```mermaid
flowchart TD
  BAA["Signed BAA + Zero-Data-Retention\n(the contract)"]
  BAA --> S1["Chat completions (text)\nCOVERED by ZDR"]
  BAA --> S2["Embeddings endpoint\nCHECK eligibility per endpoint"]
  BAA --> S3["Image / vision inputs\nFREQUENTLY EXCLUDED"]
  BAA --> S4["Assistants / Threads\n(stateful) UNCLEAR / narrower"]
  BAA --> S5["Batch API\nCHECK eligibility"]
  BAA --> S6["Fine-tuning endpoint\noften NOT ZDR-eligible"]
  BAA --> S7["Subprocessors\nflow-down not always complete"]

  GAP["THE TEACHING POINT:\nyou can't get a BAA that covers everything\nA real workflow almost always touches >=1 uncovered surface"]
  S3 -.-> GAP
  S4 -.-> GAP
  S6 -.-> GAP

  style BAA fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style S1 fill:#14141f,stroke:#82e0aa,color:#e4e4e8
  style S2 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style S3 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style S4 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style S5 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style S6 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style S7 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style GAP fill:#08080c,stroke:rgba(240,128,128,0.6),stroke-dasharray:4 2,color:#f08080
```

---

## Diagram 3 — The Four Ways to Run an LLM on PHI

**Type**: Gradient / posture ranking
**Purpose**: The taxonomy of deployment shapes, ranked weakest-to-strongest by data-exposure posture. The local/self-hosted path (Options 3 and 4) is the destination.
**Reading the diagram**: Left = weakest posture (PHI leaves, multi-tenant). Right = strongest posture (PHI never leaves the building). Every step rightward moves the boundary from contractual (a BAA) to physical (a cable not plugged in).

```mermaid
flowchart LR
  O1["1. Cloud endpoints\nunder BAA\n(multi-tenant)"]
  O2["2. Dedicated capacity\n(single-tenant)"]
  O3["3. Self-hosted\nopen weights\n(your VPC)"]
  O4["4. On-prem GPUs\n(your metal)"]

  O1 -->|"stronger"| O2
  O2 -->|"stronger"| O3
  O3 -->|"stronger"| O4

  O1 -.- E1["PHI leaves ->\nvendor infra\nBAA required"]
  O2 -.- E2["PHI leaves ->\nsingle-tenant\nBAA required"]
  O3 -.- E3["PHI may stay\nin your VPC\nBAA often avoidable"]
  O4 -.- E4["PHI never leaves\nthe premises\nNO BAA for the LLM"]

  WEAK["WEAKEST POSTURE\n(contractual boundary)"]
  STRONG["STRONGEST POSTURE\n(physical boundary)"]
  O1 -.- WEAK
  O4 -.- STRONG

  style O1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style O2 fill:#14141f,stroke:#f0a868,color:#e4e4e8
  style O3 fill:#14141f,stroke:rgba(94,234,212,0.6),color:#e4e4e8
  style O4 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style E1 fill:#08080c,stroke:rgba(240,128,128,0.3),color:#f08080
  style E2 fill:#08080c,stroke:rgba(240,168,104,0.3),color:#f0a868
  style E3 fill:#08080c,stroke:rgba(94,234,212,0.3),color:#5eead4
  style E4 fill:#08080c,stroke:rgba(94,234,212,0.5),color:#5eead4
  style WEAK fill:#08080c,stroke:rgba(255,255,255,0.06),color:#9494a0
  style STRONG fill:#08080c,stroke:rgba(94,234,212,0.4),color:#5eead4
```

---

## Diagram 4 — The Local Architecture (data stays on-prem)

**Type**: Architecture / data-flow
**Purpose**: The target architecture for a PHI workload. Every component that touches PHI lives inside the trust boundary. The only thing that crosses the boundary is the de-identified model artifact (downloaded once) and the audit log (if shipped to a SIEM under BAA).
**Reading the diagram**: The dashed box is the on-prem trust boundary. PHI enters, is de-identified for fine-tuning, the model is trained/served inside the boundary, responses leave to clinicians inside the boundary. No PHI crosses the boundary outbound.

```mermaid
flowchart LR
  subgraph BOUND["ON-PREM TRUST BOUNDARY (your building, your network)"]
    direction TB
    SRC["Clinical data sources\nEHR, notes, imaging metadata"]
    DEID["De-identification pipeline\nPresidio / Tonic / custom\n(Safe Harbor or Expert Det.)"]
    CORP["De-identified fine-tuning corpus"]
    TRAIN["Training / fine-tuning\n(open-weights base + LoRA)"]
    SERVE["Serving stack\nvLLM / TGI / Ollama\n(from FT20)"]
    CLIN["Clinician UI\n(RBAC, MFA)"]
    AUDIT["Audit log store\n(every prompt / response / access)"]
    ENC["Encryption at rest\n(disk) + in transit (TLS)"]

    SRC --> DEID
    DEID --> CORP
    CORP --> TRAIN
    TRAIN --> SERVE
    CLIN -->|"prompt (PHI)"| SERVE
    SERVE -->|"response"| CLIN
    SERVE -.->|"every call"| AUDIT
    ENC -.-> SERVE
    ENC -.-> AUDIT
  end

  MODEL_IN["Open-weights model\n(downloaded once, no PHI)"]
  SIEM["SIEM / log warehouse\n(under BAA if external)"]

  MODEL_IN -->|"crosses boundary once\n(no PHI)"| TRAIN
  AUDIT -.->|"shipped under BAA"| SIEM

  style BOUND fill:#08080c,stroke:rgba(94,234,212,0.4),stroke-dasharray:6 3,color:#5eead4
  style SRC fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style DEID fill:#14141f,stroke:#5eead4,color:#e4e4e8
  style CORP fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style TRAIN fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style SERVE fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style CLIN fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style AUDIT fill:#14141f,stroke:#5eead4,color:#e4e4e8
  style ENC fill:#14141f,stroke:rgba(255,255,255,0.12),color:#9494a0
  style MODEL_IN fill:#08080c,stroke:rgba(94,234,212,0.3),color:#9494a0
  style SIEM fill:#08080c,stroke:rgba(255,255,255,0.08),color:#9494a0
```

---

## Diagram 5 — The Fine-Tuning Data Risk and De-Identification

**Type**: Risk flow / defense-in-depth
**Purpose**: Why fine-tuning on raw PHI is dangerous (memorization → extraction) and why de-identification is defense-in-depth even under local. The model is one control in a stack, not the only control.
**Reading the diagram**: Top = the wrong path (train on raw PHI → model memorizes → PHI extractable). Bottom = the right path (de-identify → train → evaluate for memorization → serve under audit). Each control compensates for the failure modes of the others.

```mermaid
flowchart TD
  subgraph BAD["THE WRONG PATH — train on raw PHI"]
    direction LR
    RAW["Raw PHI\ncorpus\n(names, MRNs, dates)"]
    FT1["Fine-tune\non raw PHI"]
    MEM["Model MEMORIZES\nidentifiers\n(Carlini et al.)"]
    EXTRACT["PHI EXTRACTABLE\nvia prompting\n(insider / adversary)"]

    RAW --> FT1
    FT1 --> MEM
    MEM --> EXTRACT
  end

  subgraph GOOD["THE RIGHT PATH — defense-in-depth"]
    direction LR
    RAW2["Raw PHI\ncorpus"]
    DEID2["De-identify\n(Presidio / Tonic)\nSafe Harbor or Expert Det."]
    CORP2["PHI-scarce corpus"]
    FT2["Fine-tune\non de-identified data"]
    EVAL["Evaluate for memorization\n(canary, membership inference,\nextraction attacks)"]
    DPSGD["DP-SGD if high-sensitivity\n(behavioral health, HIV, SUD)"]
    SERVE2["Serve under audit\n+ access controls\n+ local boundary"]

    RAW2 --> DEID2
    DEID2 --> CORP2
    CORP2 --> FT2
    FT2 --> EVAL
    EVAL --> DPSGD
    DPSGD --> SERVE2
  end

  PRINCIPLE["DEFENSE-IN-DEPTH:\nde-identify because the model might memorize\naudit because de-identification might miss something\nrun local because the API might leak\nno single control is trusted alone"]
  GOOD -.-> PRINCIPLE

  style RAW fill:#14141f,stroke:#f08080,color:#e4e4e8
  style FT1 fill:#14141f,stroke:#f08080,color:#e4e4e8
  style MEM fill:#14141f,stroke:#f08080,color:#e4e4e8
  style EXTRACT fill:#14141f,stroke:#f08080,stroke-width:1.5px,color:#f08080
  style RAW2 fill:#14141f,stroke:rgba(255,255,255,0.12),color:#e4e4e8
  style DEID2 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style CORP2 fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style FT2 fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style EVAL fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style DPSGD fill:#14141f,stroke:rgba(94,234,212,0.5),color:#e4e4e8
  style SERVE2 fill:#14141f,stroke:#5eead4,stroke-width:1.5px,color:#e4e4e8
  style PRINCIPLE fill:#08080c,stroke:rgba(94,234,212,0.5),stroke-dasharray:4 2,color:#5eead4
  style BAD fill:#08080c,stroke:rgba(240,128,128,0.2),color:#9494a0
  style GOOD fill:#08080c,stroke:rgba(94,234,212,0.2),color:#9494a0
```

---

## Validation notes

- All five diagrams use the course design system colors: `#14141f` panel fill, `#5eead4` accent for primary/safe, `#f08080` for danger/risk, `#f0a868` for caution/unclear, `rgba(255,255,255,0.12)` for neutral borders, `#e4e4e8` / `#9494a0` for text.
- Paste each into [Mermaid Live Editor](https://mermaid.live) to render. All use stable Mermaid syntax (`flowchart LR`/`TD`, `subgraph`) supported in current Mermaid (v10.4+). No `block-beta` is used here so all diagrams render on the widest set of Mermaid versions.
- For the slide deck (artifact 03), these are rendered as static SVG/PNG captures from Mermaid Live, inlined into reveal.js.
- Note on Mermaid `subgraph` with `direction`: supported in Mermaid v10+. If rendering on an older version, the inner `direction LR`/`TB` lines can be removed without changing semantics.