# Diagrams — SDD-08: Threat Modeling Harness Stack

---

## Diagram 1 — The Ingestion-to-STRIDE Pipeline (Architecture)

```mermaid
flowchart TB
    subgraph INPUTS["Three Input Modalities"]
        IAC[Terraform / IaC<br/>resource graph · trust boundaries · exposure]
        OAS[OpenAPI / spec<br/>endpoints · schemas · auth schemes]
        DIO[draw.io / Mermaid<br/>manual annotation · implicit flows]
    end
    INPUTS --> MERGE
    subgraph MERGE["Normalized Model Merge"]
        N[resources + endpoints + trust boundaries + manual flows<br/>→ resolve into DFD element types<br/>external entity · process · data store · data flow]
    end
    MERGE --> RENDER
    subgraph RENDER["DFD Renderer (Mermaid)"]
        D[text-based · diff-able · reviewable in PRs<br/>the architecture-as-ground-truth]
    end
    RENDER --> STRIDE
    subgraph STRIDE["STRIDE Engine"]
        R[per DFD element:<br/>rule lookup → baseline threats]
        L[LLM enrichment → system-specific context]
        R --> L
        L --> TL[structured threat list<br/>per element · STRIDE-categorized]
    end
    TL --> TRACK[(threat tracker<br/>findings, like bugs)]

    style MERGE fill:#0d1b2a,stroke:#5eead4,color:#5eead4
    style RENDER fill:#0d1b2a,stroke:#5eead4,color:#5eead4
    style STRIDE fill:#0d1b2a,stroke:#5eead4,color:#5eead4
    style INPUTS fill:#1a1015,stroke:#5eead4,color:#e4e4e8
```

**Reading**: The stack ingests three modalities — declarative IaC (the resource topology), OpenAPI (the API surface), and manual annotation (implicit flows) — merges them into a normalized DFD model, renders it as diff-able Mermaid, and runs STRIDE with an LLM-enrichment layer that turns rule-lookup boilerplate into system-specific threats. The DFD is derived from ground truth (the artifacts that define the system), so it cannot drift from the implementation. The threat list is tracked like bugs.

---

## Diagram 2 — STRIDE Mapped to DFD Element Types

```mermaid
flowchart LR
    subgraph ELEMENTS["DFD Element Types"]
        EE[External Entity]
        P[Process]
        DS[Data Store]
        DF[Data Flow]
    end
    EE --> EE_S["Spoofing<br/>Repudiation"]
    P --> P_S["Spoofing<br/>Tampering<br/>Repudiation<br/>DoS<br/>EoP"]
    DS --> DS_S["Tampering<br/>Repudiation<br/>Info Disclosure<br/>DoS"]
    DF --> DF_S["Tampering<br/>Repudiation<br/>Info Disclosure<br/>DoS"]
    EE_S --> RULE[rule lookup<br/>baseline threats]
    P_S --> RULE
    DS_S --> RULE
    DF_S --> RULE
    RULE --> ENRICH[LLM enrichment<br/>+ system-specific context<br/>from merged model]
    ENRICH --> OUT[actionable, specific threats]

    style ELEMENTS fill:#1a1015,stroke:#5eead4,color:#e4e4e8
    style RULE fill:#0d1b2a,stroke:#5eead4,color:#5eead4
    style ENRICH fill:#0d1b2a,stroke:#5eead4,color:#5eead4
```

**Reading**: STRIDE maps cleanly to DFD element types — external entities are spoofing/repudiation candidates, processes span the full set, data stores and flows carry tampering/disclosure/DoS. A rule lookup generates the baseline threats per element. The LLM enrichment is where the value compounds: it takes the generic baseline and attaches the system-specific context (resource names, data classifications, trust boundaries) that turns "consider Spoofing" into "the payment webhook has no mTLS — spoofing enables fraudulent refunds." The rule lookup provides the coverage; the LLM provides the relevance.

---

## Diagram 3 — Continuous Threat Modeling vs the Quarterly Ritual (Comparison)

```mermaid
flowchart TB
    subgraph MANUAL["Manual Threat Modeling (quarterly ritual)"]
        M1[whiteboard session<br/>DFD drawn from memory]
        M2[STRIDE pass<br/>same recurring threats]
        M3[→ document<br/>decays immediately]
        M1 --> M2 --> M3
    end
    subgraph HARNESS["Harness Stack (continuous, design-time)"]
        H1[ingest Terraform + OpenAPI<br/>on every change]
        H2[DFD regenerated from ground truth<br/>cannot drift]
        H3[STRIDE re-run<br/>new threats as findings]
        H4[→ threat tracker<br/>stays current]
        H1 --> H2 --> H3 --> H4
    end
    MANUAL -.the inversion.-> HARNESS

    style MANUAL fill:#1a1015,stroke:#9494a0,color:#9494a0
    style HARNESS fill:#0d1b2a,stroke:#5eead4,color:#5eead4
```

**Reading**: The manual ritual produces a DFD from memory that decays the day after the session and a STRIDE pass that surfaces the same boilerplate every time. The harness stack derives the DFD from the IaC and OpenAPI — ground truth that regenerates on every change — and re-runs STRIDE so new threats appear as findings the moment the architecture shifts. The human is not eliminated (they review the DFD and triage the threats); the decay and the boilerplate are. This is Course 2A's central inversion applied to threat modeling.

---

## Diagram 4 — Mermaid DFD as a Source-Controlled Artifact (Workflow)

```mermaid
flowchart LR
    PR[IaC / OpenAPI PR<br/>opened by engineer] --> CI[CI runs threat-model pipeline]
    CI --> DIFF[DFD regenerated<br/>diff vs main branch]
    DIFF --> REVIEW[PR review surface:<br/>+ DFD diff<br/>+ new threats introduced by this change]
    REVIEW --> GATE{engineer + reviewer<br/>accept threats?}
    GATE -->|yes, address or accept| MERGE[merge — architecture record updated]
    GATE -->|no, redesign| REVISE[revise IaC / spec]

    style PR fill:#1a1015,stroke:#5eead4,color:#e4e4e8
    style CI fill:#0d1b2a,stroke:#5eead4,color:#5eead4
    style DIFF fill:#0d1b2a,stroke:#5eead4,color:#5eead4
    style REVIEW fill:#0d1b2a,stroke:#5eead4,color:#5eead4
    style GATE fill:#1a1015,stroke:#5eead4,color:#e4e4e8
```

**Reading**: Mermaid is the canonical DFD format because it is text — it diffs in git and reviews in PRs. When the threat-model pipeline runs in CI on every IaC/OpenAPI change, the PR review surface shows the DFD diff and the new threats the change introduces. Threat modeling becomes a creation-time guardrail (Course 2A S08): the engineer sees the security consequence of their architecture change before it merges, not in a quarterly meeting months later. The architecture record (the versioned Mermaid DFD + threat history) stays current because it is regenerated from ground truth on every change.
