Parent: #28
Surfaced while scoping #48's relay:use enforcement. relay-hub.ts's createRelayHub().handleConnection() owns a connection's entire frame stream wholesale via its own for-await loop, and its handleFrame explicitly drops manage-request/manage-response ("not the relay role's business"). Confirmed wire-mesh-node's server never runs a MeshSession alongside it -- a dedicated hub deployment never answers a manage-request at all today.
Enforcing relay:use (or anything else that needs to correlate a manage-request-layer grant with a transport-layer relay-connect/relay-data on the same connection) requires relay-hub.ts to become one frame handler among several dispatched by a shared consumption loop, rather than the sole owner of connection.receive(). This is the same class of problem room-client.ts's createRoomRouter already solves for room.send/room.join sharing a session's incomingManageRequests -- two independent for-await loops over one AsyncIterable would race for its items.
Scope: design and build the shared-consumption pattern for a connection that needs both relay-hub.ts's own gossip/relay-connect/relay-data handling and a MeshSession's manage-request handling at once (the "ordinary opted-in node relays for peers it's already talking to" case from the plan's own Section B reframing, not the dedicated wire-mesh-node/cloudflare-hub deployment, which can stay exactly as it is and remain open to anyone gossiped). Blocks the real enforcement half of #48.
Parent: #28
Surfaced while scoping #48's relay:use enforcement. relay-hub.ts's createRelayHub().handleConnection() owns a connection's entire frame stream wholesale via its own for-await loop, and its handleFrame explicitly drops manage-request/manage-response ("not the relay role's business"). Confirmed wire-mesh-node's server never runs a MeshSession alongside it -- a dedicated hub deployment never answers a manage-request at all today.
Enforcing relay:use (or anything else that needs to correlate a manage-request-layer grant with a transport-layer relay-connect/relay-data on the same connection) requires relay-hub.ts to become one frame handler among several dispatched by a shared consumption loop, rather than the sole owner of connection.receive(). This is the same class of problem room-client.ts's createRoomRouter already solves for room.send/room.join sharing a session's incomingManageRequests -- two independent for-await loops over one AsyncIterable would race for its items.
Scope: design and build the shared-consumption pattern for a connection that needs both relay-hub.ts's own gossip/relay-connect/relay-data handling and a MeshSession's manage-request handling at once (the "ordinary opted-in node relays for peers it's already talking to" case from the plan's own Section B reframing, not the dedicated wire-mesh-node/cloudflare-hub deployment, which can stay exactly as it is and remain open to anyone gossiped). Blocks the real enforcement half of #48.