FR-3: Federation Activation

1. Overview

Phases 14–19 delivered every federation building block: OR-Set/LWW CRDTs, a PBFT state machine, web-of-trust membership crypto, BLAKE3-verified content replication, a mutual Ed25519/X25519 + ChaCha20-Poly1305 handshake, and a full set of inbound frame handlers. There are no stubs in that path.

What does not exist is the activation layer — the runtime wiring that makes those components actually operate across multiple machines. Today the server is a passive federation node: it accepts /federation sockets and reacts to frames, but it never dials out, never bootstraps itself, never registers peer keys, never runs a sync loop, and never broadcasts PBFT messages. Two servers started with --peer pointing at each other produce zero connections, zero replication, zero membership — and would reject each other even if connected.

FR-3 closes that gap: turn the finished components into a running federation of machines, including a trust model for donated hosts (machines contributed by different users).

2. Goals / Non-goals

Goals - A working federation of N machines: each can connect to peers, be recognised, replicate content (BLAKE3-verified), converge membership, and reach PBFT decisions. - A trust model so a donated host can prove its identity and be endorsed into the federation without central infrastructure. - Minimal operational footprint (each donor runs one xudanu-server).

Non-goals (for v1) - NAT traversal / hole-punching (peers must be directly reachable, or via a relay/VPN the donor provides). - Gossip/DNS-based peer discovery (static seed list for v1). - PBFT view-change / checkpointing / log GC (happy-path consensus only). - Cross-federation royalties/micropayments settlement.

3. Current state (from audit) — what's already there

Implemented and real (do not re-implement): - CRDTs: OrSet, LwwRegister, ReconcileStore (federation.rs). - PBFT core: propose/receive_prepare/receive_commit, 2f+1 quorum, seal_round, governance_execute_tx (federation.rs:1578–1794; wrappers server.rs:11712–11896). - Membership crypto: membership_bootstrap_init, membership_process_join (verifies each EndorsementProof Ed25519 sig), membership_endorse, OR-Set merge (server.rs:11457–11706). - BLAKE3 replication: federation_import_works/editions/blobs dedups by recomputed fingerprint; tampered blobs rejected (server.rs:10867–11071, blob check 11051–11058). - Mutual handshake + AEAD framing, inbound (federation_handler.rs:178–426). - Every inbound frame handler (federation_handler.rs:428–835).

The gaps (this FR): - --peer is parsed (xudanu-server.rs:446–452) but never dialed. - membership_bootstrap_init() is never called at startup (test-only). - federation_register_peer_key (server.rs:10794) is never called outside testsis_peer_known (federation.rs:253–264) rejects everyone when federation is enabled (self-DoS trap). - No periodic sync/heartbeat sender (handlers exist, nothing triggers them). - PBFT proposals die on the proposer; Prepare/Commit votes only flow inbound.

4. Functional requirements

FR-3.1 Outbound dialer / connection manager

FR-3.2 Startup bootstrap

FR-3.3 Peer-key registration path (fix the reject-all trap)

FR-3.4 Periodic sync / heartbeat loop

FR-3.5 PBFT broadcast (consensus that actually runs)

FR-3.6 Donated-host join (trust model)

5. Donated-host trust model

A donated machine is one a user contributes to run a peer node. It must prove its identity and be vouched for before it can participate.

6. Implementation details (backend)

7. Security considerations

8. Operational concerns (donated machines / cost)

9. Acceptance criteria

  1. Two servers started with mutual --peer + cross-registered keys connect and hold an encrypted channel (real handshake, not fake keys).
  2. A content edit on machine A replicates to machine B (BLAKE3-verified) within one sync interval.
  3. Membership converges: a node endorsed on A appears in B's membership via MembershipSyncPush.
  4. A donated host with a registered key + endorsement joins via MembershipJoinRequest and appears cluster-wide.
  5. A PBFT GovernancePropose reaches quorum across nodes and seals (happy path).
  6. is_peer_known no longer rejects everyone when federation is enabled.
  7. A real two-server integration test replaces the fake-key handshake test (integration.rs:4944).

10. Out of scope / future

11. Sequencing recommendation

Build in this order (each unblocks the next): 1. FR-3.3 peer-key registration + FR-3.2 bootstrap (smallest, fixes the reject-all trap so anything can connect at all). 2. FR-3.1 outbound dialer (the hard blocker — without it nothing is active). 3. FR-3.4 sync/heartbeat loop (turns connection into convergence). 4. FR-3.6 donated-host join (the trust/UX path for donors). 5. FR-3.5 PBFT broadcast (cluster-wide decisions). 6. Real two-server integration test (§9.7) — proves 1–5 end-to-end.