Wires the FIPS transport end-to-end so peer-to-peer calls can reach
other nodes over the mesh without going through Tor:
- fips::dial — raw RFC 1035 DNS client (zero new deps) that queries the
FIPS daemon's local resolver at 127.0.0.1:5354 for `<npub>.fips` AAAA
records. Exposes peer_base_url(npub) → "http://[fd9d:…]:5679" plus a
reqwest client factory for call-site migrations.
- fips::iface — parses /proc/net/if_inet6 to find the ULA address on
`fips0`. Runs under the archipelago service user without extra caps.
- FipsTransport::is_available() — live probe of archipelago-fips and
upstream fips.service via `systemctl is-active`, cached 10s so the
send hot path doesn't thrash DBus.
- FipsTransport::send() — resolve npub, POST TransportMessage JSON to
the peer's /transport/inbox. Today /transport/inbox isn't wired on
the receive side, so call-site migrations use dial::peer_base_url
directly against the already-signed endpoints (/rpc/v1,
/archipelago/node-message, /content/*). The inbox handler lands as
part of the Settings/transport work.
- server::serve_with_shutdown — takes an optional peer_addr and spawns
a second listener bound specifically to the fips0 ULA on port 5679.
The peer listener applies is_peer_allowed_path() — a whitelist of
endpoints that already do per-request signature auth — and returns
404 for everything else. Shutdown cascades to both listeners via a
watch channel; 5s drain window preserved.
- main.rs — if fips0 has a ULA at startup, pass the peer SocketAddr to
serve_with_shutdown; otherwise run the main listener only.
Security: the peer listener is bound to the fips0 ULA directly, not
wildcard, so it's unreachable from WAN IPv6. The path whitelist limits
exposure to endpoints whose handlers verify ed25519 signatures or
federation DID headers server-side.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>