feat: add optional pinned-mutual-TLS QUIC transport - #18
Merged
Merged
Conversation
QUIC is additive: TCP stays first class and USB is unchanged. One QUIC connection carries three reliable streams (Control, Video, Audio), each opened with an explicit 8-byte MEOW preface, using the existing identity, SPKI pins and verify block (ALPN meowdisplay-quic/1, no tickets or resumption, so no 0-RTT). Protocol selection (Auto/QUIC/TCP per device) runs inside the chosen network route, falls back to secure TCP only after an ordinary reachability failure in Auto, and never after a security or protocol failure. Receivers add a QUIC listener alongside the TLS listener with bounded connections, streams and frame sizes, and hand the Control stream to the existing session pipeline. Wire version 22 adds an explicit authenticated transports/qv capability; minSupportedPeer stays 1.
…d loopback security
raiseCatError
force-pushed
the
claude/cool-galileo-bkgznr
branch
from
September 27, 2026 08:11
3c842f5 to
ae5ebec
Compare
raiseCatError
marked this pull request as ready for review
September 27, 2026 08:22
…orts a pre-QUIC pv
5 tasks done
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.
What changed
Adds QUIC as an optional second secure transport on network routes (LAN / AWDL / Remote). TCP remains fully supported and unchanged on the wire; USB never uses QUIC.
Transport
MEOWpreface (version 1, channel byte, zero flags). The existing[UInt32 BE length][payload]framing follows. Channel identity never comes from stream IDs.TLSConfigurator.pinnedQUICOptionsuses the same identity, the same client-certificate requirement on the listener and the same SPKI verify block, with ALPNmeowdisplay-quic/1. Session tickets and resumption are disabled, so there is no 0-RTT.TLSConfigurator.authenticatedPeerSPKI(of:)).send(channel:content:)). Over TCP every channel is the same connection with identical bytes. Video backpressure (pendingSends) now counts Video only, Audio is tracked separately and Control is never gated. Every completion carries a transport epoch, so a retired connection can't touch the new connection's counters.Selection (Mac, per device: Auto / QUIC / TCP, default Auto)
TransportProtocolSelectorruns inside the already-chosen route; route arbitration is unchanged._meowdisp-q._udphint is enough to attempt QUIC. Auto uses TCP when there's no capability or a cooldown is active. Whichever protocol first completes the authenticated hello is sticky for the logical session: no re-challenge, no metric switching.switchTransporthot swap (input cancelled, authority invalidated, re-authentication, re-admission, keyframe resync, new audio generation) only when the protocol differs. Auto keeps the current protocol.Receiver
TLSListenerState.quic: pairing suppression, trust refresh and teardown._meowdisp-q._udpwithid/pv/qvonly (never thecrtoken).quiconly while the listener is bound.ReceiverMediaAdmissionGate).ReceiverPipelineActorretires a QUIC connection whenever it lets go of its Control stream (replace, drop, revoke, failure). Forget/Block also closes connections that haven't presented a session yet.Compatibility
WireProtocol.version22;minSupportedPeerstays 1; pairing version unchanged.transports,qv) is added to hello/welcome. A missing capability means TCP only.streamingProfileRequest) is pinned to 21, so pv 21 receivers keep working.Docs: PROTOCOL.md §2.4 (new), COMPATIBILITY.md, SECURITY.md, ARCHITECTURE.md, and one README bullet. No performance claims are made.
Why
Today Control, Video and Audio share one ordered TCP/TLS byte stream, so a large Video write can hold back input and audio. Separate reliable QUIC streams remove that cross-channel head-of-line blocking. Every existing trust and session rule is kept, and TCP remains available.
Verification
CI (macos-26) on the current head
f67b75d8b73f43d7988ba379bf7c140deb7af23bis green:xcodegenCapability-cache regression fix (
f67b75d): an authenticated hello with a pre-QUICpv(below 22) clears any remembered QUIC support for that peer. A pv 22+ hello that lists TCP only (for example, the receiver's QUIC listener is momentarily unbound) may keep a previously authenticated capability. The decision uses the authenticated hello's ownpv, never Bonjour.TransportProtocolSelectionTestscovers these cases:qvis still remembered as incompatibleSWIFT_VERSIONis unchanged and strict concurrency is still on. There are no new warnings in production files. The QUIC tests use the deprecatedSecKeychainCreateAPI to build throwaway keychains.New tests:
TransportProtocolSelectionTests: selection, no-downgrade, one live recovery, anti-thrash, cooldown, stores, Forget, classifier.QUICStreamProtocolTests: preface, split/multi/truncated/oversized frames, bounded buffering, topology, capability, hint.QUICReceiverAuthorityTests: connection bound, retirement with the Control stream, revoke, parked media, admission-gated media, strict Control framing, stale generations.QUICMigrationTests: fresh authentication/admission/input grant across TCP↔QUIC, epoch-guarded counters, no shared send gate, repeated switches.QUICSecureTransportTests: real loopback QUIC between isolated temporary keychain identities using the production options. Covers correct mutual pins, Control arriving past 8 MiB of unread Video, wrong server pin (reported as security), wrong client pin, unknown pin, missing client certificate, ALPN mismatch, and peer-ID mismatch.Not done here: physical TCP-vs-QUIC latency/CPU/energy A/B on real devices and networks.
The change is focused, without unrelated refactors
Relevant behaviour was verified (tests and/or on device) — tests and loopback QUIC in CI; on-device A/B still pending
Documentation updated if needed
No credentials, secrets or signing material included
No unrelated generated or build artifacts