# RFC-0011 — Security Threat Model & Trust Boundaries

- **Status:** **RATIFIED v1.0 — 2026-04-23. CHAIR-APPROVED.**
- **Author:** 🧠 Agentic Architect.
- **Sprint:** pre-Sprint-3 (synthesis of four-turn pre-S3 security audit).
- **Audience:** Cloud Agents (LLMs); 🛡️ devex-protocol-sec; ☁️ cloudflare-native-edge; 🦀 edge-kubelet-engineer; CTO chair.
- **Depends on:** RFC-0001 v1.3, RFC-0002 v2.2, RFC-0003 v1.4 (+ §V13.10 footnote), RFC-0006 v1.0, RFC-0007 v1.1 RATIFIED, RFC-0009 v1.0.
- **Does not modify:** any ratified RFC body. References only.
- **Scope:** Operational threat model — assets, actors, attack trees for the top-3 in-scope scenarios, mitigation map, residual-risk register.

---

## §1. Trust Boundaries

```
┌──────────────┐        ┌────────────────────────┐        ┌──────────────────┐
│ User browser │  TLS   │  aethermesh.app Worker │  R2    │ R2 bucket(s):    │
│ (homepage,   ├───────▶│  - homepage HTML       ├───────▶│  -dev (rw CI)    │
│  install.sh  │        │  - llms.txt            │        │  -prod (RO srv)  │
│  fetch)      │        │  - /v1/devices/enroll  │        │  signed binaries │
└──────┬───────┘        │  - /v1/wss             │        │  + .minisig      │
       │ curl|sh        │  - /.well-known/jwks   │        └──────────────────┘
       ▼                └─────────┬──────────────┘
┌────────────────┐                │ EdDSA JWKS
│ end-user host  │                ▼
│ install.sh     │       ┌──────────────────┐
│  + minisign    │  WSS  │ aiot-edge binary │
│  verifies      ├──────▶│ (device leaf-key │
│  fail-CLOSED   │       │  in tmpfs only)  │
└────────────────┘       └──────────────────┘
```

Boundaries (each a hostile interface):

| # | Boundary                          | Threat surface                                                        |
|---|-----------------------------------|-----------------------------------------------------------------------|
| B1 | Browser → Worker (HTTPS)         | TLS PKI, CDN cache poisoning, JS supply chain (none served).          |
| B2 | install.sh → R2 (HTTPS GET)      | Artifact swap, .minisig absence/strip, TOCTOU on download path.       |
| B3 | install.sh → minisign verify     | Trust-anchor distribution (which pubkey?), fail-open vs fail-closed.  |
| B4 | aiot-edge → WSS gateway          | TLS pinning, runtime-token theft, replay.                             |
| B5 | enroll round-trip (B4 special)   | One-shot bearer (`enroll_token`); EdDSA pubkey TOFU at first contact. |
| B6 | gateway → D1 / KV / R2 (CF API)  | API token scope creep, blast-radius if leaked.                        |

---

## §2. Trust Roots

### §2.1 Minisign release pubkey (artifact + script signing)

**Pubkey (canonical):** `RWS7TatrmwpCgr+chZpBn7gLyBwoYvQqG7rodsXrOjiehSGJcBFnRtV4`

**Distribution channels — ratified pick (§10 Q1 RESOLVED):**

- **(a) MUST:** Embedded in homepage HTML + `/.well-known/llms.txt` (at domain, easy to fetch).
- **(b) SHOULD:** DNS TXT record `_minisign.aethermesh.app` (Sprint-3 add-on; DNSSEC opt-in).
- **(c) MUST:** GitHub Release notes pinned (signed git tag + repo settings lock; independent custodian).

**Rationale:** (a)+(c) gives two independent custodians (CF + GitHub) at zero added ops cost; (b) raises the bar to "compromise CF + GitHub + DNS registrar." Anchor MUST appear byte-identical across all selected channels. Mismatch → fail-CLOSED.

### §2.2 EdDSA gateway signing key (JWKS)

- Endpoint: `https://gateway-{env}.aethermesh.app/.well-known/jwks.json` (RFC-0003 §V13.2).
- `kid` format: `gw-<26-char ULID>` (RFC-0003 §V13).
- Rotation: documented in RFC-0003 §V13.3 (overlap window, audit-logged).

### §2.3 Device leaf key

- Generated **on the device**, Ed25519, private key **never** transmitted.
- PEM public-key submitted at enroll (RFC-0007 v1.1 §V11.2 `public_key_pem`).
- Gateway persists at enroll into `devices.enroll_pubkey_pem` (D1); verifies all subsequent `client-assertion` JWTs against it.
- No revocation list at v1.0 (§8 residual).

---

## §3. Asset Inventory

| Asset                                         | Sensitivity | Custodian          | Boundary |
|-----------------------------------------------|-------------|--------------------|----------|
| Minisign **secret** key                       | Top Secret  | Release operator (laptop, offline preferred) | out-of-band |
| Gateway EdDSA signing key (current `kid`)     | Top Secret  | CF Workers Secrets | B6       |
| CF API token (`.dev.vars`, scope unverified)  | Top Secret  | Local dev fs (0600)| B6       |
| `enroll_token` (per-device, ≤24h, single-use) | Secret      | Operator → device env-var/stdin | B5  |
| Device leaf private key                       | Secret      | Device tmpfs       | B4       |
| `runtime_token` (device JWT, 1h)              | Secret      | Device memory      | B4       |
| `audit_log` rows (D1)                         | Internal    | D1                 | B6       |
| Released binaries + `.minisig`                | Public      | R2 `-prod` (RO)    | B2       |
| Homepage HTML, llms.txt, served RFCs          | Public      | Worker             | B1       |
| Minisign **public** key                       | Public      | (a)/(b)/(c) §2.1   | B3       |

---

## §4. Threat Actors

| Actor                  | Capability                                              | Motivation                  |
|------------------------|---------------------------------------------------------|-----------------------------|
| Curious user           | Reads served bodies, runs install.sh as documented      | Learn / tinker              |
| Script kiddie          | Replays `enroll_token`, fuzzes `/v1/devices/enroll`     | Notoriety / nuisance        |
| Cost-griefer           | Mass HTTP to amplify CF/D1/KV write costs               | Financial harm to operator  |
| Sophisticated (CDN/DNS)| BGP/DNS hijack, CA mis-issuance, cache poisoning        | Targeted device takeover    |
| Insider                | Has CF dashboard or repo write                          | Exfiltration / sabotage     |

---

## §5. Attack Trees (top 3)

### §5.1 Mass device impersonation (audit P0-2 path)

```
GOAL: forge runtime_token / WSS-as-foreign-device
└── steal a valid leaf private key
    ├── exfiltrate from device tmpfs (requires root on target)  ← out-of-scope (host compromise)
    └── EXPLOIT pre-fix: gateway accepts client-assertion w/o verifying
        signature against the per-device pubkey persisted at enroll.
        ├── Replay any captured client-assertion against another node_id  ← FIXED (P0-2)
        └── Mint forged client-assertion with attacker key                ← FIXED (P0-2)
```

**Mitigation (RFC-0007 v1.1):** D1 column `enroll_pubkey_pem` populated at enroll; every WSS upgrade EdDSA-verifies the `client-assertion` against that key; failure → `E_INVALID_CLIENT_ASSERTION` (HTTP 401), audit-logged.

### §5.2 Cost-amplification (audit P0-3, P1-1)

```
GOAL: drive D1 / KV write spend
├── flood /v1/devices/enroll with junk tokens
│   ├── pre-fix: D1 audit row written BEFORE rate-limit decision  ← FIXED (P0-3)
│   └── KV write per attempt for dedup index                       ← P1-1, Sprint 3
├── flood /v1/wss upgrade with bogus client-assertion              ← per-IP RL, RFC-0007 §7
└── flood /v1/sse subscribers (RFC-0009)                           ← per-token RL, in spec
```

**Mitigation:** rate-limit-first / audit-after on all unauthenticated paths; KV write coalescing (Sprint 3 backlog, P1-1).

### §5.3 Supply chain via install.sh swap (P1-2, P1-3)

```
GOAL: ship a backdoored binary to user curl | sh
├── swap binary in R2
│   ├── pre-fix: shared bucket, dev write = prod write  ← FIXED (P1-2: -dev/-prod split, prod RO)
│   └── prod bucket write requires CF dashboard role + audit  ← residual
├── swap install.sh
│   ├── pre-fix: install.sh unsigned                    ← FIXED (P1-3: install.sh.minisig)
│   └── pre-fix: install.sh fail-OPEN if minisign absent← FIXED (Turn-3 P1-3)
└── strip .minisig at the CDN edge
    └── install.sh fail-CLOSED if .minisig fetch fails  ← FIXED (Turn-3 P1-3)
```

**Mitigation evidence:**
- v0.1.1 binary SHA256: `881a8208ec2fe61e1126cc8ebb69351c482dff1d8c3122c50e4b3130679a2e03` — pinned in release/v0.1.1/aiot-edge-aarch64-musl.sha256.
- Minisign anchor `RWS7TatrmwpCgr+chZpBn7gLyBwoYvQqG7rodsXrOjiehSGJcBFnRtV4` distributed per §2.1.
- `make dist-public` script committed → reproducible export provenance.

---

## §6. Risk Matrix (likelihood × impact)

Scale: L = {1 rare, 2 plausible, 3 likely}; I = {1 nuisance, 2 fleet-localized, 3 PaaS-wide}.

| Vector                            | L (before) | I | Score | L (after) | Score | Status                |
|-----------------------------------|:---------:|:-:|:-----:|:---------:|:-----:|-----------------------|
| Mass device impersonation (§5.1)  |    3      | 3 |   9   |    1      |   3   | mitigated (in flight) |
| Cost amplification (§5.2)         |    3      | 2 |   6   |    2      |   4   | partially mitigated   |
| Supply-chain swap (§5.3)          |    2      | 3 |   6   |    1      |   3   | mitigated             |
| CF API token scope creep          |    2      | 3 |   6   |    2      |   6   | **pending CTO**       |
| Insider repo write (no CI gate)   |    2      | 3 |   6   |    2      |   6   | residual (Sprint 3)   |
| Minisign sec-key compromise       |    1      | 3 |   3   |    1      |   3   | residual (no HSM)     |
| Compromised device leaf — no CRL  |    1      | 2 |   2   |    1      |   2   | residual              |

---

## §7. Mitigation Summary

| Vector                          | Defense (normative refs)                                                     |
|---------------------------------|------------------------------------------------------------------------------|
| §5.1 impersonation              | RFC-0007 v1.1 §V11.2; D1 `enroll_pubkey_pem`; `E_INVALID_CLIENT_ASSERTION`  |
| §5.2 cost-amp                   | RFC-0007 §7 (per-IP RL); audit-after-RL ordering; Sprint-3 KV coalescing     |
| §5.3 supply-chain               | install.sh fail-CLOSED; `.minisig` mandatory; R2 split `-dev`/`-prod` (prod RO) |
| Local secret hygiene            | `.dev.vars` 0600; `umask 0o077`; `/etc/aiot-edge` 0700; `PR_SET_DUMPABLE=0`  |
| `enroll_token` exposure         | RFC-0007 v1.1 §V11.1: env-var or stdin only, zeroizing, no disk              |
| EdDSA cutover hardcoding        | KV `config:eddsa_cutover_override_ms` overrides compiled default             |
| Audit IP exposure               | RFC-0003 §V13.10: `source_ip` stored as truncated SHA-256                   |

---

## §8. Known Unmitigated Risks (Sprint 3+ backlog)

1. **No CI/CD deploy gate** — manual `wrangler deploy` from operator laptop (P2-7).
2. **No HSM for minisign secret key** — currently on operator laptop.
3. **No revocation list for compromised device leaf keys** — RFC-0007 §11 explicitly defers CRL/OCSP.
4. **CF dashboard verification gates pending CTO** — G-SEC-1 (CF API token scope) and G-SEC-2 (R2 prod bucket RO confirmation).
5. **Single-channel trust anchor** — until §2.1 DNS TXT add-on, anchor distribution has only two roots (CF + GitHub).
6. **No per-tenant rate limiting** on `/v1/devices/enroll` — per-IP only at v1.0.
7. **Hardware attestation is self-reported** — TPM/PSA quote verification is future work.

---

## §9. References

- RFC-0001 v1.3 — node_id / error envelope.
- RFC-0002 v2.2 — WSS envelope.
- RFC-0003 v1.4 (+ §V13.10 footnote) — RBAC, JWKS, audit IP-hashing.
- RFC-0006 v1.0 — safety_class enforcement.
- RFC-0007 v1.1 RATIFIED — enrollment.
- RFC-0009 v1.0 — system metrics SSE.
- Pre-Sprint-3 audit reports: Turn 1 (CF resource layer), Turn 2 (gateway request path), Turn 3 (filesystem/repo hygiene), Turn 4 (binary supply chain).

---

## §10. CTO Sign-off (RESOLVED 2026-04-23)

1. **Trust-anchor channel pick** — RESOLVED: **(a) homepage+llms.txt MUST + (c) GitHub Release MUST + (b) DNS TXT SHOULD Sprint-3.**
2. **Ratification bundle** — RESOLVED: RFC-0011 v1.0 RATIFIED, RFC-0007 v1.1 RATIFIED, RFC-0003 §V13.10 in-place merge — all approved.
3. **Carry-forward residuals** — items 1–3 (CI/CD gate, HSM, revocation list) confirmed Sprint-3 backlog; items 4–5 (CF dashboard verification, anchor channel) remain CTO action items.
