fix: federation peer-joined updates empty onion addresses

When a node was already known (via link-node) but had an empty onion
address, the peer-joined handler returned early without updating the
onion. Now it patches missing onion/pubkey fields on existing nodes.

Also adds update_node() to federation storage and updates the
architecture comparison doc with system resources, StartOS/umbrelOS
tabs, Web5 section, and comparison view.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-04-01 16:25:27 +01:00
parent 9968b2f915
commit f49138270a
4 changed files with 344 additions and 26 deletions

View File

@@ -364,7 +364,20 @@ impl RpcHandler {
}
let nodes = federation::load_nodes(&self.config.data_dir).await?;
if nodes.iter().any(|n| n.did == did) {
if let Some(existing) = nodes.iter().find(|n| n.did == did) {
// If already known but missing onion/pubkey, update them
if existing.onion.is_empty() || existing.pubkey.is_empty() {
let mut updated = existing.clone();
if existing.onion.is_empty() && !onion.is_empty() {
updated.onion = onion.to_string();
}
if existing.pubkey.is_empty() && !pubkey.is_empty() {
updated.pubkey = pubkey.to_string();
}
updated.last_seen = Some(chrono::Utc::now().to_rfc3339());
federation::update_node(&self.config.data_dir, &updated).await?;
info!(peer_did = %did, peer_onion = %onion, "Updated existing peer with missing onion/pubkey");
}
return Ok(serde_json::json!({ "accepted": true, "already_known": true }));
}

View File

@@ -12,7 +12,7 @@ mod types;
// Re-export all public items so `crate::federation::*` continues to work.
pub use invites::{accept_invite, create_invite};
pub use storage::{
add_node, load_nodes, remove_node, save_nodes, set_trust_level,
add_node, load_nodes, remove_node, save_nodes, set_trust_level, update_node,
};
pub use sync::{build_local_state, deploy_to_peer, sync_with_peer};
pub use types::{AppStatus, FederatedNode, NodeStateSnapshot, TrustLevel};

View File

@@ -96,6 +96,27 @@ pub async fn set_trust_level(
Ok(nodes)
}
/// Update a federated node's metadata (onion, pubkey, name, last_seen).
pub async fn update_node(data_dir: &Path, updated: &FederatedNode) -> Result<()> {
let mut nodes = load_nodes(data_dir).await?;
if let Some(node) = nodes.iter_mut().find(|n| n.did == updated.did) {
if !updated.onion.is_empty() {
node.onion = updated.onion.clone();
}
if !updated.pubkey.is_empty() {
node.pubkey = updated.pubkey.clone();
}
if updated.name.is_some() {
node.name = updated.name.clone();
}
if updated.last_seen.is_some() {
node.last_seen = updated.last_seen.clone();
}
save_nodes(data_dir, &nodes).await?;
}
Ok(())
}
pub async fn update_node_state(
data_dir: &Path,
did: &str,