fix(federation): thread invite trust level end-to-end — 'Invite a Peer' now federates as Observer

Invites carried no trust level, and both accept_invite and the
peer-joined handler hardcoded TrustLevel::Trusted — so 'Invite a Peer'
(Observer) federated both sides as fully Trusted.

- invite codes now carry a 'trust' field (legacy codes parse as Trusted)
- federation.invite accepts trust_level: trusted|observer
- accept_invite assigns the invite's level on the acceptor side
- peer-joined resolves the granted level authoritatively by matching the
  acceptor's echoed invite token against our stored outgoing invites;
  the peer's own unsigned claim is honored only as a downgrade, so no
  escalation is possible
- discovery/connection-request approvals mint Observer invites directly
  (the post-hoc demotion in handshake.rs stays as a legacy safety net)
- asymmetry self-heal re-asserts at the locally-held level

Tests: observer threading + legacy default-trusted parse.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-14 06:24:38 -04:00
co-authored by Claude Fable 5
parent 919665fb16
commit 950549304d
7 changed files with 282 additions and 13 deletions
+4
View File
@@ -515,6 +515,10 @@ impl Server {
&local_pubkey,
local_fips_npub.as_deref(),
local_name.as_deref(),
// Re-assert at the level WE hold for
// this peer; no invite token on heal.
None,
node.trust_level,
|b| node_identity.sign(b),
)
.await