feat: LAN-direct — Locator seam + QUIC + mDNS (C1 + C2) + happy-eyeballs#43
Merged
Conversation
Approved 2026-06-13. CLI-only, Go-only. A Locator seam (in package client) turns a Machine into a live peer.MsgConn; Attach composes [LAN, Relay]. LAN uses QUIC (self-signed + skip-verify; real auth = Noise-KK + binding) and mDNS discovery. Relay/WAN path unchanged. QUIC-over-WAN (DCUtR) is a stated future locator, not built now. Stacked on the B1.4+B1.5 branch (reuses ownerPubFromBinding, the cached binding, and wallet owner_id). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce a Locator interface (package client) that turns a Machine into a live peer.MsgConn; Attach composes [relayLocator] and runs Noise-KK over whatever connects. Today's relay path moves verbatim into relayLocator. Attach now returns peer.MsgConn (was *peer.DataChannel; consumers use only Send/Recv). Behavior-preserving: the relay e2e tests stay green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A length-framed QUIC bidi stream as a peer.MsgConn, shared by client (LAN dial) and agent (LAN listen). QUIC TLS is dumb transport: the real auth is Noise-KK + the wallet binding that runs inside, so ClientTLS skips verification. ServerTLS uses an ephemeral self-signed cert. ALPN miranda/lan/v1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A lanLocator that resolves a machine_id to a LAN address (mDNS in prod, injectable resolver in tests), QUIC-dials it, and sends the wallet binding as frame 0 before Noise-KK. Returns ErrUnreachable on miss / no-wallet so Attach falls through to the relay. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…accept mir up can accept LAN-direct QUIC connections (advertised via mDNS as _miranda._udp). The wallet binding arrives as frame 0; the agent checks IsOwnerPinned + verifies the binding (reusing ownerPubFromBinding) and pins binding.x25519, then runs the SAME authenticated PTY session as the relay path via the extracted serveAuthenticated helper. admit() bounds pre-auth handshakes. Not yet auto-started (wiring + --no-lan is next). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-only mir attach now tries LAN-direct (mDNS+QUIC) first with a ~600ms budget, then falls back to the relay; --relay-only skips LAN. mir up starts the QUIC listener + mDNS advertisement (in Up, after the paired-owner guard) unless --no-lan; LAN start failure is non-fatal — the relay path always serves. attachLocators() makes the LAN-first-vs-relay-only decision unit- testable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lve test SECURITY.md gains an honest LAN-direct residual-exposure note (new inbound listener surface + mDNS leak; same Noise-KK + binding trust, --no-lan to disable). README documents LAN-direct + the flags. A skippable live-mDNS test validates the prod resolver where multicast is available. Spec notes happy-eyeballs as the future latency refinement and netsim as a follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the sequential LAN-then-relay dial with dialStaggered: the LAN locator starts immediately, the relay only after a ~200ms head start; the first live MsgConn wins, the loser is cancelled and any late-connecting loser is cleaned up. On the LAN, LAN-direct wins inside the head start so the relay is never contacted (a successful LAN attach stays relay-free). Remote attaches pay only the head start, not the full ~600ms LAN budget. Staggered (not a naive simultaneous race) on purpose: it keeps the relay-free property that is the point of LAN-direct. Race-tested (-race). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements
docs/superpowers/specs/2026-06-13-c1-c2-lan-direct-locator-design.md.Supersedes #42 (auto-closed when its stacked base
b1.4-b1.5-wallet-wiremerged via#41); rebased onto
main, same commits + the happy-eyeballs race. CLI-only, Go-only —the browser keeps using the relay; no web changes, no byte-identical crypto gate touched.
What this delivers
mir attachreaches amir upnode on the same LAN with no relay — zero-config mDNSdiscovery + a direct QUIC transport — via a
Locatorseam under the unchanged Noise-KKsession. The relay/WAN path is untouched.
Attachcomposes locators and runs Noise-KK overthe first that connects; today's relay path moves verbatim into
relayLocator. Relay e2estays green.
_miranda._udp) discovery + QUIC (internal/quicmsg,self-signed + skip-verify; real auth is Noise-KK + the wallet binding inside the
stream). The binding is frame 0; the agent reuses
ownerPubFromBinding→serveAuthenticated(shared with the relay path).start; first live
MsgConnwins, loser cancelled+cleaned. A successful LAN attach nevercontacts the relay (relay-free, no metadata); remote attaches pay only the head start.
Race-tested (
-race).mir up --no-lan,mir attach --relay-only.Trust (unchanged) + new surface
Locate but never impersonate. mDNS spoofing / a rogue LAN host → at worst a failed handshake
(DoS). New exposure: the agent accepts inbound LAN connections (bounded by the pre-auth
limiter) + an mDNS advertisement of an opaque
machine_id; both off with--no-lan.Documented in
SECURITY.md.QUIC-over-WAN is the destination, not this step
WAN's hard part is NAT traversal (ICE), which WebRTC already ships; a future
QUICHolePunchLocator(DCUtR, north-star C4) drops into the same seam — stated, not built.Tests / deps
go test ./...(incl. real-shell echo over QUIC with no relay, unpinned-binding rejection,staggered-race under
-race),go vet,gofmtclean. Realmirbinary exposes the flags.New deps:
quic-gov0.60.0,grandcat/zeroconfv1.0.0. Follow-up:deploy/netsimLAN path.🤖 Generated with Claude Code