# Diagrams — Module S00: Legal, Ethics, and Rules of Engagement

> All Mermaid validated in Mermaid Live Editor. n8n JSON is structurally valid and importable.

---

## Diagram 1 — The Authorization Chain (and where it breaks)

**Type**: Mermaid (flowchart with break annotations)
**Purpose**: The central visual of S00.1. Authorization is a *chain* from asset owner to atomic tool call. A break anywhere voids downstream cover. Three named breaks correspond to the three failure modes in the teaching doc.

```mermaid
flowchart TD
    OWNER["Asset Owner<br/>owns the system under test"]
    SPONSOR["Program / Engagement Sponsor<br/>operates the bounty or pentest"]
    POLICY["Program Policy / SOW<br/>scope · RoE · safe harbor · evidence rules"]
    SCOPE["Scope File (JSON)<br/>machine-checkable boundary"]
    MW["Scope Enforcement Middleware<br/>intercepts every outbound call"]
    CALL["Tool Call<br/>nmap · http · ffuf · exploit"]

    OWNER -->|chain of title| SPONSOR
    SPONSOR -->|warrants owner auth| POLICY
    POLICY -->|formalized| SCOPE
    SCOPE -->|loaded into| MW
    MW -->|permits only if in-scope| CALL

    BREAK1(("BREAK 1<br/>Sponsor ≠ Owner"))
    BREAK2(("BREAK 2<br/>Action outside RoE"))
    BREAK3(("BREAK 3<br/>Stale scope"))

    BREAK1 -.voids.-> SPONSOR
    BREAK2 -.voids.-> MW
    BREAK3 -.voids.-> SCOPE

    style OWNER fill:#0d1b2a,stroke:#5eead4,color:#e4e4e8
    style SPONSOR fill:#101018,stroke:#5a5a68,color:#e4e4e8
    style POLICY fill:#101018,stroke:#5a5a68,color:#e4e4e8
    style SCOPE fill:#14141f,stroke:#5eead4,color:#e4e4e8
    style MW fill:#14141f,stroke:#5eead4,color:#5eead4
    style CALL fill:#101018,stroke:#5a5a68,color:#9494a0
    style BREAK1 fill:#2a0d0d,stroke:#a00000,color:#f08080
    style BREAK2 fill:#2a0d0d,stroke:#a00000,color:#f08080
    style BREAK3 fill:#2a0d0d,stroke:#a00000,color:#f08080
```

**Reading the diagram**: Read top-down. Each arrow is a link in the chain — and the *only* place legal cover is created is at the top (the asset owner's consent). The three red BREAK nodes are where the chain voids in practice. Break 1: a program operator that doesn't actually hold the owner's authorization. Break 2: an action the RoE forbids, even on an in-scope host. Break 3: a scope file that was valid last week but whose targets were since removed. The scope enforcement middleware (teal) is the engineering realization of the chain — it converts "is this call authorized?" into a binary, code-level check.

---

## Diagram 2 — Scope Enforcement as Harness Middleware (n8n)

**Type**: n8n workflow (importable JSON)
**Purpose**: The primary visual per the course tech stack (n8n first). Shows scope enforcement as a middleware node that sits between the agent's tool request and the network — the load-bearing architectural pattern of S01.2, previewed here in its legal-control framing.

```json
{
  "name": "S00 — Scope Enforcement Middleware",
  "nodes": [
    {
      "parameters": {},
      "name": "Tool Request",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [240, 300],
      "notes": "Agent (or sub-agent) emits a tool_use: {tool, target, action}"
    },
    {
      "parameters": {
        "dataType": "string",
        "value1": "={{ $json.target }}",
        "rules": {
          "rules": [
            { "value2": "={{ $env.SCOPE_IN_SCOPE.split(',') }}", "operation": "isInList" }
          ]
        }
      },
      "name": "Target in Scope?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1.1,
      "position": [460, 300],
      "notes": "Check target against scope.in_scope[]. Match is exact, not glob."
    },
    {
      "parameters": {
        "dataType": "string",
        "value1": "={{ $json.action }}",
        "rules": {
          "rules": [
            { "value2": "={{ $env.ROE_FORBIDDEN.split(',') }}", "operation": "notInList" }
          ]
        }
      },
      "name": "Action under RoE?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1.1,
      "position": [680, 300],
      "notes": "Check action against rules_of_engagement.forbidden[]. e.g. 'dos','exfil','socialeng'"
    },
    {
      "parameters": {
        "dataType": "dateTime",
        "value1": "={{ $now.toISO() }}",
        "rules": {
          "rules": [
            { "value2": "={{ $env.SCOPE_VALID_UNTIL }}", "operation": "before" }
          ]
        }
      },
      "name": "Scope Fresh?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1.1,
      "position": [900, 300],
      "notes": "Reject if scope.valid_until has passed. Prevents stale-scope drift (Break 3)."
    },
    {
      "parameters": {
        "keepOnlySet": true,
        "values": {
          "string": [
            { "name": "scope_ref", "value": "={{ $json.target }}::{{ $json.action }}::{{ $now.toISO() }}" }
          ]
        }
      },
      "name": "Stamp scope_ref",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [1120, 240],
      "notes": "Annotate the call with the scope entry that authorized it. This is the legal anchor in the evidence log."
    },
    {
      "parameters": {},
      "name": "Execute Tool",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [1320, 240],
      "notes": "Only reached if all three checks pass. The network call happens here."
    },
    {
      "parameters": {
        "values": {
          "string": [
            { "name": "blocked_reason", "value": "out_of_scope" }
          ]
        }
      },
      "name": "Block + Log",
      "type": "n8n-nodes-base.set",
      "typeVersion": 2,
      "position": [1120, 360],
      "notes": "Blocked call. Logged with reason. Never reaches the network. This is the legal control."
    }
  ],
  "connections": {
    "Tool Request": { "main": [[{ "node": "Target in Scope?", "type": "main", "index": 0 }]] },
    "Target in Scope?": { "main": [[{ "node": "Action under RoE?", "type": "main", "index": 0 }], [{ "node": "Block + Log", "type": "main", "index": 0 }]] },
    "Action under RoE?": { "main": [[{ "node": "Scope Fresh?", "type": "main", "index": 0 }], [{ "node": "Block + Log", "type": "main", "index": 0 }]] },
    "Scope Fresh?": { "main": [[{ "node": "Stamp scope_ref", "type": "main", "index": 0 }], [{ "node": "Block + Log", "type": "main", "index": 0 }]] },
    "Stamp scope_ref": { "main": [[{ "node": "Execute Tool", "type": "main", "index": 0 }]] }
  }
}
```

**Reading the diagram**: A tool request enters from the agent. Three sequential IF gates — target in scope, action permitted by RoE, scope not stale — each can divert to Block+Log. Only a request passing all three reaches the network. The `scope_ref` stamp is the legal anchor: it records *which scope entry* authorized *this call* at *this time*, producing the "authorization chain to the atom" that protects the operator if the call is ever questioned. This is the n8n shape of the pattern S01.2 implements in code.

---

## Diagram 3 — The Gates-Down Model (post-Van Buren CFAA authorization)

**Type**: Mermaid (statechart)
**Purpose**: Makes the *Van Buren v. United States* (2021) ruling concrete. Authorization is assessed at the "gate" (the file/folder/host boundary), not at the motive layer. A harness must treat each gate as binary.

```mermaid
stateDiagram-v2
    [*] --> Unauth: target never authorized
    [*] --> Auth: scope file permits target

    Unauth --> VIOLATION: any access
    note right of VIOLATION
        § 1030(a)(2): access without authorization.
        Van Buren offers NO shelter here.
        The gate was never opened.
    end note

    Auth --> AuthorizedArea: access permitted file/host
    Auth --> Exceeded: access file/host NOT in scope
    note right of Exceeded
        "Exceeds authorized access" (post-Van Buren):
        accessing an area you are NOT authorized
        to access at all. Not a motive question.
    end note

    AuthorizedArea --> OK: used for security testing
    AuthorizedArea --> STILL_OK: used for improper purpose
    note left of STILL_OK
        Van Buren: improper purpose on an
        authorized area is NOT a CFAA (a)(2)
        violation. Gates-down, not motives-down.
    end note

    Exceeded --> VIOLATION
    OK --> [*]
    STILL_OK --> [*]
    VIOLATION --> [*]
```

**Reading the diagram**: Two entry states — the target is either in your scope file (Auth) or not (Unauth). From Auth, you either stay in an authorized area or exceed into one you were never granted. The *Van Buren* holding is the lower-left: improper purpose on an *authorized* area is not an (a)(2) violation — that is the narrowing. The critical warning for harness builders is the right side: "exceeds authorized access" still cleanly captures reaching an area the scope file never permitted. The narrowing moved the motive inquiry; it did not move the gate. Build the gate (scope enforcement), not a motive detector.

---

## Diagram 4 — When Scanning Becomes DoS (effect-based, not rate-based)

**Type**: Mermaid (flowchart with threshold)
**Purpose**: The CFAA § 1030(a)(5) / CMA s.3 risk model. There is no bright-line request rate. The threshold is *effect on the target*. Shows the harness's required reaction to distress signals.

```mermaid
flowchart LR
    subgraph SCAN["Scanner at rate R"]
        S1["Outbound requests"]
    end

    S1 --> T1{"Target showing<br/>distress?"}
    T1 -->|"5xx spike"| DISTRESS
    T1 -->|"conn resets"| DISTRESS
    T1 -->|"latency spike"| DISTRESS
    T1 -->|"rate-limit hit"| DISTRESS
    T1 -->|"none"| CONTINUE

    DISTRESS["Distress signal<br/>detected"]
    CONTINUE["Continue at R"]

    DISTRESS --> REACT{"Harness reaction"}
    REACT -->|"back off (R/2)"| SCAN
    REACT -->|"threshold exceeded"| HALT

    HALT["STOP — stop condition<br/>this is a CFAA (a)(5) mitigation,<br/>not a performance tweak"]

    style DISTRESS fill:#2a1810,stroke:#a04000,color:#f0a868
    style HALT fill:#2a0d0d,stroke:#a00000,color:#f08080
    style SCAN fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style CONTINUE fill:#0d2818,stroke:#1e8449,color:#82e0aa
```

**Reading the diagram**: The threshold between "scanning" and "DoS" is the target's distress, not your request rate. A scanner at 5 req/s that takes down a fragile target is a DoS; a scanner at 500 req/s against a hardened one may be fine. The harness cannot know in advance which is which — so it must *react* to distress signals (5xx spikes, connection resets, latency degradation, rate-limit responses) by backing off, and halt entirely if distress persists. That halt is a stop condition (Course 1, Module 1.2) and its legal function is a § 1030(a)(5) mitigation. Default to low concurrency; back off on distress; treat persistent distress as a hard stop.

---

## Diagram 5 — The Evidence Record and its Retention Lifecycle

**Type**: Mermaid (flowchart + statechart hybrid)
**Purpose**: S00.2's two-sided evidence obligation. A finding record has a lifecycle: capture → classify → retain or destroy. The classification determines the retention. Over-retention is as much a liability as under-retention.

```mermaid
flowchart TD
    FIND["Finding detected"]
    CAP["Capture minimum proof<br/>COUNT(*) or 1 redacted row<br/>NOT SELECT *"]

    CAP --> CLASS{"Classify"}

    CLASS -->|"no sensitive data"| PUB["Public"]
    CLASS -->|"redacted at capture"| RED["Redacted"]
    CLASS -->|"real PII / credentials"| REST["Restricted"]

    PUB --> KEEP1["Retain indefinitely<br/>(portfolio artifact)"]
    RED --> KEEP2["Retain for engagement<br/>+ contractual tail"]
    REST --> DESTROY["Destroy on report<br/>or per contract<br/>(whichever sooner)"]

    KEEP1 --> LOG["Evidence store<br/>(append-only, scope-referenced)"]
    KEEP2 --> LOG
    DESTROY --> DELETED["Documented destruction<br/>(record the deletion, not the data)"]

    LOG --> REPORT["Ties finding to scope_ref<br/>from Diagram 2"]

    style CAP fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style DESTROY fill:#2a0d0d,stroke:#a00000,color:#f08080
    style DELETED fill:#101018,stroke:#5a5a68,color:#9494a0
    style REST fill:#2a1810,stroke:#a04000,color:#f0a868
    style LOG fill:#14141f,stroke:#5eead4,color:#5eead4
```

**Reading the diagram**: Capture is the first decision point — and it is *minimum* proof, by default. The classification gate routes each record to a retention class. Public records can live forever as portfolio artifacts; Redacted records survive the engagement plus a tail; Restricted records (real PII, credentials) are *destroyed on report submission*. The destruction is itself recorded (you keep the record of the deletion, not the deleted data). The evidence store at the bottom is the same append-only, scope-referenced log from Diagram 2 — every record carries the `scope_ref` that authorized the call that produced it. An evidence store that captures everything and destroys nothing has built a compliance time bomb, not an evidence chain.

---

## Diagram 6 — Coordinated Vulnerability Disclosure Timeline

**Type**: Mermaid (sequence/gantt-style flow)
**Purpose**: The CVD baseline. The harness must *emit* disclosure metadata (report date, vendor response, agreed publication date) as part of every finding — this diagram shows why those fields exist.

```mermaid
flowchart LR
    D0["Day 0<br/>Discovery +<br/>private report"]
    D0 -->|"vendor ack"| D1["Day 1–7<br/>Vendor triage<br/>(expected ack)"]
    D1 -->|"fix in progress"| D45["Day ~45<br/>CERT/CC default<br/>coordination window"]
    D45 -->|"vendor fixed"| PUB["Coordinated<br/>public disclosure"]
    D45 -->|"vendor silent"| D90["Day ~90<br/>GPa / program<br/>disclosure window"]
    D90 -->|"still silent"| PUB

    D0 -.->|"DON'T"| EARLY["Public disclosure<br/>before fix<br/>(voids safe harbor,<br/>burns goodwill)"]

    style D0 fill:#0d1b2a,stroke:#5eead4,color:#e4e4e8
    style PUB fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style EARLY fill:#2a0d0d,stroke:#a00000,color:#f08080
    style D45 fill:#14141f,stroke:#5eead4,color:#9494a0
    style D90 fill:#14141f,stroke:#5a5a68,color:#9494a0
```

**Reading the diagram**: The timeline runs left to right. Day 0: you discover and report privately. Vendor acknowledges and triages within roughly a week. The default CERT/CC coordination window is ~45 days; Google Project Zero and several programs run ~90 days. Public disclosure happens *coordinated with the vendor*, at or after the window — not before. The red node is the failure mode: early public disclosure voids safe harbor and invites legal action even when the initial finding was authorized. The harness's job is to stamp every finding with `report_date`, `vendor_response`, `agreed_publication_date` — those fields exist so the disclosure timeline is auditable, not improvised.

---

## Diagram 7 — Liability Does Not Transfer to the Model

**Type**: Mermaid (flowchart, the operator-instrument doctrine)
**Purpose**: The load-bearing point of S00.3, Risk 4. When an autonomous harness exceeds authorization, the liability stays with the operator. Diagrams the controls that follow from accepting this.

```mermaid
flowchart TD
    OP["Operator (you)<br/>deploy · configure · point at target"]
    HARNESS["Autonomous Harness<br/>acts at machine speed"]
    MODEL["Model<br/>reasons, proposes tool calls"]

    OP -->|"deploys + configures scope"| HARNESS
    HARNESS -->|"calls (model is an instrument)"| MODEL
    MODEL -->|"tool proposals"| HARNESS

    HARNESS -.->|"if out-of-scope action"| HARM["§ 1030(a)(2) violation<br/>or CMA s.1 / s.3 offence"]
    HARM -.->|"liability flows to"| OP

    DEFENSE["&quot;the model did it&quot;"]
    DEFENSE -.->.->|"NOT a defense"| X["No court accepts this.<br/>The harness is the operator's instrument."]

    OP -->|"controls that flow from this"| C1["Autonomy ≤ Level 3 in production<br/>(propose → approve → execute)"]
    OP --> C2["Scope enforcement in code<br/>(not the system prompt)"]
    OP --> C3["Audit log: scope_ref per call<br/>(Diagram 2)"]
    OP --> C4["Kill switch + bounded blast radius"]

    style OP fill:#0d1b2a,stroke:#5eead4,color:#e4e4e8
    style HARNESS fill:#14141f,stroke:#5a5a68,color:#e4e4e8
    style MODEL fill:#101018,stroke:#5a5a68,color:#9494a0
    style HARM fill:#2a0d0d,stroke:#a00000,color:#f08080
    style DEFENSE fill:#2a0d0d,stroke:#a00000,color:#f08080
    style X fill:#2a0d0d,stroke:#a00000,color:#f08080
    style C1 fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style C2 fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style C3 fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style C4 fill:#0d2818,stroke:#1e8449,color:#82e0aa
```

**Reading the diagram**: Top — the operator deploys and configures the harness; the harness calls the model as one of its instruments; the model proposes actions. The red path: if the harness acts out of scope, the violation occurs and liability flows *up* to the operator. The lower-right "the model did it" is explicitly marked as not a defense. The four green controls at the bottom are what acceptance of this doctrine *requires* you to build: bounded autonomy in production, scope enforcement in code, an audit log that reconstructs authorization per call, and a kill switch with bounded blast radius. None of these are optional. Together they are the difference between a defensible engagement and an indictment.
