2b52a48efed18120a0c3de0edf34160862d2195e
The gossip `author` field was self-asserted, so an in-room member could forge it to impersonate (chat), force-evict (Leave), or poison presence + the address book (Announce). Now every GossipPayload is signed with the node's ed25519 secret key and verified on receipt; a forged author can't validate because the attacker lacks the victim's key. Done as the complete fix (forgery + replay): - GossipPayload gains `ts` (sender-stamped) + `sig` (iroh::Signature, serde-64B); Debug is hand-written since Signature has none. - Signature covers domain tag + room topic_id + author + ts + msg (`signable_bytes`): topic binding blocks cross-room replay, ts + a 2-min freshness window block temporal replay (within-window replays are byte- identical and de-duped by the swarm), author binding makes spoofing fail. - New pure seams `sign_gossip` / `verify_gossip` (+ `GossipReject`); all four outgoing broadcasts sign, the receive loop verifies-then-trusts (drops unauthenticated/stale before any peer-map / event / address-book action). - IrohGossipState now holds the node SecretKey + active topic bytes; callers (core, test_net) updated. NOTE: breaking gossip wire change — all peers must run this build (the staged friend release + dopedart need rebuild). Node identity is ephemeral, so no migration concern beyond rebuild. +5 unit tests (genuine accept; forged author, tampered msg, cross-room, stale/ future all rejected). 163 lib tests (was 158), clippy --all-targets clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>