1	> **Amended 2026-05-20** — Findings from the docs/research/index/ mapping pass have been folded into this brief. The pre-amendment version is preserved at `docs/research/archive/SPT Networked Messaging Research Brief.original.md`. Per-correction provenance: see `docs/research/index/README.md` §Caveats.
2
3	# SPT Networked Messaging: Research Brief
4	**Sentience Pocket Transacter — Cross-Host Agent Messaging**
5	*Rust single-binary constraint · No central operator · No credentials · LAN + WAN*
6
7	***
8
9	## 1. Executive Shortlist
10
11	Candidates are ranked by fit against the seven hard requirements (no central server, no credentials, minimal setup, free, single static binary, cross-platform, backward-compatible surface).
12
13	### Rank 1 — **Iroh** (`iroh` / `n0-computer`)
14
15	Iroh is a QUIC-based P2P library that dials peers by Ed25519 public key and builds connections using a relay-assisted hole punch that falls back to encrypted relay. Roughly 9 out of 10 connection attempts go direct; the relay is only a temporary stepping stone and never sees plaintext. The default relays are operated by n0.computer, free to use, but the relay binary is open source and trivially self-hosted — making the architecture genuinely multi-operator in practice. It links against tokio (already ubiquitous in Rust async work), builds to a single static binary, ships prebuilt for Linux/macOS/Windows. As of `iroh = 1.0.0-rc.0` the public types are `EndpointId` and `EndpointAddr` (renamed from `NodeId` / `NodeAddr` in pre-1.0) [amended 2026-05-20], and LAN/mDNS discovery has been factored out of the main crate — the in-tree `discovery-local-network` feature flag was removed and SPT must depend on the external `iroh-mdns-address-lookup` crate (or implement the `AddressLookup` trait itself) for LAN-first discovery [amended 2026-05-20]. The compiled crate size is noted as ~43–93 MB before LTO/stripping, which is large but manageable with standard profile tuning. Identity is purely a keypair generated at startup — no registration required. `libp2p-iroh` (0.1.x) further bridges iroh's transport into the libp2p swarm if gossipsub or Kademlia are later needed. **Fit: passes all 7 hard requirements.** Key tradeoff: relays are n0.computer-operated by default, creating a soft trust dependency until users self-host or the network diversifies.[^1][^2][^3][^4][^5][^6][^7][^8][^9]
16
17	### Rank 2 — **rust-libp2p** with DCUtR + Kademlia
18
19	The rust-libp2p stack is modular: pick TCP/QUIC transport, add the DCUtR hole-punching protocol for NAT traversal via relay, layer Kademlia DHT for peer discovery, and gossipsub for pub/sub messaging. DCUtR achieves **70% ± 7.1% direct-connection success** on the production libp2p/IPFS network (4.4M attempts across 85k networks, 2025 measurement) — with TCP and QUIC traversal rates statistically indistinguishable, refuting long-held assumptions of UDP superiority [amended 2026-05-20].[^82] QUIC hole punching support was merged in 2023. **The rust-libp2p library ships zero hardcoded bootstrap nodes** [amended 2026-05-20]; the famous `bootstrap.libp2p.io` IPFS bootnodes appear only as example constants in `examples/ipfs-kad/src/main.rs`. A private SPT DHT namespace is a one-string change: `kad::Config::new(StreamProtocol::new("/spt/kad/1.0.0"))`. The library is MIT/Apache-2, actively maintained, and used in production by Ethereum, Filecoin, and IPFS. Binary size impact is significant (examples run 2–5 MB stripped) but feature-flags can shrink this. **Fit: passes all 7 hard requirements with configuration.** Key tradeoff: higher learning curve than iroh; SPT operators must furnish their own bootstrap peers.[^10][^11][^12][^13][^14][^15][^16]
20
21	### Rank 3 — **Iroh + mdns-sd (hybrid LAN/WAN)**
22
23	The practical minimum-surprise architecture is: `mdns-sd` crate for zero-config LAN discovery (mDNS/DNS-SD per RFC 6762/6763)[^17][^18], then iroh for WAN connectivity when peers are not on the same link. This mirrors how Syncthing combines UDP broadcast local discovery with a global discovery server[^19][^20]. The two layers are additive: SPT tries mDNS first, falls back to iroh. This pattern requires no changes to the backward-compatible `$OWL deliver|ring|send|reply` surface. **Fit: passes all 7 hard requirements. Recommended architecture for prototype.**
24
25	### Rank 4 — **Veilid** (`veilid-core`)
26
27	Veilid (Cult of the Dead Cow, 2023) is a Rust-native P2P framework with a fully distributed DHT, onion-routing-style privacy, and an identity model based purely on 256-bit public keys. No nodes are special; any node can bootstrap a network; DNS is used only once and is not required thereafter. veilid-core supports tokio by default and can switch to async-std. Licensed MPL-2.0. **Fit: passes all 7 hard requirements.** Key tradeoffs: the network routes all data through multiple hops by design (Tor-inspired), adding ~100–300 ms latency vs. direct; every node contributes relay bandwidth (~5 GB/month at idle); the app-visible RPC payload cap is **32 KiB** (`MAX_APP_MESSAGE_MESSAGE_LEN = 32768`) — the 64 KiB figure cited elsewhere refers to the lower envelope layer (`ENV0_MAX_ENVELOPE_SIZE = 65507`); there is **no built-in chunking**, so the application must shard anything larger than 32 KiB [amended 2026-05-20]. Best fit if anonymity matters more than latency.[^21][^22][^23][^24][^25][^26][^27]
28
29	### Rank 5 — **Mainline DHT + Magic Wormhole pairing (rendezvous only)**
30
31	BitTorrent's Mainline DHT (Kademlia-based, ~20 M nodes, no single operator) can serve as a pure key-value rendezvous layer: a peer announces its iroh or raw QUIC endpoint under its public-key hash, the other peer looks it up, and then a direct connection is made. Magic Wormhole (`magic-wormhole.rs` crate) provides the initial SPAKE2-based short-code pairing ceremony for trust establishment, after which peers can exchange raw public keys out-of-band. This combination avoids operating any rendezvous infrastructure: DHT is the global yellow pages, Wormhole is the first-contact handshake. **Fit: passes all 7 hard requirements.** Key tradeoff: Mainline DHT stores values for only ~30 minutes, requiring periodic re-announcement; more moving parts than iroh alone.[^28][^29][^30][^31][^32]
32
33	**[amended 2026-05-20] Source liveness caveat.** During fetch verification of the citation corpus, four source URLs were gated by Cloudflare/captcha walls or returned 502 stubs: three reddit threads ([^27] Veilid sentiment, [^37] OpenRelay TURN, [^76] Windows Firewall UX), the icannwiki RFC 6762 page ([^78]), and the Tailscale homelab article ([^58]). These citations remain in the brief as anchor references, but direct quotes were not extractable; the surrounding claims either rely on additional sources or on the unchanged structural facts they cite (Tailscale's SSO requirement, the existence of a Windows Firewall prompt, etc.). Refetch with a real browser session if verbatim evidence is needed.
34
35	***
36
37	## 2. Per-Target Findings
38
39	### 2.1 LAN Discovery & Messaging
40
41	| Name | Primary URL | License | Last Release | Rust Support | Fits Hard Reqs | Key Tradeoff |
42	|---|---|---|---|---|---|---|
43	| mDNS / DNS-SD (RFC 6762 / RFC 6763) | https://datatracker.ietf.org/doc/rfc6762/ | IETF Standard | Feb 2013 | `mdns-sd` (pure Rust), `simple-mdns` | ✅ Y | Windows mDNS works but `mdns-sd` must open a UDP socket on port 5353; Windows Defender may prompt on first use[^17][^18] |
44	| mdns-sd crate | https://crates.io/crates/mdns-sd | Apache-2.0 | Active 2024–2025 | Native | ✅ Y | Spawns a background thread, not tokio-native; wrap in `spawn_blocking` |
45	| Syncthing Local Discovery v4 | https://docs.syncthing.net/specs/localdisco-v4 | MPL-2.0 spec | Active | Implementable | ✅ Y | Uses UDP broadcast (IPv4 255.255.255.255:21027) + IPv6 multicast; device ID = SHA-256 of X.509 cert[^19][^33] |
46	| SSDP / UPnP Discovery | https://datatracker.ietf.org/doc/html/draft-cai-ssdp-v1 | Vendor spec | — | `rupnp` crate | ⚠ Partial | Router-specific; widely deployed but not all devices respond; overkill vs. mDNS for service discovery |
47	| LLMNR (RFC 4795) | https://datatracker.ietf.org/doc/html/rfc4795 | IETF Informational | 2007 | No dedicated crate | ⚠ Partial | Windows-only by common deployment; DNS hostname resolution only, not service discovery |
48	| Magic Wormhole (LAN pairing) | https://github.com/magic-wormhole/magic-wormhole.rs | MIT | Active | `magic-wormhole` crate | ✅ Y | SPAKE2 short-code ceremony; requires mailbox server for initial handshake only; direct P2P afterwards[^34][^29] |
49
50	**arxiv citation:** Bryan Ford, Pyda Srisuresh, Dan Kegel. "Peer-to-Peer Communication Across Network Address Translators." *USENIX Annual Technical Conference 2005*. arXiv:cs/0603074. https://arxiv.org/abs/cs/0603074[^35][^36]
51
52	***
53
54	### 2.2 NAT Traversal & WAN P2P Transport
55
56	| Name | Primary URL | License | Last Release | Rust Support | Fits Hard Reqs | Key Tradeoff |
57	|---|---|---|---|---|---|---|
58	| STUN (RFC 8489) | https://datatracker.ietf.org/doc/html/rfc8489 | IETF Standard | Mar 2020 | `stun` crate | ✅ Y | Free public STUN at `stun.l.google.com:19302`, `stun.cloudflare.com`; only discovers public IP/port, no relay |
59	| TURN (RFC 8656) | https://datatracker.ietf.org/doc/html/rfc8656 | IETF Standard | Feb 2020 | `turn` crate | ⚠ Partial | Relays all media — expensive bandwidth; free public TURN (OpenRelay Project, 20 GB/month) limited for production[^37][^38] |
60	| ICE (RFC 8445) | https://datatracker.ietf.org/doc/html/rfc8445 | IETF Standard | July 2018 | Via `str0m`, WebRTC libs | ✅ Y | Full STUN+TURN candidate gathering; TURN only needed for symmetric NAT[^39][^40] |
61	| UDP Hole Punching | https://bford.info/pub/net/p2pnat/ | — | 2005 | Quinn + manual | ✅ Y | 2025 production measurement: **70% ± 7.1%** direct success, with TCP and QUIC statistically indistinguishable [amended 2026-05-20]; symmetric NAT remains the dominant failure mode[^82][^35][^36] |
62	| Quinn (QUIC) | https://github.com/quinn-rs/quinn | MIT/Apache-2.0 | Active (0-RTT, 2025) | Native (tokio) | ✅ Y | Pure-Rust QUIC; supports simultaneous-open hole punching; tested on Linux/macOS/Windows[^41][^42] |
63	| QUIC hole punching | arXiv:2408.01791 | — | Aug 2024 | Via quinn + iroh | ✅ Y | QUIC-based HP reduces punching time vs TCP; connection migration restores sessions after NAT timeout saving 2 RTTs[^43] |
64	| NAT-PMP / PCP | RFC 6887 | IETF Standard | 2013 | `nat-pmp` crate | ⚠ Partial | Apple/Linksys routers; not universal; avoids UPnP but same coverage problem |
65	| WebRTC data channels | https://github.com/webrtc-rs/webrtc | MIT/Apache-2.0 | Active 2024 | `webrtc-rs`, `str0m` | ⚠ Partial | Headless use possible; large dependency tree; `str0m` is lighter; not worth it when QUIC is available directly |
66
67	**arxiv citation:** Jinyu Liang et al. "Implementing NAT Hole Punching with QUIC." *VTC2024-Fall*. arXiv:2408.01791. https://arxiv.org/abs/2408.01791[^43]
68
69	**[amended 2026-05-20] Critical integration gotchas (quinn).** When integrating `quinn` directly (Rank 2/3 path), watch for:
70
71	- **No native simultaneous-open / DCUTR.** QUIC's TLS handshake fixes client/server roles before either peer sends data, so SPT must assign roles itself — e.g. lexicographic perch-id ordering decides who calls `connect` and who calls `accept` on a shared, pre-punched UDP socket (`quinn-proto/src/endpoint.rs:729` comment: simultaneous-initial CID collision "will fail fast and may be retried by the application layer").
72	- **Migration silently dies without keepalives.** `ServerConfig.migration` defaults to `true`, but defaults let connections die silently across NAT timeout. Always set `TransportConfig::keep_alive_interval(Some(Duration::from_secs(15)))` *and* `max_idle_timeout(Some(IdleTimeout::try_from(Duration::from_secs(30))?))`.
73	- **0-RTT requires opt-in on custom rustls configs.** Quinn forces `enable_early_data = true` on its built-in `QuicClientConfig`, but a hand-built `rustls::ClientConfig` must set this explicitly or `Connecting::into_0rtt()` will silently downgrade to 1-RTT.
74	- **Minimum binary recipe for Windows-native portability.** `quinn = { version = "0.12", default-features = false, features = ["runtime-tokio", "rustls-ring"] }` — avoid `rustls-aws-lc-rs` (large C blob) and `platform-verifier` (heavyweight OS trust store integration) unless explicitly needed.
75
76	***
77
78	### 2.3 Decentralized P2P Networking Frameworks
79
80	| Name | Primary URL | License | Last Release | Rust Binding Quality | No Daemon | Relay Operator | NAT Traversal | Message Limit | Fits Hard Reqs |
81	|---|---|---|---|---|---|---|---|---|---|
82	| rust-libp2p | https://github.com/libp2p/rust-libp2p | MIT/Apache-2.0 | Aug 2024 (0.54) | Native — the library IS Rust | ✅ Y | User-configured (zero in core)[^11][^12] | DCUtR + QUIC HP (~70%)[^82] [amended 2026-05-20] | Stream-based, no limit | ✅ Y |
83	| Iroh | https://github.com/n0-computer/iroh | MIT/Apache-2.0 | Active May 2026 | Native — library-first | ✅ Y | n0.computer (self-hostable)[^3][^4] | QUIC HP + relay fallback (~90% direct)[^5] | Stream-based, no limit | ✅ Y |
84	| libp2p-iroh | https://lib.rs/crates/libp2p-iroh | MIT/Apache-2.0 | 2025 | Native bridge | ✅ Y | Inherits iroh relays | Inherits iroh HP | Inherits libp2p | ✅ Y |
85	| Veilid | https://gitlab.com/veilid/veilid | MPL-2.0 | Aug 2025 (0.4.8) | Native (veilid-core crate)[^24] | ✅ Y | Fully distributed — all nodes relay[^26][^44] | Onion + UDP/TCP | 32 KiB app payload (64 KiB envelope)[^26] [amended 2026-05-20] | ✅ Y |
86	| Hyperswarm / Hypercore | https://github.com/hypercore-protocol/hypercore | MIT | JS-first | No stable Rust crate (hypercore-rs is prototype) | — | — | — | — | ❌ N (no production Rust) |
87	| GNUnet | https://gnunet.org | AGPL-3.0 | 2024 | C library; thin Rust bindings only (`gnunet-sys`) | ❌ Requires daemon | Volunteer nodes | Limited | — | ❌ N (daemon + AGPL) |
88	| Yggdrasil | https://yggdrasil-network.github.io | LGPL-3.0 | Active (Go) | Go only (no Rust crate) | ❌ Requires daemon | Manual public peers[^45][^46] | Peer-to-peer IPv6 | IPv6 only | ❌ N (no Rust, daemon) |
89	| cjdns | https://github.com/cjdelisle/cjdns | GPL-3.0 | Sporadic | C only | ❌ Requires daemon | Manual bootstrap | Via IPv6 mesh | — | ❌ N (no Rust, daemon) |
90	| Earendil | https://earendil.network | MIT | Early alpha 2024 | Partial Rust impl | ✅ Y | Relay graph | Relay-based | — | ⚠ Too immature |
91
92	**Bootstrap / centralization note (libp2p)** [amended 2026-05-20]: **The rust-libp2p library itself ships zero hardcoded bootstrap nodes.** The `bootstrap.libp2p.io` / IPFS bootnodes appear only as a `BOOTNODES: [&str; 4]` example constant in `examples/ipfs-kad/src/main.rs:41-46`. SPT operators supply their own seeds via `kad::Behaviour::add_address(&peer_id, multiaddr)` followed by `kad::Behaviour::bootstrap()`. A fully private DHT namespace is a one-string change: `kad::Config::new(StreamProtocol::new("/spt/kad/1.0.0"))` — only peers using the same `StreamProtocol` will gossip. One of the four IPFS bootstrap nodes runs `rust-libp2p-server`, demonstrating production readiness of the underlying server pattern.[^13][^16]
93
94	**[amended 2026-05-20] Critical integration gotchas (rust-libp2p).**
95
96	- `libp2p-quic` ships its own version (`0.14.0`) independently of the `libp2p` meta-crate (`0.57.0`) — breaking changes in `libp2p-quic` don't block meta releases. SPT must pin both.
97	- QUIC connections are never `upgrade()`'d with Noise/yamux — QUIC supplies security and muxing natively.
98	- DCUtR's `MAX_NUMBER_OF_UPGRADE_ATTEMPTS = 3` is a hard constant.
99	- Hole-punch inbound matching is by `SocketAddr` only, not PeerId — PeerId verification is the caller's job.
100
101	***
102
103	### 2.4 Decentralized Identity / Zero-Credential Pairing
104
105	| Name | Primary URL | License | Last Release | Rust Support | Fits Hard Reqs | Key Tradeoff |
106	|---|---|---|---|---|---|---|
107	| Noise Protocol Framework | https://noiseprotocol.org/noise.html | Public Domain spec | Rev 34 (current) | `snow` (MIT, active 2024–2025)[^47], `noise-rust` (Unlicense)[^48] | ✅ Y | Mutual auth without PKI; used in WireGuard and WhatsApp[^49]; `snow` supports `no_std` |
108	| Magic Wormhole (SPAKE2) | https://github.com/magic-wormhole/magic-wormhole.rs | MIT | Active | `magic-wormhole` crate | ✅ Y | Short human-typeable code; PAKE ceremony; relay server needed for rendezvous only[^34][^28][^29] |
109	| SSB / Scuttlebutt identity | https://ssbc.github.io/ssb-db/ | AGPL-3.0 | Active | JS-first; `ssb-db2` in JS | ⚠ Partial | ed25519 pubkey as identity; no global registry[^50][^51] |
110	| Syncthing device IDs | https://docs.syncthing.net/dev/device-ids.html | MPL-2.0 | Active | Implementable pattern | ✅ Y | SHA-256 of self-signed X.509 cert; trust-on-first-use; proven in production[^19][^33] |
111	| Briar contact model | https://briarproject.org | GPL-3.0 | Active | Android/Java | ⚠ Reference | QR/link exchange; direct pubkey swap; no account[^52][^53] |
112	| W3C DIDs (`did:key`) | https://w3c-ccg.github.io/did-key-spec/ | W3C CG | 2025 draft | `did` crate | ⚠ Overkill | Encoding a pubkey as a URI; useful if you ever need cross-ecosystem interop, but heavy for SPT |
113	| SSH-style TOFU | N/A (pattern) | — | — | Trivial to implement | ✅ Y | Accept on first connection, record fingerprint, warn on change; lowest friction |
114
115	**Recommended pairing UX:** Generate an Ed25519 keypair on first run → derive the SPT node ID as the hex/base58 of the public key → for initial peer introduction, print a Magic Wormhole-style code via `$OWL pair` → complete SPAKE2 exchange → store the peer's pubkey in the local trust store. Subsequent connections authenticate by public key (Noise XX or IK pattern). No account, no server.
116
117	***
118
119	### 2.5 Free Relay / Rendezvous Infrastructure (Not Single-Operator)
120
121	| Name | Primary URL | License | Rust Crate | Account Required | Latency Reality | Rate Limits | Fits Hard Reqs |
122	|---|---|---|---|---|---|---|---|
123	| Nostr (DM events as signaling) | https://github.com/nostr-protocol/nostr | Public Domain spec | `nostr-sdk` (MIT)[^54][^55] | ❌ No (pubkey = identity) | 200–500 ms typical | Relay-specific; many free relays | ✅ Y — DM (kind 4/NIP-44) usable for signaling; SPT messages as ephemeral events |
124	| BitTorrent Mainline DHT | https://en.wikipedia.org/wiki/Mainline_DHT | BEP 5 spec | `mainline` crate (MIT)[^32] | ❌ No | ~1–5 s for lookup | None for read; short TTL (~30 min) | ✅ Y — rendezvous only |
125	| Iroh public relays | https://docs.iroh.computer/concepts/relays | MIT | Built into `iroh` | ❌ No | <50 ms | Rate-limited[^4][^5] | ✅ Y — with self-hosting path |
126	| IPFS Pubsub / Gossipsub | https://libp2p.io | MIT | `rust-libp2p` | ❌ No | Variable | Network-dependent | ✅ Y — requires bootstrap nodes |
127	| Arti / Tor hidden services | https://gitlab.torproject.org/tpo/core/arti | MIT/Apache-2.0 | `arti-client`, `tor-hsservice`[^56][^57] | ❌ No | 300–1000 ms | Tor network limits | ✅ Y — but latency cost; anonymity benefit |
128	| Matrix (guest access) | https://matrix.org | Apache-2.0 | `matrix-sdk` | ⚠ Guest OK | ~200 ms | matrix.org rate-limited | ⚠ Partial — guest accounts quasi-violate "no credentials" |
129	| Nostr public relays list | https://nostr.watch | — | — | ❌ No | — | Variable | ✅ Y — multiple operators |
130	| DNS-based rendezvous | Cloudflare Workers / free DNS TXT | — | `hickory-dns` | ❌ for CF free | High TTL | API limits | ⚠ Partial — read-only key-value, not real-time |
131	| Bluesky / ATProto PDS | https://atproto.com | MIT | — | ✅ Required | — | — | ❌ N — account required |
132	| Yggdrasil Network | https://yggdrasil-network.github.io | LGPL-3.0 | Go daemon | ❌ No | LAN-speed | None | ❌ N — requires installed daemon, Go only |
133
134	**Nostr as signaling layer:** Using Nostr DM events (NIP-04 / NIP-44) as a transport for SPT signaling messages is feasible and genuinely multi-operator. A SPT node publishes its iroh endpoint in a Nostr DM to the target peer's pubkey. The receiver polls its relay set and retrieves the endpoint. No single relay is required; users choose their own relay set. The `nostr-sdk` crate is mature. Latency is 200–500 ms which is acceptable for initial connection signaling (not for message delivery).[^54]
135
136	***
137
138	### 2.6 Mesh-VPN Alternatives
139
140	| Name | Primary URL | Free & Accountless | Single Operator | Verdict |
141	|---|---|---|---|---|
142	| Tailscale | https://tailscale.com | Free tier 100 devices but **requires** SSO account[^58] | Tailscale Inc. controls plane | ❌ Disqualified — account required |
143	| Headscale | https://github.com/juanfont/headscale | Free, self-hosted | Per-user-operated | ❌ Disqualified — requires someone to run it (violates "no central operator" for multi-party use) |
144	| ZeroTier | https://zerotier.com | Free 25 devices but **requires** account[^59] | ZeroTier Inc. + user controllers | ❌ Disqualified — account required |
145	| Nebula (Slack) | https://github.com/slackhq/nebula | Free, open source | Self-hosted CA | ❌ Disqualified — requires CA distribution; cert coordination = a central operator |
146	| WireGuard (raw) | https://wireguard.com | Free | None | ⚠ Partial — manual key exchange; usable IF Magic Wormhole handles pairing UX; no daemon on Linux 5.6+ |
147	| Innernet | https://github.com/tonarino/innernet | MIT | Self-hosted CA | ❌ Same as Nebula |
148	| Yggdrasil | https://yggdrasil-network.github.io | Free, no account | None (public peers) | ❌ Disqualified — Go daemon required, no Rust library |
149
150	***
151
152	### 2.7 Existing Agent-to-Agent Messaging Systems
153
154	| System | Model | Transport / Identity | Account Required | P2P WAN | Rust Support | Key Lesson for SPT |
155	|---|---|---|---|---|---|---|
156	| Matrix federation | Federated servers | HTTPS + Matrix ID | ✅ Yes (per homeserver) | Via bridges | `matrix-sdk` | Federation model is good; account requirement disqualifies |
157	| XMPP federation / XEP-0174 | Federated servers + serverless local | XML streams + mDNS for local[^60] | ⚠ Optional (serverless mode) | Via s2s | `xmpp-rs` | Serverless XMPP (XEP-0174) is mDNS-based and account-free on LAN — relevant for SPT LAN mode |
158	| ActivityPub | Push-based federated | HTTP + server identity | ✅ Yes | Via servers | `activitypub-core` | Server-required by design; not useful |
159	| SSB (Secure Scuttlebutt) | Gossip + signed feed | ed25519 pubkey | ❌ None | Via "pub" servers (optional)[^50][^61][^51] | JS-first | Best identity model: pubkey IS identity; no global registry; pub servers are optional and untrusted |
160	| Briar | Tor + BT + LAN | Tor hidden services + mDNS | ❌ None (username+password local only)[^52][^53] | Via Tor | Android/Java | Contact model: QR/link exchange at first contact — directly applicable to SPT pairing UX |
161	| DAT / Hypercore | Gossip + signed log | Ed25519 | ❌ None | Via Hyperswarm | JS-first (`hypercore-rs` prototype) | Append-only signed feed concept; Rust port immature |
162	| Nostr | Relay-broadcast events | Pubkey (secp256k1) | ❌ None | Via relays | `nostr-sdk` (MIT)[^54] | Multi-relay model eliminates single-operator; event model maps naturally to SPT message spooling |
163	| MLS (RFC 9420) | Group key agreement | Delivery Service (DS) | Depends on DS | Via DS | `openmls` crate | Group forward secrecy for SPT multi-agent chats; requires a DS (can be any spool) — relevant at crypto layer[^62][^63] |
164	| **Anthropic MCP** | Tool/context protocol | JSON-RPC 2.0 over stdio/SSE | ❌ None | Remote MCP being added (2025)[^64][^65] | `mcp-rs` | MCP transports are local by design; remote MCP is HTTP-based and requires a server URL — not a P2P transport |
165	| **Google A2A** | Agent capability protocol | HTTP + AgentCard + A2A SDK | Depends on server | Via HTTP | None yet (Python SDK only)[^66][^67] | Enterprise-oriented; HTTP client-server model; no P2P addressing or identity; not applicable to SPT constraints |
166	| AutoGen / LangGraph / CrewAI | Multi-agent orchestration | In-process or HTTP | Framework-specific | Limited (HTTP) | None | These frameworks do not address multi-machine transport; they assume a shared process or a reachable HTTP server[^68] |
167
168	**MCP / A2A gap:** Neither MCP nor A2A addresses multi-machine P2P transport. MCP in 2025 is evolving toward "remote MCP connections" over HTTPS, but this requires a URL-accessible server, not a P2P endpoint. A2A is an enterprise HTTP orchestration protocol. Neither provides NAT traversal, account-free identity, or relay infrastructure — all three problems SPT must solve. The networking layer developed for SPT would be complementary to MCP/A2A at the protocol surface level.[^67][^64][^69]
169
170	***
171
172	### 2.8 Embeddable Runtime Concerns (Rust + Claude Code Plugin)
173
174	**Binary size.** With LTO, `opt-level = "z"`, and `strip = true`, a tokio + quinn + iroh binary typically lands at 5–15 MB stripped vs. the 43–93 MB figure reported for the unoptimized crate. The key technique is disabling default features on transitive dependencies. libp2p with a minimal feature set (tcp, quic, dcutr, kad, mdns) adds approximately 2–5 MB. Neither is disqualifying for a desktop tool.[^70][^71][^9]
175
176	**Async runtime.** Both iroh and veilid-core default to tokio. Quinn is tokio-native. If SPT currently uses a synchronous or async-std runtime, pulling in tokio adds ~1–2 MB and requires a `#[tokio::main]` entry point or a `Runtime::new().block_on(...)` wrapper in the existing main. This is a one-time integration cost, not an ongoing complexity.[^41][^72][^73][^24][^74][^8][^75]
177
178	**Windows Firewall prompt.** Any application that binds an inbound UDP or TCP socket for the first time will trigger a Windows Defender Firewall dialog. This is unavoidable without pre-shipping a signed application with a pre-declared firewall exception. The mitigation is: (a) frame it in the CLI UX ("SPT is requesting network access — click Allow"), (b) prefer outbound-initiated UDP hole punching where possible (outbound is not blocked by default), and (c) consider using a high-numbered port (>1024) in user space to reduce "public network" warnings.[^76][^77]
179
180	**IPv6 reliance.** Iroh and QUIC work over both IPv4 and IPv6. mDNS sends on both IPv4 multicast (224.0.0.251) and IPv6 multicast (FF02::FB). Consumer IPv6 deployment is uneven (~40–50% global), so the implementation must not assume IPv6 WAN reachability. Both iroh and libp2p handle dual-stack automatically.[^78][^17][^2][^1]
181
182	**[amended 2026-05-20] Iroh workspace integration: `noq` patch requirement.** Iroh 1.0-rc has migrated its QUIC stack to `noq` — n0.computer's vendored fork of `quinn`. The iroh workspace `Cargo.toml` pins `noq`, `noq-proto`, and `noq-udp` to `n0-computer/noq` git `main` via `[patch.crates-io]` entries. **SPT's workspace `Cargo.toml` must mirror those same `[patch.crates-io]` entries** or cargo will fail to resolve iroh's transitive dependencies (the `noq*` crates do not exist on crates.io). Example:
183
184	```toml
185	[patch.crates-io]
186	noq = { git = "https://github.com/n0-computer/noq", branch = "main" }
187	noq-proto = { git = "https://github.com/n0-computer/noq", branch = "main" }
188	noq-udp = { git = "https://github.com/n0-computer/noq", branch = "main" }
189	```
190
191	This couples SPT to whatever `noq` revision iroh's `main` is tracking; pin to a specific commit hash for reproducible builds.
192
193	***
194
195	### 2.9 arxiv Papers
196
197	| Title | Authors | Year | arXiv URL | Relevance to SPT |
198	|---|---|---|---|---|
199	| "Peer-to-Peer Communication Across Network Address Translators" | Bryan Ford, Pyda Srisuresh, Dan Kegel | 2005 | https://arxiv.org/abs/cs/0603074 | Foundational hole-punching analysis; 82% UDP NAT success rate in 2005 lab conditions[^35][^36] |
200	| "Implementing NAT Hole Punching with QUIC" | Jinyu Liang, Wei Xu, Taotao Wang, Qing Yang, Shengli Zhang | 2024 | https://arxiv.org/abs/2408.01791 | QUIC HP reduces punching time; connection migration saves 2 RTTs on NAT timeout[^43] |
201	| "Scalability limitations of Kademlia DHTs when enabling Data Availability Sampling" | Various | 2024 | https://arxiv.org/abs/2402.09993 | Kademlia DHT at scale; undialable NAT'd peers inflate routing table churn[^79] |
202	| "Honeybee: Decentralized Peer Sampling with Verifiable Random Walks" | Yunqi Zhang, Shaileshh Bojja Venkatakrishnan | 2024 | https://arxiv.org/abs/2402.16201 | GossipSub vs Kademlia adversarial sampling; Honeybee outperforms by 4–63%[^80] |
203	| "Towards Communication-Efficient Peer-to-Peer Networks" | Hourani, Moses, Pandurangan | 2024 | https://arxiv.org/abs/2406.16661 | Random-topology P2P networks and propagation delay; relevant to gossipsub topology design[^81] |
204	| "Large Scale Measurement Campaign on Decentralized NAT Traversal" | Trautwein, Ihle, Schubotz, Gipp | 2025 | https://arxiv.org/abs/2510.27500 | First large-scale (4.4M attempts) production measurement of DCUtR; **70% ± 7.1% success, TCP ≈ QUIC** [amended 2026-05-20]; centralization risks in P2P re-introduced through traversal infrastructure[^82] |
205
206	***
207
208	## 3. Disqualified Options
209
210	| Option | Hard Requirement Failed | Reasoning |
211	|---|---|---|
212	| **Tailscale** | #2 (no credentials) | Free tier requires SSO account (Google/Microsoft/GitHub login)[^58]; cannot be used without account creation |
213	| **Headscale** | #1 (no central server) | Self-hosted Tailscale control plane; someone must operate it for all users — violates "no single operator" in a multi-party scenario |
214	| **ZeroTier** | #2 (no credentials) | Account required even on free tier[^59][^83]; reduced device cap on free tier |
215	| **Nebula (Slack)** | #1 (no central server) | Requires a CA operator to sign certificates for all nodes; cert distribution is a coordination point |
216	| **Innernet** | #1 (no central server) | Same as Nebula: CA-based WireGuard mesh requires a trusted CA operator |
217	| **Yggdrasil** | #5 (single binary) | Go implementation only; no production Rust library; requires daemon install[^45][^46][^84] |
218	| **GNUnet** | #2, #5 | AGPL-3.0 license; C daemon; thin Rust bindings only; complex multi-service architecture unsuitable for embedding |
219	| **Hyperswarm/Hypercore** | #5 (single binary) | JavaScript-first; `hypercore-rs` is an unmaintained prototype; no production Rust crate[^85] |
220	| **Matrix** | #2 (no credentials) | Standard use requires account registration; guest access is rate-limited and quasi-violates the no-credentials requirement |
221	| **Bluesky / ATProto PDS** | #2 (no credentials) | Account required even on self-hosted PDS |
222	| **cjdns** | #5 (single binary) | C implementation; requires daemon install; GPL-3.0 license conflicts with potential commercial use |
223	| **Tor (arti) as primary transport** | #4 (free at hobbyist scale) + latency | Functionally free and embeddable (`arti-client`)[^56][^86], but 300–1000 ms latency is incompatible with interactive agent-to-agent messaging; reserved as an anonymity-mode fallback |
224	| **WebRTC data channels** | #5 (single binary) | Large dependency tree; headless use requires significant integration work; QUIC via Quinn provides the same capabilities more directly without ICE complexity |
225	| **Google A2A protocol** | #1, #2 | HTTP client-server model; requires URL-reachable server; enterprise-oriented; no P2P addressing[^66][^67] |
226	| **Anthropic MCP (as transport)** | #1, #2 | Local stdio/SSE transport; remote MCP requires HTTP server; not a P2P NAT-traversing transport[^64][^65] |
227
228	***
229
230	## 4. Open Questions
231
232	1. **Relay operator commitment.** Are the SPT maintainers willing to operate a small fleet of iroh relay nodes (`iroh-relay` binary on a $5/month VPS) as "best effort community infrastructure"? This eliminates the n0.computer dependency for production users while keeping the default config working. Without this, production deployments silently depend on a third party.
233
234	2. **Bootstrap node strategy for libp2p / DHT path.** If rust-libp2p + Kademlia is chosen, who runs the bootstrap nodes? [amended 2026-05-20] Since the library ships *no* hardcoded bootstrap nodes, this is purely an SPT operational decision. Options: (a) embed a hardcoded list of well-known community nodes shipped with the SPT binary, (b) ship empty and require user-supplied seeds via config, or (c) build a "bring your own bootstrap" model where each install can self-bootstrap from a paired peer.
235
236	3. **Pairing ceremony UX scope.** How interactive should the initial peer introduction be? Options range from "paste a public key string" (power-user) to "run `$OWL pair` and exchange a 6-word code via any out-of-band channel" (Magic Wormhole style) to "scan a QR code" (Briar style). The choice constrains the identity primitives.
237
238	4. **Message delivery semantics.** SPT currently has `spool` (SQLite-backed). For WAN delivery: should the protocol guarantee at-least-once delivery with a spool on the sender side until the remote acknowledges, or best-effort? This determines whether a relay spool is needed (complexity) or delivery is fire-and-forget (simpler, risk of loss).
239
240	5. **Nostr signaling relay governance.** If Nostr is used for endpoint signaling (not message delivery), which relay set does the binary default to? The community relay list changes. A curated default list of 3–5 high-uptime relays should be embedded with a runtime override mechanism.
241
242	6. **Veilid all-node-as-relay model.** Veilid routes all traffic through intermediate nodes by design, contributing ~5 GB/month of relay bandwidth at idle. Is this acceptable for SPT users? A disclosure in the `$OWL provision` UX is required if Veilid is chosen.[^27]
243
244	7. **Windows code signing.** Without a signed binary, the Windows Firewall dialog labels SPT as "unknown publisher." Is there a plan to sign Windows builds? Unsigned is functional but degrades first-run UX.
245
246	8. **IPv6-only CGNAT users.** Some ISPs (mobile carriers, some residential) double-NAT users behind CGNAT on IPv4 with IPv6 exposed. Symmetric UDP hole punching fails for these users. Does the relay fallback automatically handle this, or does the UX degrade to "relay-only mode" with user warning?[^87][^88]
247
248	***
249
250	## 5. Recommended Next Prototype
251
252	**Experiment: Iroh + mdns-sd LAN+WAN smoke test in ≤ 1 week**
253
254	### Goal
255	Validate that two SPT instances on separate machines, behind separate NATs, can establish a bidirectional QUIC stream using iroh's endpoint, with mDNS discovery auto-detecting LAN peers.
256
257	### Steps
258
259	1. **Add dependencies** to `Cargo.toml` [amended 2026-05-20: updated for iroh 1.0-rc — `discovery-local-network` feature removed; LAN now via external `iroh-mdns-address-lookup` crate; `noq` patches required]:
260	   ```toml
261	   iroh = { version = "1.0.0-rc.0", default-features = false, features = ["tls-ring"] }
262	   iroh-mdns-address-lookup = "0.1"   # external; LAN discovery moved here in 1.0-rc
263	   mdns-sd = "0.11"
264	   tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
265
266	   [patch.crates-io]
267	   noq       = { git = "https://github.com/n0-computer/noq", branch = "main" }
268	   noq-proto = { git = "https://github.com/n0-computer/noq", branch = "main" }
269	   noq-udp   = { git = "https://github.com/n0-computer/noq", branch = "main" }
270	   ```
271
272	2. **Generate identity on first run.** On startup, if no keypair exists in `%LOCALAPPDATA%\spt\owlery\node.key` (Windows) / `~/.spt/owlery/node.key` (Unix), generate an Ed25519 keypair via `iroh::SecretKey::generate()` and persist it. The node's public key (`EndpointId`) is its SPT address [amended 2026-05-20: renamed from `NodeId` in 1.0-rc].
273
274	3. **LAN discovery.** Register an mDNS service `_spt._udp.local.` with the iroh `EndpointAddr` serialized as a TXT record [amended 2026-05-20: renamed from `NodeAddr` in 1.0-rc]. Simultaneously browse for `_spt._udp.local.` services to discover neighbors without WAN. Alternatively, plug `iroh-mdns-address-lookup` into the endpoint builder via `.address_lookup(...)` and let iroh manage the mDNS layer.
275
276	4. **WAN connection.** When a peer's iroh `EndpointId` is known (from mDNS TXT or out-of-band key exchange), call `endpoint.connect(endpoint_id, ALPN)`. Iroh contacts the configured relays for signaling, attempts QUIC hole punching, falls back to relay if needed. Use `presets::Minimal` (not `presets::N0`) to avoid silently phoning home to n0.computer's pkarr/DNS infrastructure.
277
278	5. **Wrap the `$OWL deliver` surface.** On successful connection, open a bidirectional QUIC stream and encode existing SPT messages as length-prefixed JSON frames. The local spool remains the source-of-truth; remote delivery is an async best-effort push with acknowledged receipt.
279
280	6. **Measure.** On two machines behind residential NAT (or two cloud VMs in different regions), time to first message. Record whether connection went direct or through relay (iroh's `RemoteInfo` exposes path stats). Report binary size (stripped release build).
281
282	### Success criteria
283	- Two SPT instances exchange an `$OWL deliver` message end-to-end with no user configuration beyond exchanging endpoint IDs.
284	- Connection goes direct (not relay-only) on at least one typical residential NAT test — targeting the 70% direct-success baseline established by 2025 measurement [amended 2026-05-20].
285	- Stripped binary size increase ≤ 8 MB vs. baseline.
286	- `$OWL list` and `$OWL poll` continue to work unchanged (backward compatibility check).
287
288	### Fallback if iroh fails
289	If iroh's binary size or tokio dependency proves incompatible, switch to: raw `quinn` (QUIC transport) + `mainline` crate (Mainline DHT for rendezvous) + `mdns-sd` for LAN. This requires implementing the hole-punching coordination manually using the DHT as the signaling channel (and lexicographic perch-id role assignment, since QUIC has no native simultaneous-open — see §2.2 quinn gotchas [amended 2026-05-20]), but avoids any third-party relay infrastructure entirely.
290
291	---
292
293	## References
294
295	1. [Crate irohCopy item path](https://docs.rs/iroh/0.90.0/iroh/) - Peer-to-peer QUIC connections.
296
297	2. [n0-computer/iroh: peer-2-peer that just works](https://github.com/n0-computer/iroh) - peer-2-peer that just works. Contribute to n0-computer/iroh development by creating an account on Gi...
298
299	3. [Custom relays - iroh](https://docs.iroh.computer/add-a-relay) - Configure dedicated relays so your endpoints don't share infrastructure with the public network
300
301	4. [Relays - iroh](https://docs.iroh.computer/concepts/relays)
302
303	5. [FAQ - irohdocs.iroh.computer › about › faq](https://docs.iroh.computer/about/faq)
304
305	6. [johnthagen/min-sized-rust: How to minimize Rust binary size - GitHub](https://github.com/johnthagen/min-sized-rust) - 🦀 How to minimize Rust binary size 📦. Contribute to johnthagen/min-sized-rust development by creatin...
306
307	7. [libp2p-iroh 0.1.1 on Cargo - Libraries.io](https://libraries.io/cargo/libp2p-iroh) - iroh quic as libp2p transport
308
309	8. [iroh-loro/Cargo.toml at main · loro-dev/iroh-loro](https://github.com/loro-dev/iroh-loro/blob/main/Cargo.toml) - Contribute to loro-dev/iroh-loro development by creating an account on GitHub.
310
311	9. [Iroh — Rust network library // Lib.rs](https://lib.rs/crates/iroh) - p2p quic connections dialed by public key
312
313	10. [libp2p::tutorials::hole_punching - Rust - Docs.rs](https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html) - Hole Punching Tutorial
314
315	11. [NAT Traversal rust-libp2p](https://discuss.libp2p.io/t/nat-traversal-rust-libp2p/1316) - We are building a decentralized peer-to-peer network using rust-libp2p and i saw there are many chan... [amended 2026-05-20: the ~60% figure from this forum thread is superseded by arxiv-2510-27500's 2025 production measurement of 70% ± 7.1%; cited here for historical context only]
316
317	12. [DCUtR - libp2p](https://libp2p.io/docs/dcutr/) - DCUtR is a protocol for establishing direct connections between nodes behind NATs.
318
319	13. [A Rusty Bootstrapper | IPFS Blog & News](https://blog.ipfs.tech/2023-rust-libp2p-based-ipfs-bootstrap-node/) - Running rust-libp2p-server on one of our four IPFS bootstrap nodes.
320
321	14. [Kademlia DHT - libp2p](https://libp2p.io/docs/kademlia-dht/) - The libp2p Kad-DHT subsystem is an implementation of the Kademlia DHT, a distributed hash table.
322
323	15. [feat(quic): implement hole punching by arpankapoor · Pull Request #3964 · libp2p/rust-libp2p](https://github.com/libp2p/rust-libp2p/pull/3964) - Description Implement Transport::dial_as_listener for QUIC as specified by the DCUtR spec. To facili...
324
325	16. [Modify the bootstrap list - IPFS Docs](https://docs.ipfs.tech/how-to/modify-bootstrap-list/) - Learn how to modify the IPFS bootstrap peers list to create a personal IPFS network. [amended 2026-05-20: the rust-libp2p *library* ships zero hardcoded bootstrap nodes; this IPFS-docs page describes Kubo's `~/.ipfs/config` bootstrap list, not anything baked into rust-libp2p]
326
327	17. [RFC 6762 - Multicast DNS - IETF Datatracker](https://datatracker.ietf.org/doc/rfc6762/) - As networked devices become smaller, more portable, and more ubiquitous, the ability to operate with...
328
329	18. [mdns_sd - Rust - Docs.rs](https://docs.rs/mdns-sd/latest/mdns_sd/) - A small and safe library for Multicast DNS-SD (Service Discovery). This library creates one new thre...
330
331	19. [Local Discovery Protocol v4¶](https://docs.syncthing.net/specs/localdisco-v4)
332
333	20. [Local Discovery Protocol v4 - Syncthing documentation](https://docs.syncthing.net/specs/localdisco-v4.html)
334
335	21. [Cult of the Dead Cow unveils 'Veilid', "a secure peer-to-peer network for apps that flips off the surveillance economy" - Garuda's Lemmy](https://lemmy.garudalinux.org/post/19900/64062) - DEF CON Infosec super-band the Cult of the Dead Cow has released Veilid (pronounced vay-lid), an ope...
336
337	22. [Cult of the Dead Cow unveils Veilid peer-to-peer project - The Register](https://www.theregister.com/2023/08/12/veilid_privacy_data/) - DEF CON: ‘It's like Tor and IPFS had sex and produced this thing'
338
339	23. [Veilid - Wikipedia](https://en.wikipedia.org/wiki/Veilid)
340
341	24. [veilid-core 0.4.8](https://docs.rs/crate/veilid-core/latest)
342
343	25. [veilid-tools](https://lib.rs/crates/veilid-tools) - A collection of baseline tools for Rust development use by Veilid and Veilid-enabled Rust applicatio...
344
345	26. [Networking - Veilid](https://veilid.com/how-it-works/networking/) - Any node can bootstrap a Veilid network. Networks can be 'keyed' to keep nodes off that don't have t... [amended 2026-05-20: the app-visible RPC payload cap is 32 KiB (`MAX_APP_MESSAGE_MESSAGE_LEN = 32768` in `rpc_processor/coders/operations/operation_app_message.rs:3`), not 64 KiB. The 65507-byte cap is the envelope layer (`ENV0_MAX_ENVELOPE_SIZE` in `crypto/envelope/mod.rs:12`). No built-in chunking — the application must shard above 32 KiB.]
346
347	27. [Thoughts on Veilid (privacy network, cult of the dead cow) - Reddit](https://www.reddit.com/r/opensource/comments/1qdlgg3/thoughts_on_veilid_privacy_network_cult_of_the/) - Veilid is "Tor for apps" and relies on users hosting nodes. It seems similar to Freenet which is als... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only]
348
349	28. [magic_wormhole - Rust - Docs.rs](https://docs.rs/magic-wormhole) - Magic Wormhole is known for its ability to transfer files. This is implemented in the transfer modul...
350
351	29. [Rust implementation of Magic Wormhole, with new features ... - GitHub](https://github.com/magic-wormhole/magic-wormhole.rs) - New features that exceed the other implementations: Can do direct connections across the internet (N...
352
353	30. [Welcome — Magic-Wormhole 0.24.0+16.g92eda0c documentation](https://magic-wormhole.readthedocs.io/en/latest/welcome.html) - The wormhole tool uses PAKE "Password-Authenticated Key Exchange", a family of cryptographic algorit...
354
355	31. [Mainline DHT - Wikipedia](https://en.wikipedia.org/wiki/Mainline_DHT) - Mainline DHT is the name given to the Kademlia-based distributed hash table (DHT) used by BitTorrent...
356
357	32. [mainline - Rust - Docs.rs](https://docs.rs/mainline) - Simple, robust, BitTorrent's Mainline DHT implementation. This library is focused on being the best ...
358
359	33. [Local Discovery Protocol v4](https://docs.syncthing.net/v1.28.0/specs/localdisco-v4.html)
360
361	34. [Magic Wormhole - Flaviu Vlaicu](https://vlaicu.io/posts/wormhole/) - How PAKE Works: Uses a short, low-entropy password (the wormhole code) to establish a strong, high-e...
362
363	35. [Peer-to-Peer Communication Across Network Address Translators](https://arxiv.org/abs/cs/0603074) - This paper documents and analyzes one of the simplest but most robust and practical NAT traversal te... [amended 2026-05-20: Ford 2005's 82% UDP hole-punch success reflects NATs of that era; 2025 production measurement (arxiv-2510-27500) reports 70% ± 7.1% on today's CGNAT-heavy networks]
364
365	36. [Peer-to-Peer Communication Across Network Address Translators](http://arxiv.org/abs/cs/0603074v1) - Network Address Translation (NAT) causes well-known difficulties for peer-to-peer (P2P) communicatio...
366
367	37. [OpenRelay Project: Free Reliable WebRTC TURN Server - Reddit](https://www.reddit.com/r/WebRTC/comments/sqx3ip/openrelay_project_free_reliable_webrtc_turn_server/) - Open Relay Project (https://openrelayproject.org) is a reliable, production ready WebRTC TURN+STUN S... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only]
368
369	38. [RFC 8656 - Traversal Using Relays around NAT (TURN)](https://datatracker.ietf.org/doc/html/rfc8656) - This specification defines a protocol, called "Traversal Using Relays around NAT" (TURN), that allow...
370
371	39. [RFC 8445 - Interactive Connectivity Establishment (ICE)](https://datatracker.ietf.org/doc/html/rfc8445) - This document describes a protocol for Network Address Translator (NAT) traversal for UDP-based comm...
372
373	40. [rfc8445.txt - » RFC Editor](https://www.rfc-editor.org/rfc/rfc8445.txt)
374
375	41. [GitHub - quinn-rs/quinn: Async-friendly QUIC implementation in Rust](http://github.com/quinn-rs/quinn) - Async-friendly QUIC implementation in Rust. Contribute to quinn-rs/quinn development by creating an ...
376
377	42. [quinn-rs/quinn: Async-friendly QUIC implementation in Rust](https://github.com/quinn-rs/quinn) - Async-friendly QUIC implementation in Rust. Contribute to quinn-rs/quinn development by creating an ...
378
379	43. [[2408.01791] Implementing NAT Hole Punching with QUIC - arXiv](https://arxiv.org/abs/2408.01791) - We find that the QUIC-based scheme effectively reduces the hole punching time, exhibiting a pronounc...
380
381	44. [How It Works · Veilid](https://veilid.com/how-it-works/) - The framework is conceptually similar to IPFS and Tor, but faster and designed from the ground-up to...
382
383	45. [Yggdrasil Network — Join the Global Mesh](https://dev.to/byteknight/yggdrasil-network-join-the-global-mesh-1kcc) - The Yggdrasil Network is an experimental, end‑to‑end encrypted IPv6 overlay that links nodes into a....
384
385	46. [Yggdrasil Network | End-to-end encrypted IPv6 networking to ...](https://yggdrasil-network.github.io) - End-to-end encrypted IPv6 networking to connect worlds
386
387	47. [snow - Rust - Docs.rs](https://docs.rs/snow/) - The snow crate aims to be a straightforward Noise Protocol implementation. See the Noise Protocol Fr...
388
389	48. [noise-protocol — Rust crypto library // Lib.rs](https://lib.rs/crates/noise-protocol) - This repository contains several crates. The noise-protocol crate contains the abstract implementati...
390
391	49. [The Noise Protocol Framework - media.ccc.de](https://media.ccc.de/v/34c3-9222-the_noise_protocol_framework) - Noise provides a simple pattern language and naming scheme for 2-party DH-based cryptographic handsh...
392
393	50. [Secure Scuttlebutt - Scuttlebot](https://scuttlebot.io/more/protocols/secure-scuttlebutt.html)
394
395	51. [Secure Scuttlebutt - SSBC](https://ssbc.github.io/ssb-db/) - Secure Scuttlebutt is a database protocol for unforgeable append-only message feeds. "Unforgeable" m...
396
397	52. [Secure, Peer-To-Peer Messaging Apps - Brax Community](https://community.braxtech.net/t/secure-peer-to-peer-messaging-apps/2668) - To add a contact, users must connect directly, typically by scanning each other's QR codes, ensuring...
398
399	53. [Briar: Secure messaging, anywhere](https://briarproject.org) - Censorship-resistant peer-to-peer messaging that bypasses centralized servers. Connect via Bluetooth...
400
401	54. [Rust implementation of the nostr protocol, high-level client ... - GitHub](https://github.com/rust-nostr/nostr) - nostr-relay-builder: Build your own custom nostr relay; nostr-sdk: A full-featured SDK for building ...
402
403	55. [nostr - Rust - Docs.rs](https://docs.rs/nostr) - Rust implementation of Nostr protocol. You may be interested in: nostr-sdk if you want to write a ty...
404
405	56. [tor-hsservice — Rust network library // Lib.rs](https://lib.rs/crates/tor-hsservice) - Arti's implementation of an onion service provider
406
407	57. [tor_hsservice - Rust - Docs.rs](https://docs.rs/tor-hsservice/latest/tor_hsservice/) - tor-hsservice
408
409	58. [Tailscale: The Zero-Config VPN Your Homelab Needs](https://www.antlatt.com/blog/tailscale-homelab-vpn/) - Skip the port forwarding headaches. Tailscale gives you instant, secure access to your homelab from ... [amended 2026-05-20: URL returned a 502 stub at fetch time; cited as anchor only — Tailscale's SSO requirement is independently verifiable from the vendor's own docs]
410
411	59. [Tailscale vs Zerotier vs … - Duplicacy Forum](https://forum.duplicacy.com/t/tailscale-vs-zerotier-vs/9795) - Completely off-topic, but try Zerotier instead. It's a Layer 2 solution (as opposed to Layer 3 servi...
412
413	60. [XEP-0174: Serverless Messaging - XMPP](https://xmpp.org/extensions/xep-0174.html) - This specification defines how to communicate over local or wide-area networks using the principles ...
414
415	61. [Gossip - Introduction · GitBook](https://handbook.scuttlebutt.nz/concepts/gossip) - In Scuttlebutt, 3rd parties can relay (gossip) information for you, which improves availability. Eve...
416
417	62. [Information on RFC 9420 - » RFC Editor](https://www.rfc-editor.org/info/rfc9420)
418
419	63. [The Messaging Layer Security (MLS) Protocol](https://www.rfc-editor.org/rfc/rfc9420) - Messaging applications are increasingly making use of end-to-end security mechanisms to ensure that ...
420
421	64. [Introducing the Model Context Protocol](https://www.anthropic.com/news/model-context-protocol?guides=understanding-tradeoffs)
422
423	65. [Introducing the Model Context ...](https://www.anthropic.com/news/model-context-protocol)
424
425	66. [Announcing the Agent2Agent Protocol - A2A (Google Blog, April 2025)](https://www.facebook.com/groups/DeepNetGroup/posts/2456717144721153/) - The A2A protocol will allow AI agents to communicate with each other, securely exchange information,...
426
427	67. [What Is Agent2Agent (A2A) Protocol?](https://www.ibm.com/think/topics/agent2agent-protocol) - The Agent2Agent (A2A) protocol is an open communication protocol for artificial intelligence (AI) ag...
428
429	68. [Multi-agent Conversation Framework | AutoGen 0.2](https://microsoft.github.io/autogen/0.2/docs/Use-Cases/agent_chat/) - AutoGen offers a unified multi-agent conversation framework as a high-level abstraction of using fou...
430
431	69. [Anthropic Officially Releases MCP Protocol 2025 Semi-Annual ...](https://www.kdjingpai.com/en/anthropic-zhengshifaa/) - Our Plans for the Evolution of the Model Context Protocol (first half of 2025) The Model Context Pro...
432
433	70. [Binary size · Issue #1051 · libp2p/rust-libp2p](https://github.com/libp2p/rust-libp2p/issues/1051) - I have tried compiling the examples, ipfs-kad.rs and chat.rs, and I am getting quite heavy binary si...
434
435	71. [I shrunk my Rust binary from 11MB to 4.5MB with bloaty-metafile](https://dev.to/ahaoboy/i-shrunk-my-rust-binary-from-11mb-to-45mb-with-bloaty-metafile-1n7i) - TL;DR: Used bloaty-metafile to analyze binary size, disabled default features on key dependencies,.....
436
437	72. [TokioRuntime in iroh_quinn - Rust - Docs.rs](https://docs.rs/iroh-quinn/latest/iroh_quinn/struct.TokioRuntime.html) - A Quinn runtime for Tokio
438
439	73. [Hello Tokio - An asynchronous Rust runtime](https://tokio.rs/tokio/tutorial/hello-tokio) - Tokio is a runtime for writing reliable asynchronous applications with Rust. It provides async I/O, ...
440
441	74. [veilid-tools 0.4.7](https://docs.rs/crate/veilid-tools/latest)
442
443	75. [How to use async/await in Rust when you can't make main function async](https://stackoverflow.com/questions/71116502/how-to-use-async-await-in-rust-when-you-cant-make-main-function-async) - I have a function to download a file which is async: async fn download_file() { fn main() { let resp...
444
445	76. [Windows Firewall Inbound Rule behavior : r/sysadmin - Reddit](https://www.reddit.com/r/sysadmin/comments/17c4r18/windows_firewall_inbound_rule_behavior/) - When you first open many networked applications, Windows pops up asking you to allow the application... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only]
446
447	77. [Windows Firewall Rules | Microsoft Learn](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/rules) - This article describes the concepts and recommendations for creating and managing firewall rules.
448
449	78. [RFC 6762 - ICANNWiki](https://icannwiki.org/RFC_6762) - For implications on Internet governance, see Multicast DNS. RFC 6762, Multicast DNS, is an IETF Stan... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only — RFC 6762 itself is the authoritative source]
450
451	79. [[PDF] Scalability limitations of Kademlia DHTs when enabling Data ... - arXiv](https://arxiv.org/pdf/2402.09993.pdf) - This paper provides insights after exploring the usage of a Kademlia-based DHT to enable Data Availa...
452
453	80. [Honeybee: Decentralized Peer Sampling with Verifiable Random ...](https://arxiv.org/html/2402.16201v1) - However, when the network contains adversarial nodes, Honeybee outperforms GossipSub and Kademlia by...
454
455	81. [Towards Communication-Efficient Peer-to-Peer Networks](https://arxiv.org/abs/2406.16661) - We focus on designing Peer-to-Peer (P2P) networks that enable efficient communication. Over the last...
456
457	82. [Large Scale Measurement Campaign on Decentralized NAT Traversal](https://arxiv.org/html/2510.27500v1) [amended 2026-05-20: Trautwein, Ihle, Schubotz, Gipp (2025). First large-scale production measurement of DCUtR — 4.4M traversal attempts across 85k networks in 167 countries. Headline result: 70% ± 7.1% direct-connect success rate, with TCP and QUIC statistically indistinguishable. Replaces both the 60% (libp2p forum) and 82% (Ford 2005) figures used elsewhere in the original brief.]
458
459	83. [Wireguard, Zerotier or Tailscale - General Discussion - DietPi](https://dietpi.com/forum/t/wireguard-zerotier-or-tailscale/13546) - In upcoming dietpi Zerotier, Tailscale are coming as new software. Any advice or recommendation for ...
460
461	84. [yggdrasil-network/yggdrasil-go: An experiment in scalable ... - GitHub](https://github.com/yggdrasil-network/yggdrasil-go) - An experiment in scalable routing as an encrypted IPv6 overlay network - yggdrasil-network/yggdrasil...
462
463	85. [libp2p — Rust network library // Lib.rs](https://lib.rs/crates/libp2p) - Peer-to-peer networking library
464
465	86. [Arti 1.4.6 is released: Hidden Service resilience](https://forum.torproject.org/t/arti-1-4-6-is-released-hidden-service-resilience-work-on-flow-control-conflux-and-cgo/20258) - by Diziet | August 5, 2025 Arti is our ongoing project to create a next-generation Tor client in Rus...
466
467	87. [How to Implement UDP Hole Punching for NAT Traversal - OneUptime](https://oneuptime.com/blog/post/2026-03-20-udp-hole-punching-nat/view) - Implement UDP hole punching to establish direct peer-to-peer UDP connections between hosts behind NA...
468
469	88. [A P2P Vision for QUIC (2024) - Hacker News](https://news.ycombinator.com/item?id=45822982) - > UDP-based protocols are well suited for P2P, since hole punching is straightforward if you have pr...
470

C:\Users\decid\Documents\projects\claude_skill_owl\docs\research\SPT Networked Messaging Research Brief.md

> **Amended 2026-05-20** — Findings from the docs/research/index/ mapping pass have been folded into this brief. The pre-amendment version is preserved at `docs/research/archive/SPT Networked Messaging Research Brief.original.md`. Per-correction provenance: see `docs/research/index/README.md` §Caveats.

# SPT Networked Messaging: Research Brief
**Sentience Pocket Transacter — Cross-Host Agent Messaging**
*Rust single-binary constraint · No central operator · No credentials · LAN + WAN*

***

## 1. Executive Shortlist

Candidates are ranked by fit against the seven hard requirements (no central server, no credentials, minimal setup, free, single static binary, cross-platform, backward-compatible surface).

### Rank 1 — **Iroh** (`iroh` / `n0-computer`)

Iroh is a QUIC-based P2P library that dials peers by Ed25519 public key and builds connections using a relay-assisted hole punch that falls back to encrypted relay. Roughly 9 out of 10 connection attempts go direct; the relay is only a temporary stepping stone and never sees plaintext. The default relays are operated by n0.computer, free to use, but the relay binary is open source and trivially self-hosted — making the architecture genuinely multi-operator in practice. It links against tokio (already ubiquitous in Rust async work), builds to a single static binary, ships prebuilt for Linux/macOS/Windows. As of `iroh = 1.0.0-rc.0` the public types are `EndpointId` and `EndpointAddr` (renamed from `NodeId` / `NodeAddr` in pre-1.0) [amended 2026-05-20], and LAN/mDNS discovery has been factored out of the main crate — the in-tree `discovery-local-network` feature flag was removed and SPT must depend on the external `iroh-mdns-address-lookup` crate (or implement the `AddressLookup` trait itself) for LAN-first discovery [amended 2026-05-20]. The compiled crate size is noted as ~43–93 MB before LTO/stripping, which is large but manageable with standard profile tuning. Identity is purely a keypair generated at startup — no registration required. `libp2p-iroh` (0.1.x) further bridges iroh's transport into the libp2p swarm if gossipsub or Kademlia are later needed. **Fit: passes all 7 hard requirements.** Key tradeoff: relays are n0.computer-operated by default, creating a soft trust dependency until users self-host or the network diversifies.[^1][^2][^3][^4][^5][^6][^7][^8][^9]

### Rank 2 — **rust-libp2p** with DCUtR + Kademlia

The rust-libp2p stack is modular: pick TCP/QUIC transport, add the DCUtR hole-punching protocol for NAT traversal via relay, layer Kademlia DHT for peer discovery, and gossipsub for pub/sub messaging. DCUtR achieves **70% ± 7.1% direct-connection success** on the production libp2p/IPFS network (4.4M attempts across 85k networks, 2025 measurement) — with TCP and QUIC traversal rates statistically indistinguishable, refuting long-held assumptions of UDP superiority [amended 2026-05-20].[^82] QUIC hole punching support was merged in 2023. **The rust-libp2p library ships zero hardcoded bootstrap nodes** [amended 2026-05-20]; the famous `bootstrap.libp2p.io` IPFS bootnodes appear only as example constants in `examples/ipfs-kad/src/main.rs`. A private SPT DHT namespace is a one-string change: `kad::Config::new(StreamProtocol::new("/spt/kad/1.0.0"))`. The library is MIT/Apache-2, actively maintained, and used in production by Ethereum, Filecoin, and IPFS. Binary size impact is significant (examples run 2–5 MB stripped) but feature-flags can shrink this. **Fit: passes all 7 hard requirements with configuration.** Key tradeoff: higher learning curve than iroh; SPT operators must furnish their own bootstrap peers.[^10][^11][^12][^13][^14][^15][^16]

### Rank 3 — **Iroh + mdns-sd (hybrid LAN/WAN)**

The practical minimum-surprise architecture is: `mdns-sd` crate for zero-config LAN discovery (mDNS/DNS-SD per RFC 6762/6763)[^17][^18], then iroh for WAN connectivity when peers are not on the same link. This mirrors how Syncthing combines UDP broadcast local discovery with a global discovery server[^19][^20]. The two layers are additive: SPT tries mDNS first, falls back to iroh. This pattern requires no changes to the backward-compatible `$OWL deliver|ring|send|reply` surface. **Fit: passes all 7 hard requirements. Recommended architecture for prototype.**

### Rank 4 — **Veilid** (`veilid-core`)

Veilid (Cult of the Dead Cow, 2023) is a Rust-native P2P framework with a fully distributed DHT, onion-routing-style privacy, and an identity model based purely on 256-bit public keys. No nodes are special; any node can bootstrap a network; DNS is used only once and is not required thereafter. veilid-core supports tokio by default and can switch to async-std. Licensed MPL-2.0. **Fit: passes all 7 hard requirements.** Key tradeoffs: the network routes all data through multiple hops by design (Tor-inspired), adding ~100–300 ms latency vs. direct; every node contributes relay bandwidth (~5 GB/month at idle); the app-visible RPC payload cap is **32 KiB** (`MAX_APP_MESSAGE_MESSAGE_LEN = 32768`) — the 64 KiB figure cited elsewhere refers to the lower envelope layer (`ENV0_MAX_ENVELOPE_SIZE = 65507`); there is **no built-in chunking**, so the application must shard anything larger than 32 KiB [amended 2026-05-20]. Best fit if anonymity matters more than latency.[^21][^22][^23][^24][^25][^26][^27]

### Rank 5 — **Mainline DHT + Magic Wormhole pairing (rendezvous only)**

BitTorrent's Mainline DHT (Kademlia-based, ~20 M nodes, no single operator) can serve as a pure key-value rendezvous layer: a peer announces its iroh or raw QUIC endpoint under its public-key hash, the other peer looks it up, and then a direct connection is made. Magic Wormhole (`magic-wormhole.rs` crate) provides the initial SPAKE2-based short-code pairing ceremony for trust establishment, after which peers can exchange raw public keys out-of-band. This combination avoids operating any rendezvous infrastructure: DHT is the global yellow pages, Wormhole is the first-contact handshake. **Fit: passes all 7 hard requirements.** Key tradeoff: Mainline DHT stores values for only ~30 minutes, requiring periodic re-announcement; more moving parts than iroh alone.[^28][^29][^30][^31][^32]

**[amended 2026-05-20] Source liveness caveat.** During fetch verification of the citation corpus, four source URLs were gated by Cloudflare/captcha walls or returned 502 stubs: three reddit threads ([^27] Veilid sentiment, [^37] OpenRelay TURN, [^76] Windows Firewall UX), the icannwiki RFC 6762 page ([^78]), and the Tailscale homelab article ([^58]). These citations remain in the brief as anchor references, but direct quotes were not extractable; the surrounding claims either rely on additional sources or on the unchanged structural facts they cite (Tailscale's SSO requirement, the existence of a Windows Firewall prompt, etc.). Refetch with a real browser session if verbatim evidence is needed.

***

## 2. Per-Target Findings

### 2.1 LAN Discovery & Messaging

| Name | Primary URL | License | Last Release | Rust Support | Fits Hard Reqs | Key Tradeoff |
|---|---|---|---|---|---|---|
| mDNS / DNS-SD (RFC 6762 / RFC 6763) | https://datatracker.ietf.org/doc/rfc6762/ | IETF Standard | Feb 2013 | `mdns-sd` (pure Rust), `simple-mdns` | ✅ Y | Windows mDNS works but `mdns-sd` must open a UDP socket on port 5353; Windows Defender may prompt on first use[^17][^18] |
| mdns-sd crate | https://crates.io/crates/mdns-sd | Apache-2.0 | Active 2024–2025 | Native | ✅ Y | Spawns a background thread, not tokio-native; wrap in `spawn_blocking` |
| Syncthing Local Discovery v4 | https://docs.syncthing.net/specs/localdisco-v4 | MPL-2.0 spec | Active | Implementable | ✅ Y | Uses UDP broadcast (IPv4 255.255.255.255:21027) + IPv6 multicast; device ID = SHA-256 of X.509 cert[^19][^33] |
| SSDP / UPnP Discovery | https://datatracker.ietf.org/doc/html/draft-cai-ssdp-v1 | Vendor spec | — | `rupnp` crate | ⚠ Partial | Router-specific; widely deployed but not all devices respond; overkill vs. mDNS for service discovery |
| LLMNR (RFC 4795) | https://datatracker.ietf.org/doc/html/rfc4795 | IETF Informational | 2007 | No dedicated crate | ⚠ Partial | Windows-only by common deployment; DNS hostname resolution only, not service discovery |
| Magic Wormhole (LAN pairing) | https://github.com/magic-wormhole/magic-wormhole.rs | MIT | Active | `magic-wormhole` crate | ✅ Y | SPAKE2 short-code ceremony; requires mailbox server for initial handshake only; direct P2P afterwards[^34][^29] |

**arxiv citation:** Bryan Ford, Pyda Srisuresh, Dan Kegel. "Peer-to-Peer Communication Across Network Address Translators." *USENIX Annual Technical Conference 2005*. arXiv:cs/0603074. https://arxiv.org/abs/cs/0603074[^35][^36]

***

### 2.2 NAT Traversal & WAN P2P Transport

| Name | Primary URL | License | Last Release | Rust Support | Fits Hard Reqs | Key Tradeoff |
|---|---|---|---|---|---|---|
| STUN (RFC 8489) | https://datatracker.ietf.org/doc/html/rfc8489 | IETF Standard | Mar 2020 | `stun` crate | ✅ Y | Free public STUN at `stun.l.google.com:19302`, `stun.cloudflare.com`; only discovers public IP/port, no relay |
| TURN (RFC 8656) | https://datatracker.ietf.org/doc/html/rfc8656 | IETF Standard | Feb 2020 | `turn` crate | ⚠ Partial | Relays all media — expensive bandwidth; free public TURN (OpenRelay Project, 20 GB/month) limited for production[^37][^38] |
| ICE (RFC 8445) | https://datatracker.ietf.org/doc/html/rfc8445 | IETF Standard | July 2018 | Via `str0m`, WebRTC libs | ✅ Y | Full STUN+TURN candidate gathering; TURN only needed for symmetric NAT[^39][^40] |
| UDP Hole Punching | https://bford.info/pub/net/p2pnat/ | — | 2005 | Quinn + manual | ✅ Y | 2025 production measurement: **70% ± 7.1%** direct success, with TCP and QUIC statistically indistinguishable [amended 2026-05-20]; symmetric NAT remains the dominant failure mode[^82][^35][^36] |
| Quinn (QUIC) | https://github.com/quinn-rs/quinn | MIT/Apache-2.0 | Active (0-RTT, 2025) | Native (tokio) | ✅ Y | Pure-Rust QUIC; supports simultaneous-open hole punching; tested on Linux/macOS/Windows[^41][^42] |
| QUIC hole punching | arXiv:2408.01791 | — | Aug 2024 | Via quinn + iroh | ✅ Y | QUIC-based HP reduces punching time vs TCP; connection migration restores sessions after NAT timeout saving 2 RTTs[^43] |
| NAT-PMP / PCP | RFC 6887 | IETF Standard | 2013 | `nat-pmp` crate | ⚠ Partial | Apple/Linksys routers; not universal; avoids UPnP but same coverage problem |
| WebRTC data channels | https://github.com/webrtc-rs/webrtc | MIT/Apache-2.0 | Active 2024 | `webrtc-rs`, `str0m` | ⚠ Partial | Headless use possible; large dependency tree; `str0m` is lighter; not worth it when QUIC is available directly |

**arxiv citation:** Jinyu Liang et al. "Implementing NAT Hole Punching with QUIC." *VTC2024-Fall*. arXiv:2408.01791. https://arxiv.org/abs/2408.01791[^43]

**[amended 2026-05-20] Critical integration gotchas (quinn).** When integrating `quinn` directly (Rank 2/3 path), watch for:

- **No native simultaneous-open / DCUTR.** QUIC's TLS handshake fixes client/server roles before either peer sends data, so SPT must assign roles itself — e.g. lexicographic perch-id ordering decides who calls `connect` and who calls `accept` on a shared, pre-punched UDP socket (`quinn-proto/src/endpoint.rs:729` comment: simultaneous-initial CID collision "will fail fast and may be retried by the application layer").
- **Migration silently dies without keepalives.** `ServerConfig.migration` defaults to `true`, but defaults let connections die silently across NAT timeout. Always set `TransportConfig::keep_alive_interval(Some(Duration::from_secs(15)))` *and* `max_idle_timeout(Some(IdleTimeout::try_from(Duration::from_secs(30))?))`.
- **0-RTT requires opt-in on custom rustls configs.** Quinn forces `enable_early_data = true` on its built-in `QuicClientConfig`, but a hand-built `rustls::ClientConfig` must set this explicitly or `Connecting::into_0rtt()` will silently downgrade to 1-RTT.
- **Minimum binary recipe for Windows-native portability.** `quinn = { version = "0.12", default-features = false, features = ["runtime-tokio", "rustls-ring"] }` — avoid `rustls-aws-lc-rs` (large C blob) and `platform-verifier` (heavyweight OS trust store integration) unless explicitly needed.

***

### 2.3 Decentralized P2P Networking Frameworks

| Name | Primary URL | License | Last Release | Rust Binding Quality | No Daemon | Relay Operator | NAT Traversal | Message Limit | Fits Hard Reqs |
|---|---|---|---|---|---|---|---|---|---|
| rust-libp2p | https://github.com/libp2p/rust-libp2p | MIT/Apache-2.0 | Aug 2024 (0.54) | Native — the library IS Rust | ✅ Y | User-configured (zero in core)[^11][^12] | DCUtR + QUIC HP (~70%)[^82] [amended 2026-05-20] | Stream-based, no limit | ✅ Y |
| Iroh | https://github.com/n0-computer/iroh | MIT/Apache-2.0 | Active May 2026 | Native — library-first | ✅ Y | n0.computer (self-hostable)[^3][^4] | QUIC HP + relay fallback (~90% direct)[^5] | Stream-based, no limit | ✅ Y |
| libp2p-iroh | https://lib.rs/crates/libp2p-iroh | MIT/Apache-2.0 | 2025 | Native bridge | ✅ Y | Inherits iroh relays | Inherits iroh HP | Inherits libp2p | ✅ Y |
| Veilid | https://gitlab.com/veilid/veilid | MPL-2.0 | Aug 2025 (0.4.8) | Native (veilid-core crate)[^24] | ✅ Y | Fully distributed — all nodes relay[^26][^44] | Onion + UDP/TCP | 32 KiB app payload (64 KiB envelope)[^26] [amended 2026-05-20] | ✅ Y |
| Hyperswarm / Hypercore | https://github.com/hypercore-protocol/hypercore | MIT | JS-first | No stable Rust crate (hypercore-rs is prototype) | — | — | — | — | ❌ N (no production Rust) |
| GNUnet | https://gnunet.org | AGPL-3.0 | 2024 | C library; thin Rust bindings only (`gnunet-sys`) | ❌ Requires daemon | Volunteer nodes | Limited | — | ❌ N (daemon + AGPL) |
| Yggdrasil | https://yggdrasil-network.github.io | LGPL-3.0 | Active (Go) | Go only (no Rust crate) | ❌ Requires daemon | Manual public peers[^45][^46] | Peer-to-peer IPv6 | IPv6 only | ❌ N (no Rust, daemon) |
| cjdns | https://github.com/cjdelisle/cjdns | GPL-3.0 | Sporadic | C only | ❌ Requires daemon | Manual bootstrap | Via IPv6 mesh | — | ❌ N (no Rust, daemon) |
| Earendil | https://earendil.network | MIT | Early alpha 2024 | Partial Rust impl | ✅ Y | Relay graph | Relay-based | — | ⚠ Too immature |

**Bootstrap / centralization note (libp2p)** [amended 2026-05-20]: **The rust-libp2p library itself ships zero hardcoded bootstrap nodes.** The `bootstrap.libp2p.io` / IPFS bootnodes appear only as a `BOOTNODES: [&str; 4]` example constant in `examples/ipfs-kad/src/main.rs:41-46`. SPT operators supply their own seeds via `kad::Behaviour::add_address(&peer_id, multiaddr)` followed by `kad::Behaviour::bootstrap()`. A fully private DHT namespace is a one-string change: `kad::Config::new(StreamProtocol::new("/spt/kad/1.0.0"))` — only peers using the same `StreamProtocol` will gossip. One of the four IPFS bootstrap nodes runs `rust-libp2p-server`, demonstrating production readiness of the underlying server pattern.[^13][^16]

**[amended 2026-05-20] Critical integration gotchas (rust-libp2p).**

- `libp2p-quic` ships its own version (`0.14.0`) independently of the `libp2p` meta-crate (`0.57.0`) — breaking changes in `libp2p-quic` don't block meta releases. SPT must pin both.
- QUIC connections are never `upgrade()`'d with Noise/yamux — QUIC supplies security and muxing natively.
- DCUtR's `MAX_NUMBER_OF_UPGRADE_ATTEMPTS = 3` is a hard constant.
- Hole-punch inbound matching is by `SocketAddr` only, not PeerId — PeerId verification is the caller's job.

***

### 2.4 Decentralized Identity / Zero-Credential Pairing

| Name | Primary URL | License | Last Release | Rust Support | Fits Hard Reqs | Key Tradeoff |
|---|---|---|---|---|---|---|
| Noise Protocol Framework | https://noiseprotocol.org/noise.html | Public Domain spec | Rev 34 (current) | `snow` (MIT, active 2024–2025)[^47], `noise-rust` (Unlicense)[^48] | ✅ Y | Mutual auth without PKI; used in WireGuard and WhatsApp[^49]; `snow` supports `no_std` |
| Magic Wormhole (SPAKE2) | https://github.com/magic-wormhole/magic-wormhole.rs | MIT | Active | `magic-wormhole` crate | ✅ Y | Short human-typeable code; PAKE ceremony; relay server needed for rendezvous only[^34][^28][^29] |
| SSB / Scuttlebutt identity | https://ssbc.github.io/ssb-db/ | AGPL-3.0 | Active | JS-first; `ssb-db2` in JS | ⚠ Partial | ed25519 pubkey as identity; no global registry[^50][^51] |
| Syncthing device IDs | https://docs.syncthing.net/dev/device-ids.html | MPL-2.0 | Active | Implementable pattern | ✅ Y | SHA-256 of self-signed X.509 cert; trust-on-first-use; proven in production[^19][^33] |
| Briar contact model | https://briarproject.org | GPL-3.0 | Active | Android/Java | ⚠ Reference | QR/link exchange; direct pubkey swap; no account[^52][^53] |
| W3C DIDs (`did:key`) | https://w3c-ccg.github.io/did-key-spec/ | W3C CG | 2025 draft | `did` crate | ⚠ Overkill | Encoding a pubkey as a URI; useful if you ever need cross-ecosystem interop, but heavy for SPT |
| SSH-style TOFU | N/A (pattern) | — | — | Trivial to implement | ✅ Y | Accept on first connection, record fingerprint, warn on change; lowest friction |

**Recommended pairing UX:** Generate an Ed25519 keypair on first run → derive the SPT node ID as the hex/base58 of the public key → for initial peer introduction, print a Magic Wormhole-style code via `$OWL pair` → complete SPAKE2 exchange → store the peer's pubkey in the local trust store. Subsequent connections authenticate by public key (Noise XX or IK pattern). No account, no server.

***

### 2.5 Free Relay / Rendezvous Infrastructure (Not Single-Operator)

| Name | Primary URL | License | Rust Crate | Account Required | Latency Reality | Rate Limits | Fits Hard Reqs |
|---|---|---|---|---|---|---|---|
| Nostr (DM events as signaling) | https://github.com/nostr-protocol/nostr | Public Domain spec | `nostr-sdk` (MIT)[^54][^55] | ❌ No (pubkey = identity) | 200–500 ms typical | Relay-specific; many free relays | ✅ Y — DM (kind 4/NIP-44) usable for signaling; SPT messages as ephemeral events |
| BitTorrent Mainline DHT | https://en.wikipedia.org/wiki/Mainline_DHT | BEP 5 spec | `mainline` crate (MIT)[^32] | ❌ No | ~1–5 s for lookup | None for read; short TTL (~30 min) | ✅ Y — rendezvous only |
| Iroh public relays | https://docs.iroh.computer/concepts/relays | MIT | Built into `iroh` | ❌ No | <50 ms | Rate-limited[^4][^5] | ✅ Y — with self-hosting path |
| IPFS Pubsub / Gossipsub | https://libp2p.io | MIT | `rust-libp2p` | ❌ No | Variable | Network-dependent | ✅ Y — requires bootstrap nodes |
| Arti / Tor hidden services | https://gitlab.torproject.org/tpo/core/arti | MIT/Apache-2.0 | `arti-client`, `tor-hsservice`[^56][^57] | ❌ No | 300–1000 ms | Tor network limits | ✅ Y — but latency cost; anonymity benefit |
| Matrix (guest access) | https://matrix.org | Apache-2.0 | `matrix-sdk` | ⚠ Guest OK | ~200 ms | matrix.org rate-limited | ⚠ Partial — guest accounts quasi-violate "no credentials" |
| Nostr public relays list | https://nostr.watch | — | — | ❌ No | — | Variable | ✅ Y — multiple operators |
| DNS-based rendezvous | Cloudflare Workers / free DNS TXT | — | `hickory-dns` | ❌ for CF free | High TTL | API limits | ⚠ Partial — read-only key-value, not real-time |
| Bluesky / ATProto PDS | https://atproto.com | MIT | — | ✅ Required | — | — | ❌ N — account required |
| Yggdrasil Network | https://yggdrasil-network.github.io | LGPL-3.0 | Go daemon | ❌ No | LAN-speed | None | ❌ N — requires installed daemon, Go only |

**Nostr as signaling layer:** Using Nostr DM events (NIP-04 / NIP-44) as a transport for SPT signaling messages is feasible and genuinely multi-operator. A SPT node publishes its iroh endpoint in a Nostr DM to the target peer's pubkey. The receiver polls its relay set and retrieves the endpoint. No single relay is required; users choose their own relay set. The `nostr-sdk` crate is mature. Latency is 200–500 ms which is acceptable for initial connection signaling (not for message delivery).[^54]

***

### 2.6 Mesh-VPN Alternatives

| Name | Primary URL | Free & Accountless | Single Operator | Verdict |
|---|---|---|---|---|
| Tailscale | https://tailscale.com | Free tier 100 devices but **requires** SSO account[^58] | Tailscale Inc. controls plane | ❌ Disqualified — account required |
| Headscale | https://github.com/juanfont/headscale | Free, self-hosted | Per-user-operated | ❌ Disqualified — requires someone to run it (violates "no central operator" for multi-party use) |
| ZeroTier | https://zerotier.com | Free 25 devices but **requires** account[^59] | ZeroTier Inc. + user controllers | ❌ Disqualified — account required |
| Nebula (Slack) | https://github.com/slackhq/nebula | Free, open source | Self-hosted CA | ❌ Disqualified — requires CA distribution; cert coordination = a central operator |
| WireGuard (raw) | https://wireguard.com | Free | None | ⚠ Partial — manual key exchange; usable IF Magic Wormhole handles pairing UX; no daemon on Linux 5.6+ |
| Innernet | https://github.com/tonarino/innernet | MIT | Self-hosted CA | ❌ Same as Nebula |
| Yggdrasil | https://yggdrasil-network.github.io | Free, no account | None (public peers) | ❌ Disqualified — Go daemon required, no Rust library |

***

### 2.7 Existing Agent-to-Agent Messaging Systems

| System | Model | Transport / Identity | Account Required | P2P WAN | Rust Support | Key Lesson for SPT |
|---|---|---|---|---|---|---|
| Matrix federation | Federated servers | HTTPS + Matrix ID | ✅ Yes (per homeserver) | Via bridges | `matrix-sdk` | Federation model is good; account requirement disqualifies |
| XMPP federation / XEP-0174 | Federated servers + serverless local | XML streams + mDNS for local[^60] | ⚠ Optional (serverless mode) | Via s2s | `xmpp-rs` | Serverless XMPP (XEP-0174) is mDNS-based and account-free on LAN — relevant for SPT LAN mode |
| ActivityPub | Push-based federated | HTTP + server identity | ✅ Yes | Via servers | `activitypub-core` | Server-required by design; not useful |
| SSB (Secure Scuttlebutt) | Gossip + signed feed | ed25519 pubkey | ❌ None | Via "pub" servers (optional)[^50][^61][^51] | JS-first | Best identity model: pubkey IS identity; no global registry; pub servers are optional and untrusted |
| Briar | Tor + BT + LAN | Tor hidden services + mDNS | ❌ None (username+password local only)[^52][^53] | Via Tor | Android/Java | Contact model: QR/link exchange at first contact — directly applicable to SPT pairing UX |
| DAT / Hypercore | Gossip + signed log | Ed25519 | ❌ None | Via Hyperswarm | JS-first (`hypercore-rs` prototype) | Append-only signed feed concept; Rust port immature |
| Nostr | Relay-broadcast events | Pubkey (secp256k1) | ❌ None | Via relays | `nostr-sdk` (MIT)[^54] | Multi-relay model eliminates single-operator; event model maps naturally to SPT message spooling |
| MLS (RFC 9420) | Group key agreement | Delivery Service (DS) | Depends on DS | Via DS | `openmls` crate | Group forward secrecy for SPT multi-agent chats; requires a DS (can be any spool) — relevant at crypto layer[^62][^63] |
| **Anthropic MCP** | Tool/context protocol | JSON-RPC 2.0 over stdio/SSE | ❌ None | Remote MCP being added (2025)[^64][^65] | `mcp-rs` | MCP transports are local by design; remote MCP is HTTP-based and requires a server URL — not a P2P transport |
| **Google A2A** | Agent capability protocol | HTTP + AgentCard + A2A SDK | Depends on server | Via HTTP | None yet (Python SDK only)[^66][^67] | Enterprise-oriented; HTTP client-server model; no P2P addressing or identity; not applicable to SPT constraints |
| AutoGen / LangGraph / CrewAI | Multi-agent orchestration | In-process or HTTP | Framework-specific | Limited (HTTP) | None | These frameworks do not address multi-machine transport; they assume a shared process or a reachable HTTP server[^68] |

**MCP / A2A gap:** Neither MCP nor A2A addresses multi-machine P2P transport. MCP in 2025 is evolving toward "remote MCP connections" over HTTPS, but this requires a URL-accessible server, not a P2P endpoint. A2A is an enterprise HTTP orchestration protocol. Neither provides NAT traversal, account-free identity, or relay infrastructure — all three problems SPT must solve. The networking layer developed for SPT would be complementary to MCP/A2A at the protocol surface level.[^67][^64][^69]

***

### 2.8 Embeddable Runtime Concerns (Rust + Claude Code Plugin)

**Binary size.** With LTO, `opt-level = "z"`, and `strip = true`, a tokio + quinn + iroh binary typically lands at 5–15 MB stripped vs. the 43–93 MB figure reported for the unoptimized crate. The key technique is disabling default features on transitive dependencies. libp2p with a minimal feature set (tcp, quic, dcutr, kad, mdns) adds approximately 2–5 MB. Neither is disqualifying for a desktop tool.[^70][^71][^9]

**Async runtime.** Both iroh and veilid-core default to tokio. Quinn is tokio-native. If SPT currently uses a synchronous or async-std runtime, pulling in tokio adds ~1–2 MB and requires a `#[tokio::main]` entry point or a `Runtime::new().block_on(...)` wrapper in the existing main. This is a one-time integration cost, not an ongoing complexity.[^41][^72][^73][^24][^74][^8][^75]

**Windows Firewall prompt.** Any application that binds an inbound UDP or TCP socket for the first time will trigger a Windows Defender Firewall dialog. This is unavoidable without pre-shipping a signed application with a pre-declared firewall exception. The mitigation is: (a) frame it in the CLI UX ("SPT is requesting network access — click Allow"), (b) prefer outbound-initiated UDP hole punching where possible (outbound is not blocked by default), and (c) consider using a high-numbered port (>1024) in user space to reduce "public network" warnings.[^76][^77]

**IPv6 reliance.** Iroh and QUIC work over both IPv4 and IPv6. mDNS sends on both IPv4 multicast (224.0.0.251) and IPv6 multicast (FF02::FB). Consumer IPv6 deployment is uneven (~40–50% global), so the implementation must not assume IPv6 WAN reachability. Both iroh and libp2p handle dual-stack automatically.[^78][^17][^2][^1]

**[amended 2026-05-20] Iroh workspace integration: `noq` patch requirement.** Iroh 1.0-rc has migrated its QUIC stack to `noq` — n0.computer's vendored fork of `quinn`. The iroh workspace `Cargo.toml` pins `noq`, `noq-proto`, and `noq-udp` to `n0-computer/noq` git `main` via `[patch.crates-io]` entries. **SPT's workspace `Cargo.toml` must mirror those same `[patch.crates-io]` entries** or cargo will fail to resolve iroh's transitive dependencies (the `noq*` crates do not exist on crates.io). Example:

```toml
[patch.crates-io]
noq = { git = "https://github.com/n0-computer/noq", branch = "main" }
noq-proto = { git = "https://github.com/n0-computer/noq", branch = "main" }
noq-udp = { git = "https://github.com/n0-computer/noq", branch = "main" }
```

This couples SPT to whatever `noq` revision iroh's `main` is tracking; pin to a specific commit hash for reproducible builds.

***

### 2.9 arxiv Papers

| Title | Authors | Year | arXiv URL | Relevance to SPT |
|---|---|---|---|---|
| "Peer-to-Peer Communication Across Network Address Translators" | Bryan Ford, Pyda Srisuresh, Dan Kegel | 2005 | https://arxiv.org/abs/cs/0603074 | Foundational hole-punching analysis; 82% UDP NAT success rate in 2005 lab conditions[^35][^36] |
| "Implementing NAT Hole Punching with QUIC" | Jinyu Liang, Wei Xu, Taotao Wang, Qing Yang, Shengli Zhang | 2024 | https://arxiv.org/abs/2408.01791 | QUIC HP reduces punching time; connection migration saves 2 RTTs on NAT timeout[^43] |
| "Scalability limitations of Kademlia DHTs when enabling Data Availability Sampling" | Various | 2024 | https://arxiv.org/abs/2402.09993 | Kademlia DHT at scale; undialable NAT'd peers inflate routing table churn[^79] |
| "Honeybee: Decentralized Peer Sampling with Verifiable Random Walks" | Yunqi Zhang, Shaileshh Bojja Venkatakrishnan | 2024 | https://arxiv.org/abs/2402.16201 | GossipSub vs Kademlia adversarial sampling; Honeybee outperforms by 4–63%[^80] |
| "Towards Communication-Efficient Peer-to-Peer Networks" | Hourani, Moses, Pandurangan | 2024 | https://arxiv.org/abs/2406.16661 | Random-topology P2P networks and propagation delay; relevant to gossipsub topology design[^81] |
| "Large Scale Measurement Campaign on Decentralized NAT Traversal" | Trautwein, Ihle, Schubotz, Gipp | 2025 | https://arxiv.org/abs/2510.27500 | First large-scale (4.4M attempts) production measurement of DCUtR; **70% ± 7.1% success, TCP ≈ QUIC** [amended 2026-05-20]; centralization risks in P2P re-introduced through traversal infrastructure[^82] |

***

## 3. Disqualified Options

| Option | Hard Requirement Failed | Reasoning |
|---|---|---|
| **Tailscale** | #2 (no credentials) | Free tier requires SSO account (Google/Microsoft/GitHub login)[^58]; cannot be used without account creation |
| **Headscale** | #1 (no central server) | Self-hosted Tailscale control plane; someone must operate it for all users — violates "no single operator" in a multi-party scenario |
| **ZeroTier** | #2 (no credentials) | Account required even on free tier[^59][^83]; reduced device cap on free tier |
| **Nebula (Slack)** | #1 (no central server) | Requires a CA operator to sign certificates for all nodes; cert distribution is a coordination point |
| **Innernet** | #1 (no central server) | Same as Nebula: CA-based WireGuard mesh requires a trusted CA operator |
| **Yggdrasil** | #5 (single binary) | Go implementation only; no production Rust library; requires daemon install[^45][^46][^84] |
| **GNUnet** | #2, #5 | AGPL-3.0 license; C daemon; thin Rust bindings only; complex multi-service architecture unsuitable for embedding |
| **Hyperswarm/Hypercore** | #5 (single binary) | JavaScript-first; `hypercore-rs` is an unmaintained prototype; no production Rust crate[^85] |
| **Matrix** | #2 (no credentials) | Standard use requires account registration; guest access is rate-limited and quasi-violates the no-credentials requirement |
| **Bluesky / ATProto PDS** | #2 (no credentials) | Account required even on self-hosted PDS |
| **cjdns** | #5 (single binary) | C implementation; requires daemon install; GPL-3.0 license conflicts with potential commercial use |
| **Tor (arti) as primary transport** | #4 (free at hobbyist scale) + latency | Functionally free and embeddable (`arti-client`)[^56][^86], but 300–1000 ms latency is incompatible with interactive agent-to-agent messaging; reserved as an anonymity-mode fallback |
| **WebRTC data channels** | #5 (single binary) | Large dependency tree; headless use requires significant integration work; QUIC via Quinn provides the same capabilities more directly without ICE complexity |
| **Google A2A protocol** | #1, #2 | HTTP client-server model; requires URL-reachable server; enterprise-oriented; no P2P addressing[^66][^67] |
| **Anthropic MCP (as transport)** | #1, #2 | Local stdio/SSE transport; remote MCP requires HTTP server; not a P2P NAT-traversing transport[^64][^65] |

***

## 4. Open Questions

1. **Relay operator commitment.** Are the SPT maintainers willing to operate a small fleet of iroh relay nodes (`iroh-relay` binary on a $5/month VPS) as "best effort community infrastructure"? This eliminates the n0.computer dependency for production users while keeping the default config working. Without this, production deployments silently depend on a third party.

2. **Bootstrap node strategy for libp2p / DHT path.** If rust-libp2p + Kademlia is chosen, who runs the bootstrap nodes? [amended 2026-05-20] Since the library ships *no* hardcoded bootstrap nodes, this is purely an SPT operational decision. Options: (a) embed a hardcoded list of well-known community nodes shipped with the SPT binary, (b) ship empty and require user-supplied seeds via config, or (c) build a "bring your own bootstrap" model where each install can self-bootstrap from a paired peer.

3. **Pairing ceremony UX scope.** How interactive should the initial peer introduction be? Options range from "paste a public key string" (power-user) to "run `$OWL pair` and exchange a 6-word code via any out-of-band channel" (Magic Wormhole style) to "scan a QR code" (Briar style). The choice constrains the identity primitives.

4. **Message delivery semantics.** SPT currently has `spool` (SQLite-backed). For WAN delivery: should the protocol guarantee at-least-once delivery with a spool on the sender side until the remote acknowledges, or best-effort? This determines whether a relay spool is needed (complexity) or delivery is fire-and-forget (simpler, risk of loss).

5. **Nostr signaling relay governance.** If Nostr is used for endpoint signaling (not message delivery), which relay set does the binary default to? The community relay list changes. A curated default list of 3–5 high-uptime relays should be embedded with a runtime override mechanism.

6. **Veilid all-node-as-relay model.** Veilid routes all traffic through intermediate nodes by design, contributing ~5 GB/month of relay bandwidth at idle. Is this acceptable for SPT users? A disclosure in the `$OWL provision` UX is required if Veilid is chosen.[^27]

7. **Windows code signing.** Without a signed binary, the Windows Firewall dialog labels SPT as "unknown publisher." Is there a plan to sign Windows builds? Unsigned is functional but degrades first-run UX.

8. **IPv6-only CGNAT users.** Some ISPs (mobile carriers, some residential) double-NAT users behind CGNAT on IPv4 with IPv6 exposed. Symmetric UDP hole punching fails for these users. Does the relay fallback automatically handle this, or does the UX degrade to "relay-only mode" with user warning?[^87][^88]

***

## 5. Recommended Next Prototype

**Experiment: Iroh + mdns-sd LAN+WAN smoke test in ≤ 1 week**

### Goal
Validate that two SPT instances on separate machines, behind separate NATs, can establish a bidirectional QUIC stream using iroh's endpoint, with mDNS discovery auto-detecting LAN peers.

### Steps

1. **Add dependencies** to `Cargo.toml` [amended 2026-05-20: updated for iroh 1.0-rc — `discovery-local-network` feature removed; LAN now via external `iroh-mdns-address-lookup` crate; `noq` patches required]:
   ```toml
   iroh = { version = "1.0.0-rc.0", default-features = false, features = ["tls-ring"] }
   iroh-mdns-address-lookup = "0.1"   # external; LAN discovery moved here in 1.0-rc
   mdns-sd = "0.11"
   tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

   [patch.crates-io]
   noq       = { git = "https://github.com/n0-computer/noq", branch = "main" }
   noq-proto = { git = "https://github.com/n0-computer/noq", branch = "main" }
   noq-udp   = { git = "https://github.com/n0-computer/noq", branch = "main" }
   ```

2. **Generate identity on first run.** On startup, if no keypair exists in `%LOCALAPPDATA%\spt\owlery\node.key` (Windows) / `~/.spt/owlery/node.key` (Unix), generate an Ed25519 keypair via `iroh::SecretKey::generate()` and persist it. The node's public key (`EndpointId`) is its SPT address [amended 2026-05-20: renamed from `NodeId` in 1.0-rc].

3. **LAN discovery.** Register an mDNS service `_spt._udp.local.` with the iroh `EndpointAddr` serialized as a TXT record [amended 2026-05-20: renamed from `NodeAddr` in 1.0-rc]. Simultaneously browse for `_spt._udp.local.` services to discover neighbors without WAN. Alternatively, plug `iroh-mdns-address-lookup` into the endpoint builder via `.address_lookup(...)` and let iroh manage the mDNS layer.

4. **WAN connection.** When a peer's iroh `EndpointId` is known (from mDNS TXT or out-of-band key exchange), call `endpoint.connect(endpoint_id, ALPN)`. Iroh contacts the configured relays for signaling, attempts QUIC hole punching, falls back to relay if needed. Use `presets::Minimal` (not `presets::N0`) to avoid silently phoning home to n0.computer's pkarr/DNS infrastructure.

5. **Wrap the `$OWL deliver` surface.** On successful connection, open a bidirectional QUIC stream and encode existing SPT messages as length-prefixed JSON frames. The local spool remains the source-of-truth; remote delivery is an async best-effort push with acknowledged receipt.

6. **Measure.** On two machines behind residential NAT (or two cloud VMs in different regions), time to first message. Record whether connection went direct or through relay (iroh's `RemoteInfo` exposes path stats). Report binary size (stripped release build).

### Success criteria
- Two SPT instances exchange an `$OWL deliver` message end-to-end with no user configuration beyond exchanging endpoint IDs.
- Connection goes direct (not relay-only) on at least one typical residential NAT test — targeting the 70% direct-success baseline established by 2025 measurement [amended 2026-05-20].
- Stripped binary size increase ≤ 8 MB vs. baseline.
- `$OWL list` and `$OWL poll` continue to work unchanged (backward compatibility check).

### Fallback if iroh fails
If iroh's binary size or tokio dependency proves incompatible, switch to: raw `quinn` (QUIC transport) + `mainline` crate (Mainline DHT for rendezvous) + `mdns-sd` for LAN. This requires implementing the hole-punching coordination manually using the DHT as the signaling channel (and lexicographic perch-id role assignment, since QUIC has no native simultaneous-open — see §2.2 quinn gotchas [amended 2026-05-20]), but avoids any third-party relay infrastructure entirely.

---

## References

1. [Crate irohCopy item path](https://docs.rs/iroh/0.90.0/iroh/) - Peer-to-peer QUIC connections.

2. [n0-computer/iroh: peer-2-peer that just works](https://github.com/n0-computer/iroh) - peer-2-peer that just works. Contribute to n0-computer/iroh development by creating an account on Gi...

3. [Custom relays - iroh](https://docs.iroh.computer/add-a-relay) - Configure dedicated relays so your endpoints don't share infrastructure with the public network

4. [Relays - iroh](https://docs.iroh.computer/concepts/relays)

5. [FAQ - irohdocs.iroh.computer › about › faq](https://docs.iroh.computer/about/faq)

6. [johnthagen/min-sized-rust: How to minimize Rust binary size - GitHub](https://github.com/johnthagen/min-sized-rust) - 🦀 How to minimize Rust binary size 📦. Contribute to johnthagen/min-sized-rust development by creatin...

7. [libp2p-iroh 0.1.1 on Cargo - Libraries.io](https://libraries.io/cargo/libp2p-iroh) - iroh quic as libp2p transport

8. [iroh-loro/Cargo.toml at main · loro-dev/iroh-loro](https://github.com/loro-dev/iroh-loro/blob/main/Cargo.toml) - Contribute to loro-dev/iroh-loro development by creating an account on GitHub.

9. [Iroh — Rust network library // Lib.rs](https://lib.rs/crates/iroh) - p2p quic connections dialed by public key

10. [libp2p::tutorials::hole_punching - Rust - Docs.rs](https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html) - Hole Punching Tutorial

11. [NAT Traversal rust-libp2p](https://discuss.libp2p.io/t/nat-traversal-rust-libp2p/1316) - We are building a decentralized peer-to-peer network using rust-libp2p and i saw there are many chan... [amended 2026-05-20: the ~60% figure from this forum thread is superseded by arxiv-2510-27500's 2025 production measurement of 70% ± 7.1%; cited here for historical context only]

12. [DCUtR - libp2p](https://libp2p.io/docs/dcutr/) - DCUtR is a protocol for establishing direct connections between nodes behind NATs.

13. [A Rusty Bootstrapper | IPFS Blog & News](https://blog.ipfs.tech/2023-rust-libp2p-based-ipfs-bootstrap-node/) - Running rust-libp2p-server on one of our four IPFS bootstrap nodes.

14. [Kademlia DHT - libp2p](https://libp2p.io/docs/kademlia-dht/) - The libp2p Kad-DHT subsystem is an implementation of the Kademlia DHT, a distributed hash table.

15. [feat(quic): implement hole punching by arpankapoor · Pull Request #3964 · libp2p/rust-libp2p](https://github.com/libp2p/rust-libp2p/pull/3964) - Description Implement Transport::dial_as_listener for QUIC as specified by the DCUtR spec. To facili...

16. [Modify the bootstrap list - IPFS Docs](https://docs.ipfs.tech/how-to/modify-bootstrap-list/) - Learn how to modify the IPFS bootstrap peers list to create a personal IPFS network. [amended 2026-05-20: the rust-libp2p *library* ships zero hardcoded bootstrap nodes; this IPFS-docs page describes Kubo's `~/.ipfs/config` bootstrap list, not anything baked into rust-libp2p]

17. [RFC 6762 - Multicast DNS - IETF Datatracker](https://datatracker.ietf.org/doc/rfc6762/) - As networked devices become smaller, more portable, and more ubiquitous, the ability to operate with...

18. [mdns_sd - Rust - Docs.rs](https://docs.rs/mdns-sd/latest/mdns_sd/) - A small and safe library for Multicast DNS-SD (Service Discovery). This library creates one new thre...

19. [Local Discovery Protocol v4¶](https://docs.syncthing.net/specs/localdisco-v4)

20. [Local Discovery Protocol v4 - Syncthing documentation](https://docs.syncthing.net/specs/localdisco-v4.html)

21. [Cult of the Dead Cow unveils 'Veilid', "a secure peer-to-peer network for apps that flips off the surveillance economy" - Garuda's Lemmy](https://lemmy.garudalinux.org/post/19900/64062) - DEF CON Infosec super-band the Cult of the Dead Cow has released Veilid (pronounced vay-lid), an ope...

22. [Cult of the Dead Cow unveils Veilid peer-to-peer project - The Register](https://www.theregister.com/2023/08/12/veilid_privacy_data/) - DEF CON: ‘It's like Tor and IPFS had sex and produced this thing'

23. [Veilid - Wikipedia](https://en.wikipedia.org/wiki/Veilid)

24. [veilid-core 0.4.8](https://docs.rs/crate/veilid-core/latest)

25. [veilid-tools](https://lib.rs/crates/veilid-tools) - A collection of baseline tools for Rust development use by Veilid and Veilid-enabled Rust applicatio...

26. [Networking - Veilid](https://veilid.com/how-it-works/networking/) - Any node can bootstrap a Veilid network. Networks can be 'keyed' to keep nodes off that don't have t... [amended 2026-05-20: the app-visible RPC payload cap is 32 KiB (`MAX_APP_MESSAGE_MESSAGE_LEN = 32768` in `rpc_processor/coders/operations/operation_app_message.rs:3`), not 64 KiB. The 65507-byte cap is the envelope layer (`ENV0_MAX_ENVELOPE_SIZE` in `crypto/envelope/mod.rs:12`). No built-in chunking — the application must shard above 32 KiB.]

27. [Thoughts on Veilid (privacy network, cult of the dead cow) - Reddit](https://www.reddit.com/r/opensource/comments/1qdlgg3/thoughts_on_veilid_privacy_network_cult_of_the/) - Veilid is "Tor for apps" and relies on users hosting nodes. It seems similar to Freenet which is als... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only]

28. [magic_wormhole - Rust - Docs.rs](https://docs.rs/magic-wormhole) - Magic Wormhole is known for its ability to transfer files. This is implemented in the transfer modul...

29. [Rust implementation of Magic Wormhole, with new features ... - GitHub](https://github.com/magic-wormhole/magic-wormhole.rs) - New features that exceed the other implementations: Can do direct connections across the internet (N...

30. [Welcome — Magic-Wormhole 0.24.0+16.g92eda0c documentation](https://magic-wormhole.readthedocs.io/en/latest/welcome.html) - The wormhole tool uses PAKE "Password-Authenticated Key Exchange", a family of cryptographic algorit...

31. [Mainline DHT - Wikipedia](https://en.wikipedia.org/wiki/Mainline_DHT) - Mainline DHT is the name given to the Kademlia-based distributed hash table (DHT) used by BitTorrent...

32. [mainline - Rust - Docs.rs](https://docs.rs/mainline) - Simple, robust, BitTorrent's Mainline DHT implementation. This library is focused on being the best ...

33. [Local Discovery Protocol v4](https://docs.syncthing.net/v1.28.0/specs/localdisco-v4.html)

34. [Magic Wormhole - Flaviu Vlaicu](https://vlaicu.io/posts/wormhole/) - How PAKE Works: Uses a short, low-entropy password (the wormhole code) to establish a strong, high-e...

35. [Peer-to-Peer Communication Across Network Address Translators](https://arxiv.org/abs/cs/0603074) - This paper documents and analyzes one of the simplest but most robust and practical NAT traversal te... [amended 2026-05-20: Ford 2005's 82% UDP hole-punch success reflects NATs of that era; 2025 production measurement (arxiv-2510-27500) reports 70% ± 7.1% on today's CGNAT-heavy networks]

36. [Peer-to-Peer Communication Across Network Address Translators](http://arxiv.org/abs/cs/0603074v1) - Network Address Translation (NAT) causes well-known difficulties for peer-to-peer (P2P) communicatio...

37. [OpenRelay Project: Free Reliable WebRTC TURN Server - Reddit](https://www.reddit.com/r/WebRTC/comments/sqx3ip/openrelay_project_free_reliable_webrtc_turn_server/) - Open Relay Project (https://openrelayproject.org) is a reliable, production ready WebRTC TURN+STUN S... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only]

38. [RFC 8656 - Traversal Using Relays around NAT (TURN)](https://datatracker.ietf.org/doc/html/rfc8656) - This specification defines a protocol, called "Traversal Using Relays around NAT" (TURN), that allow...

39. [RFC 8445 - Interactive Connectivity Establishment (ICE)](https://datatracker.ietf.org/doc/html/rfc8445) - This document describes a protocol for Network Address Translator (NAT) traversal for UDP-based comm...

40. [rfc8445.txt - » RFC Editor](https://www.rfc-editor.org/rfc/rfc8445.txt)

41. [GitHub - quinn-rs/quinn: Async-friendly QUIC implementation in Rust](http://github.com/quinn-rs/quinn) - Async-friendly QUIC implementation in Rust. Contribute to quinn-rs/quinn development by creating an ...

42. [quinn-rs/quinn: Async-friendly QUIC implementation in Rust](https://github.com/quinn-rs/quinn) - Async-friendly QUIC implementation in Rust. Contribute to quinn-rs/quinn development by creating an ...

43. [[2408.01791] Implementing NAT Hole Punching with QUIC - arXiv](https://arxiv.org/abs/2408.01791) - We find that the QUIC-based scheme effectively reduces the hole punching time, exhibiting a pronounc...

44. [How It Works · Veilid](https://veilid.com/how-it-works/) - The framework is conceptually similar to IPFS and Tor, but faster and designed from the ground-up to...

45. [Yggdrasil Network — Join the Global Mesh](https://dev.to/byteknight/yggdrasil-network-join-the-global-mesh-1kcc) - The Yggdrasil Network is an experimental, end‑to‑end encrypted IPv6 overlay that links nodes into a....

46. [Yggdrasil Network | End-to-end encrypted IPv6 networking to ...](https://yggdrasil-network.github.io) - End-to-end encrypted IPv6 networking to connect worlds

47. [snow - Rust - Docs.rs](https://docs.rs/snow/) - The snow crate aims to be a straightforward Noise Protocol implementation. See the Noise Protocol Fr...

48. [noise-protocol — Rust crypto library // Lib.rs](https://lib.rs/crates/noise-protocol) - This repository contains several crates. The noise-protocol crate contains the abstract implementati...

49. [The Noise Protocol Framework - media.ccc.de](https://media.ccc.de/v/34c3-9222-the_noise_protocol_framework) - Noise provides a simple pattern language and naming scheme for 2-party DH-based cryptographic handsh...

50. [Secure Scuttlebutt - Scuttlebot](https://scuttlebot.io/more/protocols/secure-scuttlebutt.html)

51. [Secure Scuttlebutt - SSBC](https://ssbc.github.io/ssb-db/) - Secure Scuttlebutt is a database protocol for unforgeable append-only message feeds. "Unforgeable" m...

52. [Secure, Peer-To-Peer Messaging Apps - Brax Community](https://community.braxtech.net/t/secure-peer-to-peer-messaging-apps/2668) - To add a contact, users must connect directly, typically by scanning each other's QR codes, ensuring...

53. [Briar: Secure messaging, anywhere](https://briarproject.org) - Censorship-resistant peer-to-peer messaging that bypasses centralized servers. Connect via Bluetooth...

54. [Rust implementation of the nostr protocol, high-level client ... - GitHub](https://github.com/rust-nostr/nostr) - nostr-relay-builder: Build your own custom nostr relay; nostr-sdk: A full-featured SDK for building ...

55. [nostr - Rust - Docs.rs](https://docs.rs/nostr) - Rust implementation of Nostr protocol. You may be interested in: nostr-sdk if you want to write a ty...

56. [tor-hsservice — Rust network library // Lib.rs](https://lib.rs/crates/tor-hsservice) - Arti's implementation of an onion service provider

57. [tor_hsservice - Rust - Docs.rs](https://docs.rs/tor-hsservice/latest/tor_hsservice/) - tor-hsservice

58. [Tailscale: The Zero-Config VPN Your Homelab Needs](https://www.antlatt.com/blog/tailscale-homelab-vpn/) - Skip the port forwarding headaches. Tailscale gives you instant, secure access to your homelab from ... [amended 2026-05-20: URL returned a 502 stub at fetch time; cited as anchor only — Tailscale's SSO requirement is independently verifiable from the vendor's own docs]

59. [Tailscale vs Zerotier vs … - Duplicacy Forum](https://forum.duplicacy.com/t/tailscale-vs-zerotier-vs/9795) - Completely off-topic, but try Zerotier instead. It's a Layer 2 solution (as opposed to Layer 3 servi...

60. [XEP-0174: Serverless Messaging - XMPP](https://xmpp.org/extensions/xep-0174.html) - This specification defines how to communicate over local or wide-area networks using the principles ...

61. [Gossip - Introduction · GitBook](https://handbook.scuttlebutt.nz/concepts/gossip) - In Scuttlebutt, 3rd parties can relay (gossip) information for you, which improves availability. Eve...

62. [Information on RFC 9420 - » RFC Editor](https://www.rfc-editor.org/info/rfc9420)

63. [The Messaging Layer Security (MLS) Protocol](https://www.rfc-editor.org/rfc/rfc9420) - Messaging applications are increasingly making use of end-to-end security mechanisms to ensure that ...

64. [Introducing the Model Context Protocol](https://www.anthropic.com/news/model-context-protocol?guides=understanding-tradeoffs)

65. [Introducing the Model Context ...](https://www.anthropic.com/news/model-context-protocol)

66. [Announcing the Agent2Agent Protocol - A2A (Google Blog, April 2025)](https://www.facebook.com/groups/DeepNetGroup/posts/2456717144721153/) - The A2A protocol will allow AI agents to communicate with each other, securely exchange information,...

67. [What Is Agent2Agent (A2A) Protocol?](https://www.ibm.com/think/topics/agent2agent-protocol) - The Agent2Agent (A2A) protocol is an open communication protocol for artificial intelligence (AI) ag...

68. [Multi-agent Conversation Framework | AutoGen 0.2](https://microsoft.github.io/autogen/0.2/docs/Use-Cases/agent_chat/) - AutoGen offers a unified multi-agent conversation framework as a high-level abstraction of using fou...

69. [Anthropic Officially Releases MCP Protocol 2025 Semi-Annual ...](https://www.kdjingpai.com/en/anthropic-zhengshifaa/) - Our Plans for the Evolution of the Model Context Protocol (first half of 2025) The Model Context Pro...

70. [Binary size · Issue #1051 · libp2p/rust-libp2p](https://github.com/libp2p/rust-libp2p/issues/1051) - I have tried compiling the examples, ipfs-kad.rs and chat.rs, and I am getting quite heavy binary si...

71. [I shrunk my Rust binary from 11MB to 4.5MB with bloaty-metafile](https://dev.to/ahaoboy/i-shrunk-my-rust-binary-from-11mb-to-45mb-with-bloaty-metafile-1n7i) - TL;DR: Used bloaty-metafile to analyze binary size, disabled default features on key dependencies,.....

72. [TokioRuntime in iroh_quinn - Rust - Docs.rs](https://docs.rs/iroh-quinn/latest/iroh_quinn/struct.TokioRuntime.html) - A Quinn runtime for Tokio

73. [Hello Tokio - An asynchronous Rust runtime](https://tokio.rs/tokio/tutorial/hello-tokio) - Tokio is a runtime for writing reliable asynchronous applications with Rust. It provides async I/O, ...

74. [veilid-tools 0.4.7](https://docs.rs/crate/veilid-tools/latest)

75. [How to use async/await in Rust when you can't make main function async](https://stackoverflow.com/questions/71116502/how-to-use-async-await-in-rust-when-you-cant-make-main-function-async) - I have a function to download a file which is async: async fn download_file() { fn main() { let resp...

76. [Windows Firewall Inbound Rule behavior : r/sysadmin - Reddit](https://www.reddit.com/r/sysadmin/comments/17c4r18/windows_firewall_inbound_rule_behavior/) - When you first open many networked applications, Windows pops up asking you to allow the application... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only]

77. [Windows Firewall Rules | Microsoft Learn](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/rules) - This article describes the concepts and recommendations for creating and managing firewall rules.

78. [RFC 6762 - ICANNWiki](https://icannwiki.org/RFC_6762) - For implications on Internet governance, see Multicast DNS. RFC 6762, Multicast DNS, is an IETF Stan... [amended 2026-05-20: URL is Cloudflare/captcha-walled at fetch time; cited as anchor only — RFC 6762 itself is the authoritative source]

79. [[PDF] Scalability limitations of Kademlia DHTs when enabling Data ... - arXiv](https://arxiv.org/pdf/2402.09993.pdf) - This paper provides insights after exploring the usage of a Kademlia-based DHT to enable Data Availa...

80. [Honeybee: Decentralized Peer Sampling with Verifiable Random ...](https://arxiv.org/html/2402.16201v1) - However, when the network contains adversarial nodes, Honeybee outperforms GossipSub and Kademlia by...

81. [Towards Communication-Efficient Peer-to-Peer Networks](https://arxiv.org/abs/2406.16661) - We focus on designing Peer-to-Peer (P2P) networks that enable efficient communication. Over the last...

82. [Large Scale Measurement Campaign on Decentralized NAT Traversal](https://arxiv.org/html/2510.27500v1) [amended 2026-05-20: Trautwein, Ihle, Schubotz, Gipp (2025). First large-scale production measurement of DCUtR — 4.4M traversal attempts across 85k networks in 167 countries. Headline result: 70% ± 7.1% direct-connect success rate, with TCP and QUIC statistically indistinguishable. Replaces both the 60% (libp2p forum) and 82% (Ford 2005) figures used elsewhere in the original brief.]

83. [Wireguard, Zerotier or Tailscale - General Discussion - DietPi](https://dietpi.com/forum/t/wireguard-zerotier-or-tailscale/13546) - In upcoming dietpi Zerotier, Tailscale are coming as new software. Any advice or recommendation for ...

84. [yggdrasil-network/yggdrasil-go: An experiment in scalable ... - GitHub](https://github.com/yggdrasil-network/yggdrasil-go) - An experiment in scalable routing as an encrypted IPv6 overlay network - yggdrasil-network/yggdrasil...

85. [libp2p — Rust network library // Lib.rs](https://lib.rs/crates/libp2p) - Peer-to-peer networking library

86. [Arti 1.4.6 is released: Hidden Service resilience](https://forum.torproject.org/t/arti-1-4-6-is-released-hidden-service-resilience-work-on-flow-control-conflux-and-cgo/20258) - by Diziet | August 5, 2025 Arti is our ongoing project to create a next-generation Tor client in Rus...

87. [How to Implement UDP Hole Punching for NAT Traversal - OneUptime](https://oneuptime.com/blog/post/2026-03-20-udp-hole-punching-nat/view) - Implement UDP hole punching to establish direct peer-to-peer UDP connections between hosts behind NA...

88. [A P2P Vision for QUIC (2024) - Hacker News](https://news.ycombinator.com/item?id=45822982) - > UDP-based protocols are well suited for P2P, since hole punching is straightforward if you have pr...