Lifecycle

One owner and one disposable handle for every active avenue

Constructing OpenRTC({ apiKey }) is local and side-effect free. Network work begins when a capability starts.

const room = await rtc.rooms.join('call-42');

try {
  // Use room.peers and room.channels.
} finally {
  await room.leave();
  await rtc.close();
}

One handle owns one active avenue, one socket, and its grant refresh. Same-scope identity refresh does not reopen the socket. Closing a handle cancels refresh, retires presence, and prevents callbacks from the old generation.

Do not add an app-layer heartbeat, reconnect timer, peer registry, or presence repair loop. The SDK, gateway socket, Durable Object, and Rust runtime each own a distinct transition boundary.