feat(federation): advertise own_fips_npub in state snapshots

Pre-v1.4 federation pairs (who exchanged invites before fips_npub
was part of the invite code) had no path to learn each other's FIPS
npub — they'd stay Tor-only forever even after upgrading. Fix:
every state snapshot now carries the sender's own_fips_npub, and
update_node_state refreshes the stored fips_npub on the receiver
side whenever it differs.

- NodeStateSnapshot.own_fips_npub (serde default for back-compat).
- build_local_state takes own_fips_npub alongside the other
  single-value fields.
- handle_federation_get_state populates own_fips_npub from
  identity::fips_npub, with a fallback to the upstream daemon's
  /etc/fips/fips.pub for legacy nodes that never materialised a
  seed-derived key.
- storage::update_node_state now writes fips_npub into the
  FederatedNode when a new value arrives and trims whitespace
  before comparing, so key rotations also flow through.
- Test fixtures (storage + transport/delta + sync) updated for the
  new field; existing tests pass.

Net effect: on the next sync, .116 and .228 learn each other's
fips_npub (currently null from the old invite) and subsequent
federation calls route FIPS-first automatically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-04-19 04:16:05 -04:00
co-authored by Claude Opus 4.7
parent ab85c2e361
commit 6399b6881e
5 changed files with 43 additions and 1 deletions
+4 -1
View File
@@ -160,6 +160,7 @@ pub fn build_local_state(
tor_active: bool,
server_name: Option<String>,
nostr_npub: Option<String>,
own_fips_npub: Option<String>,
federated_peers: &[FederatedNode],
) -> NodeStateSnapshot {
let hints = federated_peers
@@ -186,6 +187,7 @@ pub fn build_local_state(
uptime_secs: Some(uptime),
tor_active: Some(tor_active),
nostr_npub,
own_fips_npub,
federated_peers: hints,
}
}
@@ -274,6 +276,7 @@ mod tests {
true,
Some("Test Node".to_string()),
None,
None,
&[],
);
assert_eq!(state.apps.len(), 1);
@@ -328,7 +331,7 @@ mod tests {
];
let state = build_local_state(
vec![],
0.0, 0, 0, 0, 0, 0, true, None, None, &peers,
0.0, 0, 0, 0, 0, 0, true, None, None, None, &peers,
);
assert_eq!(state.federated_peers.len(), 1);
assert_eq!(state.federated_peers[0].did, "did:key:zTrusted");