Files
npub1cc3ha7z055mu0rwwu7806t2wt8mj3pvu0uv5mfp2c50dahaqhczshdalg6andTyler Longwell 748e65f46f feat(relay/audio): community rides RegisterPeer; structural-only Hello (OPTION 1)
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>
2026-07-08 14:17:44 -04:00
..