Channels

Channels are the core pub/sub primitive in Konet.

Topic Pattern

room:<identifier>

Examples:

  • room:lobby
  • room:project:42
  • room:user:123:inbox

Lifecycle

Join

const channel = client.channel('room:lobby')
await channel.subscribe()

The server replies with ok or error. On join, presence is automatically tracked.

Broadcast

channel.send('message', { text: 'Hello!' })

Server handler:

def handle_in("broadcast", %{"event" => event, "payload" => payload}, socket) do
  broadcast!(socket, event, payload)
  {:noreply, socket}
end

Listen

channel.on('message', (payload) => {
  console.log(payload)
})

Leave

channel.unsubscribe()

Authorization

Rooms are open by default: any client connecting with a valid token can join any room:* topic. This is fine for public channels.

To make a channel private, mint the client's token with a channels claim (see Authentication) listing the topics it may join. Entries may end in * for prefix matching — room:user-42:* covers every room under that namespace. Joining any other topic returns:

{ "status": "error", "response": { "reason": "unauthorized" } }

History Replay

With KONET_HISTORY_LIMIT=N set on the server, each room keeps its last N broadcasts in memory, and a client that joins late receives them in one push right after presence_state:

channel.on("konet:history", ({ messages }) => {
  // messages: [{ event, payload, timestamp }, ...] oldest first
})

This is a replay buffer, not storage — it survives an empty room (an agent can broadcast before anyone is listening) but not a server restart. It is off by default.

Binary Frames

A channel also carries binary frames, for anything at a media rate — audio, in practice. They come with floor control, which decides who is allowed to send. See Binary Frames & Floor Control.

Rate Limiting

Each socket may send up to KONET_RATE_LIMIT broadcasts per second (default 60), and each IP may open KONET_CONN_RATE_LIMIT connections per minute (default 200). Exceeding the message limit returns:

{ "status": "error", "response": { "reason": "rate_limited" } }

Binary frames have a separate budget — see Binary Frames & Floor Control.