mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Implements the ratified owner-side community-derivation contract for the cross-pod huddle join path (PLANS/MESH_GREENFIELD_DESIGN.md § "Owner-Side Community Derivation, FINAL 2026-07-08"). The mesh dispatcher callback is community-agnostic — Hello and the fenced header carry no community — yet the owner's Redis fence key is (community_id, session_id). Rather than a shared community-of-session registry, the community rides the wire on the first stateful frame and is self-verified by the fence. Hello is now structural-only: authenticated sender == from, HuddleControl Session role, owner_runtime_id == local. It admits nothing and touches no room, so it is deliberately NOT Redis-fenced (community unknown at Hello time). The prior accept-time validate() call is dropped. RegisterPeer carries community_id (as a raw Uuid — CommunityId is deliberately non-deserializable so it can never be minted from client input; this is a server-to-server mesh frame and the owner reconstitutes the CommunityId via from_uuid before fencing). The serve loop latches the community on first receipt and rejects any later frame naming a different one (tenant-boundary guard). Validate-before-admit: the Redis fence keyed by the asserted community must pass before room.add_peer. A wrong community keys a lease the owner never wrote → typed no_active_lease → nothing mutates. The per-frame `f != fenced` check stays (a lease that moves mid-stream rejects subsequent frames); a fence rejection now returns RegisterRejected(Fenced(..)) and keeps the stream alive, while a non-fence validate error (Redis unreachable, decode) still tears it down — classified via the existing FenceRejection::from_mesh_error. UnregisterPeer needs no fence (touches only this stream's registered map). accept_inbound / serve_control_loop drop their community_id parameter to match the dispatcher callback shape (from, hello, stream). dial_remote_owner gains a community_id param; the handler passes tenant.community(). Adds two handshake round-trip tests over the public MeshStream::new seam with an in-memory channel-backed stream pair: one asserting PeerRegistered on a valid fence, one asserting RegisterRejected(Fenced) on a fence failure with no peer admitted. fmt + clippy clean; 12 join tests pass. Scoped out (Perci's increment, Wren-gated): the renew loop + teardown on Lost/NotOwner. The huddle-side reaction (room teardown + floor.forget) is a future seam to be agreed in-thread before coding. Co-authored-by: Tyler Longwell <tlongwell@block.xyz> Signed-off-by: Tyler Longwell <tlongwell@block.xyz>