Add src_addr to SessionDatagram envelope (34-byte header: msg_type +
src_addr + dest_addr + hop_limit) so transit routers can route error
signals back to the packet's originator.
Reclassify CoordsRequired/PathBroken as link-layer error signals
(plaintext inside SessionDatagram) rather than e2e encrypted session
messages. Transit routers generate these when forwarding fails and
route them to src_addr; if source is also unreachable, drop silently.
Remove redundant src_addr/dest_addr/hop_limit from SessionSetup,
SessionAck, and DataPacket (now in envelope). DataPacket header
reduced from 36 to 4 bytes. Remove PathBroken.original_src.
Fix routing loop vulnerability: gate bloom filter path on having
cached dest_coords to prevent blind forwarding between peers.
Simplify select_best_candidate() to require coordinates.
Fix gossip protocol type codes (0x11->0x20, 0x12->0x30, 0x13->0x31)
for consistency across all design docs.
All 5 design docs updated and cross-checked for consistency.
335 tests pass, zero warnings.
Noise IK parity fix:
- Pre-message hash normalizes responder static key to even parity (0x02)
so initiator and responder hash chains match regardless of actual parity
- ECDH uses shared_secret_point() + SHA-256(x-only) instead of
SharedSecret::new() which includes a parity-dependent version byte
- Fixes handshake failure for ~50% of keys when initiator has only npub
Graceful disconnect protocol (link message 0x50):
- DisconnectReason enum with 8 reason codes
- Disconnect struct with encode/decode
- send_encrypted_link_message() reusable helper
- handle_disconnect() with immediate peer removal
- send_disconnect_to_all_peers() called during Node::stop()
Cross-connection fix in handle_msg1():
- addr_to_link check now distinguishes inbound duplicates (reject) from
outbound links (cross-connection, allow and resolve via tie-breaker)
- remove_link() only clears addr_to_link if entry maps to same link_id
- Link cleanup and addr_to_link restoration in cross-connection branches
Handshake timeout cleanup:
- RX loop uses tokio::select! with 1-second interval tick
- check_timeouts() scans for stale (>30s) and failed connections
- cleanup_stale_connection() removes all associated state
Tests: 279 passing (4 new: cross-connection, stale cleanup, failed
cleanup, odd-parity handshake)
Rename NodeId to NodeAddr and npub to pubkey throughout documentation
and source code for consistency with the established identity model.
Add FIPS API vs IPv6 adapter overview to session protocol document.
Add transport address terminology note to wire protocol document.
Add comprehensive wire format diagrams with byte offsets, field sizes,
and concrete examples to three protocol documents:
fips-wire-protocol.md (Appendix A):
- Encrypted frame (0x00) with plaintext structure breakdown
- Noise IK msg1/msg2 with payload breakdown
- Complete handshake flow diagram
fips-gossip-protocol.md (Appendix A):
- TreeAnnounce with ancestry entry structure and size table
- FilterAnnounce with bloom filter layout
- LookupRequest/LookupResponse with examples
- Message flow showing packet nesting
fips-session-protocol.md (§8):
- SessionSetup, SessionAck, DataPacket, CoordsRequired, PathBroken
- Full nested packet example showing link + session layers
fips-routing.md:
- Refactored Part 4 to "Route Cache Management"
- Moved wire format content to fips-session-protocol.md