--- status: draft last_updated: 2026-05-07 --- # Iroh Hub Event Target **Import**: `@alkdev/pubsub/event-target-iroh-hub` **Peer dep**: `@rayhanadev/iroh` (optional, NAPI-RS native addon) **Status**: Not yet implemented. Needs R&D on binding stability, NAPI under Deno. P2P QUIC event target for the hub (server) side. The hub accepts incoming connections and bidirectional streams. Manages multiple connected spokes. ## `createIrohHubEventTarget` ```ts async function createIrohHubEventTarget( args: CreateIrohHubEventTargetArgs, ): Promise>; ``` ### `CreateIrohHubEventTargetArgs` | Field | Type | Required | Description | |-------|------|----------|-------------| | `endpoint` | `Endpoint` | Yes | iroh endpoint (created with `Endpoint.create()`) | | `alpn` | `string` | No | Application-layer protocol. Default: `"alkpubsub/1"` | ## How It Works Similar to the WebSocket server adapter, the Iroh hub adapter manages multiple connections: - `dispatchEvent` → writes JSON envelope to all connected spokes' `SendStream`s - `addEventListener` → registers local listeners for events from any spoke - On incoming connection → `endpoint.accept()` → `connection.acceptBi()` → new spoke tracked Each spoke gets its own read loop that parses length-prefixed JSON messages from `RecvStream` and dispatches locally. ## Connection Lifecycle 1. Hub creates `Endpoint` and starts accepting 2. Spoke connects → hub gets `Connection` from `endpoint.accept()` 3. Hub accepts stream → `connection.acceptBi()` → `SendStream` + `RecvStream` 4. Hub creates per-spoke read loop 5. On disconnect → `RecvStream.readExact()` throws → remove spoke from set 6. Hub continues accepting new connections ## Fan-Out ```ts dispatchEvent(event) { const message = encodeEnvelope(event.detail); for (const spoke of this.spokes) { spoke.sendStream.writeAll(message); } return true; } ``` ## Key Properties - **Multi-connection** — manages a set of connected spokes - **Fan-out** — dispatchEvent sends to all connected spokes - **Accepts incoming** — endpoint.accept() loop runs continuously - **Cryptographic identity** — each spoke verified by Ed25519 NodeId ## R&D Needed 1. **Binding stability** — same as spoke adapter. `@rayhanadev/iroh` needs testing. 2. **Concurrent accept** — can `endpoint.accept()` handle multiple simultaneous connections? 3. **Stream vs. Connection per spoke** — current design: one bidirectional stream per spoke on a single connection. Alternative: one connection per spoke. Need to benchmark which is better for the expected workload. 4. **1:N fan-out** — for hub to N spokes, each spoke gets its own stream. For true broadcast, `iroh-gossip` would be better (not yet available in TS). 5. **Connection rejection** — how to reject connections from unknown `NodeId`s. See [../iroh-transport.md](../iroh-transport.md) for full protocol details, identity, and comparison with WebSocket.