{"version":3,"sources":["../../src/protocol.ts","../../src/server/admin-snapshot.ts","../../src/server/config.ts","../../src/server/coordinator.ts","../../src/server/server.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Shared wire protocol for `@reactor-team/queue`.\n *\n * Both the PartyKit server (`@reactor-team/queue/server`) and the browser\n * client (`@reactor-team/queue`) import these types so the messages they\n * exchange over the WebSocket stay in lockstep. Nothing here depends on\n * PartyKit, the Reactor SDK, React, or the DOM — it is plain data.\n */\n\n/** Current protocol version. Bumped only on breaking wire changes. */\nexport const PROTOCOL_VERSION = 2 as const;\n\n/** Default PartyKit room id. A single room is the source of truth for one queue. */\nexport const DEFAULT_ROOM = \"reactor-queue\";\n\n/** Query-string key used to carry the stable per-browser id on connect. */\nexport const CLIENT_ID_QUERY_KEY = \"rqClientId\";\n\n/** Set to `1` on the WebSocket URL to open an admin connection (not queued). */\nexport const ADMIN_MODE_QUERY_KEY = \"rqAdmin\";\n\n/**\n * Default tunables. Every one of these is overridable from server config and/or\n * environment variables (see `@reactor-team/queue/server`).\n */\nexport const DEFAULTS = {\n  /** Max concurrent Reactor sessions (GPU ceiling). */\n  maxSessions: 1,\n  /** Members per session (default 1 = today's behavior; >1 when platform allows N). */\n  usersPerSession: 1,\n  /** Full session budget once a user has `claim()`ed their slot. */\n  sessionDurationMs: 120_000,\n  /**\n   * Grace window an admitted user gets to actually start (claim) their session\n   * before the slot is reclaimed. Prevents an idle admit from wasting a slot.\n   */\n  admissionGraceMs: 45_000,\n  /** How long before expiry to emit a `time_warning`. */\n  warningBeforeMs: 30_000,\n  /** Lifetime requested for each minted Reactor JWT. Deliberately short. */\n  tokenTtlSeconds: 60,\n  /**\n   * How often the server re-checks tracked live sessions against the Reactor\n   * API to catch sessions that ended without a clean `session_ended`/close.\n   */\n  pollIntervalMs: 15_000,\n  /** Client-side skew: refresh the JWT this long before it actually expires. */\n  tokenSkewMs: 10_000,\n} as const;\n\n/** Reactor session states that mean \"the slot is free again\". */\nexport const TERMINAL_SESSION_STATES = [\"CLOSED\", \"INACTIVE\"] as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Server → Client messages\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** You are waiting in line. `position` is 1-based. */\nexport interface QueuePositionMessage {\n  type: \"queue_position\";\n  position: number;\n  total: number;\n  active: number;\n  capacity: number;\n}\n\n/**\n * You reached the front and a capacity slot is reserved for you. No Reactor\n * session exists yet — the server creates it only when you `claim()`, so an\n * abandoned grace never leaves an orphaned GPU session. You have until the\n * admission grace expires to `claim()`.\n */\nexport interface AdmittedMessage {\n  type: \"admitted\";\n  active: number;\n  /** Total live users = maxSessions * usersPerSession. */\n  capacity: number;\n  /** ms the client has to `claim()` before the slot is reclaimed. */\n  graceMs: number;\n  /** Full session budget (ms) the client receives once it `claim()`s. For countdown UI. */\n  sessionDurationMs: number;\n}\n\n/**\n * Sent after `claim()`: the server has created (or reused) the Reactor session\n * and minted a WebRTC connection under it for this member. Attach with\n * `connect({ sessionId, connectionId })` — the server owns both, so the client\n * never creates or stops anything.\n */\nexport interface SessionReadyMessage {\n  type: \"session_ready\";\n  /** Reactor session id created by the server — pass to connect({ sessionId }). */\n  sessionId: string;\n  /**\n   * Server-minted WebRTC connection id for this member — pass to\n   * connect({ connectionId }). The server registered it under `sessionId`, so\n   * the client adopts it instead of registering its own.\n   */\n  connectionId: number;\n  /** Full session budget (ms). */\n  sessionDurationMs: number;\n  /** Unix epoch ms when the session ends. */\n  expiresAt: number;\n}\n\n/** A freshly minted, short-lived Reactor JWT. Sent on admission and on each `request_token`. */\nexport interface TokenMessage {\n  type: \"token\";\n  jwt: string;\n  /** Unix epoch seconds at which the JWT expires. */\n  expiresAt: number;\n}\n\n/** Your session is about to end. */\nexport interface TimeWarningMessage {\n  type: \"time_warning\";\n  secondsLeft: number;\n  /** Unix epoch ms when the session ends. */\n  expiresAt: number;\n}\n\n/** Your session ended (time ran out, or the server reclaimed the slot). */\nexport interface ExpiredMessage {\n  type: \"expired\";\n  reason: \"timeout\" | \"grace_timeout\" | \"server\";\n}\n\n/** You were refused entry. */\nexport interface RejectedMessage {\n  type: \"rejected\";\n  reason: \"already_connected\" | \"server_error\" | \"forbidden_origin\" | string;\n}\n\n/** A non-fatal error (e.g. token mint failed); the client may retry. */\nexport interface ErrorMessage {\n  type: \"error\";\n  message: string;\n}\n\nexport type ServerMessage =\n  | QueuePositionMessage\n  | AdmittedMessage\n  | SessionReadyMessage\n  | TokenMessage\n  | TimeWarningMessage\n  | ExpiredMessage\n  | RejectedMessage\n  | ErrorMessage;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Client → Server messages\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** \"I'm actually entering the demo\" — upgrades the grace window to the full session. */\nexport interface ClaimMessage {\n  type: \"claim\";\n}\n\n/** Ask for a fresh JWT. The server only answers if you currently hold a slot. */\nexport interface RequestTokenMessage {\n  type: \"request_token\";\n}\n\n/** The user ended the Reactor session from the client; free the slot now. */\nexport interface SessionEndedMessage {\n  type: \"session_ended\";\n}\n\n/** Leave the queue / release the slot without intending to rejoin. */\nexport interface LeaveMessage {\n  type: \"leave\";\n}\n\nexport type ClientMessage = ClaimMessage | RequestTokenMessage | SessionEndedMessage | LeaveMessage;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Admin mode (server → admin client)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Read-only server tunables included in every admin snapshot. */\nexport interface AdminConfigSnapshot {\n  maxSessions: number;\n  usersPerSession: number;\n  capacity: number;\n  model: string;\n  webrtcVersion: string;\n  sessionDurationMs: number;\n  admissionGraceMs: number;\n  warningBeforeMs: number;\n  tokenTtlSeconds: number;\n  pollIntervalMs: number;\n  coordinatorUrl: string;\n  apiVersion: number;\n  stopSessionsOnExpiry: boolean;\n  allowDuplicateConnections: boolean;\n  /** \"default\" = queue creates/stops sessions; \"custom\" = acquire/release overridden. */\n  sessionSource: \"default\" | \"custom\";\n}\n\n/** One person waiting in the FIFO queue. */\nexport interface AdminQueuedUserSnapshot {\n  connId: string;\n  /** 1-based position in line. */\n  position: number;\n  clientId: string | null;\n}\n\n/** One admitted member (may or may not have claimed yet). */\nexport interface AdminMemberSnapshot {\n  connId: string;\n  /** Reactor session id once claimed; null while still in grace (no session yet). */\n  sessionId: string | null;\n  /** Server-minted WebRTC connection id once claimed; null while still in grace. */\n  connectionId: number | null;\n  clientId: string | null;\n  claimed: boolean;\n  expiresAt: number;\n  msLeft: number;\n}\n\n/** One capacity slot and its member connection ids. */\nexport interface AdminSessionSnapshot {\n  /** Reactor session id, or null while the slot is reserved but unclaimed (no GPU session yet). */\n  sessionId: string | null;\n  members: string[];\n  createdAt: number;\n  msSinceCreated: number;\n}\n\n/** Full room state pushed to authenticated admin connections. */\nexport interface AdminSnapshotMessage {\n  type: \"admin_snapshot\";\n  at: number;\n  activeCount: number;\n  sessionCount: number;\n  config: AdminConfigSnapshot;\n  queue: AdminQueuedUserSnapshot[];\n  sessions: AdminSessionSnapshot[];\n  members: AdminMemberSnapshot[];\n}\n\n/** Admin WebSocket authenticated; snapshots follow on changes. */\nexport interface AdminReadyMessage {\n  type: \"admin_ready\";\n}\n\nexport interface AdminRejectedMessage {\n  type: \"admin_rejected\";\n  reason: \"admin_disabled\" | \"invalid_password\" | \"auth_required\" | \"forbidden_origin\";\n}\n\nexport interface AdminActionResultMessage {\n  type: \"admin_action_result\";\n  action: \"kick_member\" | \"kick_queued\" | \"close_session\";\n  ok: boolean;\n  message?: string;\n}\n\n/** Severity of an {@link AdminLogEntry}. Mirrors `console.log`/`warn`/`error`. */\nexport type AdminLogLevel = \"info\" | \"warn\" | \"error\";\n\n/**\n * One structured server event. The queue server emits these for every notable\n * thing that happens in a room — a user joining, an admission, a session being\n * created or closed, and crucially the **reason an API call failed** (e.g. a\n * Coordinator quota rejection, with its HTTP status and body in `data`). They\n * are streamed live to admins and kept in a bounded server-side ring buffer so\n * a freshly-connected admin sees recent history.\n */\nexport interface AdminLogEntry {\n  /** Stable unique id (also usable as a React key). */\n  id: string;\n  /** Unix epoch ms when the event happened. */\n  at: number;\n  level: AdminLogLevel;\n  /** Machine-readable event code, e.g. `\"user_admitted\"`, `\"session_create_failed\"`. */\n  event: string;\n  /** Human-readable, already-formatted summary line. */\n  message: string;\n  /** The connection this event concerns, when applicable. */\n  connId?: string;\n  /** The Reactor session this event concerns, when applicable. */\n  sessionId?: string;\n  /** Extra structured context (HTTP status, response body, reason, …). */\n  data?: Record<string, unknown>;\n}\n\n/** A single new log line, pushed live to authenticated admins as it happens. */\nexport interface AdminLogMessage {\n  type: \"admin_log\";\n  entry: AdminLogEntry;\n}\n\n/** Recent log history (oldest → newest), sent once right after admin auth. */\nexport interface AdminLogHistoryMessage {\n  type: \"admin_log_history\";\n  entries: AdminLogEntry[];\n}\n\nexport type AdminServerMessage =\n  | AdminReadyMessage\n  | AdminRejectedMessage\n  | AdminSnapshotMessage\n  | AdminActionResultMessage\n  | AdminLogMessage\n  | AdminLogHistoryMessage;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Admin mode (admin client → server)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** First message on an admin connection; password must match `RQ_ADMIN_PASSWORD`. */\nexport interface AdminAuthMessage {\n  type: \"admin_auth\";\n  password: string;\n}\n\n/** Remove a member from their session and free capacity (same as forced expiry). */\nexport interface AdminKickMemberMessage {\n  type: \"admin_kick_member\";\n  connId: string;\n}\n\n/** Drop a still-waiting connection from the queue and close its socket. */\nexport interface AdminKickQueuedMessage {\n  type: \"admin_kick_queued\";\n  connId: string;\n}\n\n/** Stop the Reactor session and evict all members. */\nexport interface AdminCloseSessionMessage {\n  type: \"admin_close_session\";\n  sessionId: string;\n}\n\n/** Request a fresh snapshot (also sent automatically on room changes). */\nexport interface AdminRefreshMessage {\n  type: \"admin_refresh\";\n}\n\nexport type AdminClientMessage =\n  | AdminAuthMessage\n  | AdminKickMemberMessage\n  | AdminKickQueuedMessage\n  | AdminCloseSessionMessage\n  | AdminRefreshMessage;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Narrowing parse for an inbound server message. Returns null on garbage. */\nexport function parseServerMessage(raw: string): ServerMessage | null {\n  try {\n    const msg = JSON.parse(raw) as ServerMessage;\n    return typeof msg?.type === \"string\" ? msg : null;\n  } catch {\n    return null;\n  }\n}\n\n/** Narrowing parse for an inbound client message. Returns null on garbage. */\nexport function parseClientMessage(raw: string): ClientMessage | null {\n  try {\n    const msg = JSON.parse(raw) as ClientMessage;\n    if (typeof msg?.type !== \"string\") return null;\n    if (msg.type.startsWith(\"admin_\")) return null;\n    return msg;\n  } catch {\n    return null;\n  }\n}\n\n/** Parse an admin client message. Returns null on garbage or non-admin types. */\nexport function parseAdminClientMessage(raw: string): AdminClientMessage | null {\n  try {\n    const msg = JSON.parse(raw) as AdminClientMessage;\n    if (typeof msg?.type !== \"string\" || !msg.type.startsWith(\"admin_\")) return null;\n    return msg;\n  } catch {\n    return null;\n  }\n}\n\n/** Parse a server message sent to an admin connection. */\nexport function parseAdminServerMessage(raw: string): AdminServerMessage | null {\n  try {\n    const msg = JSON.parse(raw) as AdminServerMessage;\n    if (typeof msg?.type !== \"string\" || !msg.type.startsWith(\"admin_\")) return null;\n    return msg;\n  } catch {\n    return null;\n  }\n}\n","import type {\n  AdminConfigSnapshot,\n  AdminMemberSnapshot,\n  AdminQueuedUserSnapshot,\n  AdminSessionSnapshot,\n  AdminSnapshotMessage,\n} from \"../protocol\";\nimport type { ResolvedConfig } from \"./config\";\n\ninterface MemberData {\n  sessionId: string | null;\n  connectionId: number | null;\n  expiresAt: number;\n  claimed: boolean;\n}\n\ninterface SlotRecord {\n  slotId: string;\n  sessionId: string | null;\n  members: string[];\n  createdAt: number;\n}\n\nexport function configSnapshot(c: ResolvedConfig): AdminConfigSnapshot {\n  return {\n    maxSessions: c.maxSessions,\n    usersPerSession: c.usersPerSession,\n    capacity: c.capacity,\n    model: c.model,\n    webrtcVersion: c.webrtcVersion,\n    sessionDurationMs: c.sessionDurationMs,\n    admissionGraceMs: c.admissionGraceMs,\n    warningBeforeMs: c.warningBeforeMs,\n    tokenTtlSeconds: c.tokenTtlSeconds,\n    pollIntervalMs: c.pollIntervalMs,\n    coordinatorUrl: c.coordinatorUrl,\n    apiVersion: c.apiVersion,\n    stopSessionsOnExpiry: c.stopSessionsOnExpiry,\n    allowDuplicateConnections: c.allowDuplicateConnections,\n    sessionSource: c.acquireSession || c.releaseSession ? \"custom\" : \"default\",\n  };\n}\n\nexport function buildAdminSnapshot(opts: {\n  config: ResolvedConfig;\n  queue: string[];\n  slots: Map<string, SlotRecord>;\n  members: Map<string, MemberData>;\n  resolveClientId: (connId: string) => Promise<string | null>;\n}): Promise<AdminSnapshotMessage> {\n  const now = Date.now();\n  return (async () => {\n    const queue: AdminQueuedUserSnapshot[] = [];\n    for (let i = 0; i < opts.queue.length; i++) {\n      const connId = opts.queue[i]!;\n      queue.push({\n        connId,\n        position: i + 1,\n        clientId: await opts.resolveClientId(connId),\n      });\n    }\n\n    const sessions: AdminSessionSnapshot[] = [];\n    let createdSessions = 0;\n    for (const [, slot] of opts.slots) {\n      if (slot.sessionId) createdSessions++;\n      sessions.push({\n        sessionId: slot.sessionId,\n        members: [...slot.members],\n        createdAt: slot.createdAt,\n        msSinceCreated: now - slot.createdAt,\n      });\n    }\n    sessions.sort((a, b) => a.createdAt - b.createdAt);\n\n    const members: AdminMemberSnapshot[] = [];\n    for (const [key, data] of opts.members) {\n      const connId = key.replace(\"member:\", \"\");\n      members.push({\n        connId,\n        sessionId: data.sessionId,\n        connectionId: data.connectionId,\n        clientId: await opts.resolveClientId(connId),\n        claimed: data.claimed,\n        expiresAt: data.expiresAt,\n        msLeft: Math.max(0, data.expiresAt - now),\n      });\n    }\n    members.sort((a, b) => a.expiresAt - b.expiresAt);\n\n    return {\n      type: \"admin_snapshot\",\n      at: now,\n      activeCount: opts.members.size,\n      sessionCount: createdSessions,\n      config: configSnapshot(opts.config),\n      queue,\n      sessions,\n      members,\n    };\n  })();\n}\n","import { DEFAULTS, DEFAULT_ROOM } from \"../protocol\";\n\n/** Passed to a custom {@link ReactorQueueServerConfig.acquireSession}. */\nexport interface AcquireSessionContext {\n  /** The configured model name. */\n  model: string;\n}\n\n/** Passed to a custom {@link ReactorQueueServerConfig.releaseSession}. */\nexport interface ReleaseSessionContext {\n  /** The Reactor session the user was in. */\n  sessionId: string;\n  /** The connection id of the user who left. */\n  userId: string;\n  /** Why they left: `timeout`, `grace_timeout`, or `server`. */\n  reason: string;\n  /** True if they were the last member — the session is now empty. */\n  lastMember: boolean;\n}\n\nexport type AcquireSessionFn = (ctx: AcquireSessionContext) => Promise<string>;\nexport type ReleaseSessionFn = (ctx: ReleaseSessionContext) => Promise<void>;\n\n/**\n * Operator-facing configuration for the queue server.\n *\n * Every field is optional. Resolution order (last wins): built-in default →\n * value passed to {@link createReactorQueueServer} → environment variable\n * (PartyKit `room.env`). Putting env last lets you bake sensible defaults into\n * code and still tune a deployment without a redeploy.\n */\nexport interface ReactorQueueServerConfig {\n  /** Max concurrent Reactor sessions (GPU ceiling). Env: `RQ_MAX_SESSIONS`. */\n  maxSessions?: number;\n  /** Members per session. Env: `RQ_USERS_PER_SESSION`. */\n  usersPerSession?: number;\n  /** Model name for `POST /sessions`. Env: `RQ_MODEL`. Required. */\n  model?: string;\n  /** WebRTC transport version for session create. Env: `RQ_WEBRTC_VERSION`. */\n  webrtcVersion?: string;\n  /** Full session budget after claim, in ms. Env: `RQ_SESSION_DURATION_MS`. */\n  sessionDurationMs?: number;\n  /** Grace window to claim an admitted slot, in ms. Env: `RQ_ADMISSION_GRACE_MS`. */\n  admissionGraceMs?: number;\n  /** Lead time for the `time_warning`, in ms. Env: `RQ_WARNING_BEFORE_MS`. */\n  warningBeforeMs?: number;\n  /**\n   * Requested lifetime for each minted Reactor JWT, in seconds. Keep it short:\n   * the client refreshes over `request_token` as needed. Env:\n   * `RQ_TOKEN_TTL_SECONDS`.\n   */\n  tokenTtlSeconds?: number;\n  /** How often to reconcile tracked sessions with Reactor, in ms. Env: `RQ_POLL_INTERVAL_MS`. */\n  pollIntervalMs?: number;\n\n  /** Reactor Coordinator base URL. Env: `RQ_COORDINATOR_URL`. Default `https://api.reactor.inc`. */\n  coordinatorUrl?: string;\n  /**\n   * Reactor API key (`rk_...`). **Server-side secret** — set it via a PartyKit\n   * secret (`RQ_REACTOR_API_KEY`), never bake it into code that ships to\n   * clients. Required for the server to mint JWTs and reap sessions.\n   */\n  apiKey?: string;\n  /** `Reactor-API-Version` header value. Env: `RQ_API_VERSION`. Default `1`. */\n  apiVersion?: number;\n\n  /**\n   * When true (default), the server calls `DELETE /sessions/{id}` the moment a\n   * user's time runs out or they vanish, instead of waiting for Reactor's own\n   * idle timeout. Env: `RQ_STOP_SESSIONS=false` to disable.\n   */\n  stopSessionsOnExpiry?: boolean;\n\n  /**\n   * Password for admin dashboard connections (`rqAdmin=1` on the WebSocket URL).\n   * Env: `RQ_ADMIN_PASSWORD`. When unset, admin mode is disabled.\n   */\n  adminPassword?: string;\n\n  /**\n   * Allow the same browser (stable `clientId`) to hold multiple simultaneous\n   * connections. Default false: a second tab is rejected with `already_connected`.\n   * Env: `RQ_ALLOW_DUPLICATE_CONNECTIONS=true`.\n   */\n  allowDuplicateConnections?: boolean;\n\n  /**\n   * Cross-origin allow-list for incoming WebSocket connections. Each entry is an\n   * exact `Origin` header value (scheme + host + optional port, no path), e.g.\n   * `\"https://demo.example.com\"`. A single `\"*\"` entry allows any origin.\n   *\n   * When empty/unset (the default) **all** origins are accepted — same as before\n   * this option existed — so it is purely opt-in. Once set, a browser whose\n   * `Origin` is not on the list (and any connection with no `Origin` header) is\n   * rejected before it joins the queue. This is the cross-site abuse control:\n   * without it, any page on the web can open a socket to your room and consume\n   * GPU capacity. Env: `RQ_ALLOWED_ORIGINS` (comma-separated).\n   */\n  allowedOrigins?: string[];\n\n  /**\n   * Override how a session id is obtained when an admitted user `claim()`s.\n   * Default: create one via the Reactor API (`POST /sessions`). Override to\n   * source sessions from elsewhere — e.g. lease a pre-provisioned session from\n   * another service that already has a different kind of client attached.\n   * Called once per session (the first member's claim). Not configurable via\n   * env — pass a function.\n   */\n  acquireSession?: AcquireSessionFn;\n\n  /**\n   * Called when a user **leaves** a session (timeout, disconnect, end, or kick),\n   * with their `userId` and whether they were the `lastMember`. Default: when\n   * the last member leaves, delete the session via the Reactor API\n   * (`DELETE /sessions/{id}`, subject to `stopSessionsOnExpiry`). Override to\n   * keep the session alive and just react to the departure (e.g. hand it back to\n   * the owning service to be reset and reused). Not configurable via env — pass\n   * a function.\n   */\n  releaseSession?: ReleaseSessionFn;\n\n  /** Optional lifecycle hooks for logging / metrics. Not configurable via env. */\n  hooks?: ReactorQueueServerHooks;\n}\n\nexport interface ReactorQueueServerHooks {\n  onUserConnected?: (connId: string) => void;\n  onUserDisconnected?: (connId: string) => void;\n  onUserEnteredSession?: (connId: string, sessionId: string) => void;\n  onSessionCreated?: (sessionId: string) => void;\n  onSessionClosed?: (sessionId: string, reason: string) => void;\n  onError?: (where: string, error: unknown) => void;\n}\n\n/** Fully-resolved config with all values present. */\nexport interface ResolvedConfig {\n  maxSessions: number;\n  usersPerSession: number;\n  model: string;\n  webrtcVersion: string;\n  sessionDurationMs: number;\n  admissionGraceMs: number;\n  warningBeforeMs: number;\n  tokenTtlSeconds: number;\n  pollIntervalMs: number;\n  coordinatorUrl: string;\n  apiKey: string;\n  apiVersion: number;\n  stopSessionsOnExpiry: boolean;\n  hooks: ReactorQueueServerHooks;\n  /** Total live users = maxSessions * usersPerSession. */\n  capacity: number;\n  /** When set, admin WebSocket connections may authenticate with this password. */\n  adminPassword: string | null;\n  /** When true, the duplicate-tab (same `clientId`) rejection is disabled. */\n  allowDuplicateConnections: boolean;\n  /** Allowed `Origin` values for WebSocket connections. Empty = allow all. `[\"*\"]` = allow all explicitly. */\n  allowedOrigins: string[];\n  /** Custom session acquisition, or null to create via the Reactor API. */\n  acquireSession: AcquireSessionFn | null;\n  /** Custom user-left handler, or null to delete via the Reactor API on last member. */\n  releaseSession: ReleaseSessionFn | null;\n}\n\nconst DEFAULT_COORDINATOR_URL = \"https://api.reactor.inc\";\nconst DEFAULT_WEBRTC_VERSION = \"1.0\";\n\ntype Env = Record<string, unknown>;\n\nfunction envNum(env: Env, key: string): number | undefined {\n  const raw = env[key];\n  if (raw === undefined || raw === null || raw === \"\") return undefined;\n  const n = Number(raw);\n  return Number.isFinite(n) ? n : undefined;\n}\n\nfunction envStr(env: Env, key: string): string | undefined {\n  const raw = env[key];\n  if (raw === undefined || raw === null || raw === \"\") return undefined;\n  return String(raw);\n}\n\nfunction envBool(env: Env, key: string): boolean | undefined {\n  const raw = env[key];\n  if (raw === undefined || raw === null || raw === \"\") return undefined;\n  const s = String(raw).toLowerCase();\n  return s === \"true\" || s === \"1\" || s === \"yes\";\n}\n\n/** Parse a comma-separated env var into a trimmed, non-empty list. */\nfunction envList(env: Env, key: string): string[] | undefined {\n  const raw = env[key];\n  if (raw === undefined || raw === null || raw === \"\") return undefined;\n  const list = String(raw)\n    .split(\",\")\n    .map((s) => s.trim())\n    .filter(Boolean);\n  return list.length > 0 ? list : undefined;\n}\n\nfunction pickNum(envVal: number | undefined, cfgVal: number | undefined, def: number): number {\n  if (envVal !== undefined && envVal > 0) return envVal;\n  if (cfgVal !== undefined && cfgVal > 0) return cfgVal;\n  return def;\n}\n\n/**\n * Merge built-in defaults, factory config, and `room.env` into a single\n * resolved config object. Throws if the API key or model is missing.\n */\nexport function resolveConfig(config: ReactorQueueServerConfig, env: Env): ResolvedConfig {\n  const apiKey = envStr(env, \"RQ_REACTOR_API_KEY\") ?? config.apiKey;\n  if (!apiKey) {\n    throw new Error(\n      \"[reactor-queue] No Reactor API key. Set the RQ_REACTOR_API_KEY secret \" +\n        \"(`npx partykit secret put RQ_REACTOR_API_KEY`) or pass `apiKey` to createReactorQueueServer().\"\n    );\n  }\n\n  const model = envStr(env, \"RQ_MODEL\") ?? config.model;\n  if (!model) {\n    throw new Error(\n      \"[reactor-queue] No model configured. Set RQ_MODEL (e.g. helios) or pass `model` to createReactorQueueServer().\"\n    );\n  }\n\n  const maxSessions = pickNum(\n    envNum(env, \"RQ_MAX_SESSIONS\"),\n    config.maxSessions,\n    DEFAULTS.maxSessions\n  );\n  const usersPerSession = pickNum(\n    envNum(env, \"RQ_USERS_PER_SESSION\"),\n    config.usersPerSession,\n    DEFAULTS.usersPerSession\n  );\n\n  return {\n    maxSessions,\n    usersPerSession,\n    model,\n    webrtcVersion:\n      envStr(env, \"RQ_WEBRTC_VERSION\") ?? config.webrtcVersion ?? DEFAULT_WEBRTC_VERSION,\n    sessionDurationMs: pickNum(\n      envNum(env, \"RQ_SESSION_DURATION_MS\"),\n      config.sessionDurationMs,\n      DEFAULTS.sessionDurationMs\n    ),\n    admissionGraceMs: pickNum(\n      envNum(env, \"RQ_ADMISSION_GRACE_MS\"),\n      config.admissionGraceMs,\n      DEFAULTS.admissionGraceMs\n    ),\n    warningBeforeMs: pickNum(\n      envNum(env, \"RQ_WARNING_BEFORE_MS\"),\n      config.warningBeforeMs,\n      DEFAULTS.warningBeforeMs\n    ),\n    tokenTtlSeconds: pickNum(\n      envNum(env, \"RQ_TOKEN_TTL_SECONDS\"),\n      config.tokenTtlSeconds,\n      DEFAULTS.tokenTtlSeconds\n    ),\n    pollIntervalMs: pickNum(\n      envNum(env, \"RQ_POLL_INTERVAL_MS\"),\n      config.pollIntervalMs,\n      DEFAULTS.pollIntervalMs\n    ),\n    coordinatorUrl: (\n      envStr(env, \"RQ_COORDINATOR_URL\") ??\n      config.coordinatorUrl ??\n      DEFAULT_COORDINATOR_URL\n    ).replace(/\\/+$/, \"\"),\n    apiKey,\n    apiVersion: pickNum(envNum(env, \"RQ_API_VERSION\"), config.apiVersion, 1),\n    stopSessionsOnExpiry: envBool(env, \"RQ_STOP_SESSIONS\") ?? config.stopSessionsOnExpiry ?? true,\n    hooks: config.hooks ?? {},\n    capacity: maxSessions * usersPerSession,\n    adminPassword: envStr(env, \"RQ_ADMIN_PASSWORD\") ?? config.adminPassword ?? null,\n    allowDuplicateConnections:\n      envBool(env, \"RQ_ALLOW_DUPLICATE_CONNECTIONS\") ?? config.allowDuplicateConnections ?? false,\n    allowedOrigins: envList(env, \"RQ_ALLOWED_ORIGINS\") ?? config.allowedOrigins ?? [],\n    acquireSession: config.acquireSession ?? null,\n    releaseSession: config.releaseSession ?? null,\n  };\n}\n\nexport { DEFAULT_ROOM };\n","import { TERMINAL_SESSION_STATES } from \"../protocol\";\n\n/**\n * Raised when the Coordinator answers a request with a non-OK status. Carries\n * the `endpoint`, HTTP `status`, and raw response `body` so callers (and the\n * admin log) can show *why* a call failed — a quota rejection, an expired key,\n * a bad model — instead of a generic \"session create failed\".\n */\nexport class CoordinatorError extends Error {\n  readonly endpoint: string;\n  readonly status: number;\n  readonly body: string;\n\n  constructor(endpoint: string, status: number, body: string) {\n    super(`${endpoint} failed: ${status} ${body || \"(no body)\"}`);\n    this.name = \"CoordinatorError\";\n    this.endpoint = endpoint;\n    this.status = status;\n    this.body = body;\n  }\n}\n\n/**\n * Session authorization scope for a minted JWT. When passed to\n * {@link CoordinatorClient.mintToken}, the JWT is restricted to the named model\n * and to the sessions its grant holds — nothing else on the account.\n */\nexport interface TokenScope {\n  /** Model the token is confined to (fully-qualified `org/model`). */\n  model: string;\n  /**\n   * Existing sessions the grant starts bound to. Each must still be open and\n   * owned by the API key doing the minting; the Coordinator answers `403`\n   * otherwise, and refuses a session whose model falls outside `model`.\n   */\n  sessions?: string[];\n  /**\n   * How many sessions the grant may hold over its lifetime. Left unset it\n   * resolves to the number of bound sessions, which leaves the token full on\n   * arrival: it operates what it was given and cannot create more.\n   */\n  maxSessions?: number;\n}\n\n/**\n * Thin server-side client for the Reactor Coordinator REST API. From inside the\n * trusted PartyKit server it:\n *\n *  1. mints short-lived client JWTs from the API key (`POST /tokens`),\n *     optionally scoped to one model via `authorization_details`,\n *  2. creates sessions (`POST /sessions`),\n *  3. reads a session's state (`GET /sessions/{id}/runtime`), and\n *  4. stops a session (`DELETE /sessions/{id}`).\n *\n * (2)–(4) need a Bearer JWT. By default the client keeps its own cached\n * \"server JWT\" (unscoped, minted with a longer TTL) and reuses it across\n * calls; `createSession`/`createConnection` also accept an explicit `jwt` so\n * a session can be created *by* a scoped token, binding it to that token's\n * grant.\n */\nexport class CoordinatorClient {\n  private readonly baseUrl: string;\n  private readonly apiKey: string;\n  private readonly apiVersion: number;\n  private readonly webrtcVersion: string;\n\n  private serverJwt: { jwt: string; expiresAt: number } | null = null;\n  /** TTL for the server's own admin JWT. Longer than client tokens; re-minted lazily. */\n  private static readonly SERVER_JWT_TTL_SECONDS = 600;\n  private static readonly SKEW_SECONDS = 30;\n\n  constructor(opts: {\n    baseUrl: string;\n    apiKey: string;\n    apiVersion: number;\n    webrtcVersion: string;\n  }) {\n    this.baseUrl = opts.baseUrl;\n    this.apiKey = opts.apiKey;\n    this.apiVersion = opts.apiVersion;\n    this.webrtcVersion = opts.webrtcVersion;\n  }\n\n  private versionHeaders(): Record<string, string> {\n    return {\n      \"Reactor-API-Version\": String(this.apiVersion),\n      \"Reactor-API-Accept-Version\": String(this.apiVersion),\n    };\n  }\n\n  /**\n   * Exchange the API key for a JWT. `ttlSeconds` is passed as `expires_after`;\n   * the Coordinator caps it at its server maximum. With a `scope`, the JWT\n   * carries session `authorization_details`: it is confined to `scope.model`\n   * and to the sessions on its grant, which `scope.sessions` can pre-populate\n   * with sessions that already exist. The bound set is server state rather than\n   * a claim, so it never appears in the token itself.\n   */\n  async mintToken(\n    ttlSeconds: number,\n    scope?: TokenScope\n  ): Promise<{ jwt: string; expiresAt: number }> {\n    const res = await fetch(`${this.baseUrl}/tokens`, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        \"Reactor-API-Key\": this.apiKey,\n        ...this.versionHeaders(),\n      },\n      body: JSON.stringify({\n        expires_after: Math.max(1, Math.floor(ttlSeconds)),\n        ...(scope\n          ? {\n              authorization_details: [\n                {\n                  type: \"session\",\n                  resources: {\n                    models: { match: [scope.model] },\n                    ...(scope.sessions?.length ? { sessions: { bind: scope.sessions } } : {}),\n                  },\n                  ...(scope.maxSessions === undefined\n                    ? {}\n                    : { constraints: { max_sessions: scope.maxSessions } }),\n                },\n              ],\n            }\n          : {}),\n      }),\n    });\n\n    if (!res.ok) {\n      const detail = await res.text().catch(() => res.statusText);\n      throw new CoordinatorError(\"POST /tokens\", res.status, detail);\n    }\n\n    const data = (await res.json()) as { jwt?: string; token?: string; expires_at?: number };\n    const jwt = data.jwt ?? data.token;\n    if (!jwt) throw new Error(\"mintToken: no jwt in response\");\n    const expiresAt = data.expires_at ?? Math.floor(Date.now() / 1000) + ttlSeconds;\n    return { jwt, expiresAt };\n  }\n\n  private async getServerJwt(): Promise<string> {\n    const now = Math.floor(Date.now() / 1000);\n    if (this.serverJwt && this.serverJwt.expiresAt - now > CoordinatorClient.SKEW_SECONDS) {\n      return this.serverJwt.jwt;\n    }\n    this.serverJwt = await this.mintToken(CoordinatorClient.SERVER_JWT_TTL_SECONDS);\n    return this.serverJwt.jwt;\n  }\n\n  /**\n   * Returns the session's current state string, `\"CLOSED\"` if the session is\n   * gone (404), or `null` if the lookup itself failed (so callers can avoid\n   * freeing a slot on a transient network error).\n   */\n  async getSessionState(sessionId: string): Promise<string | null> {\n    let jwt: string;\n    try {\n      jwt = await this.getServerJwt();\n    } catch {\n      return null;\n    }\n\n    const res = await fetch(`${this.baseUrl}/sessions/${encodeURIComponent(sessionId)}/runtime`, {\n      method: \"GET\",\n      headers: { Authorization: `Bearer ${jwt}`, ...this.versionHeaders() },\n    });\n\n    if (res.status === 404) return \"CLOSED\";\n    if (!res.ok) return null;\n\n    const data = (await res.json().catch(() => null)) as { state?: string } | null;\n    return data?.state ?? null;\n  }\n\n  /** True if a state string means the slot should be released. */\n  static isTerminal(state: string | null): boolean {\n    return state !== null && (TERMINAL_SESSION_STATES as readonly string[]).includes(state);\n  }\n\n  /**\n   * Create a Reactor session for the configured model. Returns the new\n   * `session_id`. Runs billing/quota checks against the server's API key.\n   */\n  async createSession(opts: { model: string; webrtcVersion: string }): Promise<string> {\n    const jwt = await this.getServerJwt();\n    const res = await fetch(`${this.baseUrl}/sessions`, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: `Bearer ${jwt}`,\n        ...this.versionHeaders(),\n      },\n      body: JSON.stringify({\n        model: { name: opts.model },\n        // Identifies the caller to the Coordinator for telemetry only; not the\n        // package version. Left as a fixed marker for the queue server rather\n        // than wired to package.json — bump by hand if the contract changes.\n        client_info: {\n          sdk_version: \"0.1.0\",\n          sdk_type: \"js\",\n        },\n        supported_transports: [{ protocol: \"webrtc\", version: opts.webrtcVersion }],\n      }),\n    });\n\n    if (!res.ok) {\n      const detail = await res.text().catch(() => res.statusText);\n      throw new CoordinatorError(\"POST /sessions\", res.status, detail);\n    }\n\n    const data = (await res.json()) as { session_id?: string };\n    const sessionId = data.session_id;\n    if (!sessionId) throw new Error(\"createSession: no session_id in response\");\n    return sessionId;\n  }\n\n  /**\n   * Register a WebRTC connection under an existing session and return the\n   * server-minted `connection_id`. This is a transport call, so it carries\n   * `Reactor-WebRTC-Version` rather than the API-version headers.\n   *\n   * A {@link CoordinatorError} with `status === 429` means the session hit its\n   * `connections_per_session` cap; the caller falls back to another/new session.\n   */\n  async createConnection(sessionId: string): Promise<number> {\n    const jwt = await this.getServerJwt();\n    const endpoint = `/sessions/${encodeURIComponent(sessionId)}/transport/webrtc/connections`;\n    const res = await fetch(`${this.baseUrl}${endpoint}`, {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: `Bearer ${jwt}`,\n        \"Reactor-WebRTC-Version\": this.webrtcVersion,\n      },\n      body: JSON.stringify({ client_info: { sdk_version: \"0.1.0\", sdk_type: \"js\" } }),\n    });\n\n    if (!res.ok) {\n      const detail = await res.text().catch(() => res.statusText);\n      throw new CoordinatorError(`POST ${endpoint}`, res.status, detail);\n    }\n\n    const data = (await res.json()) as { connection_id?: number };\n    const connectionId = data.connection_id;\n    if (typeof connectionId !== \"number\") {\n      throw new Error(\"createConnection: no connection_id in response\");\n    }\n    return connectionId;\n  }\n\n  /** Force-close a session. Swallows \"already gone\" responses. */\n  async stopSession(sessionId: string, reason = \"queue: session time elapsed\"): Promise<void> {\n    const jwt = await this.getServerJwt();\n    const res = await fetch(`${this.baseUrl}/sessions/${encodeURIComponent(sessionId)}`, {\n      method: \"DELETE\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        Authorization: `Bearer ${jwt}`,\n        ...this.versionHeaders(),\n      },\n      body: JSON.stringify({ reason }),\n    });\n    if (!res.ok && res.status !== 404) {\n      const detail = await res.text().catch(() => res.statusText);\n      throw new CoordinatorError(`DELETE /sessions/${sessionId}`, res.status, detail);\n    }\n  }\n}\n","import type * as Party from \"partykit/server\";\nimport {\n  ADMIN_MODE_QUERY_KEY,\n  CLIENT_ID_QUERY_KEY,\n  parseAdminClientMessage,\n  parseClientMessage,\n  type AdminLogEntry,\n  type AdminLogLevel,\n  type AdminServerMessage,\n  type ServerMessage,\n} from \"../protocol\";\nimport { buildAdminSnapshot } from \"./admin-snapshot\";\nimport { resolveConfig, type ReactorQueueServerConfig, type ResolvedConfig } from \"./config\";\nimport type { ReleaseSessionContext } from \"./config\";\nimport { CoordinatorClient, CoordinatorError } from \"./coordinator\";\n\n/** Max activity-log entries kept in the room's durable ring buffer. */\nconst MAX_LOG_ENTRIES = 200;\n\n/** How many times a transient connection mint is retried before spilling to the next session. */\nconst CONNECTION_MINT_ATTEMPTS = 3;\n/** Backoff between transient connection-mint retries, in ms. */\nconst CONNECTION_MINT_RETRY_MS = 250;\n\n/**\n * Turn an arbitrary thrown value into a log-friendly message + structured data.\n * A {@link CoordinatorError} surfaces the endpoint, HTTP status, and (truncated)\n * response body — so an admin sees *why* the Reactor API said no (quota, expired\n * key, bad model, …) rather than an opaque failure.\n */\nfunction describeError(error: unknown): { message: string; data?: Record<string, unknown> } {\n  if (error instanceof CoordinatorError) {\n    const body = error.body.length > 2000 ? `${error.body.slice(0, 2000)}…` : error.body;\n    return {\n      message: error.message,\n      data: { endpoint: error.endpoint, status: error.status, body },\n    };\n  }\n  if (error instanceof Error) {\n    return {\n      message: error.message,\n      data: error.name && error.name !== \"Error\" ? { name: error.name } : undefined,\n    };\n  }\n  return { message: String(error) };\n}\n\n/** Per admitted member. Lives in durable storage under `member:<connId>`. */\ninterface MemberData {\n  /** The capacity slot this member occupies. */\n  slotId: string;\n  /** Reactor session id once the slot's session is created (on claim); null during grace. */\n  sessionId: string | null;\n  /** Server-minted WebRTC connection id once claimed; null during grace. */\n  connectionId: number | null;\n  /** Epoch ms when this member's slot is reclaimed (grace or full session). */\n  expiresAt: number;\n  warned: boolean;\n  claimed: boolean;\n  /** True while a claim is mid-flight (session being acquired) to reject duplicates. */\n  claiming?: boolean;\n}\n\n/**\n * A capacity slot shared by up to `usersPerSession` members. Reserved at\n * admission; its Reactor session is created lazily on the first `claim()` so an\n * abandoned grace never orphans a GPU session.\n */\ninterface SlotRecord {\n  slotId: string;\n  /** Reactor session id, or null until the first member claims. */\n  sessionId: string | null;\n  members: string[];\n  createdAt: number;\n  lastPollAt?: number;\n}\n\n/** Maps a stable browser id → its current connection, for duplicate-tab eviction. */\ninterface ClientEntry {\n  connId: string;\n}\n\n/**\n * Build a PartyKit `Server` class implementing the Reactor queue. Use it as the\n * default export of your PartyKit entrypoint:\n *\n * ```ts\n * // partykit/server.ts\n * import { createReactorQueueServer } from \"@reactor-team/queue/server\";\n * export default createReactorQueueServer({ model: \"helios\" });\n * ```\n */\nexport function createReactorQueueServer(\n  config: ReactorQueueServerConfig = {}\n): new (room: Party.Room) => Party.Server {\n  return class ReactorQueueServer implements Party.Server {\n    options: Party.ServerOptions = { hibernate: true };\n\n    private cfg: ResolvedConfig | null = null;\n    private coordinator: CoordinatorClient | null = null;\n    // Coalescing flags. Set during a handler, flushed once before it returns —\n    // never across the hibernation boundary, so no in-memory timer is needed.\n    private positionsDirty = false;\n    private adminDirty = false;\n    // Structured events produced during the current handler. Flushed (persisted\n    // to the ring buffer + streamed to admins) once, alongside the broadcasts.\n    private pendingLogs: AdminLogEntry[] = [];\n\n    constructor(readonly room: Party.Room) {}\n\n    private get config(): ResolvedConfig {\n      if (!this.cfg) {\n        this.cfg = resolveConfig(config, this.room.env as Record<string, unknown>);\n      }\n      return this.cfg;\n    }\n\n    private get api(): CoordinatorClient {\n      if (!this.coordinator) {\n        const c = this.config;\n        this.coordinator = new CoordinatorClient({\n          baseUrl: c.coordinatorUrl,\n          apiKey: c.apiKey,\n          apiVersion: c.apiVersion,\n          webrtcVersion: c.webrtcVersion,\n        });\n      }\n      return this.coordinator;\n    }\n\n    /**\n     * Obtain a session id for a slot's first claim. Uses the configured\n     * `acquireSession` override, or creates one via the Reactor API by default.\n     */\n    private async runAcquire(model: string): Promise<string> {\n      if (this.config.acquireSession) return this.config.acquireSession({ model });\n      return this.api.createSession({ model, webrtcVersion: this.config.webrtcVersion });\n    }\n\n    /**\n     * Mint one member's own token for `sessionId`: confined to the configured\n     * model and bound to that single session. Binding at mint is what lets a\n     * member operate a session the server created for them, so members sharing\n     * a slot hold distinct tokens rather than copies of one. The session limit\n     * is left to resolve to the bound count, which makes the grant full on\n     * arrival — the token drives the session it was given and can open none.\n     */\n    private mintMemberToken(sessionId: string): Promise<{ jwt: string; expiresAt: number }> {\n      return this.api.mintToken(this.config.tokenTtlSeconds, {\n        model: this.config.model,\n        sessions: [sessionId],\n      });\n    }\n\n    /**\n     * A user left a session. Uses the configured `releaseSession` override, or by\n     * default deletes the session via the Reactor API once the last member leaves\n     * (subject to `stopSessionsOnExpiry`). Never throws into the caller.\n     */\n    private async runRelease(ctx: ReleaseSessionContext): Promise<void> {\n      try {\n        if (this.config.releaseSession) {\n          await this.config.releaseSession(ctx);\n          return;\n        }\n        if (ctx.lastMember && this.config.stopSessionsOnExpiry) {\n          await this.api.stopSession(ctx.sessionId, `queue: ${ctx.reason}`);\n        }\n      } catch (err) {\n        this.reportError(\"releaseSession\", err);\n      }\n    }\n\n    /**\n     * Log a non-fatal error as a structured `error` event (visible in the admin\n     * activity log, with the API status/body for {@link CoordinatorError}) and\n     * fire the `onError` hook. `where` doubles as the event code.\n     */\n    private reportError(\n      where: string,\n      error: unknown,\n      opts: { connId?: string; sessionId?: string } = {}\n    ) {\n      const { message, data } = describeError(error);\n      this.log(\"error\", where, message, { ...opts, data });\n      try {\n        this.config.hooks.onError?.(where, error);\n      } catch {\n        /* hook must never throw the server over */\n      }\n    }\n\n    /** Write a structured line to the server console, nothing else. */\n    private writeConsole(\n      level: AdminLogLevel,\n      event: string,\n      message: string,\n      data?: Record<string, unknown>\n    ): void {\n      const line = `[reactor-queue] ${event}: ${message}`;\n      const ctx = data ?? \"\";\n      if (level === \"error\") console.error(line, ctx);\n      else if (level === \"warn\") console.warn(line, ctx);\n      else console.log(line, ctx);\n    }\n\n    /**\n     * Record one structured server event. Always writes to the server console;\n     * when admin mode is enabled (`adminPassword` set) it is also queued for the\n     * admin stream. This is the single place server events become visible — call\n     * it wherever something notable happens.\n     *\n     * Only console + in-memory work happens here; the persist/broadcast is\n     * deferred to `flushBroadcasts()` so it lands inside the handler turn\n     * (hibernation-safe) and coalesces with the queue/admin broadcasts. There,\n     * `info` events are streamed to live admins only, while `warn`/`error` are\n     * also written to the durable ring buffer — so the high-frequency hot path\n     * (connects/disconnects) never touches storage, but failures stay in history.\n     *\n     * Do **not** use this for connection rejections (forbidden origin, duplicate\n     * tab): those are unauthenticated and attacker-driven, so queuing them would\n     * let a flood drive admin-stream work. Log rejections with `writeConsole`.\n     */\n    private log(\n      level: AdminLogLevel,\n      event: string,\n      message: string,\n      opts: { connId?: string; sessionId?: string; data?: Record<string, unknown> } = {}\n    ): void {\n      this.writeConsole(level, event, message, opts.data);\n\n      // Only pay the stream/storage cost when an operator can actually read it.\n      if (!this.config.adminPassword) return;\n      this.pendingLogs.push({\n        id: this.genId(),\n        at: Date.now(),\n        level,\n        event,\n        message,\n        ...(opts.connId ? { connId: opts.connId } : {}),\n        ...(opts.sessionId ? { sessionId: opts.sessionId } : {}),\n        ...(opts.data ? { data: opts.data } : {}),\n      });\n    }\n\n    // ── storage helpers ────────────────────────────────────────────────────\n\n    // ── queue: ordered keys, not one array ───────────────────────────────────\n    // Each waiter is its own storage entry `q:<zero-padded seq>` → connId, with a\n    // reverse lookup `qpos:<connId>` → key. This makes enqueue/dequeue/position\n    // lookups O(1) and removes the 128 KiB single-value cap, so the line can grow\n    // far past the ~3k a single JSON array allowed. `qseq` is a monotonic counter\n    // for FIFO ordering; `qcount` is the O(1) length.\n\n    private queueItemKey(seq: number): string {\n      return `q:${String(seq).padStart(16, \"0\")}`;\n    }\n    private async getQueueSeq(): Promise<number> {\n      return (await this.room.storage.get<number>(\"qseq\")) ?? 0;\n    }\n    private async getQueueCount(): Promise<number> {\n      return (await this.room.storage.get<number>(\"qcount\")) ?? 0;\n    }\n    private async isQueued(connId: string): Promise<boolean> {\n      return Boolean(await this.room.storage.get<string>(`qpos:${connId}`));\n    }\n    private async enqueue(connId: string): Promise<void> {\n      if (await this.isQueued(connId)) return;\n      const seq = await this.getQueueSeq();\n      const key = this.queueItemKey(seq);\n      await this.room.storage.put(key, connId);\n      await this.room.storage.put(`qpos:${connId}`, key);\n      await this.room.storage.put(\"qseq\", seq + 1);\n      await this.room.storage.put(\"qcount\", (await this.getQueueCount()) + 1);\n    }\n    /** Remove a waiter from the queue (by connId). Returns true if it was queued. */\n    private async dequeue(connId: string): Promise<boolean> {\n      const key = await this.room.storage.get<string>(`qpos:${connId}`);\n      if (!key) return false;\n      await this.room.storage.delete(key);\n      await this.room.storage.delete(`qpos:${connId}`);\n      await this.room.storage.put(\"qcount\", Math.max(0, (await this.getQueueCount()) - 1));\n      return true;\n    }\n    /** Full FIFO list of waiting connIds. O(N) — used for broadcasts (no approximation). */\n    private async listQueue(): Promise<string[]> {\n      const items = await this.room.storage.list<string>({ prefix: \"q:\" });\n      return [...items.values()];\n    }\n    /** Front `limit` waiting entries `[key, connId]` in FIFO order, after `startAfter`. */\n    private async frontQueue(limit: number, startAfter?: string): Promise<[string, string][]> {\n      const items = await this.room.storage.list<string>({ prefix: \"q:\", limit, startAfter });\n      return [...items.entries()];\n    }\n\n    private memberKey(connId: string): string {\n      return `member:${connId}`;\n    }\n    private slotKey(slotId: string): string {\n      return `slot:${slotId}`;\n    }\n\n    private async getMember(connId: string): Promise<MemberData | undefined> {\n      return this.room.storage.get<MemberData>(this.memberKey(connId));\n    }\n    private async setMember(connId: string, data: MemberData): Promise<void> {\n      await this.room.storage.put(this.memberKey(connId), data);\n    }\n    private async deleteMember(connId: string): Promise<void> {\n      await this.room.storage.delete(this.memberKey(connId));\n    }\n\n    private async getSlot(slotId: string): Promise<SlotRecord | undefined> {\n      return this.room.storage.get<SlotRecord>(this.slotKey(slotId));\n    }\n    private async setSlot(record: SlotRecord): Promise<void> {\n      await this.room.storage.put(this.slotKey(record.slotId), record);\n    }\n    private async deleteSlot(slotId: string): Promise<void> {\n      await this.room.storage.delete(this.slotKey(slotId));\n    }\n\n    private async getAllMembers(): Promise<Map<string, MemberData>> {\n      return this.room.storage.list<MemberData>({ prefix: \"member:\" });\n    }\n    private async getAllSlots(): Promise<Map<string, SlotRecord>> {\n      return this.room.storage.list<SlotRecord>({ prefix: \"slot:\" });\n    }\n\n    private async getActiveMemberCount(): Promise<number> {\n      return (await this.getAllMembers()).size;\n    }\n\n    private async getSlotCount(): Promise<number> {\n      return (await this.getAllSlots()).size;\n    }\n\n    /** First slot with a free seat, or undefined. */\n    private async findOpenSlot(): Promise<SlotRecord | undefined> {\n      const cap = this.config.usersPerSession;\n      for (const [, record] of await this.getAllSlots()) {\n        if (record.members.length < cap) return record;\n      }\n      return undefined;\n    }\n\n    private async findSlotBySessionId(sessionId: string): Promise<SlotRecord | undefined> {\n      for (const [, slot] of await this.getAllSlots()) {\n        if (slot.sessionId === sessionId) return slot;\n      }\n      return undefined;\n    }\n\n    /** The slot currently listing `connId` as a member, or undefined. */\n    private async findSlotByMember(connId: string): Promise<SlotRecord | undefined> {\n      for (const [, slot] of await this.getAllSlots()) {\n        if (slot.members.includes(connId)) return slot;\n      }\n      return undefined;\n    }\n\n    private genId(): string {\n      return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n    }\n\n    private async getClientEntry(clientId: string): Promise<ClientEntry | undefined> {\n      return this.room.storage.get<ClientEntry>(`cid:${clientId}`);\n    }\n    private async setClientEntry(clientId: string, connId: string): Promise<void> {\n      await this.room.storage.put(`cid:${clientId}`, { connId });\n      await this.room.storage.put(`conn:${connId}`, clientId);\n    }\n\n    private send(conn: Party.Connection, msg: ServerMessage) {\n      const ws = conn as { readyState?: number };\n      if (ws.readyState !== undefined && ws.readyState !== 1 /* OPEN */) return;\n      try {\n        conn.send(JSON.stringify(msg));\n      } catch {\n        /* connection closed between the check and the send */\n      }\n    }\n    // O(1) lookup via the platform connection registry (survives hibernation),\n    // instead of scanning all connections.\n    private sendTo(connId: string, msg: ServerMessage) {\n      const conn = this.room.getConnection(connId);\n      if (conn) this.send(conn, msg);\n    }\n\n    private sendAdmin(conn: Party.Connection, msg: AdminServerMessage) {\n      const ws = conn as { readyState?: number };\n      if (ws.readyState !== undefined && ws.readyState !== 1 /* OPEN */) return;\n      try {\n        conn.send(JSON.stringify(msg));\n      } catch {\n        /* connection closed */\n      }\n    }\n\n    private sendAdminTo(connId: string, msg: AdminServerMessage) {\n      const conn = this.room.getConnection(connId);\n      if (conn) this.sendAdmin(conn, msg);\n    }\n\n    private adminKey(connId: string): string {\n      return `admin:${connId}`;\n    }\n\n    private async getAdminStatus(connId: string): Promise<\"pending\" | \"active\" | undefined> {\n      return this.room.storage.get<\"pending\" | \"active\">(this.adminKey(connId));\n    }\n\n    private async resolveClientIdForConn(connId: string): Promise<string | null> {\n      return (await this.room.storage.get<string>(`conn:${connId}`)) ?? null;\n    }\n\n    private async buildSnapshot() {\n      return buildAdminSnapshot({\n        config: this.config,\n        queue: await this.listQueue(),\n        slots: await this.getAllSlots(),\n        members: await this.getAllMembers(),\n        resolveClientId: (connId) => this.resolveClientIdForConn(connId),\n      });\n    }\n\n    private async getActiveAdminConnIds(): Promise<string[]> {\n      const all = await this.room.storage.list<\"pending\" | \"active\">({ prefix: \"admin:\" });\n      const out: string[] = [];\n      for (const [key, status] of all) {\n        if (status === \"active\") out.push(key.replace(\"admin:\", \"\"));\n      }\n      return out;\n    }\n\n    /** Mark admin snapshots dirty; flushed once at the end of the current handler. */\n    private scheduleAdminBroadcast(): void {\n      this.adminDirty = true;\n    }\n\n    private async broadcastAdminSnapshots(admins: string[]): Promise<void> {\n      if (admins.length === 0) return;\n      const snapshot = await this.buildSnapshot();\n      for (const connId of admins) this.sendAdminTo(connId, snapshot);\n    }\n\n    // ── activity log: bounded ring buffer + live admin stream ────────────────\n    // One key per entry (`log:<padded seq>`) with `logseq` (next) and `logmin`\n    // (oldest) counters, mirroring the queue's storage model: appends are O(1),\n    // history survives hibernation, and the buffer self-trims to MAX_LOG_ENTRIES.\n\n    private logKey(seq: number): string {\n      return `log:${String(seq).padStart(16, \"0\")}`;\n    }\n\n    /** Append entries to the durable ring buffer, trimming the oldest past the cap. */\n    private async persistLogs(entries: AdminLogEntry[]): Promise<void> {\n      let seq = (await this.room.storage.get<number>(\"logseq\")) ?? 0;\n      let min = (await this.room.storage.get<number>(\"logmin\")) ?? 0;\n      for (const entry of entries) {\n        await this.room.storage.put(this.logKey(seq), entry);\n        seq++;\n      }\n      await this.room.storage.put(\"logseq\", seq);\n      while (seq - min > MAX_LOG_ENTRIES) {\n        await this.room.storage.delete(this.logKey(min));\n        min++;\n      }\n      await this.room.storage.put(\"logmin\", min);\n    }\n\n    /** Recent log entries in chronological order (oldest → newest). */\n    private async listLogHistory(): Promise<AdminLogEntry[]> {\n      const items = await this.room.storage.list<AdminLogEntry>({ prefix: \"log:\" });\n      return [...items.values()];\n    }\n\n    private broadcastLogs(admins: string[], entries: AdminLogEntry[]): void {\n      for (const connId of admins) {\n        for (const entry of entries) this.sendAdminTo(connId, { type: \"admin_log\", entry });\n      }\n    }\n\n    private async adminKickMember(connId: string): Promise<{ ok: boolean; message?: string }> {\n      const member = await this.getMember(connId);\n      if (member) {\n        await this.releaseMember(connId, member, \"server\", { notify: true });\n        await this.tryAdmitNext();\n        this.log(\"warn\", \"admin_kick_member\", \"Admin evicted an admitted member\", {\n          connId,\n          sessionId: member.sessionId ?? undefined,\n        });\n        this.scheduleAdminBroadcast();\n        return { ok: true };\n      }\n\n      // No member record, but the connId may be a *stale* entry left in a slot by\n      // a release/poll race. Scrub it (dropping the slot if it empties) so an\n      // operator can always clear an orphan the normal eviction can't reach.\n      const slot = await this.findSlotByMember(connId);\n      if (!slot) return { ok: false, message: \"member_not_found\" };\n\n      const live = slot.members.filter((id) => id !== connId);\n      if (live.length === 0) {\n        await this.dropSlot(slot.slotId, \"server\", { notify: false });\n      } else {\n        await this.setSlot({ ...slot, members: live });\n      }\n      await this.tryAdmitNext();\n      this.log(\"warn\", \"admin_kick_member\", \"Admin cleared a stale member from a slot\", {\n        connId,\n        sessionId: slot.sessionId ?? undefined,\n      });\n      this.scheduleAdminBroadcast();\n      return { ok: true };\n    }\n\n    private async adminKickQueued(connId: string): Promise<{ ok: boolean; message?: string }> {\n      const removed = await this.dequeue(connId);\n      if (!removed) return { ok: false, message: \"not_in_queue\" };\n      const conn = this.room.getConnection(connId);\n      if (conn) {\n        try {\n          conn.close(1000, \"evicted\");\n        } catch {\n          /* already gone */\n        }\n      }\n      this.log(\"warn\", \"admin_kick_queued\", \"Admin removed a waiting user from the queue\", {\n        connId,\n      });\n      this.scheduleBroadcast();\n      this.scheduleAdminBroadcast();\n      return { ok: true };\n    }\n\n    private async adminCloseSession(sessionId: string): Promise<{ ok: boolean; message?: string }> {\n      const slot = await this.findSlotBySessionId(sessionId);\n      if (!slot) return { ok: false, message: \"session_not_found\" };\n\n      // Release members that still have records so a custom `releaseSession` sees\n      // each departing user; the last one tears the slot down normally.\n      for (const connId of [...slot.members]) {\n        const member = await this.getMember(connId);\n        if (member) await this.releaseMember(connId, member, \"server\", { notify: true });\n      }\n      // If the slot survived — its listed members had no records (an orphan) —\n      // force it closed so \"Close session\" always actually closes the session.\n      await this.dropSlot(slot.slotId, \"server\", { notify: true });\n\n      await this.tryAdmitNext();\n      this.log(\"warn\", \"admin_close_session\", \"Admin force-closed a session\", { sessionId });\n      this.scheduleAdminBroadcast();\n      return { ok: true };\n    }\n\n    // ── connection lifecycle ────────────────────────────────────────────────\n\n    /**\n     * Enforce the configured cross-origin allow-list. Empty list = allow all\n     * (opt-in). A `\"*\"` entry allows everything, including connections with no\n     * `Origin` header. Otherwise the browser's `Origin` must match exactly.\n     */\n    private isOriginAllowed(origin: string | null): boolean {\n      const allowed = this.config.allowedOrigins;\n      if (allowed.length === 0 || allowed.includes(\"*\")) return true;\n      return origin !== null && allowed.includes(origin);\n    }\n\n    async onConnect(conn: Party.Connection, ctx: Party.ConnectionContext) {\n      try {\n        const url = new URL(ctx.request.url);\n        const isAdmin = url.searchParams.get(ADMIN_MODE_QUERY_KEY) === \"1\";\n\n        if (!this.isOriginAllowed(ctx.request.headers.get(\"origin\"))) {\n          if (isAdmin) {\n            this.sendAdmin(conn, { type: \"admin_rejected\", reason: \"forbidden_origin\" });\n          } else {\n            this.send(conn, { type: \"rejected\", reason: \"forbidden_origin\" });\n          }\n          // Console-only: an unauthenticated origin flood must not be able to\n          // drive admin-stream/storage work — that would amplify the very abuse\n          // the allow-list exists to reject cheaply.\n          this.writeConsole(\n            \"warn\",\n            \"forbidden_origin\",\n            \"Rejected a connection from a disallowed origin\",\n            {\n              origin: ctx.request.headers.get(\"origin\") ?? null,\n              admin: isAdmin,\n            }\n          );\n          conn.close(1008, \"forbidden_origin\");\n          return;\n        }\n\n        if (isAdmin) {\n          if (!this.config.adminPassword) {\n            this.sendAdmin(conn, { type: \"admin_rejected\", reason: \"admin_disabled\" });\n            conn.close(1008, \"admin_disabled\");\n            return;\n          }\n          await this.room.storage.put(this.adminKey(conn.id), \"pending\");\n          return;\n        }\n\n        const clientId = url.searchParams.get(CLIENT_ID_QUERY_KEY);\n        if (clientId) {\n          if (!this.config.allowDuplicateConnections) {\n            const entry = await this.getClientEntry(clientId);\n            if (entry && entry.connId !== conn.id) {\n              // The platform tracks connection liveness across hibernation, so\n              // a live connection for this clientId means a real duplicate tab.\n              // No app-level heartbeat needed; `onClose` cleans the mapping.\n              if (this.room.getConnection(entry.connId)) {\n                this.send(conn, { type: \"rejected\", reason: \"already_connected\" });\n                // Console-only (same reasoning as forbidden_origin): a rejection\n                // path must stay cheap and not feed the admin stream/storage.\n                this.writeConsole(\n                  \"warn\",\n                  \"duplicate_rejected\",\n                  \"Rejected a duplicate connection (same browser already connected in another tab)\",\n                  { connId: conn.id }\n                );\n                conn.close(1008, \"already_connected\");\n                return;\n              }\n              await this.room.storage.delete(`cid:${clientId}`);\n              await this.room.storage.delete(`conn:${entry.connId}`);\n            }\n          }\n          await this.setClientEntry(clientId, conn.id);\n        }\n\n        await this.enqueue(conn.id);\n        this.config.hooks.onUserConnected?.(conn.id);\n        this.log(\"info\", \"user_connected\", \"User connected and joined the queue\", {\n          connId: conn.id,\n        });\n        await this.tryAdmitNext();\n        this.scheduleAdminBroadcast();\n        await this.flushBroadcasts();\n      } catch (err) {\n        this.reportError(\"onConnect\", err);\n        try {\n          this.send(conn, { type: \"rejected\", reason: \"server_error\" });\n          conn.close(1011, \"connect_failed\");\n        } catch {\n          /* connection already gone */\n        }\n      }\n    }\n\n    async onClose(conn: Party.Connection) {\n      try {\n        const adminStatus = await this.getAdminStatus(conn.id);\n        if (adminStatus) {\n          await this.room.storage.delete(this.adminKey(conn.id));\n          return;\n        }\n\n        const clientId = await this.room.storage.get<string>(`conn:${conn.id}`);\n        if (clientId) {\n          const entry = await this.getClientEntry(clientId);\n          if (entry?.connId === conn.id) {\n            await this.room.storage.delete(`cid:${clientId}`);\n          }\n          await this.room.storage.delete(`conn:${conn.id}`);\n        }\n\n        if (await this.dequeue(conn.id)) {\n          this.scheduleBroadcast();\n          this.scheduleAdminBroadcast();\n        }\n\n        const member = await this.getMember(conn.id);\n        if (member) {\n          await this.releaseMember(conn.id, member, \"server\", { notify: false });\n          await this.tryAdmitNext();\n        }\n\n        this.config.hooks.onUserDisconnected?.(conn.id);\n        this.log(\"info\", \"user_disconnected\", \"User connection closed\", { connId: conn.id });\n        await this.flushBroadcasts();\n      } catch (err) {\n        this.reportError(\"onClose\", err);\n      }\n    }\n\n    async onMessage(raw: string, sender: Party.Connection) {\n      const adminStatus = await this.getAdminStatus(sender.id);\n      if (adminStatus) {\n        const adminMsg = parseAdminClientMessage(raw);\n        try {\n          if (adminStatus === \"pending\") {\n            if (adminMsg?.type !== \"admin_auth\") {\n              this.sendAdmin(sender, { type: \"admin_rejected\", reason: \"auth_required\" });\n              sender.close(1008, \"auth_required\");\n              return;\n            }\n            if (adminMsg.password !== this.config.adminPassword) {\n              this.sendAdmin(sender, { type: \"admin_rejected\", reason: \"invalid_password\" });\n              sender.close(1008, \"invalid_password\");\n              await this.room.storage.delete(this.adminKey(sender.id));\n              return;\n            }\n            await this.room.storage.put(this.adminKey(sender.id), \"active\");\n            this.sendAdmin(sender, { type: \"admin_ready\" });\n            this.sendAdmin(sender, await this.buildSnapshot());\n            this.sendAdmin(sender, {\n              type: \"admin_log_history\",\n              entries: await this.listLogHistory(),\n            });\n            return;\n          }\n\n          if (!adminMsg) return;\n\n          switch (adminMsg.type) {\n            case \"admin_refresh\": {\n              this.sendAdmin(sender, await this.buildSnapshot());\n              break;\n            }\n            case \"admin_kick_member\": {\n              const result = await this.adminKickMember(adminMsg.connId);\n              this.sendAdmin(sender, {\n                type: \"admin_action_result\",\n                action: \"kick_member\",\n                ok: result.ok,\n                message: result.message,\n              });\n              if (result.ok) this.sendAdmin(sender, await this.buildSnapshot());\n              break;\n            }\n            case \"admin_kick_queued\": {\n              const result = await this.adminKickQueued(adminMsg.connId);\n              this.sendAdmin(sender, {\n                type: \"admin_action_result\",\n                action: \"kick_queued\",\n                ok: result.ok,\n                message: result.message,\n              });\n              if (result.ok) this.sendAdmin(sender, await this.buildSnapshot());\n              break;\n            }\n            case \"admin_close_session\": {\n              const result = await this.adminCloseSession(adminMsg.sessionId);\n              this.sendAdmin(sender, {\n                type: \"admin_action_result\",\n                action: \"close_session\",\n                ok: result.ok,\n                message: result.message,\n              });\n              if (result.ok) this.sendAdmin(sender, await this.buildSnapshot());\n              break;\n            }\n            case \"admin_auth\":\n              break;\n          }\n        } catch (err) {\n          this.reportError(`onMessage:admin:${adminMsg?.type ?? \"unknown\"}`, err);\n        }\n        await this.flushBroadcasts();\n        return;\n      }\n\n      const msg = parseClientMessage(raw);\n      if (!msg) return;\n\n      try {\n        switch (msg.type) {\n          case \"claim\": {\n            const member = await this.getMember(sender.id);\n            if (member && !member.claimed && !member.claiming) {\n              await this.claimMember(sender.id, member);\n            }\n            break;\n          }\n\n          case \"request_token\": {\n            const member = await this.getMember(sender.id);\n            if (member) await this.sendMemberToken(sender);\n            break;\n          }\n\n          case \"session_ended\": {\n            const member = await this.getMember(sender.id);\n            if (member) {\n              await this.releaseMember(sender.id, member, \"server\", { notify: false });\n              await this.tryAdmitNext();\n            }\n            break;\n          }\n\n          case \"leave\": {\n            sender.close(1000, \"left\");\n            break;\n          }\n        }\n      } catch (err) {\n        this.reportError(`onMessage:${msg.type}`, err);\n      }\n      await this.flushBroadcasts();\n    }\n\n    // ── alarm: warnings, expiry, and session reconciliation ──────────────────\n\n    async onAlarm() {\n      try {\n        const members = await this.getAllMembers();\n        const now = Date.now();\n        let freedAny = false;\n\n        for (const [key, data] of members) {\n          const connId = key.replace(\"member:\", \"\");\n\n          // Liveness reconcile: if the member's PartyKit WS is gone but `onClose`\n          // never fired, release them so the slot seat frees and (on the last\n          // member) the server stops the session. The platform already reaped\n          // this member's WebRTC connection on its side. Skip members mid-claim —\n          // that network round-trip completes or grace-expires on its own.\n          if (!data.claiming && !this.room.getConnection(connId)) {\n            await this.releaseMember(connId, data, \"server\", { notify: false });\n            freedAny = true;\n            continue;\n          }\n\n          if (now >= data.expiresAt) {\n            const reason = data.claimed ? \"timeout\" : \"grace_timeout\";\n            await this.releaseMember(connId, data, reason, { notify: true });\n            freedAny = true;\n            continue;\n          }\n\n          if (data.claimed && !data.warned && now >= data.expiresAt - this.config.warningBeforeMs) {\n            this.sendTo(connId, {\n              type: \"time_warning\",\n              secondsLeft: Math.round((data.expiresAt - now) / 1000),\n              expiresAt: data.expiresAt,\n            });\n            await this.setMember(connId, { ...data, warned: true });\n          }\n        }\n\n        // Prune orphaned slots (stale members, no member records) before polling,\n        // so the platform isn't queried for slots that are about to be freed.\n        if (await this.reconcileSlots()) freedAny = true;\n\n        for (const [, slot] of await this.getAllSlots()) {\n          // Only poll slots whose Reactor session actually exists.\n          if (!slot.sessionId || slot.members.length === 0) continue;\n          if (now - (slot.lastPollAt ?? 0) < this.config.pollIntervalMs) continue;\n\n          const state = await this.api.getSessionState(slot.sessionId);\n          if (CoordinatorClient.isTerminal(state)) {\n            // Session already ended on the platform; releasing each member empties\n            // and deletes the slot. The default release's DELETE is a no-op (404).\n            this.log(\"info\", \"session_reaped\", \"Session ended on the platform; freeing the slot\", {\n              sessionId: slot.sessionId,\n              data: { state },\n            });\n            for (const connId of [...slot.members]) {\n              const member = await this.getMember(connId);\n              if (member) {\n                await this.releaseMember(connId, member, \"server\", { notify: true });\n              }\n            }\n            // Force-drop if the slot is orphaned (listed members had no records),\n            // so a terminal session can never wedge a slot forever.\n            await this.dropSlot(slot.slotId, \"server\", { notify: true });\n            freedAny = true;\n          } else {\n            // Re-read before writing: `getSessionState` opened the input gate, so\n            // the slot may have just been deleted. Never re-persist a stale copy.\n            const fresh = await this.getSlot(slot.slotId);\n            if (fresh) await this.setSlot({ ...fresh, lastPollAt: now });\n          }\n        }\n\n        if (freedAny) await this.tryAdmitNext();\n        // Always refresh countdowns for waiting clients and admin dashboards.\n        this.scheduleBroadcast();\n        this.scheduleAdminBroadcast();\n        await this.flushBroadcasts();\n      } catch (err) {\n        this.reportError(\"onAlarm\", err);\n      } finally {\n        await this.scheduleNextAlarm();\n      }\n    }\n\n    private async scheduleNextAlarm(): Promise<void> {\n      const members = await this.getAllMembers();\n      const slots = await this.getAllSlots();\n      if (members.size === 0 && slots.size === 0) {\n        await this.room.storage.deleteAlarm();\n        return;\n      }\n\n      const now = Date.now();\n      let earliest = Infinity;\n\n      for (const [, data] of members) {\n        earliest = Math.min(earliest, data.expiresAt);\n        if (data.claimed && !data.warned) {\n          earliest = Math.min(earliest, data.expiresAt - this.config.warningBeforeMs);\n        }\n      }\n\n      for (const [, slot] of slots) {\n        if (slot.sessionId && slot.members.length > 0) {\n          earliest = Math.min(earliest, now + this.config.pollIntervalMs);\n        }\n      }\n\n      if (earliest !== Infinity) {\n        await this.room.storage.setAlarm(Math.max(earliest, now + 100));\n      }\n    }\n\n    // ── admission + token minting ────────────────────────────────────────────\n\n    private async tryAdmitNext() {\n      let queueChanged = false;\n      let admittedAny = false;\n      let startAfter: string | undefined = undefined;\n\n      // Walk the front of the queue in small FIFO batches. We only ever admit up\n      // to the (small, GPU-bounded) remaining capacity, plus we skip any dead\n      // front entries — so this touches O(admitted + stale) keys, not the whole\n      // line. `frontQueue` reads individual keys, never one giant array.\n      admit: while (true) {\n        const batch = await this.frontQueue(20, startAfter);\n        if (batch.length === 0) break;\n\n        for (const [key, connId] of batch) {\n          startAfter = key;\n\n          const open = await this.findOpenSlot();\n          const slotCount = await this.getSlotCount();\n          // Reserve a seat in an open slot, or open a new slot if under the cap.\n          if (!open && slotCount >= this.config.maxSessions) break admit;\n\n          if (!this.room.getConnection(connId)) {\n            // Dead/stale front entry — drop it.\n            await this.dequeue(connId);\n            queueChanged = true;\n            continue;\n          }\n\n          const slot: SlotRecord = open ?? {\n            slotId: this.genId(),\n            sessionId: null,\n            members: [],\n            createdAt: Date.now(),\n          };\n          await this.setSlot({ ...slot, members: [...slot.members, connId] });\n\n          await this.dequeue(connId);\n          queueChanged = true;\n\n          await this.setMember(connId, {\n            slotId: slot.slotId,\n            sessionId: null,\n            connectionId: null,\n            expiresAt: Date.now() + this.config.admissionGraceMs,\n            warned: false,\n            claimed: false,\n          });\n\n          const activeCount = await this.getActiveMemberCount();\n          this.sendTo(connId, {\n            type: \"admitted\",\n            active: activeCount,\n            capacity: this.config.capacity,\n            graceMs: this.config.admissionGraceMs,\n            sessionDurationMs: this.config.sessionDurationMs,\n          });\n          this.log(\n            \"info\",\n            \"user_admitted\",\n            \"User reached the front and was admitted (slot reserved, no session yet)\",\n            {\n              connId,\n            }\n          );\n          // A member seated on a slot that is already running can be handed a\n          // token now; one holding a freshly reserved slot has no session to\n          // bind against yet and receives theirs at claim.\n          const conn = this.room.getConnection(connId);\n          if (conn) await this.sendMemberToken(conn);\n          admittedAny = true;\n        }\n      }\n\n      if (admittedAny) await this.scheduleNextAlarm();\n      this.scheduleBroadcast();\n      if (queueChanged || admittedAny) this.scheduleAdminBroadcast();\n    }\n\n    /**\n     * The member confirmed entry. Seat them on a session that accepts a freshly\n     * minted WebRTC connection (their own slot's, an existing one with room, or a\n     * new one), start the full session timer, and hand back the `sessionId` +\n     * server-minted `connectionId` to attach with. The server owns both, so the\n     * client only adopts — it never creates or stops anything.\n     */\n    private async claimMember(connId: string, member: MemberData): Promise<void> {\n      // Mark mid-claim *before* the first yield. Acquiring a session and minting\n      // a connection are network calls and the DO input gate is open across them,\n      // so a duplicate `claim` could otherwise slip past the `!claimed` guard.\n      // This persisted flag closes that window; it is cleared on completion or\n      // failure (a stuck flag self-heals on grace expiry, which still releases\n      // the member).\n      await this.setMember(connId, { ...member, claiming: true });\n\n      const placement = await this.placeMemberWithConnection(connId, member);\n      if (!placement) {\n        // No session could take the member (all at their connection cap, or\n        // session creation failed). The admin log already carries the\n        // Coordinator status/body from the failing call.\n        await this.setMember(connId, { ...member, claiming: false });\n        this.sendTo(connId, { type: \"error\", message: \"no_capacity\" });\n        return;\n      }\n\n      const { slotId, sessionId, connectionId } = placement;\n      const expiresAt = Date.now() + this.config.sessionDurationMs;\n      await this.setMember(connId, {\n        ...member,\n        slotId,\n        sessionId,\n        connectionId,\n        expiresAt,\n        warned: false,\n        claimed: true,\n        claiming: false,\n      });\n\n      // A member's token binds to exactly one session and the claim is what\n      // decides which — their own slot, a shared slot with room, or a fresh\n      // one — so it can only be minted here. Sent before session_ready so the\n      // SDK holds it the moment it is told what to attach to.\n      const conn = this.room.getConnection(connId);\n      if (conn) await this.sendMemberToken(conn);\n\n      this.sendTo(connId, {\n        type: \"session_ready\",\n        sessionId,\n        connectionId,\n        sessionDurationMs: this.config.sessionDurationMs,\n        expiresAt,\n      });\n      this.config.hooks.onUserEnteredSession?.(connId, sessionId);\n      this.log(\"info\", \"session_ready\", \"User claimed and entered the session\", {\n        connId,\n        sessionId,\n        data: { connectionId },\n      });\n      await this.scheduleNextAlarm();\n      this.scheduleAdminBroadcast();\n    }\n\n    /**\n     * Seat a claiming member on a slot whose Reactor session accepts a freshly\n     * minted WebRTC connection, returning that placement. Tries the member's own\n     * slot first, then any other slot with a free seat, then a brand-new slot\n     * (bounded by `maxSessions`). The connection mint is the real capacity test:\n     * a 429 means the session hit its `connections_per_session` cap, so we spill\n     * to the next candidate; transient mint errors retry on the same session.\n     * Returns null when nothing could take the member.\n     */\n    private async placeMemberWithConnection(\n      connId: string,\n      member: MemberData\n    ): Promise<{ slotId: string; sessionId: string; connectionId: number } | null> {\n      const candidates: string[] = [member.slotId];\n      for (const [, slot] of await this.getAllSlots()) {\n        if (slot.slotId !== member.slotId && slot.members.length < this.config.usersPerSession) {\n          candidates.push(slot.slotId);\n        }\n      }\n\n      for (const slotId of candidates) {\n        const minted = await this.mintConnectionOnSlot(connId, slotId);\n        if (minted) {\n          await this.assignMemberToSlot(connId, member.slotId, slotId);\n          return { slotId, ...minted };\n        }\n      }\n\n      // No existing session could take the member — open a new slot if under the cap.\n      if ((await this.getSlotCount()) < this.config.maxSessions) {\n        const newSlot: SlotRecord = {\n          slotId: this.genId(),\n          sessionId: null,\n          members: [],\n          createdAt: Date.now(),\n        };\n        await this.setSlot(newSlot);\n        const minted = await this.mintConnectionOnSlot(connId, newSlot.slotId);\n        if (minted) {\n          await this.assignMemberToSlot(connId, member.slotId, newSlot.slotId);\n          return { slotId: newSlot.slotId, ...minted };\n        }\n        // The fresh slot couldn't take a connection either — drop it + its session.\n        await this.dropSlot(newSlot.slotId, \"server\", { notify: false });\n      }\n\n      return null;\n    }\n\n    /**\n     * Ensure the slot has a Reactor session (creating one if needed) and mint a\n     * WebRTC connection under it, retrying transient failures. Returns the\n     * session + connection id on success, or null if the session is at its\n     * connection cap, if creation failed, or if the slot vanished — the caller\n     * spills to the next candidate. Writes re-read after each network await (the\n     * input gate is open across them) so a concurrent handler isn't clobbered.\n     */\n    private async mintConnectionOnSlot(\n      connId: string,\n      slotId: string\n    ): Promise<{ sessionId: string; connectionId: number } | null> {\n      const slot = await this.getSlot(slotId);\n      if (!slot) return null;\n\n      let sessionId = slot.sessionId;\n      if (!sessionId) {\n        try {\n          sessionId = await this.runAcquire(this.config.model);\n        } catch (err) {\n          this.reportError(\"session_create_failed\", err, { connId });\n          return null;\n        }\n        const fresh = await this.getSlot(slotId);\n        if (!fresh) return null;\n        await this.setSlot({ ...fresh, sessionId });\n        this.config.hooks.onSessionCreated?.(sessionId);\n        this.log(\"info\", \"session_created\", \"Created a new Reactor session\", { connId, sessionId });\n      }\n\n      for (let attempt = 1; attempt <= CONNECTION_MINT_ATTEMPTS; attempt++) {\n        try {\n          const connectionId = await this.api.createConnection(sessionId);\n          return { sessionId, connectionId };\n        } catch (err) {\n          if (err instanceof CoordinatorError && err.status === 429) {\n            this.log(\"info\", \"connection_cap_reached\", \"Session at its connection cap; spilling\", {\n              connId,\n              sessionId,\n            });\n            return null;\n          }\n          if (attempt === CONNECTION_MINT_ATTEMPTS) {\n            this.reportError(\"connection_mint_failed\", err, { connId, sessionId });\n            return null;\n          }\n          await this.sleep(CONNECTION_MINT_RETRY_MS);\n        }\n      }\n      return null;\n    }\n\n    /**\n     * Move a member's slot membership from `fromSlotId` to `toSlotId` (no-op when\n     * they are the same). The member is removed from the source first; if that\n     * empties the source, its session is released and the slot dropped, so a\n     * session created for a member who then spilled elsewhere never lingers.\n     */\n    private async assignMemberToSlot(\n      connId: string,\n      fromSlotId: string,\n      toSlotId: string\n    ): Promise<void> {\n      if (fromSlotId === toSlotId) return;\n\n      const to = await this.getSlot(toSlotId);\n      if (to && !to.members.includes(connId)) {\n        await this.setSlot({ ...to, members: [...to.members, connId] });\n      }\n\n      const from = await this.getSlot(fromSlotId);\n      if (!from) return;\n      const remaining = from.members.filter((id) => id !== connId);\n      if (remaining.length > 0) {\n        await this.setSlot({ ...from, members: remaining });\n        return;\n      }\n\n      // Source emptied by the move: release its session (if any) and drop it.\n      if (from.sessionId) {\n        await this.runRelease({\n          sessionId: from.sessionId,\n          userId: connId,\n          reason: \"server\",\n          lastMember: true,\n        });\n        this.config.hooks.onSessionClosed?.(from.sessionId, \"server\");\n      }\n      // Re-read after the network release before deleting (gate was open).\n      const recheck = await this.getSlot(fromSlotId);\n      if (recheck && recheck.members.filter((id) => id !== connId).length === 0) {\n        await this.deleteSlot(fromSlotId);\n        this.scheduleAdminBroadcast();\n      }\n    }\n\n    private sleep(ms: number): Promise<void> {\n      return new Promise((resolve) => setTimeout(resolve, ms));\n    }\n\n    /**\n     * Send a member a token for the session their slot holds. A member still in\n     * the admission grace has no session to bind to yet and is answered at\n     * claim instead; the SDK has nothing to attach to until then, and its\n     * `getJwt` resolver re-asks over `request_token` when it does.\n     *\n     * There is no unscoped path. A session an `acquireSession` override sourced\n     * from another user cannot be bound, and the Coordinator's refusal is\n     * reported as-is rather than quietly answered with an account-wide token.\n     */\n    private async sendMemberToken(conn: Party.Connection): Promise<void> {\n      try {\n        const member = await this.getMember(conn.id);\n        if (!member) return;\n        const slot = await this.getSlot(member.slotId);\n        if (!slot?.sessionId) return;\n        const token = await this.mintMemberToken(slot.sessionId);\n        this.send(conn, { type: \"token\", jwt: token.jwt, expiresAt: token.expiresAt });\n      } catch (err) {\n        this.reportError(\"mintToken\", err);\n        this.send(conn, { type: \"error\", message: \"token_mint_failed\" });\n      }\n    }\n\n    /**\n     * Remove a member from its slot. If the slot has a session, fire the\n     * `release` callback (a user left) with `lastMember`; the default deletes the\n     * session when the last member leaves. When the slot empties, delete its\n     * record and fire `onSessionClosed`. A slot whose session was never created\n     * (abandoned grace) just disappears — no orphan, no release.\n     */\n    private async releaseMember(\n      connId: string,\n      data: MemberData,\n      reason: \"timeout\" | \"grace_timeout\" | \"server\",\n      opts: { notify: boolean }\n    ): Promise<void> {\n      if (opts.notify) {\n        this.sendTo(connId, { type: \"expired\", reason });\n      }\n\n      if (reason === \"timeout\") {\n        this.log(\"info\", \"session_timeout\", \"Session time elapsed; reclaiming the slot\", {\n          connId,\n          sessionId: data.sessionId ?? undefined,\n        });\n      } else if (reason === \"grace_timeout\") {\n        this.log(\"info\", \"grace_timeout\", \"Admitted user did not claim in time; slot reclaimed\", {\n          connId,\n        });\n      }\n\n      const slot = await this.getSlot(data.slotId);\n      if (slot) {\n        const lastMember = slot.members.filter((id) => id !== connId).length === 0;\n\n        if (slot.sessionId) {\n          await this.runRelease({\n            sessionId: slot.sessionId,\n            userId: connId,\n            reason,\n            lastMember,\n          });\n        }\n\n        // Re-read after `runRelease`: the input gate is open across that network\n        // call, so a concurrent handler may have mutated or deleted this slot.\n        // Writing back the pre-call snapshot is what resurrects a just-deleted\n        // slot into an orphan (members listed, member record gone), so apply the\n        // removal to the *current* record — or skip entirely if it's already gone.\n        const fresh = await this.getSlot(data.slotId);\n        if (fresh) {\n          const nextMembers = fresh.members.filter((id) => id !== connId);\n          if (nextMembers.length === 0) {\n            await this.deleteSlot(fresh.slotId);\n            if (fresh.sessionId) {\n              this.config.hooks.onSessionClosed?.(fresh.sessionId, reason);\n              this.log(\"info\", \"session_closed\", \"Reactor session closed (last member left)\", {\n                sessionId: fresh.sessionId,\n                data: { reason },\n              });\n            }\n            this.scheduleAdminBroadcast();\n          } else {\n            await this.setSlot({ ...fresh, members: nextMembers });\n          }\n        }\n      }\n\n      await this.deleteMember(connId);\n    }\n\n    /**\n     * Tear a slot down directly, independent of whether its member records still\n     * exist. Releases the Reactor session (if any), drops any member records the\n     * slot still lists, and deletes the slot. This is the recovery path for an\n     * *orphaned* slot — one listing members whose `member:` records were already\n     * deleted by a concurrent release — which `releaseMember` can never reach\n     * because it keys off the member record. Safe to call on an already-gone slot.\n     *\n     * Storage is torn down first (no network in between, so it lands atomically\n     * w.r.t. other handlers); the best-effort session release runs afterwards,\n     * once internal state is already consistent.\n     */\n    private async dropSlot(\n      slotId: string,\n      reason: \"timeout\" | \"grace_timeout\" | \"server\",\n      opts: { notify: boolean }\n    ): Promise<void> {\n      const slot = await this.getSlot(slotId);\n      if (!slot) return;\n\n      for (const connId of slot.members) {\n        if (opts.notify) this.sendTo(connId, { type: \"expired\", reason });\n        await this.deleteMember(connId);\n      }\n      await this.deleteSlot(slot.slotId);\n      this.scheduleAdminBroadcast();\n\n      if (slot.sessionId) {\n        await this.runRelease({ sessionId: slot.sessionId, userId: \"\", reason, lastMember: true });\n        this.config.hooks.onSessionClosed?.(slot.sessionId, reason);\n        this.log(\"info\", \"session_closed\", \"Reactor session closed (slot dropped)\", {\n          sessionId: slot.sessionId,\n          data: { reason },\n        });\n      }\n    }\n\n    /**\n     * Self-heal slot/member drift. A release spans the `DELETE /sessions` network\n     * call with the input gate open, so it can interleave with a concurrent slot\n     * write and leave a slot referencing a connId whose `member:` record is gone\n     * — an orphan no normal path reaps (the reap and admin close both key off the\n     * member record). Prune stale connIds from every slot; if that empties a\n     * slot, drop it (releasing its Reactor session). Returns true if it freed a\n     * slot, so the caller can re-run admission.\n     */\n    private async reconcileSlots(): Promise<boolean> {\n      let freed = false;\n      for (const [slotKey] of await this.getAllSlots()) {\n        const slotId = slotKey.replace(\"slot:\", \"\");\n        const slot = await this.getSlot(slotId);\n        if (!slot) continue;\n\n        const live: string[] = [];\n        for (const connId of slot.members) {\n          if (await this.getMember(connId)) live.push(connId);\n        }\n        if (live.length === slot.members.length) continue;\n\n        if (live.length === 0) {\n          this.log(\"warn\", \"slot_reconciled\", \"Dropped an orphaned slot (no live members)\", {\n            sessionId: slot.sessionId ?? undefined,\n            data: { staleMembers: slot.members.length },\n          });\n          await this.dropSlot(slot.slotId, \"server\", { notify: false });\n          freed = true;\n        } else {\n          this.log(\"warn\", \"slot_reconciled\", \"Pruned stale members from a slot\", {\n            sessionId: slot.sessionId ?? undefined,\n            data: { before: slot.members.length, after: live.length },\n          });\n          await this.setSlot({ ...slot, members: live });\n        }\n      }\n      return freed;\n    }\n\n    // ── broadcasting (coalesced, hibernation-safe) ────────────────────────────\n\n    /** Mark queue positions dirty; flushed once at the end of the current handler. */\n    private scheduleBroadcast(): void {\n      this.positionsDirty = true;\n    }\n\n    /**\n     * Flush any pending broadcasts. Called at the end of every top-level handler\n     * (onConnect/onClose/onMessage/onAlarm) so the work completes inside the\n     * awaited handler turn — before PartyKit can hibernate the room. Multiple\n     * `schedule*` calls within one handler collapse into a single broadcast.\n     */\n    private async flushBroadcasts(): Promise<void> {\n      if (this.positionsDirty) {\n        this.positionsDirty = false;\n        try {\n          await this.broadcastPositions();\n        } catch (err) {\n          this.reportError(\"broadcast\", err);\n        }\n      }\n      const haveLogs = this.pendingLogs.length > 0;\n      if (this.adminDirty || haveLogs) {\n        // Resolve the active admin set once: the snapshot push and the log stream\n        // both target it, so we don't scan `admin:` twice per flush.\n        const admins = await this.getActiveAdminConnIds();\n\n        if (this.adminDirty) {\n          this.adminDirty = false;\n          try {\n            await this.broadcastAdminSnapshots(admins);\n          } catch (err) {\n            this.reportError(\"adminBroadcast\", err);\n          }\n        }\n\n        if (haveLogs) {\n          const batch = this.pendingLogs;\n          this.pendingLogs = [];\n          try {\n            // Persist only warn/error — the rare, diagnostic history (kept even\n            // with no admin watching, so it's there when one connects). `info`\n            // is streamed to live admins but never written to storage, so the\n            // high-frequency connect/disconnect hot path stays storage-free.\n            const durable = batch.filter((e) => e.level !== \"info\");\n            if (durable.length > 0) await this.persistLogs(durable);\n            this.broadcastLogs(admins, batch);\n          } catch (err) {\n            // Never route through reportError → log() (would re-enqueue and recurse).\n            console.error(\"[reactor-queue] logFlush\", err);\n          }\n        }\n      }\n    }\n\n    private async broadcastPositions() {\n      // Full FIFO scan — every waiter gets their exact position (no approximation).\n      // O(N) iteration over individual keys; each send is an O(1) connection lookup.\n      const queue = await this.listQueue();\n      const total = queue.length;\n      const activeCount = await this.getActiveMemberCount();\n      for (let i = 0; i < queue.length; i++) {\n        const connId = queue[i]!;\n        this.sendTo(connId, {\n          type: \"queue_position\",\n          position: i + 1,\n          total,\n          active: activeCount,\n          capacity: this.config.capacity,\n        });\n      }\n    }\n  };\n}\n"]}