feat(messaging,dwn,mesh): route peer messaging + DWN sync + blob fetch via FIPS first

Migrates the remaining Tor-direct peer call sites to PeerRequest so
FIPS is the default when the peer is federated and running the daemon:

- node_message::send_to_peer / check_peer_reachable: gain a
  fips_npub parameter. Error messages updated to reference both
  transports.
- Callers (api/rpc/network.rs, api/rpc/peers.rs, server health
  loop): look up fips_npub from federation storage by onion and
  pass it.
- mesh::send_typed_wire_via_federation: the spawned background POST
  for the /archipelago/mesh-typed endpoint now uses PeerRequest with
  federation-resolved fips_npub. Signature domain unchanged.
- api/rpc/mesh/typed_messages.rs fetch_blob_from_peer: blob URL
  rebuilt as (base_url, path_with_query) so PeerRequest can append
  the query string after swapping the host. Cap/exp/peer
  parameters are still signed over the content ref itself, so
  transport choice is invisible to the signature.
- network/dwn_sync.rs sync_with_peers: per-peer fips_npub lookup
  before sync_single_peer; health/pull/push each dial through
  PeerRequest, so any DWN peer known to federation gets FIPS.

Left Tor-only on purpose:
- api/rpc/identity/handlers.rs handle_identity_resolve_peer_onion —
  resolving TO a DID, no anchor yet.
- content.browse / preview calls to non-federated peers fall
  through to Tor naturally inside PeerRequest (no fips_npub → skip
  FIPS branch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-04-19 01:36:04 -04:00
co-authored by Claude Opus 4.7
parent ba825c13a5
commit dbd19006f2
7 changed files with 112 additions and 137 deletions
+11 -9
View File
@@ -114,20 +114,20 @@ impl RpcHandler {
let fed_nodes = federation::load_nodes(&self.config.data_dir)
.await
.unwrap_or_default();
let recipient_pubkey = fed_nodes
.iter()
.find(|n| {
n.onion == onion
|| n.onion == format!("{}.onion", onion)
|| format!("{}.onion", n.onion) == onion
})
.map(|n| n.pubkey.clone());
let recipient = fed_nodes.iter().find(|n| {
n.onion == onion
|| n.onion == format!("{}.onion", onion)
|| format!("{}.onion", n.onion) == onion
});
let recipient_pubkey = recipient.map(|n| n.pubkey.clone());
let recipient_fips_npub = recipient.and_then(|n| n.fips_npub.clone());
// Include our node name so the recipient can display it
let node_name = data.server_info.name.clone();
node_message::send_to_peer(
onion,
recipient_fips_npub.as_deref(),
&pubkey,
message,
Some(node_id.signing_key()),
@@ -147,7 +147,9 @@ impl RpcHandler {
.get("onion")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing onion"))?;
let reachable = node_message::check_peer_reachable(onion)
let fips_npub =
crate::federation::fips_npub_for_onion(&self.config.data_dir, onion).await;
let reachable = node_message::check_peer_reachable(onion, fips_npub.as_deref())
.await
.unwrap_or(false);
Ok(serde_json::json!({ "onion": onion, "reachable": reachable }))