# RFCs + Specs Index

Semantic index of 12 docs covering discovery, NAT traversal, identity, and secure-messaging primitives cited in `docs/research/SPT Networked Messaging Research Brief.md`. Source files live in `docs/research/inspiration/rfcs/*.txt|.html` and `docs/research/inspiration/specs/*.html`.

## Quick lookup

| Need | Doc |
|---|---|
| mDNS UDP port + IPv4 multicast | RFC 6762 §11 / Appendix A (port 5353, 224.0.0.251, FF02::FB) |
| mDNS message format | RFC 6762 §18 |
| mDNS probing/announcing | RFC 6762 §8 |
| mDNS service-record TXT format (DNS-SD pattern in practice) | XEP-0174 §3 + §3.1 |
| LLMNR port + multicast addrs | RFC 4795 §2 (UDP/TCP 5355, 224.0.0.252, FF02:0:0:0:0:0:1:3) |
| STUN header / magic cookie | RFC 8489 §5 (20-byte hdr, magic `0x2112A442`) |
| STUN attribute encodings | RFC 8489 §14 (MAPPED-ADDRESS, XOR-MAPPED-ADDRESS, MESSAGE-INTEGRITY, FINGERPRINT) |
| STUN Binding method | RFC 8489 §3, §13 |
| TURN default port | RFC 8656 §4.1 (3478 UDP/TCP, 5349 TLS/DTLS) |
| TURN Allocate / ChannelBind | RFC 8656 §7, §12 |
| TURN attributes & methods | RFC 8656 §17, §18 |
| ICE candidate types | RFC 8445 §5.1.1 (host, server-reflexive, peer-reflexive, relayed) |
| ICE priority formula | RFC 8445 §5.1.2.1 |
| ICE checks / nomination | RFC 8445 §7, §8 |
| MLS message framing | RFC 9420 §6 + struct `MLSMessage` §6 |
| MLS cipher suites | RFC 9420 §5.1, §17.1 |
| MLS group key schedule | RFC 9420 §8 |
| SSDP multicast addr + method verbs | draft-cai-ssdp-v1 §3 (239.255.255.250, UDP port 1900, `M-SEARCH`, `NOTIFY ssdp:alive/byebye`) |
| Noise handshake patterns | noise-protocol §7 (NN, NK, NX, XX, IK, …) |
| Noise message size cap | noise-protocol §3 (≤65535 B; AEAD adds 16 B) |
| Noise protocol-name encoding | noise-protocol §8 (e.g. `Noise_XX_25519_ChaChaPoly_BLAKE2s`) |
| Syncthing local discovery port | syncthing-localdisco-v4 (UDP 21027, IPv4 broadcast 255.255.255.255, IPv6 mcast `ff12::8384`, magic `0x2EA7D90B`) |
| Syncthing device ID format | syncthing-device-ids (SHA-256 of DER cert → base32, 52 chars + check digits, grouped) |
| XMPP serverless service type | XEP-0174 §3 (`_presence._tcp.local.`, SRV+TXT+A) |
| did:key encoding | did-key-spec §2 (`did:key:` + multibase(base58-btc) + multicodec(pubkey)) |

---

## RFCs

### RFC 6762 — Multicast DNS
- **Authors/Org:** S. Cheshire, M. Krochmal (Apple Inc.)
- **Year/Status:** February 2013 / Standards Track (IETF)
- **Defines:** DNS-style query/response over IPv4/IPv6 link-local multicast; the `.local.` namespace; conflict resolution and TTL-driven cache coherency without a unicast DNS server.
- **Key sections for SPT:**
  - §3 — `.local.` namespace rules
  - §5–§6 — Querying / Responding (one-shot vs. continuous, known-answer suppression)
  - §8 — Probing & Announcing on startup (4 probes @ 250 ms, then 2 announcements)
  - §9 — Conflict resolution (rename collisions deterministically)
  - §10 — TTLs & cache coherency (goodbye = TTL 0)
  - §11 — Source-address checks (drop off-link traffic)
  - §15 — Multiple responders on the same machine (one shared mDNS socket → required when SPT colocates owl + live)
  - §17 — Message size (target ≤1500 B, MUST handle up to 9000 B)
  - §18 — Message format (DNS hdr, cache-flush bit on RR class)
  - Appendix A — Port-number rationale (why 5353)
- **Wire-format facts:**
  - UDP port **5353** (src AND dst on full responders)
  - IPv4 multicast **224.0.0.251**, IPv6 multicast **FF02::FB**
  - TTL 255 (link-local enforcement)
  - Top bit of RR CLASS field repurposed as cache-flush; top bit of QCLASS = unicast-response-requested
- **Relevance:** Locks SPT's LAN-discovery wire decisions: `_spt._udp.local.` service via `mdns-sd` crate; bind 5353; respect cache-flush + 1-second rate limit; treat goodbye packets when an owl perch shuts down.
- **Tags:** discovery, mdns, wire-format
- **Brief footnote refs:** [^17][^18]

### RFC 4795 — Link-Local Multicast Name Resolution (LLMNR)
- **Authors/Org:** B. Aboba, D. Thaler, L. Esibov (Microsoft)
- **Year/Status:** January 2007 / Informational (consensus not reached for Standards Track; shipped in Windows)
- **Defines:** DNS-compatible name resolution over link-local multicast on a separate port from DNS; primarily a Windows-deployed alternative to mDNS for hostname lookup only (no service discovery).
- **Key sections for SPT:**
  - §2 — Multicast addresses + port
  - §2.1 — Packet format (reuses DNS header)
  - §2.7 — Retransmission / jitter (100 ms JITTER_INTERVAL)
  - §4 — Conflict resolution (uniqueness verification)
  - §7 — Constants (LLMNR_TIMEOUT 100 ms on 802.11)
- **Wire-format facts:**
  - UDP **and** TCP port **5355**
  - IPv4 multicast **224.0.0.252**, IPv6 multicast **FF02:0:0:0:0:0:1:3**
  - DNS message format with C-bit (Conflict) and T-bit (Tentative) repurposed in header flags
- **Relevance:** SPT can deprioritize LLMNR vs mDNS — Windows-only practical deployment, hostname-only, no service-type discovery; no dedicated Rust crate. Listed for completeness when explaining why SPT picks mDNS.
- **Tags:** discovery, llmnr, wire-format
- **Brief footnote refs:** brief §2.1 table row

### RFC 8489 — Session Traversal Utilities for NAT (STUN)
- **Authors/Org:** Petit-Huguenin, Salgueiro, Rosenberg, Wing, Mahy, Matthews (Cisco/Five9/Citrix/Nokia)
- **Year/Status:** February 2020 / Standards Track (obsoletes RFC 5389)
- **Defines:** Lightweight client/server protocol for discovering a host's reflexive transport address through a NAT, plus a generic message framing reused by TURN, ICE, WebRTC.
- **Key sections for SPT:**
  - §5 — STUN message structure (20-byte header)
  - §6 — Base protocol procedures (transactions, retransmit RTO with exponential backoff)
  - §7 — FINGERPRINT mechanism (CRC32 XOR'd with `0x5354554e`)
  - §8 — DNS discovery of server (SRV `_stun._udp`, URI scheme)
  - §9 — Short-term & long-term credentials (HMAC-SHA1/SHA256)
  - §13 — STUN usages (defines only the `Binding` method here)
  - §14 — Attributes (each TLV-encoded)
- **Wire-format facts:**
  - 20-byte header: 2-bit zero prefix + 14-bit message type + 16-bit length + **magic cookie `0x2112A442`** + 96-bit transaction ID
  - Top two bits = `00` → distinguishes STUN from multiplexed protocols (e.g. ChannelData = `01`)
  - Binding request = `0x0001`, Binding success = `0x0101`
  - XOR-MAPPED-ADDRESS XORs address with magic cookie (defeats naive NAT ALGs)
  - Default port **3478**; TLS port **5349**
- **Relevance:** Required reading if SPT ever implements its own ICE candidate gathering (instead of inheriting via iroh/str0m). The header format + magic cookie are what `iroh-relay` traffic shaping detects when multiplexing STUN on the QUIC port.
- **Tags:** nat-traversal, stun, transport, wire-format
- **Brief footnote refs:** brief §2.2 row + n/a

### RFC 8656 — Traversal Using Relays around NAT (TURN)
- **Authors/Org:** T. Reddy, A. Johnston, P. Matthews, J. Rosenberg
- **Year/Status:** February 2020 / Standards Track (obsoletes RFC 5766, 6156)
- **Defines:** STUN extension where a server allocates a relayed transport address and forwards packets between a client behind NAT and arbitrary peers; required when symmetric NATs or restrictive enterprise firewalls defeat hole punching.
- **Key sections for SPT:**
  - §3 — Overview (allocation, permissions, send vs. channel)
  - §4 — Discovery + URI scheme `turn:`/`turns:`
  - §7 — Creating an Allocate (REQUESTED-TRANSPORT, LIFETIME)
  - §9–§10 — Permissions + CreatePermission
  - §11 — Send / Data indications (per-datagram XOR-PEER-ADDRESS)
  - §12 — Channels (efficient 4-byte ChannelData header instead of full STUN)
  - §17–§18 — TURN methods + attributes
- **Wire-format facts:**
  - Default port **3478** (UDP, TCP); **5349** for TURN over TLS/DTLS
  - Allocate method **`0x003`**; ChannelBind, Refresh, Send, Data, CreatePermission also defined
  - ChannelData magic: channel numbers **`0x4000`–`0x7FFF`** (first 2 bits = `01`, distinguishes from STUN `00`)
  - Allocations default LIFETIME 600 s; refresh required before expiry
- **Relevance:** SPT's iroh path uses TURN-shaped relay fallback only as a last resort; understanding RFC 8656 frames the cost model (per-byte relay bandwidth) and explains why SPT prefers QUIC hole punching first. Also defines wire shape that any self-hosted relay must speak.
- **Tags:** nat-traversal, turn, transport, wire-format
- **Brief footnote refs:** [^37][^38]

### RFC 8445 — Interactive Connectivity Establishment (ICE)
- **Authors/Org:** A. Keranen, C. Holmberg (Ericsson), J. Rosenberg
- **Year/Status:** July 2018 / Standards Track (obsoletes RFC 5245)
- **Defines:** End-to-end NAT-traversal coordination protocol for UDP-based communication: gather candidates (host, server-reflexive, peer-reflexive, relayed), exchange via signalling, prioritise, run connectivity checks, nominate the winning pair.
- **Key sections for SPT:**
  - §2 — ICE overview
  - §5.1.1 — Gathering candidate types
  - §5.1.2.1 — Priority formula `priority = (2^24)*type_pref + (2^8)*local_pref + (256 − component_id)`
  - §5.1.3 — Redundant-candidate elimination
  - §6 — Forming pairs + checklists
  - §7 — Connectivity checks (STUN Binding with PRIORITY, USE-CANDIDATE, ICE-CONTROLLING/CONTROLLED)
  - §8 — Concluding ICE / role conflict
  - §15 — Keepalives (STUN Binding indication every 15 s)
- **Wire-format facts:**
  - Re-uses STUN message format (no new on-wire framing); adds STUN attributes PRIORITY, USE-CANDIDATE, ICE-CONTROLLING, ICE-CONTROLLED
  - Recommended type preferences: host 126, peer-reflexive 110, server-reflexive 100, relayed 0
- **Relevance:** Iroh subsumes ICE-equivalent logic via its own QUIC-aware connection establishment. If SPT ever needs to interoperate with a WebRTC/SIP endpoint (e.g. browser-pair flow), RFC 8445 + 8489 + 8656 form the required triad.
- **Tags:** nat-traversal, ice, stun, transport
- **Brief footnote refs:** [^39][^40]

### RFC 9420 — The Messaging Layer Security (MLS) Protocol
- **Authors/Org:** R. Barnes (Cisco), B. Beurdouche (Inria/Mozilla), R. Robert (Phoenix R&D), J. Millican (Meta), E. Omara, K. Cohn-Gordon (Oxford)
- **Year/Status:** July 2023 / Standards Track
- **Defines:** Group-key-agreement and message-protection protocol for asynchronous group chats (2 → thousands of members) with forward secrecy and post-compromise security, via a TreeKEM ratchet over a logical Delivery Service.
- **Key sections for SPT:**
  - §5.1 — Cipher suites (1 = MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519, …)
  - §6 — Message framing (`FramedContent`, `MLSMessage`, `PublicMessage`, `PrivateMessage`)
  - §7 — Ratchet tree
  - §8 — Key schedule (init/joiner/welcome/epoch secrets)
  - §10 — KeyPackages (per-user advertised init keys; required for asynchronous joins)
  - §11 — Group creation
  - §12 — Group evolution (Add, Update, Remove, Commit)
  - §14 — Sequencing of state changes (epoch monotonicity → DS responsibility)
  - §16 — Security considerations (DS compromise, Authentication Service trust)
  - §17.2 — MLS Wire Formats registry (`mls_public_message`, `mls_private_message`, `mls_welcome`, `mls_group_info`, `mls_key_package`)
- **Wire-format facts:**
  - TLS-presentation-language structs; `MLSMessage` carries `ProtocolVersion=mls10 (1)` + `WireFormat` (uint16) + variant body
  - ContentType: reserved(0) / application(1) / proposal(2) / commit(3)
  - SenderType: member / external / new_member_proposal / new_member_commit
  - Media type **`message/mls`** (§17.10)
- **Relevance:** If SPT ever introduces multi-agent "rooms" (>2 owl perches in a shared session), MLS via the `openmls` crate is the modern choice for E2E forward secrecy. The Delivery Service abstraction maps cleanly to SPT's existing spool. Locks identity: each member's leaf carries a credential bound to a signing key — pairs naturally with Ed25519 node IDs from iroh.
- **Tags:** identity, mls, wire-format
- **Brief footnote refs:** [^62][^63]

---

## Specs

### draft-cai-ssdp-v1 — Simple Service Discovery Protocol (SSDP)
- **Authors/Org:** Y. Cai et al. (Microsoft, UPnP origin); Internet-Draft (expired)
- **Year/Status:** Initial drafts circa 1999–2000; foundation of UPnP device discovery; never advanced to RFC, but ubiquitous on consumer LANs.
- **Defines:** HTTPMU/HTTPU-based device discovery over IPv4 multicast — clients send `M-SEARCH`, devices announce themselves with `NOTIFY ssdp:alive` and exit with `NOTIFY ssdp:byebye`.
- **Key sections for SPT:**
  - §3 — Multicast addressing & port
  - §4 — Discovery request (`M-SEARCH * HTTP/1.1`)
  - §5 — Advertisement / announcement (`NOTIFY * HTTP/1.1` with `NTS: ssdp:alive` | `ssdp:byebye`)
  - §5.3.1 — Rationale for GENA NOTIFY (vs. dedicated verb)
- **Wire-format facts:**
  - IPv4 multicast **239.255.255.250** (administratively scoped), UDP destination port **1900** (`reservedSSDPport`)
  - Verbs: `M-SEARCH`, `NOTIFY` (HTTP-over-UDP, ASCII text)
  - `MAN: "ssdp:discover"` MUST be present on M-SEARCH
- **Relevance:** Mostly relevant as background for why SPT does NOT use SSDP — router-coupled, noisier, less consistent than mDNS, no symbolic naming, and `rupnp` Rust crate exists but adds dependency weight. Useful to cite when explaining the discovery shortlist.
- **Tags:** discovery, ssdp, wire-format
- **Brief footnote refs:** brief §2.1 row

### noise-protocol — The Noise Protocol Framework (Rev 34)
- **Authors/Org:** Trevor Perrin (independent); public-domain spec at noiseprotocol.org
- **Year/Status:** Revision 34, current; widely deployed (WireGuard, WhatsApp, Lightning, I2P, Signal-on-the-wire).
- **Defines:** A construction framework — not a single protocol — for building DH-based mutually-authenticated handshakes from a small set of tokens (`e`, `s`, `ee`, `es`, `se`, `ss`, `psk`) arranged into named patterns.
- **Key sections for SPT:**
  - §3 — Message format (≤65535 B; AEAD adds 16 B)
  - §4 — Crypto functions (DH 25519/448, ChaChaPoly/AESGCM, SHA256/512/BLAKE2)
  - §5 — Processing rules (`CipherState`, `SymmetricState`, `HandshakeState`)
  - §7 — Handshake patterns (one-way N/K/X; interactive NN, NK, NX, XN, XK, XX, KN, KK, KX, IN, IK, IX)
  - §7.7 — Per-payload security properties table
  - §7.8 — Identity hiding
  - §8 — Protocol-name encoding (e.g. `Noise_XX_25519_ChaChaPoly_BLAKE2s`)
  - §9 — Pre-shared symmetric keys (modifier `psk0..psk4`)
  - §10 — Compound protocols, fallback, Noise Pipes (0-RTT)
- **Wire-format facts:**
  - All messages ≤ 65535 bytes
  - Transport message = AEAD ciphertext (payload + 16-byte tag)
  - Handshake message = sequence of one-or-more DH public keys + optional payload; each "encrypted" field grows by 16 B (AEAD tag)
  - `protocol_name` is the literal ASCII string used as the SymmetricState initial hash input
- **Relevance:** Direct candidate for SPT pairing/transport encryption when not using QUIC's built-in TLS 1.3. Recommended pattern for SPT first-contact is **Noise_XX_25519_ChaChaPoly_BLAKE2s** (mutual auth, no prior knowledge); for "already paired" perches use **IK** (initiator knows responder's static key) → 1-RTT. The `snow` crate maps 1:1 to this spec.
- **Tags:** identity, noise, transport, wire-format
- **Brief footnote refs:** [^47][^48][^49]

### syncthing-localdisco-v4 — Syncthing Local Discovery Protocol v4
- **Authors/Org:** Syncthing project (MPL-2.0)
- **Year/Status:** Active, v2.1.0; production-shipping protocol used by millions of installs.
- **Defines:** Periodic broadcast/multicast Announcement protocol; receivers maintain a passive address table — no query/response.
- **Key sections for SPT:**
  - "Mode of Operation" — periodic 30–60 s interval, immediate retransmit on restart
  - "Device ID" — SHA-256 of X.509 cert (see device-ids spec)
  - "Announcement packet" — 4-byte magic + protobuf payload
- **Wire-format facts:**
  - Transport: UDP, dest port **21027**
  - IPv4: broadcast to link-specific or **255.255.255.255**
  - IPv6: multicast to **`ff12::8384`**
  - Magic: **`0x2EA7D90B`** (big-endian, 32-bit prefix)
  - Body: protobuf `Announce { bytes id = 1; repeated string addresses = 2; int64 instance_id = 3; }`
  - `instance_id` random per startup → recipients detect restarts
- **Relevance:** Concrete reference design SPT can mirror: a parallel pure-broadcast UDP discovery that does NOT require mDNS to be enabled (and works in environments where mDNS is firewalled). Same protobuf-style frame would carry an iroh `NodeAddr`. Adds robustness vs. mDNS-only.
- **Tags:** discovery, syncthing, wire-format
- **Brief footnote refs:** [^19][^33]

### syncthing-device-ids — Understanding Device IDs
- **Authors/Org:** Syncthing project
- **Year/Status:** Active; documents the long-standing device-ID scheme.
- **Defines:** Self-issued ECDSA-P-384 (post-v0.12.5; RSA-3072 historic) keypair persisted as `key.pem`/`cert.pem`; the device ID is the SHA-256 of the DER-encoded self-signed cert, encoded in base32 with check digits.
- **Key sections for SPT:**
  - "Keys" — algorithm choice & file layout
  - "Device IDs" — hash → base32 → 52-char ID + check digits → dash-grouped display
  - "Connection Establishment" — TLS handshake, compute peer ID from presented cert, compare against expected
  - "Problems & Vulnerabilities" — local-discovery spoofing, UX of long IDs (suggests short-ID + PIN pairing)
- **Wire-format facts:**
  - Device ID = SHA-256(DER cert) → 32 bytes
  - Base32 (RFC 4648 alphabet) → 52 chars + `====` padding; padding stripped, split into 4 groups, Luhn-style check digit per group, dash-separated:
    `MFZWI3D-BONSGYC-YLTMRWG-C43ENR5-QXGZDMM-FZWI3DP-BONSGYY-LTMRWAD`
- **Relevance:** Closest production analogue to what SPT needs for "no-account" identity. Demonstrates that hash-of-cert + TLS-handshake-verification is sufficient — no PKI, no CA, trust-on-first-use plus user-confirmed ID. SPT's iroh `NodeId` (Ed25519 pubkey, base32) follows the same pattern with a smaller payload.
- **Tags:** identity, syncthing
- **Brief footnote refs:** [^19][^33]

### XEP-0174 — Serverless Messaging (XMPP)
- **Authors/Org:** P. Saint-Andre (XMPP Standards Foundation)
- **Year/Status:** Final / Active; XSF Extension; modelled on Apple iChat / Bonjour.
- **Defines:** How to run XMPP between peers on a link with no s2s server: each client publishes a `_presence._tcp.local.` DNS-SD service (PTR + SRV + A/AAAA + TXT) via mDNS, then opens a direct XMPP XML stream to the discovered peer.
- **Key sections for SPT:**
  - §3 — DNS records to advertise (PTR, A/AAAA, SRV, TXT)
  - §3.1 — TXT-record schema (`txtvers`, `jid`, `nick`, `msg`, `status`, `port.p2pj`, …)
  - §4 — Discovery via `_presence._tcp.local.` PTR query
  - §5 — Presence exchange via TXT updates (not pushed)
  - §6–§11 — Initiating / managing XML streams over the discovered TCP socket
- **Wire-format facts:**
  - Service type: **`_presence._tcp.local.`**
  - Instance name format: `user@machine._presence._tcp.local.`
  - SRV target: `machine.local.` (mDNS-resolved)
  - TXT MUST include `txtvers=1` as first KV; MUST exist (may be a single zero byte)
- **Relevance:** Most directly transferable template for SPT LAN discovery: replace `_presence._tcp.` with `_spt._udp.` (or `_spt._tcp.`), publish an instance per perch, encode `owl_id` + iroh `NodeAddr` in the TXT record, and use mDNS browsing to populate the local registry. Validates the "DNS-SD service-type + TXT-key/value" pattern at production scale.
- **Tags:** discovery, mdns, xmpp, identity, wire-format
- **Brief footnote refs:** [^60]

### did-key-spec — The did:key Method (v0.9 draft)
- **Authors/Org:** W3C Credentials Community Group
- **Year/Status:** 2025 CG Draft (latest in this repo); not a Recommendation. Pre-1.0.
- **Defines:** A DID method that encodes a raw public key as a self-resolving DID URI — no registry lookup; the DID Document is deterministically derived from the key bytes.
- **Key sections for SPT:**
  - §2 — Identifier syntax: `did-key-format := did:key:<mb-value>` where mb-value is multibase + multicodec
  - §3 — Operations (Create / Read / Update=no-op / Deactivate=no-op)
  - §4 — Security & privacy considerations (no key rotation; correlation risk)
- **Wire-format facts:**
  - Canonical encoding: `did:key:` + **multibase(base58-btc)** + **multicodec(public-key-type, raw-public-key-bytes)**
  - Ed25519 example: `did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK`
  - Prefix `z6Mk` ⇒ Ed25519 (multicodec `0xed01`); other prefixes for X25519, P-256, Secp256k1, BLS12381
- **Relevance:** Optional encoding shell for SPT node IDs if cross-ecosystem interop becomes a goal (e.g. linking an SPT perch identity to a DIDComm or Verifiable Credentials workflow). Not needed for native peer-to-peer SPT, but cheap to add as an alternate `--print-did-key` rendering of the existing Ed25519 pubkey.
- **Tags:** identity, did, wire-format
- **Brief footnote refs:** brief §2.4 row

---

## Themes

- **Two link-local-multicast lineages dominate discovery:** the IETF Zeroconf path (mDNS / RFC 6762 + DNS-SD-style TXT records as used by XEP-0174) and the UPnP path (SSDP / draft-cai-ssdp-v1). SPT should pick mDNS — same primitive but symbolic, lower noise, better Rust support (`mdns-sd`).
- **STUN is the chassis for NAT discovery; ICE is the choreography; TURN is the fallback relay** — RFCs 8489 + 8445 + 8656 form a triad. Iroh subsumes all three under one `Endpoint::connect` call, so SPT can treat them as black boxes but must understand RFC 8489's wire format because it multiplexes with QUIC on the same UDP port (top-two-bits discriminator).
- **"No-account" identity has converged on hash-of-public-key formats** — Syncthing (SHA-256 of cert → base32 + check digits), did:key (multibase + multicodec), iroh (Ed25519 → base32 NodeId). All three share the pattern: keypair generated at first run, hash/encoded representation is the user-facing address, TOFU + display-string verification handles trust.
- **Magic constants are gold and easy to typo:**
  - mDNS: UDP 5353, 224.0.0.251, FF02::FB
  - LLMNR: UDP/TCP 5355, 224.0.0.252, FF02:0:0:0:0:0:1:3
  - SSDP: UDP 1900, 239.255.255.250
  - Syncthing: UDP 21027, magic `0x2EA7D90B`, IPv6 `ff12::8384`
  - STUN/TURN: UDP/TCP 3478, TLS 5349, magic cookie `0x2112A442`
  - XEP-0174: service type `_presence._tcp.local.`
- **MLS + Noise cover two distinct cryptographic needs.** Noise = 1:1 pairwise channel (per-perch transport encryption beyond what QUIC TLS 1.3 already gives). MLS = group key agreement once SPT supports >2-party perch rooms; reuses Ed25519 credentials already implied by node IDs.
- **Length cap convergence:** Noise transport msg ≤ 65535 B; mDNS targets ≤ 1500 B but allows up to 9000 B; STUN messages bounded by attribute encoding (~64 KB practical). SPT message framing should pick a single internal cap (e.g. 64 KiB) compatible with all three.
