# Bake networking into core; collapse spt-node into the per-machine daemon

## Status

accepted (2026-05-28) — reverses the sister project's separate-daemon decision (claude_skill_owl CONTEXT.md §Networking) for the spt-core context. · amended (2026-05-31): GitHub re-admitted as an opt-in context-sync hub (see Amendment below).

## Amendment (2026-05-31): GitHub re-admitted as an opt-in context-sync hub

This ADR retired GitHub as the *required/default* cross-node sync. It is now re-admitted as an **opt-in alternative transport for the context repo only** (`tracked/`), enabled by `spt context-github-setup`:

- **Default stays P2P** + no-account — the core promise is unchanged.
- **Hub mode (opt-in):** every node pull→merge→pushes against a private GitHub remote (always-online sync hub + live GUI view), authed by a **shared deploy key** distributed as subnet secret material (only the setup node needs a GitHub account). **Prefer-GitHub, P2P backstop.**
- **Scope:** hub mode carries the **context repo only**. Messaging, registry, remote-drive, pairing, and presence always ride P2P/Iroh; gh-on never removes the P2P requirement. So the original decision (networking baked-in, first-class, P2P) stands in full — the hub is a context-sync convenience layered on top, not a return to GitHub-as-infrastructure.

## Context

The sister project (`claude_skill_owl`) decided networking should live in a separate `spt-node` daemon, explicitly to decouple the network stack from SPT's Claude-Code-tied core binary, expose SPT-protocol-as-product, and let networking evolve on its own release cycle. That decision predates spt-core.

spt-core is a ground-up, harness-independent rebuild. The primary reason `spt-node` was separate — decoupling networking from a CC-tied binary — no longer exists, because spt-core is already decoupled from any harness. Meanwhile the product goal for networking sharpened: WAN cross-machine messaging should be **first-class and zero-config — "just works."**

## Decision

Bake the WAN transport stack (Iroh + mDNS LAN discovery + pairing) into spt-core's library crates, behind a compile-time `net` feature flag (default-on in the reference binary, optional for embedded library consumers).

"Just works WAN, reachable even when no session is running" requires a persistent per-machine network presence — the exact job `spt-node` was created to do. spt-core already commits to a single always-on, one-per-machine `spt-daemon` to supervise PTYs (the terminal wrapper). **Collapse the network-host role into that same daemon (option B1).** One process owns both PTYs and the node identity + WAN endpoint.

Rejected alternatives:
- **Seams-only in core, transport in spt-node (A):** inconsistent with first-class/zero-config networking; preserves a separate-deliverable boundary whose original justification is gone.
- **Two daemons — term-daemon + net-daemon (B2):** doubles the always-on process count and the crash/restart/binary-handoff surface for no benefit once both are in core.
- **LAN-in-core, WAN-in-node (C):** puts the repo boundary *inside* the transport layer, splitting shared discovery/identity/framing code across two repos.

**v1 relay stance:** default to n0.computer's free public relays for zero-config onboarding; ship a self-hostable-relay config knob and plain-language disclosure as the principled escape hatch. The dependency is operational, metadata-only (traffic is end-to-end encrypted), and escapable.

## Consequences

- `spt-node` is retired from the project vocabulary as a separate deliverable. WAN transport is a **first-class v1 capability** of spt-core (baked into the core crates, default-on in the reference binary) — *not* a post-v1 milestone and not a separate repo. The `SptNode` endpoint type survives unchanged — it remains how a machine is addressed.
- The "second project atop spt-core" is no longer mandated to be spt-node. The real next milestone is the rebuilt spt plugin reaching parity.
- The reference binary carries Iroh's footprint (~8MB) and the `noq` git-patch coupling when built with `net`. The feature flag keeps minimal library builds clean.
- v1 has a soft, documented runtime dependency on n0-operated relay infrastructure. Acceptable for v1; self-host path is the mitigation.
- The single daemon is a single point of failure for both PTY hosting and networking on a machine; its crash-recovery and binary-handoff story must cover both roles. (Addressed by the broker/brain split in **ADR-0004** — the stable broker holds PTYs + sockets across brain restarts.)

## Stage A red-team amendments (2026-05-31)

Codex (`docs/reviews/STAGE-A-codex-redteam.md`) sharpened the collapse's cost:

- **SERIOUS #6 — one collapsed daemon = one failure domain.** A networking bug can take out terminal hosting; a PTY-broker bug can take out WAN reachability. Accepted (the collapse is locked), but v1 owes a **fault-injection acceptance matrix**: crash/hang Iroh, mDNS, registry sync, PTY broker, and manifest invocation independently; measure blast radius + recovery. Track at M4. → Begun M4-D4: **`docs/FAULT-MATRIX.md`** is the living matrix (proven rows with test evidence; planned rows tracked as debt).
- **Interaction with ADR-0004 (FATAL #4):** preserving live WAN streams across a brain restart forces Iroh endpoint / QUIC stream state into the "stable broker," enlarging the kernel ADR-0002 wanted minimal. Resolved in ADR-0004's ownership table — "stable" now means *update cadence*, not *narrowness*.
