* spike: iroh Swift C-FFI harness (macOS + iOS-sim) for mobile transport
Minimal Rust staticlib (iroh 1.0.0-rc.1) exposing a blocking C API:
bind endpoint, dial by EndpointId via n0 relays/discovery, one bi-stream
send/recv. Swift CLI harness with listen (echo) and dial (round-trip
proof) modes. build.sh builds aarch64-apple-darwin and
aarch64-apple-ios-sim variants; artifacts are gitignored.
Co-Authored-By: Claude Fable 5 <[email protected]>
* spike: green cross-platform iroh proof (iOS-sim dials Mac by EndpointId)
- link Network.framework for the ios-sim target (netdev nw_path_monitor)
- map clean peer close (application code 0) to end-of-stream in recv
- line-buffer harness stdout so orchestration can read the endpoint id
- README records bindings decision (official iroh-ffi is archived, n0
recommends a custom wrapper), versions, build steps, proof transcript,
and the ~7.7MB per-slice binary delta
Co-Authored-By: Claude Fable 5 <[email protected]>
* plans: iroh default mobile transport design
Substrate swap for the existing length-prefixed mobile-host protocol:
iroh QUIC dial-by-EndpointId as the default iOS-to-Mac transport,
Tailscale/LAN demoted to an opt-in fallback toggle. Covers the Mac
listener seam (MobileHostByteConnection), the phone CmxByteTransport
lane, registry route publication, E2E story (QUIC raw-public-key TLS
replaces the Noise IK plan on this lane), Keychain key custody, relay
strategy (n0 now, self-host later), iOS background/battery policy,
hive-design reconciliation, and a 5-PR stacked delivery plan.
Co-Authored-By: Claude Fable 5 <[email protected]>
* spike: iroh route priority 5 so it beats Tailscale in preferredRoute
CmxAttachTicket.preferredRoute sorts ascending and lower wins. The Mac
publishes debugLoopback at 0 and Tailscale at 10+; the spike's route
JSON claimed 20, which would have lost to Tailscale, contradicting the
design's iroh-by-default ordering. 5 sits below Tailscale (default) and
above debugLoopback (DEBUG/simulator keeps the loopback mock host).
Re-ran the cross-platform proof after the change: iOS-sim dialed the
Mac by EndpointId, 46 bytes echoed, 1.04s connect, rc=0 both sides.
Co-Authored-By: Claude Fable 5 <[email protected]>
* plans: EndpointId pinning ships in the first iroh lane, not later
Sharpen the security section: the real threat on a substituted route is
Stack-token exfiltration (the phone sends its bearer token on every
RPC), and iroh is the lane that can close it because the channel is
cryptographically bound to the dialed EndpointId. So pinning moves from
'defense in depth later' into PR 3/4: pin at first trust in
MobilePairedMacStore (QR = proximity, registry auto-pair = TOFU),
refuse to send Stack tokens to a non-matching EndpointId, and surface
EndpointId changes for explicit re-trust.
Co-Authored-By: Claude Fable 5 <[email protected]>
* spike: drain finished stream before connection close
Review finding (autoreview P2): finish() only queues the FIN plus
buffered stream data, while Connection::close is immediate and abandons
buffered data, so a final frame that send() already accepted could be
dropped by close(). Wait on SendStream::stopped() (peer acked all
finished data) with a 5s bound before closing, so a vanished peer
cannot wedge close. Re-ran the cross-platform proof: iOS-sim dial rc=0,
mac listener rc=0, 0.50s connect, no drain stall (2s wall total).
Co-Authored-By: Claude Fable 5 <[email protected]>
---------
Co-authored-by: Claude Fable 5 <[email protected]>