# Spike #3 — QUIC + file-transfer stream survival across brain restart

> Date: 2026-06-01. Status: **PASS (core thesis, loopback Iroh QUIC)**.
> Throwaway code: `../spt-spikes/spike-03-quic-survival` (outside the spt-core repo, not shipped).
> Closes ADR-0004 §E.1 (codex red-team FATAL #2) — **the single highest remaining risk in the roadmap**.

## Question

ADR-0004 §B's ownership table left one row open: *Iroh endpoint + accepted QUIC streams → broker (❌ not spiked)*. Spike #1 proved a PTY child + a plain-TCP client survive a brain restart, but plain TCP is a weak proxy — QUIC carries process-local crypto + per-stream state. Codex called live-QUIC-across-restart the most likely redesign trigger. **Does the broker-owned-endpoint shape actually keep a live QUIC connection + an in-flight transfer intact across a brain restart?**

## Method

One Rust binary (`iroh =0.98.2` + tokio + std net), four modes: `broker`, `brain <ver>`, `peer`, `run`.
- **broker** owns the Iroh endpoint, the accepted QUIC connection, and the uni send stream. It **drives the file transfer itself** — an autonomous chunk pump (`chunk N` + ~1 KB padding every 50 ms), never gated on the brain. Routes brain `INJECT:` control lines into a `MARKER` frame on the QUIC stream. Never restarts.
- **brain** holds only a forwarding control socket (plain TCP) — no endpoint, no QUIC stream. Killable/relaunchable. v2 injects a marker post-restart.
- **peer** = the remote downloader: connects to the broker's Iroh endpoint, accepts the uni transfer stream, logs every byte. Must survive brain churn.
- **run** orchestrates: start broker, attach peer, start brain v1, kill it (mid-transfer), start brain v2 (injects marker), tear down, then assert from the peer's download log.

Single-machine, loopback iroh — validates the **ownership shape** (§B), not off-node transport (that's M4). The point is to falsify-or-confirm "broker-owned endpoint survives brain restart" before any daemon code rests on it.

Invariants: **A** QUIC conn alive whole transfer (chunks advance past the kill seq) · **B** chunk counter contiguous (no gap / no premature end) · **C** control from the post-restart brain reaches the broker-owned QUIC sender · **D** every chunk delivered exactly once (no duplicate seq).

## Result

```
peer chunks 0..125 contiguous, no gap across the brain kill (~seq 58) / restart window
post-restart MARKER reached the broker-owned QUIC sender | no duplicate seq
A PASS  B PASS  C PASS  D PASS  →  OVERALL PASS ✅   (4/4 runs, stable)
```

The ownership model holds over QUIC exactly as it did over the PTY: because the endpoint and the send stream live in the broker, brain death is just a closed forwarding socket — the QUIC connection, the in-flight transfer, and the per-stream crypto state are all untouched, and the broker-owned sender still obeys input from a freshly-started brain. This is the *brain-only* update class — the routine case ADR-0004 must preserve.

## What this proves (and what it deliberately does not)

- **Proven:** the §B assignment is *sufficient* — a broker-owned Iroh endpoint + QUIC stream survive a brain restart with zero interruption to a live peer download. ADR-0004 §B is **not falsified**.
- **Out of scope (by design):** off-node transport over hostile NAT (M4); the QUIC-ownership *implementation* inside the real daemon (M4 — only the *shape* is validated now). The spike does not test a brain-owned stream because §B already forbids it and Spike #1's logic covers why.

## Verdict

The highest-risk open row in ADR-0004 §B closes **PASS**. The broker-as-stable-kernel can own networking stream-state without losing it on brain restart — accepting the enlarged-broker cost §B already called out. M3b is unblocked on this gate. ADR-0004 §E.1 is closed; promote the QUIC-ownership *implementation* to M4 rather than re-opening the decision.
