openrtc 2.9.8 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +17 -18
  2. package/dist/{Connection-DJoPKC0L.d.ts → Connection-BZ6piJsh.d.ts} +0 -2
  3. package/dist/{DelegatingRuntimeAdapter-d1xrjmHE.d.ts → DelegatingRuntimeAdapter-s3QvVuTj.d.ts} +2 -2
  4. package/dist/{IpcRuntimeAdapter-BkJdH7OQ.d.ts → IpcRuntimeAdapter-CghYNfcc.d.ts} +2 -2
  5. package/dist/{WasmBridge-VGIBWCAC.js → WasmBridge-JZGJHSSU.js} +1 -1
  6. package/dist/{assembly-0EnNAgmm.d.ts → assembly-BEMgeExQ.d.ts} +2 -2
  7. package/dist/{capabilities-dnGwtGmQ.d.ts → capabilities-fJ11v3xA.d.ts} +1 -1
  8. package/dist/chunk-2Q75GXGE.js +2 -0
  9. package/dist/{chunk-TWTPJDUN.js → chunk-C3TAFNG6.js} +1 -1
  10. package/dist/chunk-CAUMGKP4.js +2 -0
  11. package/dist/chunk-F3IZBMAT.js +1 -0
  12. package/dist/{chunk-S67YUD3E.js → chunk-LTMH2AIS.js} +1 -1
  13. package/dist/{chunk-WNCBDRFC.js → chunk-R6J4PZDI.js} +1 -1
  14. package/dist/chunk-RSQCDTS2.js +1 -0
  15. package/dist/{chunk-P6G2PAWP.js → chunk-W45XAU3I.js} +1 -1
  16. package/dist/{chunk-O5EGI6OZ.js → chunk-W4IU7H7H.js} +1 -1
  17. package/dist/controlPlane-45AU3CSM.js +1 -0
  18. package/dist/coreClient-BYWmk_1O.d.ts +309 -0
  19. package/dist/coreClient.d.ts +4 -250
  20. package/dist/coreClient.js +1 -1
  21. package/dist/{deviceEnrollment-IPKFITV6.js → deviceEnrollment-OFC6DSZP.js} +2 -2
  22. package/dist/deviceHandle-3P46T7SV.js +1 -0
  23. package/dist/external-broadcast.d.ts +5 -5
  24. package/dist/external-broadcast.js +1 -1
  25. package/dist/index.d.ts +7 -7
  26. package/dist/index.js +1 -1
  27. package/dist/{ipcFactory-L73S4NGQ.js → ipcFactory-2MDPNX5M.js} +1 -1
  28. package/dist/native.d.ts +6 -6
  29. package/dist/native.js +1 -1
  30. package/dist/node.d.ts +7 -7
  31. package/dist/node.js +2 -2
  32. package/dist/openrtc-6RZZ7PEN.js +2 -0
  33. package/dist/openrtc_bg.wasm +0 -0
  34. package/dist/room-P5SHPIGF.js +1 -0
  35. package/dist/runtime/WasmRuntimeAdapter.d.ts +3 -3
  36. package/dist/runtime/WasmRuntimeAdapter.js +1 -1
  37. package/dist/runtime/device-status.d.ts +1 -1
  38. package/dist/runtime/factories.d.ts +5 -5
  39. package/dist/runtime/factories.js +1 -1
  40. package/dist/runtime/index.d.ts +10 -10
  41. package/dist/runtime/index.js +1 -1
  42. package/dist/server-browser.d.ts +5 -5
  43. package/dist/server.d.ts +5 -5
  44. package/dist/server.js +1 -1
  45. package/dist/service-node.d.ts +5 -5
  46. package/dist/service-node.js +1 -1
  47. package/dist/testing/native.d.ts +5 -5
  48. package/dist/testing/native.js +1 -1
  49. package/dist/testing.d.ts +5 -9
  50. package/dist/testing.js +1 -1
  51. package/dist/transport/index.d.ts +2 -2
  52. package/dist/{types-uDwIMPRk.d.ts → types-BXYC9Q5H.d.ts} +7 -47
  53. package/native/darwin-arm64/openrtc-node-host +0 -0
  54. package/native/darwin-arm64/openrtc-node-host.manifest.json +4 -4
  55. package/native/darwin-x64/openrtc-node-host +0 -0
  56. package/native/darwin-x64/openrtc-node-host.manifest.json +4 -4
  57. package/native/linux-x64/openrtc-node-host +0 -0
  58. package/native/linux-x64/openrtc-node-host.manifest.json +4 -4
  59. package/package.json +1 -1
  60. package/dist/chunk-4EOOERQ4.js +0 -2
  61. package/dist/chunk-MTCLMTJN.js +0 -1
  62. package/dist/chunk-XR5JZKFP.js +0 -2
  63. package/dist/controlPlane-HLMTVL5V.js +0 -1
  64. package/dist/deviceHandle-ZYN473A4.js +0 -1
  65. package/dist/openrtc-YI4N7T34.js +0 -2
  66. package/dist/room-5NW3SV4C.js +0 -1
package/README.md CHANGED
@@ -162,7 +162,7 @@ await service.listen('world-42');
162
162
 
163
163
  `maxPeers` counts everyone in the room, including the service. Node defaults to
164
164
  eight; set a value from 1 through 50 explicitly when needed. Your app's approved
165
- limit and available credits still apply, so a larger request can be denied.
165
+ capacity limits still apply, so a larger request can be denied.
166
166
  Browser and standalone Rust grant requests may omit the value to use app policy.
167
167
  These limits are not a promise of 50 simultaneous server connections or a
168
168
  replacement for the remaining authority acceptance tests.
@@ -218,24 +218,12 @@ Managed Firebase App Check, Apple App Attest, and Play Integrity are optional
218
218
  packages. A consumer backend may instead validate platform evidence and issue
219
219
  the registered OIDC assertion; that is the canonical production integration.
220
220
 
221
- ## Usage controls
221
+ ## Capacity and billing
222
222
 
223
- ```ts
224
- const rtc = OpenRTC({
225
- apiKey,
226
- usage: {
227
- warnAtSessionCreditsUsd: 0.25,
228
- maxSessionCreditsUsd: 0.50,
229
- onUsage: console.log,
230
- onWarning: console.warn,
231
- },
232
- });
233
-
234
- rtc.usage.estimate({ operation: 'coordination.connection.open', units: 3 });
235
- ```
236
-
237
- The client ceiling is an additional local guard. Server budgets and developer
238
- manifest limits remain authoritative.
223
+ Plans include app, user, room, space, and device allowances. Configure overage
224
+ consent and a finite spending ceiling in the Developer Portal. The service
225
+ checks capacity when admitting new usage; SDK sessions do not spend event credits.
226
+ Purchased limits and rates remain in effect through the paid monthly term.
239
227
 
240
228
  ## Native and WASM
241
229
 
@@ -272,6 +260,17 @@ the explicitly enabled, content-blind managed path. `advancedFanout: true` is a
272
260
  one-release alias for fixed sparse latest-state delivery. `state()` remains
273
261
  unavailable in sparse rooms; use a named channel with application revisions.
274
262
 
263
+ ### Debugging
264
+
265
+ For an opt-in, bounded support timeline, use
266
+ `const capture = ticket.diagnostics.capture({ maxEvents: 256 })`, reproduce the
267
+ problem, then call `capture.stop()` and save `capture.snapshot()`. Constructor
268
+ `diagnostics: { logger }` records activation outcomes even before a handle
269
+ exists. Rust hosts use `client.diagnostic_snapshot().await` and the standard
270
+ `tracing` subscriber owned by their app. Credentials and payloads are excluded
271
+ from these new support records; legacy verbose logs remain private.
272
+ See the [debugging guide](../../apps/docs/content/openrtc/debugging.mdx) for setup and interpretation.
273
+
275
274
  ### Passive connection metrics
276
275
 
277
276
  ```ts
@@ -1287,8 +1287,6 @@ interface RoomArchitectureSnapshot {
1287
1287
  epoch: number;
1288
1288
  phase: 'settled' | 'preparing';
1289
1289
  reason: RoomArchitectureReason;
1290
- heldCreditsUsd: number;
1291
- quoteExpiresAtMs: number;
1292
1290
  }
1293
1291
  /**
1294
1292
  * Read-only application-interest projection signed by the room's registered
@@ -1,5 +1,5 @@
1
- import { U as DiscoveryMode, V as AuthMode, W as SignalingMode, X as ClientOptions, Y as ExplicitFileDataSendParams, Z as ISignalingBackend, _ as RuntimeIdentity, O as AuthContext, $ as RoomMember, a0 as Device, a1 as DeviceStatusSnapshot, n as PeerSessionSnapshot, q as ResolvedPeerIdentity, a2 as ManagedConnectionRecord, a3 as SignalingEnvelope, a4 as DeviceEvent, d as TransferPeerDemandRequest, f as TransferPeerDemandStatus, a5 as DesiredPeerProjection, a6 as SignalingSession, a7 as SessionEvent, a8 as LocalDeviceInfo, a9 as NativeManagedSessionStartResult, j as ProtocolName, N as GrantScope, aa as TicketMeshPeerReadiness, ab as BackendPeerBiStream, ac as BackendPeerUniStream, ad as PortableMediaPublish, ae as PortableMediaPublicationStart, af as PortableMediaSample, ag as PortableMediaChunk, ah as PortableMediaControl, ai as NativeConnectParams, aj as NativeConnectResult, ak as BackendConnectionState, al as NativePeerDataEvent } from './Connection-DJoPKC0L.js';
2
- import { R as RuntimeCapabilities } from './capabilities-dnGwtGmQ.js';
1
+ import { U as DiscoveryMode, V as AuthMode, W as SignalingMode, X as ClientOptions, Y as ExplicitFileDataSendParams, Z as ISignalingBackend, _ as RuntimeIdentity, O as AuthContext, $ as RoomMember, a0 as Device, a1 as DeviceStatusSnapshot, n as PeerSessionSnapshot, q as ResolvedPeerIdentity, a2 as ManagedConnectionRecord, a3 as SignalingEnvelope, a4 as DeviceEvent, d as TransferPeerDemandRequest, f as TransferPeerDemandStatus, a5 as DesiredPeerProjection, a6 as SignalingSession, a7 as SessionEvent, a8 as LocalDeviceInfo, a9 as NativeManagedSessionStartResult, j as ProtocolName, N as GrantScope, aa as TicketMeshPeerReadiness, ab as BackendPeerBiStream, ac as BackendPeerUniStream, ad as PortableMediaPublish, ae as PortableMediaPublicationStart, af as PortableMediaSample, ag as PortableMediaChunk, ah as PortableMediaControl, ai as NativeConnectParams, aj as NativeConnectResult, ak as BackendConnectionState, al as NativePeerDataEvent } from './Connection-BZ6piJsh.js';
2
+ import { R as RuntimeCapabilities } from './capabilities-fJ11v3xA.js';
3
3
 
4
4
  /** Host-neutral configuration shared by browser/WASM and native/IPC adapters. */
5
5
  interface RuntimeBridgeOptions {
@@ -1,6 +1,6 @@
1
- import { R as RuntimeBridgeOptions, D as DelegatingRuntimeAdapter } from './DelegatingRuntimeAdapter-d1xrjmHE.js';
1
+ import { R as RuntimeBridgeOptions, D as DelegatingRuntimeAdapter } from './DelegatingRuntimeAdapter-s3QvVuTj.js';
2
2
  import { P as PlutoIpcBridge } from './ipc-DgzKqHH3.js';
3
- import { S as ServiceErrorObservation, ak as BackendConnectionState, al as NativePeerDataEvent, a0 as Device } from './Connection-DJoPKC0L.js';
3
+ import { S as ServiceErrorObservation, ak as BackendConnectionState, al as NativePeerDataEvent, a0 as Device } from './Connection-BZ6piJsh.js';
4
4
 
5
5
  /**
6
6
  * Root-client owner for the one native WebView projection.
@@ -1 +1 @@
1
- export{b as WasmBridge,a as loadBrowserWasmRuntimeModule}from'./chunk-S67YUD3E.js';import'./chunk-AYHD4X2R.js';import'./chunk-XR5JZKFP.js';import'./chunk-L4HWDDXL.js';import'./chunk-OT7IPLZE.js';import'./chunk-OWKAJPOI.js';import'./chunk-TPF643LU.js';import'./chunk-L2ZZXECX.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';
1
+ export{b as WasmBridge,a as loadBrowserWasmRuntimeModule}from'./chunk-LTMH2AIS.js';import'./chunk-AYHD4X2R.js';import'./chunk-CAUMGKP4.js';import'./chunk-L4HWDDXL.js';import'./chunk-OT7IPLZE.js';import'./chunk-OWKAJPOI.js';import'./chunk-TPF643LU.js';import'./chunk-L2ZZXECX.js';import'./chunk-CCCYE3XN.js';import'./chunk-JPBW67B3.js';import'./chunk-L7N4T2PX.js';import'./chunk-72MN7BNQ.js';import'./chunk-2GX6GB6L.js';
@@ -1,5 +1,5 @@
1
- import { k as RuntimePeerState, v as ConnectionState, o as PeerReadiness, l as PeerConnectOptions, m as Connection, I as IncomingStream, N as GrantScope, Q as RuntimeClientOptions, Z as ISignalingBackend, aD as RuntimeAuthIdentity, O as AuthContext, j as ProtocolName, L as LocalDeviceInfo, G as DeviceProfile, aq as BrowserProtocolStore, ar as NamespaceDescriptor, as as IrohMutationReceipt, at as IrohDocEntry, aj as NativeConnectResult, t as RuntimeDevice, M as ManagedOptions, y as ManagedSession, D as DeviceStatus, B as ConnectDeviceHooks, F as ConnectDeviceOptions, A as ConnectDeviceResult, z as DeviceConnectOptions, a2 as ManagedConnectionRecord, n as PeerSessionSnapshot, q as ResolvedPeerIdentity, aE as RuntimeSession, aF as AppLimits, J as JoinRoomOptions, K as RuntimeRoomMember, aG as ConnectionTarget, s as ScopedChannelOptions, u as ScopedLogicalChannel, r as PeerStreamOptions, ai as NativeConnectParams, H as RawConnection, C as ChannelDescriptor, Y as ExplicitFileDataSendParams, aH as PresenceLoopOptions, d as TransferPeerDemandRequest, f as TransferPeerDemandStatus, b as RoomArchitectureSnapshot, c as RoomAuthorityAssignment, p as RuntimePeerHealth, w as ReadinessOptions, x as ConnectionEvent } from './Connection-DJoPKC0L.js';
2
- import { R as RuntimeCapabilities, C as CapabilityProfile } from './capabilities-dnGwtGmQ.js';
1
+ import { k as RuntimePeerState, v as ConnectionState, o as PeerReadiness, l as PeerConnectOptions, m as Connection, I as IncomingStream, N as GrantScope, Q as RuntimeClientOptions, Z as ISignalingBackend, aD as RuntimeAuthIdentity, O as AuthContext, j as ProtocolName, L as LocalDeviceInfo, G as DeviceProfile, aq as BrowserProtocolStore, ar as NamespaceDescriptor, as as IrohMutationReceipt, at as IrohDocEntry, aj as NativeConnectResult, t as RuntimeDevice, M as ManagedOptions, y as ManagedSession, D as DeviceStatus, B as ConnectDeviceHooks, F as ConnectDeviceOptions, A as ConnectDeviceResult, z as DeviceConnectOptions, a2 as ManagedConnectionRecord, n as PeerSessionSnapshot, q as ResolvedPeerIdentity, aE as RuntimeSession, aF as AppLimits, J as JoinRoomOptions, K as RuntimeRoomMember, aG as ConnectionTarget, s as ScopedChannelOptions, u as ScopedLogicalChannel, r as PeerStreamOptions, ai as NativeConnectParams, H as RawConnection, C as ChannelDescriptor, Y as ExplicitFileDataSendParams, aH as PresenceLoopOptions, d as TransferPeerDemandRequest, f as TransferPeerDemandStatus, b as RoomArchitectureSnapshot, c as RoomAuthorityAssignment, p as RuntimePeerHealth, w as ReadinessOptions, x as ConnectionEvent } from './Connection-BZ6piJsh.js';
2
+ import { R as RuntimeCapabilities, C as CapabilityProfile } from './capabilities-fJ11v3xA.js';
3
3
 
4
4
  /**
5
5
  * Coalesced peer reconciliation scheduler and full reconcile orchestration.
@@ -1,4 +1,4 @@
1
- import { j as ProtocolName, i as RouteOptimization } from './Connection-DJoPKC0L.js';
1
+ import { j as ProtocolName, i as RouteOptimization } from './Connection-BZ6piJsh.js';
2
2
 
3
3
  type RuntimeAdapterKind = 'browser-wasm' | 'native-ipc' | 'tauri-ipc' | 'unknown';
4
4
  type CapabilityMaturity = 'stable' | 'preview' | 'support-only' | 'unavailable';
@@ -0,0 +1,2 @@
1
+ import {b as b$2}from'./chunk-ZA44REGI.js';import {e,a}from'./chunk-L7N4T2PX.js';import {d,b as b$1,e as e$1}from'./chunk-72MN7BNQ.js';function b(s){return {irohRelay:s.irohRelay===true||s.irohRelay===void 0&&s.relay!==false,managedTurn:s.managedTurn===true}}var B=1440*6e4,w=class extends Error{constructor(r,n,a$1){super(r);this.status=n;this.reason=a$1;this.name="RTCError";let t=[502,503,504].includes(n),o=a$1==="device-reenrollment-auth-required",i=n===412&&a$1==="device-key-recovery-required";this.code=i?a.AUTH_DEVICE_KEY_RECOVERY_REQUIRED:o?"auth/device-reenrollment-required":t?"coordination/service-unavailable":n===429?"coordination/rate-limited":n===401?"auth/expired":n===403?"admission/denied":"internal/error",this.retryable=o||t,this.plane=i||o||n===401?"auth":t||n===429?"coordination":n===403?"admission":"internal";}};function K(s){return !(s instanceof w)||s.status!==403?false:s.reason==="device-certificate-stale"||s.reason==="device-certificate-revoked"?true:!s.reason&&s.message==="Device certificate is revoked or stale."}function C(s,e,r){return `openrtc:v2:device-certificate:${s}:${e}:${r}`}function P(s,e){return `openrtc:v2:device-session:${s}:${e}`}async function _(s,e,r){let n=new TextEncoder().encode(`openrtc:v2:session\0${s}\0${e}\0${r}`),a=new Uint8Array(await crypto.subtle.digest("SHA-256",n)),t="";for(let o of a)t+=String.fromCharCode(o);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function k(s){let e=s.replace(/-/g,"+").replace(/_/g,"/"),r=e.padEnd(Math.ceil(e.length/4)*4,"="),n=atob(r);return Uint8Array.from(n,a=>a.charCodeAt(0))}function f(s){let e="";for(let r of s)e+=String.fromCharCode(r);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}async function I(s,e,r,n,a){if(typeof s.token!="string"||typeof s.expiresAtMs!="number"||s.expiresAtMs<=Date.now()+B||!s.signingPublicJwk||s.signingPublicJwk.kty!=="OKP"||s.signingPublicJwk.crv!=="Ed25519"||typeof s.signingPublicJwk.x!="string")return null;let t=s.token.split(".");if(t.length!==3)return null;let o,i;try{o=JSON.parse(new TextDecoder().decode(k(t[0]))),i=b$2(s.token);}catch{return null}if(o.alg!=="EdDSA"||s.signingPublicJwk.kid&&o.kid!==s.signingPublicJwk.kid)return null;try{let y=await crypto.subtle.importKey("jwk",s.signingPublicJwk,{name:"Ed25519"},!1,["verify"]);if(!await crypto.subtle.verify({name:"Ed25519"},y,k(t[2]),new TextEncoder().encode(`${t[0]}.${t[1]}`)))return null}catch{return null}let c=typeof i.principalId=="string"?i.principalId:"",d=Number(i.iat),l=Number(i.exp);if(i.iss!=="openrtc"||i.aud!=="openrtc:v2:gateway-grant"||i.typ!=="device-certificate"||i.appTag!==e||!c||a!==void 0&&c!==a||typeof i.principalKey!="string"||i.principalKey.length===0||i.deviceId!==r||i.deviceKeyThumbprint!==n||typeof i.jti!="string"||i.jti.length===0||!Number.isSafeInteger(d)||!Number.isSafeInteger(l)||d>=l||l*1e3!==s.expiresAtMs)return null;let u=b(i);return {token:s.token,expiresAtMs:s.expiresAtMs,principalId:c,signingPublicJwk:s.signingPublicJwk,enrolled:false,...u}}async function J(s,e,r,n,a){try{let t=C(e,r,n),o=s.readSecureRecord?await s.readSecureRecord(e,t):globalThis.localStorage?.getItem(t);if(!o)return null;let i=JSON.parse(o),c=await I(i,e,n,a,r);return c?{token:c.token,expiresAtMs:c.expiresAtMs,principalId:r,signingPublicJwk:c.signingPublicJwk}:null}catch(t){if(s.readSecureRecord)throw t;return null}}async function G(s,e,r,n,a){try{let t=P(e,n),o=s.readSecureRecord?await s.readSecureRecord(r,t):globalThis.localStorage?.getItem(t);return o?await I(JSON.parse(o),r,n,a):null}catch(t){if(s.readSecureRecord)throw t;return null}}async function O(s,e,r,n,a){try{let t=C(e,r,n),o=JSON.stringify(a);s.writeSecureRecord?await s.writeSecureRecord(e,t,o):globalThis.localStorage?.setItem(t,o);}catch(t){if(s.writeSecureRecord)throw t}}async function U(s,e,r,n,a){try{let t=P(r,n),o=JSON.stringify({token:a.token,expiresAtMs:a.expiresAtMs,principalId:a.principalId,signingPublicJwk:a.signingPublicJwk});s.writeSecureRecord?await s.writeSecureRecord(e,t,o):globalThis.localStorage?.setItem(t,o);}catch(t){if(s.writeSecureRecord)throw t}}async function A(s,e,r,n,a){try{let t=C(e,r,n);if(s.deleteSecureRecord?await s.deleteSecureRecord(e,t):globalThis.localStorage?.removeItem(t),a){let o=P(a,n);s.deleteSecureRecord?await s.deleteSecureRecord(e,o):globalThis.localStorage?.removeItem(o);}}catch(t){if(s.deleteSecureRecord)throw t}}function x(s){return `${s}_${crypto.randomUUID()}`}function $(s){if(s instanceof TypeError)return true;if(!s||typeof s!="object")return false;let e=Reflect.get(s,"name");return e==="TimeoutError"||e==="AbortError"}async function j(s,e){let r=new TextEncoder().encode(`${s}:${e}`);return [...new Uint8Array(await crypto.subtle.digest("SHA-256",r))].map(a=>a.toString(16).padStart(2,"0")).join("")}var M=class{constructor(e,r,n,a,t={},o){this.apiKey=e;this.endpoints=r;this.keyProvider=n;this.attestation=a;this.events=t;this.botVerification=o;this.keyPromise=null;this.authEpochs=new Map;this.appTag=`app_${e.slice(-16)}`;}authEpoch(e){let r=this.authEpochs.get(e);if(r)return r;let n={generation:0,devices:new Map};return this.authEpochs.set(e,n),e.subscribe&&(n.unsubscribe=e.subscribe(a=>{a?.type==="principal-changed"&&(n.generation+=1,n.devices.clear(),n.sessionKeyHash=void 0,this.events.onAuthEpochChanged?.(e));})),n}dispose(){for(let e of this.authEpochs.values())e.unsubscribe?.();this.authEpochs.clear();}key(){return this.keyPromise??(this.keyPromise=this.keyProvider.getOrCreate(this.appTag))}async deviceSigningPublicKey(){return (await this.key()).publicKeyJwk}async signDeviceBytes(e){return (await this.key()).sign(e)}async resolveBroadcastAccess(e,r){if(!/^orb1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(e)||e.length>32768)throw new Error("Broadcast grant is invalid.");if(r&&r.byteLength!==32)throw new Error("Broadcast publisher verification key is invalid.");let n=await this.key(),a=f(new Uint8Array(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(e)))),t=r?f(r):"",o=await n.proof((l,u)=>["openrtc:v2:broadcast-access",this.apiKey,a,t,l,u].join(":")),i=await this.post("/v2/broadcasts",{action:"access",grant:e,...t?{publicationVerifyingKey:t}:{},deviceProof:o});if(i.grant!==e)throw new Error("Broadcast access grant mismatch.");let c=k(i.issuerPublicKey);if(c.byteLength!==32)throw new Error("Broadcast issuer key is invalid.");let d=new URL(i.relay?.relayUrl);if(d.protocol!=="https:"||d.username||d.password)throw new Error("Broadcast relay URL is invalid.");if(typeof i.relay.token!="string"||!/^[A-Za-z0-9._-]{16,16384}$/.test(i.relay.token)||typeof i.relay.namespace!="string"||!/^[A-Za-z0-9._/-]{1,512}$/.test(i.relay.namespace))throw new Error("Broadcast relay allocation is invalid.");return {token:e,issuerPublicKey:c,signBindingChallenge:async l=>{if(!(l instanceof Uint8Array)||l.byteLength>2048)throw new Error("Broadcast binding challenge is invalid.");return k(await n.sign(l))},relay:{relayUrl:d.toString(),token:i.relay.token,namespace:i.relay.namespace}}}async manageBroadcast(e){let r=await this.deviceCertificate(e.auth,e.deviceId),n=e.grant??"",a=e.invite??"",t=e.create,o=e.invitation,i=t?f(t.publisher.verificationKey):o?.publicationVerificationKey?f(o.publicationVerificationKey):"",c=t?{maxPublishers:t.maxPublishers,maxSubscribers:t.maxSubscribers,maxBitrateBps:t.maxBitrateBps,maxDurationSeconds:t.maxDurationSeconds,maxEgressBytes:t.maxEgressBytes}:void 0,d=t?{bitrateBps:t.publisherBitrateBps,durationSeconds:t.maxDurationSeconds,reservedEgressBytes:t.reservedEgressBytes}:o?{role:o.role,sourceSlot:o.sourceSlot??"",bitrateBps:o.bitrateBps,durationSeconds:o.durationSeconds,reservedEgressBytes:o.reservedEgressBytes}:void 0,l=f(new Uint8Array(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(JSON.stringify({action:e.action,grant:n,invite:a,publicationKey:i,sourceSlot:t?.sourceSlot??o?.sourceSlot??"host-a",limits:c,reservation:d}))))),y=await(await this.key()).proof((g,v)=>["openrtc:v2:broadcast-manage",r.source.token,e.action,l,g,v].join(":")),p=await this.post("/v2/broadcasts",{action:e.action,deviceId:e.deviceId,deviceCertificate:r.source.token,deviceProof:y,...n?{grant:n}:{},...a?{invite:a}:{},...i?{publicationVerifyingKey:i}:{},...t?{sourceSlot:t.sourceSlot??"host-a",limits:c,reservation:d}:{},...o?{invitation:{...d,publicationVerifyingKey:i}}:{}});if(e.action==="create"||e.action==="renew"){if(typeof p.grant!="string"||!/^orb1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(p.grant))throw new Error("Managed broadcast grant is invalid.");return p.grant}if(e.action==="invite"){if(typeof p.invite!="string"||!/^obi1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(p.invite))throw new Error("Managed broadcast invitation is invalid.");return p.invite}if(e.action==="accept"){if(typeof p.grant!="string"||!/^orb1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(p.grant))throw new Error("Managed broadcast accepted grant is invalid.");return p.grant}}async post(e$2,r){let n=x("request"),a=JSON.stringify({apiKey:this.apiKey,...r}),t=null;for(let o=0;o<2;o+=1)try{let i=await fetch(`${this.endpoints.controlPlane}${e$2}`,{method:"POST",headers:{"Content-Type":"application/json","X-OpenRTC-Idempotency-Key":n},body:a,signal:AbortSignal.timeout(15e3)});if(i.ok)return i.json();let c=`OpenRTC request failed (${i.status}).`,d$1,l;try{let y=await i.json();typeof y.error=="string"&&(c=y.error.slice(0,256)),typeof y.reason=="string"&&/^[a-z0-9-]{1,80}$/.test(y.reason)&&(d$1=y.reason),(d(y.code)||b$1(y.code))&&(l=e({...e$1(y),code:y.code,message:c,retryable:y.retryable}));}catch{}let u=l?Object.assign(l,{status:i.status,reason:d$1}):new w(c,i.status,d$1);if(t=u,!l&&o===0&&[502,503,504].includes(i.status))continue;throw u}catch(i){if(t=i,o===0&&$(i))continue;throw i}throw t instanceof Error?t:new Error("OpenRTC request failed.")}async capability(e,r,n,a=false,t,o){let i=e==="space"?await j(this.apiKey,r):r,d=await(await this.key()).proof((p,g)=>["openrtc:v2:capability",this.apiKey,e,i,p,g].join(":")),l=this.botVerification?await this.botVerification.getToken({action:"openrtc_capability",apiKey:this.apiKey}):void 0,u=await this.post("/v2/capabilities",{avenue:{kind:e,id:i},deviceProof:d,...n?{maxPeers:n}:{},...a?{advancedFanout:true}:{},...e==="room"&&t?{architecture:t}:{},...e==="room"&&o?{roomDelivery:o}:{},...l?{turnstileToken:l}:{}}),y={type:"capability",token:u.capability,avenue:e==="ticket"?{kind:"session",id:i}:u.avenue,expiresAtMs:u.expiresAt*1e3,...b(u)};return y.renew=()=>this.capability(e,r,n,a,t,o),y}async deviceCertificate(e,r,n,a,t){if(this.keyProvider.persistence==="session")throw new Error("[OpenRTC] Durable browser device enrollment requires trust.browserPersistence: persistent. Select it explicitly before creating the client; session keys cannot enroll retained devices.");let o=this.authEpoch(e),i=o.devices.get(r)??{};if(o.devices.set(r,i),t&&i.current&&i.current.token!==t.token)return this.deviceCertificateResult(e,r,n,a,{...i.current,enrolled:false});if(!t&&i.current&&i.current.expiresAtMs>Date.now()+B)return this.deviceCertificateResult(e,r,n,a,{...i.current,enrolled:false});if(!i.inFlight){let d=o.generation;t&&(i.current=void 0,i.recoverRevokedEnrollment=true);let l=t?A(this.keyProvider,this.appTag,t.principalId,r,o.sessionKeyHash).then(()=>this.enrollAuthenticatedDevice(e,r,o.sessionKeyHash,a,true)):this.resolveAuthenticatedDevice(e,r,o,a,i.recoverRevokedEnrollment===true);i.inFlight=l.then(u=>{if(o.generation!==d)throw new Error("The OpenRTC authentication identity changed during enrollment.");return i.recoverRevokedEnrollment=false,i.current=u,u}).finally(()=>{i.inFlight=void 0;});}let c=await i.inFlight;return this.deviceCertificateResult(e,r,n,a,c)}async resolveAuthenticatedDevice(e,r,n,a,t=false){let o=await this.key();if(e.getSessionKey){let i=await e.getSessionKey();if(!i)throw new Error("The OpenRTC auth provider has no active principal.");let c=await _(this.appTag,o.thumbprint,i);n.sessionKeyHash=c;let d=await G(this.keyProvider,c,this.appTag,r,o.thumbprint);if(d)return d}return this.enrollAuthenticatedDevice(e,r,n.sessionKeyHash,a,t)}deviceCertificateResult(e,r,n,a,t){let o={type:"device-certificate",token:t.token,avenue:n??{kind:"user",id:t.principalId},expiresAtMs:t.expiresAtMs,irohRelay:t.irohRelay,managedTurn:t.managedTurn};return o.renew=async()=>(await this.deviceCertificate(e,r,n,a)).source,o.recoverRejectedCertificate=async()=>(await this.deviceCertificate(e,r,n,a,t)).source,{principalId:t.principalId,source:o,enrolled:t.enrolled}}async enrollAuthenticatedDevice(e,r,n,a,t=false){let o=async(g,v)=>{let m=await e.getAssertion({audience:"https://api.openrtc.app/v2/assertions/exchange",forceRefresh:g,deviceId:r,...{}});if(!m)throw new Error("The OpenRTC auth provider returned no assertion.");return this.post("/v2/assertions/exchange",{assertion:m,deviceId:r,...e.providerId?{providerId:e.providerId}:{}})},i;try{i=await o(!1);}catch(g){if(!(g instanceof w)||g.status!==401)throw g;i=await o(true);}let c=await this.key(),d=await J(this.keyProvider,this.appTag,i.principalId,r,c.thumbprint);if(d)return {...d,principalId:i.principalId,enrolled:false,...b(i)};let{enrollDevice:l}=await import('./deviceEnrollment-OFC6DSZP.js'),u=await l({apiKey:this.apiKey,appTag:this.appTag,auth:e,attestation:this.attestation,deviceId:r,identity:i,key:c,profile:a,recoverRevokedEnrollment:t||i.deviceRecoveryAuthorized===true,post:(g,v)=>this.post(g,v)});i=u.identity;let y=u.enrollment,p={principalId:i.principalId,token:y.deviceCertificate,expiresAtMs:y.expiresAt*1e3,signingPublicJwk:y.signingPublicJwk,enrolled:true,...b(i)};return await O(this.keyProvider,this.appTag,i.principalId,r,{token:p.token,expiresAtMs:p.expiresAtMs,signingPublicJwk:p.signingPublicJwk}),n&&await U(this.keyProvider,this.appTag,n,r,p),p}async listEnrolledDevices(e,r){let n=await this.deviceCertificate(e,r);return (await this.deviceManagement(n.source,r,"list")).devices??[]}async revokeDevice(e,r,n){let a=await this.deviceCertificate(e,r);if(await this.deviceManagement(a.source,r,"revoke",n),n===r){let t=this.authEpoch(e);await A(this.keyProvider,this.appTag,a.principalId,r,t.sessionKeyHash),t.devices.delete(r),await this.deleteDeviceKey();}}async revokeAllDevices(e,r,n){let a=await this.deviceCertificate(e,r);await this.deviceManagement(a.source,r,"revoke-all",void 0,n);let t=this.authEpoch(e);await A(this.keyProvider,this.appTag,a.principalId,r,t.sessionKeyHash),t.devices.delete(r),n?await this.deviceCertificate(e,r):(t.devices.clear(),await this.deleteDeviceKey());}async deleteDeviceKey(){this.keyPromise=null,await this.keyProvider.delete?.(this.appTag);}async deviceManagement(e,r,n,a,t=false){let{manageDevice:o}=await import('./deviceManagement-SUMBRXXC.js');return await o({source:e,currentDeviceId:r,action:n,targetDeviceId:a,exceptCurrent:t,key:()=>this.key(),post:c=>this.post("/v2/devices/manage",c),isStale:K})}async durableRoomMembership(e,r,n){if(e.type!=="device-certificate")throw new Error("Durable rooms require a device certificate.");let a=b$2(e.token),t=String(a.jti??""),i=await(await this.key()).proof((c,d)=>["openrtc:v2:room-membership",t,n,r,c,d].join(":"));await this.post("/v2/rooms/memberships",{action:n,roomId:r,deviceCertificate:e.token,deviceProof:i});}grantProvider(e,r={}){let n=Promise.resolve(),a=e;return t=>{let o=n.then(async()=>{let i=false;a.expiresAtMs<=Date.now()+3e5&&a.renew&&(a=await a.renew(),i=true);let c=async l=>{let u=b$2(l.token),y=String(u.jti??""),g=await(await this.key()).proof((v,m)=>["openrtc:v2:gateway-grant",y,t.avenue.kind,t.avenue.id,t.runtimeInstanceId,v,m].join(":"));return this.post("/v2/gateway/grants",{credentialType:l.type,credential:l.token,avenue:t.avenue,runtimeInstanceId:t.runtimeInstanceId,ticketFingerprint:t.ticketFingerprint,deviceProof:g,...t.refreshGrant?{refreshGrant:t.refreshGrant}:{},...r.maxPeers?{maxPeers:r.maxPeers}:{},...r.features?{features:r.features}:{},...t.avenue.kind==="room"&&r.architecture?{architecture:r.architecture}:{},...t.avenue.kind==="room"&&r.roomDelivery?{roomDelivery:r.roomDelivery}:{},...l.type==="device-certificate"&&r.deviceProfile?{deviceProfile:r.deviceProfile}:{}})},d;try{d=await c(a);}catch(l){if(!K(l))throw l;let u=await a.recoverRejectedCertificate?.();if(!u)throw l;a=u,i=true,d=await c(a);}return i&&await r.onSourceRenewed?.({token:a.token,expiresAtMs:a.expiresAtMs}),d});return n=o.then(()=>{},()=>{}),o}}turnProvider(e){let r=x("relay"),n=null,a=null;return async()=>{if(n&&n.expiresAtMs>Date.now()+5*6e4)return n;if(a)return a;let t=(async()=>{let o=e(),i=b$2(o.token),c=String(i.jti??""),l=await(await this.key()).proof((y,p)=>["openrtc:v2:relay-turn",c,r,y,p].join(":")),u=await this.post("/v2/relay/turn",{credentialType:o.type,credential:o.token,sessionId:r,deviceProof:l});return n=u,u})();a=t;try{return await t}finally{a===t&&(a=null);}}}};
2
+ export{M as a};
@@ -1 +1 @@
1
- import {r}from'./chunk-WNCBDRFC.js';import {e}from'./chunk-XR5JZKFP.js';function v(i,d){let t=new r(i,d),a=i.spaceKey??i.space,l=(i.discoveryMode===void 0||i.discoveryMode==="space")&&typeof i.apiKey=="string"&&i.apiKey.trim().length>0&&typeof a=="string"&&a.trim().length>0,o={runtime:t,async setAuthContext(e){await t.setAuthContext(e);},async syncPlutoAuth(e$1){if(l)return;let n=e(),c=n.getCurrentUser(),r=(typeof e$1?.userId=="string"?e$1.userId.trim():"")||c?.uid||null;if(!r){await o.setAuthContext(null);return}let m=await n.getIdToken({forceRefresh:e$1?.forceRefresh??false}).catch(()=>null),g=n.getCurrentUser()?.refreshToken??null,h=n.getCurrentUser()?.stsTokenManager?.expirationTime??null;await o.setAuthContext({userId:r,token:m,refreshToken:g,tokenProvider:async y=>n.getIdToken({forceRefresh:y??false}),expiresAtMs:h});},bindPlutoAuthHost(){let e$1=e();return o.syncPlutoAuth({userId:e$1.getCurrentUser()?.uid??null,forceRefresh:false}),e$1.onIdTokenChanged(n=>{o.syncPlutoAuth({userId:n?.uid??null,forceRefresh:false});})},signInWithPluto:()=>t.signInWithPluto(),signOut:()=>t.signOut(),stopManagedSession:()=>t.stopManagedSession(),startManagedSession:e=>t.startManagedSession(e),onAuthChange:e=>t.onIdentityChange(e),getManagedNodeId:e=>t.getManagedNodeId(e),getRuntimeStatus:()=>t.getRuntimeStatus(),listDeviceStatus:()=>t.listDeviceStatus(),watchDeviceStatus:e=>t.watchDeviceStatus(e),connectDevice:(e,n)=>t.connectDevice(e,n),excludeAutoConnect:(e,n)=>t.excludeAutoConnect(e,n)};return Object.defineProperty(o,"identity",{get:()=>t.identity,enumerable:true}),o}export{v as a};
1
+ import {r}from'./chunk-R6J4PZDI.js';import {e}from'./chunk-CAUMGKP4.js';function v(i,d){let t=new r(i,d),a=i.spaceKey??i.space,l=(i.discoveryMode===void 0||i.discoveryMode==="space")&&typeof i.apiKey=="string"&&i.apiKey.trim().length>0&&typeof a=="string"&&a.trim().length>0,o={runtime:t,async setAuthContext(e){await t.setAuthContext(e);},async syncPlutoAuth(e$1){if(l)return;let n=e(),c=n.getCurrentUser(),r=(typeof e$1?.userId=="string"?e$1.userId.trim():"")||c?.uid||null;if(!r){await o.setAuthContext(null);return}let m=await n.getIdToken({forceRefresh:e$1?.forceRefresh??false}).catch(()=>null),g=n.getCurrentUser()?.refreshToken??null,h=n.getCurrentUser()?.stsTokenManager?.expirationTime??null;await o.setAuthContext({userId:r,token:m,refreshToken:g,tokenProvider:async y=>n.getIdToken({forceRefresh:y??false}),expiresAtMs:h});},bindPlutoAuthHost(){let e$1=e();return o.syncPlutoAuth({userId:e$1.getCurrentUser()?.uid??null,forceRefresh:false}),e$1.onIdTokenChanged(n=>{o.syncPlutoAuth({userId:n?.uid??null,forceRefresh:false});})},signInWithPluto:()=>t.signInWithPluto(),signOut:()=>t.signOut(),stopManagedSession:()=>t.stopManagedSession(),startManagedSession:e=>t.startManagedSession(e),onAuthChange:e=>t.onIdentityChange(e),getManagedNodeId:e=>t.getManagedNodeId(e),getRuntimeStatus:()=>t.getRuntimeStatus(),listDeviceStatus:()=>t.listDeviceStatus(),watchDeviceStatus:e=>t.watchDeviceStatus(e),connectDevice:(e,n)=>t.connectDevice(e,n),excludeAutoConnect:(e,n)=>t.excludeAutoConnect(e,n)};return Object.defineProperty(o,"identity",{get:()=>t.identity,enumerable:true}),o}export{v as a};
@@ -0,0 +1,2 @@
1
+ import {b,d,l}from'./chunk-OT7IPLZE.js';import {a}from'./chunk-TPF643LU.js';import {a as a$1,c,b as b$1,e}from'./chunk-L7N4T2PX.js';import {d as d$1}from'./chunk-72MN7BNQ.js';import*as G from'tweetnacl';function ce(t){if(typeof t!="string"||!t||t.trim()!==t||new TextEncoder().encode(t).byteLength>256||/[\u0000-\u001f\u007f-\u009f]/.test(t))throw new Error("Invalid transfer peer demand identity.")}function Ne(t){if(!Number.isSafeInteger(t)||t<=0)throw new Error("Invalid transfer peer demand generation.")}function Ke(t){if(!t||typeof t!="object")throw new Error("Invalid transfer peer demand request.");if(ce(t.id),ce(t.deviceId),!["fileTransfer","driveAccess","contentSync"].includes(t.purpose)||Object.keys(t).some(e=>!["id","deviceId","purpose"].includes(e)))throw new Error("Invalid transfer peer demand request.")}function jt(t,e,n=false){if(typeof t!="string"||new TextEncoder().encode(t).byteLength>2048)throw new Error("Invalid transfer peer demand response.");let i=JSON.parse(t);if(i===null&&n)return null;if(!i||typeof i!="object")throw new Error("Invalid transfer peer demand response.");let r=i;if(Ke({id:r.id,deviceId:r.deviceId,purpose:r.purpose}),Ne(r.generation),r.id!==e.id||e.generation!==void 0&&r.generation!==e.generation||e.deviceId!==void 0&&r.deviceId!==e.deviceId||e.purpose!==void 0&&r.purpose!==e.purpose||!["waitingForPeer","queued","admitted"].includes(r.state))throw new Error("Invalid transfer peer demand response.");return r}function zt(){throw new Error("[OpenRTC] The rollback-only Firebase auth host is not installed. OpenRTC 2.0 applications must supply an AuthProvider; legacy runtimes must import openrtc/auth explicitly.");}var Le="openrtc-trust";var le="identity",A="managed-room-keys",T="managed-room-state";function He(){if(typeof globalThis.indexedDB>"u")throw new Error("[OpenRTC] Managed rooms require durable IndexedDB storage.");return globalThis.indexedDB}function Be(){return new Promise((t,e)=>{let n=He().open(Le,2);n.onupgradeneeded=()=>{let i=n.result;i.objectStoreNames.contains(le)||i.createObjectStore(le),i.objectStoreNames.contains(A)||i.createObjectStore(A),i.objectStoreNames.contains(T)||i.createObjectStore(T);},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error??new Error("managed room database failed")),n.onblocked=()=>e(new Error("managed room database upgrade is blocked"));})}function J(t){return new Promise((e,n)=>{t.onsuccess=()=>e(t.result),t.onerror=()=>n(t.error??new Error("managed room storage failed"));})}function M(t){return new Promise((e,n)=>{t.oncomplete=()=>e(),t.onerror=()=>n(t.error??new Error("managed room storage failed")),t.onabort=()=>n(t.error??new Error("managed room storage aborted"));})}function Ue(t,e,n){return `${t}:${e}:${n}`}function je(t,e){return `${t}:${e}`}function ue(t){return new TextEncoder().encode(`openrtc-managed-room-state-v1:${t}`)}async function Fe(t,e){let n=t.transaction(A,"readonly"),i=M(n),r=await J(n.objectStore(A).get(e));if(await i,r)return r;let o=await crypto.subtle.generateKey({name:"AES-GCM",length:256},false,["encrypt","decrypt"]),s=t.transaction(A,"readwrite"),a=M(s);s.objectStore(A).add(o,e);try{return await a,o}catch{let c=t.transaction(A,"readonly"),d=M(c),u=await J(c.objectStore(A).get(e));if(await d,!u)throw new Error("[OpenRTC] Managed room wrapping key could not be persisted.");return u}}function ze(t){let e=t;return e?.schemaVersion===1&&e.wrappedKey instanceof Uint8Array&&e.wrappingNonce instanceof Uint8Array&&e.wrappingNonce.byteLength===12&&(e.sealedState===void 0||e.sealedState instanceof Uint8Array)?e:null}async function Q(t,e,n){let i=await Be(),r=Ue(t,e,n);try{let o=await Fe(i,je(t,e)),s=i.transaction(T,"readonly"),a=M(s),c=ze(await J(s.objectStore(T).get(r)));await a;let d,u;if(c){let l=await crypto.subtle.decrypt({name:"AES-GCM",iv:c.wrappingNonce,additionalData:ue(r)},o,c.wrappedKey).catch(()=>{throw new Error("[OpenRTC] Managed room state key authentication failed.")});if(d=new Uint8Array(l),d.byteLength!==32)throw new Error("[OpenRTC] Managed room state key is invalid.");u=c;}else {d=crypto.getRandomValues(new Uint8Array(32));let l=crypto.getRandomValues(new Uint8Array(12)),y=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:l,additionalData:ue(r)},o,d));u={schemaVersion:1,wrappingNonce:l,wrappedKey:y};let f=i.transaction(T,"readwrite"),w=M(f);f.objectStore(T).add(u,r),await w;}return {wrappingKey:d,sealedState:u.sealedState,async persist(l){if(!(l instanceof Uint8Array)||l.byteLength===0)throw new Error("[OpenRTC] Managed room sealed state is invalid.");let y=i.transaction(T,"readwrite"),f=M(y);y.objectStore(T).put({...u,sealedState:l},r),await f,u={...u,sealedState:l};},close(){d.fill(0),i.close();}}}catch(o){throw i.close(),o}}var qe=3e4,$e=5*6e4,Ve=3e4,Je=100,Qe=48*1024,Ye=50,pe=64*1024,he=12,Xe=10*6e4,Ze=5*6e4,_=15e3,et=15e3,tt=1e3,ge=250;function ye(t){let e=[...new Set(t.map(n=>String(n??"").trim().toLowerCase()).filter(Boolean))].sort();if(e.length>ge)throw new Error(`Coordination excluded-peer set exceeds ${ge} devices.`);return e}var nt="openrtc.v2",it="openrtc.auth.";function Se(t){try{let e=t.split(".")[1];if(!e)return null;let n=e.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(e.length/4)*4,"="),i=JSON.parse(globalThis.atob(n));return i!==null&&typeof i=="object"&&!Array.isArray(i)?i:null}catch{return null}}function me(t){let e=Se(t)?.jti;return typeof e=="string"&&e.length>0?e:null}var h=class extends b$1{constructor(n,i,r,o={}){super({code:a$1.COORDINATION_DISCONNECTED,plane:"coordination",...d$1(r)?e({...o,code:r,message:n,retryable:i}):{},message:n,retryable:i});this.gatewayCode=r;this.name="CoordinationConnectError";}},B=class extends b$1{constructor(n,i,r,o={}){let s=e({...o,code:n,message:i,retryable:r});super({...s,retryable:r,message:`Coordination gateway ${n}: ${i}`});this.name="CoordinationGatewayProtocolError";}};function fe(t){return t instanceof h&&/\bstale-budget\b/i.test(t.message)}function x(t){if(!t||typeof t!="object")return false;let e=t;return e.gatewayCode==="credential-revoked"||e.code==="credential-revoked"||e.reason==="device-certificate-revoked"}function ve(t){if(x(t))return true;if(typeof t!="object"||t===null)return false;let e=t;if(e.retryable===false)return true;let n=e.status??e.statusCode,i=typeof n=="number"?n:Number.NaN;if(Number.isInteger(i)&&i>=400&&i<500&&![408,425,429].includes(i))return true;let r=String(e.code??"");return ["functions/unauthenticated","functions/permission-denied","functions/invalid-argument","functions/failed-precondition","functions/resource-exhausted","unauthenticated","permission-denied","invalid-argument","failed-precondition","resource-exhausted"].includes(r)}function rt(t){let e=new Uint32Array(1);return crypto.getRandomValues(e),Math.max(1,Math.round(t*(.75+e[0]/4294967295*.5)))}function v(t){if(typeof crypto.randomUUID=="function")return `${t}:${crypto.randomUUID()}`;let e=new Uint8Array(16);crypto.getRandomValues(e);let n=Array.from(e,i=>i.toString(16).padStart(2,"0")).join("");return `${t}:${n}`}async function ot(t){let e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t)),n="";for(let i of new Uint8Array(e))n+=String.fromCharCode(i);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function D(t){if(!/^[A-Za-z0-9_-]+$/.test(t))throw new Error("[OpenRTC] Managed room payload encoding is invalid.");let e=t.replace(/-/g,"+").replace(/_/g,"/"),n=atob(e.padEnd(Math.ceil(e.length/4)*4,"="));return Uint8Array.from(n,i=>i.charCodeAt(0))}function st(t,e,n){let i=new URL(t);if(i.search||i.hash||i.username||i.password)throw new Error("[OpenRTC] Coordination gateway endpoint must not contain credentials, query, or fragment.");if(i.protocol==="https:")i.protocol="wss:";else if(i.protocol==="http:")i.protocol="ws:";else if(i.protocol!=="wss:"&&i.protocol!=="ws:")throw new Error("[OpenRTC] Coordination gateway endpoint must use HTTPS/WSS.");return i.pathname=`${i.pathname.replace(/\/+$/,"")}/v${n}/connect/${e}`,i.toString()}function be(t){let e=new URL(t);return e.protocol==="wss:"&&(e.protocol="https:"),e.protocol==="ws:"&&(e.protocol="http:"),e.origin}var U=class t{constructor(e){this.options=e;this.runtimeInstanceId=v("runtime");this.socket=null;this.serviceObservationGeneration=0;this.socketReady=false;this.activeGrantToken=null;this.refillCredential=null;this.activeGrantJti=null;this.activeAvenue=null;this.activeGrantExpiresAtMs=0;this.activeGrantProtocolVersion=1;this.leaseRefreshMode="off";this.signalBatchMode="off";this.pendingSignalQueue=[];this.signalFlushScheduled=null;this.pendingLeaseRefreshKey=null;this.authenticationRefreshTail=Promise.resolve();this.authenticationRefreshes=new Map;this.connectPromise=null;this.desiredPresence=null;this.friendObservationPresence=null;this.desiredExcludedPeers=[];this.devices=new Map;this.sparseMembers=new Map;this.sparseRoutes=new Map;this.pendingMembershipPageSnapshot=null;this.pendingRosterPageSnapshot=null;this.sparseTopologyRevision=0;this.roomArchitectureSnapshot=null;this.roomAuthorityAssignment=null;this.roomAuthorityAssignmentExpiry=null;this.roomEncryptionEpoch=0;this.managedWasmClient=null;this.peerAdmissionRuntime=null;this.peerAdmissionScope=null;this.peerAdmissionRevision=0;this.managedStateProvider=Q;this.managedState=null;this.managedInitialization=null;this.managedActions=Promise.resolve();this.managedPublishQueue=[];this.managedPublishScheduled=false;this.managedMessageListeners=new Set;this.deviceListeners=new Set;this.architectureListeners=new Set;this.authorityAssignmentListeners=new Set;this.deviceStreams=new Set;this.sessionStreams=new Set;this.pendingAcks=new Map;this.pendingMessages=[];this.roomConnections=new Map;this.friendConnections=new Map;this.reconnectTimer=null;this.authRefreshTimer=null;this.keepaliveTimer=null;this.pendingAuthRefresh=null;this.budgetRenewalPromise=null;this.budgetRenewalEpoch=0;this.reconnectAttempt=0;this.reconnectOutageStartedAtMs=null;this.reconnectCircuitOpen=false;this.hostAvailable=true;this.connectionReadyWaiters=new Set;this.hostResumeReconnectPromise=null;this.lastHostResumeReconnectAtMs=0;this.desiredPresenceRevision=0;this.appliedPresenceRevision=0;this.stopped=false;this.credentialRevoked=false;if(this.initialExcludedPeers=ye(e.initialExcludedPeers??[]),this.desiredExcludedPeers=[...this.initialExcludedPeers],e.gateway.environment!=="staging"&&e.gateway.environment!=="production")throw new Error("[OpenRTC] Coordination gateway environment is invalid.");let n=new URL(e.gateway.endpoint),i=n.hostname==="127.0.0.1"||n.hostname==="localhost"||n.hostname==="[::1]",r=n.protocol==="https:"||n.protocol==="wss:",o=e.gateway.testingAllowInsecureLoopback===true&&i&&(n.protocol==="http:"||n.protocol==="ws:");if(!r&&!o)throw new Error("[OpenRTC] Coordination gateway requires HTTPS/WSS.");if(n.username||n.password||n.search||n.hash)throw new Error("[OpenRTC] Coordination gateway credentials and parameters cannot be supplied in its URL.")}async updatePresence(e,n,i,r,o,s){let a=this.desiredPresence;if(i&&this.options.roomArchitecture==="authority"){let u=this.options.avenueOverride;if(u?.kind!=="room"||!this.peerAdmissionRuntime)throw new Error("[OpenRTC] Authority rooms require Rust peer admission support.");let l=`v2:room:${u.id}`;this.peerAdmissionRuntime.__requireScopePeerAdmission(l),this.peerAdmissionScope=l;}this.desiredPresence={localNodeId:e,ticket:n,online:i,ttlMs:r,metadata:o,deviceName:s?.trim()||this.options.getDefaultDeviceName()},(!a||a.localNodeId!==e||a.ticket!==n||a.online!==i||a.ttlMs!==r||a.metadata!==o||a.deviceName!==this.desiredPresence.deviceName)&&(this.desiredPresenceRevision+=1,this.reconnectCircuitOpen=false,this.reconnectAttempt=0,this.reconnectOutageStartedAtMs=null);for(let u of this.friendConnections.values())u.updatePresence(e,n,i,r,o,this.desiredPresence.deviceName).catch(()=>{});let d=this.desiredPresenceRevision;try{await this.ensureConnected();}catch(u){if(!(u instanceof h)||!u.retryable)throw u;await this.waitForConnectionReady();}this.appliedPresenceRevision>=d||(a&&a.ticket!==n&&await this.refreshAuthentication(),await this.sendOperation({v:1,type:"presence.upsert",idempotencyKey:v("presence"),ttlMs:r,device:this.gatewayDevice(this.desiredPresence)}),this.appliedPresenceRevision=Math.max(this.appliedPresenceRevision,d));}async setOffline(e){this.desiredPresence&&(this.desiredPresence.online=false,this.socket?.readyState===WebSocket.OPEN&&await this.sendOperation({v:1,type:"presence.offline",idempotencyKey:v("offline")}));}async reconnectAfterHostResume(){if(this.desiredPresence){if(this.hostResumeReconnectPromise)return this.hostResumeReconnectPromise;if(!(Date.now()-this.lastHostResumeReconnectAtMs<et)){this.lastHostResumeReconnectAtMs=Date.now(),this.hostResumeReconnectPromise=(async()=>{(this.socket?.readyState===WebSocket.OPEN||this.socketReady)&&this.stopSocket(),await this.ensureConnected();})();try{await this.hostResumeReconnectPromise;}finally{this.hostResumeReconnectPromise=null;}}}}setHostAvailability(e){let n=e.available&&!this.hostAvailable;this.hostAvailable=e.available;for(let i of this.roomConnections.values())i.setHostAvailability(e);for(let i of this.friendConnections.values())i.setHostAvailability(e);if(!e.available){this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.reconnectTimer=null,this.connectPromise&&!this.socketReady&&this.stopSocket();return}n&&this.desiredPresence&&!this.socketReady&&!this.connectPromise&&!this.reconnectCircuitOpen&&!this.stopped&&this.ensureConnected().catch(i=>this.scheduleReconnect(i));}async updateDevice(e,n){if(e!==this.options.getLocalDeviceId())throw new Error("A coordination socket can update only its local device.");let i=n;if(n.excludedPeers!==void 0){let r=ye(n.excludedPeers);this.desiredExcludedPeers=r,i={...n,excludedPeers:r};}await this.ensureConnected(),await this.sendOperation({v:1,type:"device.patch",idempotencyKey:v("device-patch"),patch:i});}async deleteDevice(e){if(this.options.credentialPurpose!=="device-control"&&(!this.socketReady||this.socket?.readyState!==WebSocket.OPEN)){let n=new t({...this.options,credentialPurpose:"device-control"});try{await n.deleteDevice(e);}finally{n.stopAuthActivity();}return}await this.ensureConnected();try{await this.sendOperation({v:1,type:"device.delete",idempotencyKey:v("device-delete"),targetDeviceId:e});}finally{this.options.credentialPurpose==="device-control"&&this.stopSocket();}}async cleanupStaleDevices(){}async searchDevices(e){return this.snapshot(e)}async listDevices(e){return this.snapshot(e)}onDevicesChange(e,n){let i=r=>e(n?r.filter(o=>o.nodeId!==n):r);return this.deviceListeners.add(i),i(this.snapshot()),this.desiredPresence&&this.ensureConnected().catch(()=>{}),()=>this.deviceListeners.delete(i)}onRoomArchitectureChange(e){return this.architectureListeners.add(e),this.roomArchitectureSnapshot&&e({...this.roomArchitectureSnapshot}),()=>this.architectureListeners.delete(e)}onRoomAuthorityAssignmentChange(e){return this.authorityAssignmentListeners.add(e),e(this.roomAuthorityAssignmentSnapshot()),()=>this.authorityAssignmentListeners.delete(e)}async publishAuthorityAssignment(e){await this.ensureConnected(),await this.sendOperation({v:1,type:"authority.assignment.publish",idempotencyKey:v("authority-assignment"),assignment:e.assignment,signature:e.signature});}setWasmClient(e){this.setManagedRoomRuntime(e,Q);}setManagedRoomRuntime(e,n){let i=e;this.peerAdmissionRuntime=i&&typeof i.__requireScopePeerAdmission=="function"&&typeof i.__updateScopePeerAdmission=="function"?i:null;let r=e;this.managedWasmClient=r&&typeof r.__initManagedRoomGroup=="function"&&typeof r.__handleManagedRoomPreparePage=="function"&&typeof r.__handleManagedRoomArtifactChunk=="function"&&typeof r.__sealManagedRoomPayload=="function"&&typeof r.__openManagedRoomPayload=="function"&&typeof r.__forgetManagedRoomGroup=="function"?r:null,this.managedStateProvider=n,this.roomArchitectureSnapshot?.effective==="managed"&&this.enqueueManagedWork(()=>this.ensureManagedGroupInitialized());}onManagedRoomMessage(e){return this.managedMessageListeners.add(e),()=>this.managedMessageListeners.delete(e)}async publishManagedRoomMessage(e){return new Promise((n,i)=>{this.managedPublishQueue.push({input:e,resolve:n,reject:i}),!this.managedPublishScheduled&&(this.managedPublishScheduled=true,queueMicrotask(()=>{this.managedPublishScheduled=false,this.enqueueManagedWork(()=>this.flushManagedPublishBatch());}));})}async subscribeDevices(){let e=null;return new ReadableStream({start:n=>{e=n,this.deviceStreams.add(n);let i=this.snapshot().map(r=>({type:"added",device:r}));i.length>0&&n.enqueue(i);},cancel:()=>{e&&this.deviceStreams.delete(e),e=null;}})}async createSession(e){await this.ensureConnected(),await this.sendOperation({v:1,type:"session.put",idempotencyKey:v("session-put"),sessionId:e.connectionId,session:e,expiresAtMs:e.expiresAt??Date.now()+15*6e4});}async updateSession(e,n){await this.ensureConnected(),await this.sendOperation({v:1,type:"session.put",idempotencyKey:v("session-update"),sessionId:this.unscopedId(e),session:n,expiresAtMs:typeof n.expiresAt=="number"?n.expiresAt:Date.now()+15*6e4});}async subscribeSessions(e){let n=null;return new ReadableStream({start:i=>{n=i,this.sessionStreams.add(i);},cancel:()=>{n&&this.sessionStreams.delete(n),n=null;}})}async sendMessage(e,n,i,r){let o=this.serviceObservationGeneration;if(await this.ensureConnected(),o!==this.serviceObservationGeneration||!this.socket)throw new h("Signal connection retired before dispatch.",false);let s={socket:this.socket,generation:o};this.assertSignalCurrent(s);let a=Object.freeze({targetDeviceId:this.unscopedId(e),payload:n,state:i,replyPayload:r});if(this.signalBatchMode!=="ordered-v1"){let c=v("signal");return await this.sendOperation({v:1,type:"signal.send",idempotencyKey:c,...a},d=>this.assertSignalCurrent(s,d)),this.assertSignalCurrent(s,false),c}return new Promise((c,d)=>{this.pendingSignalQueue.push({input:a,binding:s,resolve:c,reject:d}),!this.signalFlushScheduled&&(this.signalFlushScheduled=s,queueMicrotask(()=>{this.signalFlushScheduled===s&&(this.signalFlushScheduled=null,this.flushSignalQueue());}));})}assertSignalCurrent(e,n=true){if(e.generation!==this.serviceObservationGeneration||this.socket!==e.socket||e.socket.readyState!==WebSocket.OPEN||!this.socketReady||this.stopped||this.credentialRevoked||n&&(!Number.isSafeInteger(this.activeGrantExpiresAtMs)||this.activeGrantExpiresAtMs<=Date.now()))throw new h("Signal connection retired before completion.",false)}rejectQueuedSignals(e){this.signalFlushScheduled=null;for(let n of this.pendingSignalQueue.splice(0))n.reject(e);}flushSignalQueue(){let e=this.pendingSignalQueue.splice(0);for(;e.length>0;){let n=e.shift();try{this.assertSignalCurrent(n.binding);}catch(c){n.reject(c);continue}let i=[n],r=v("signal-batch"),o=c=>({v:1,type:"signal.send.batch",idempotencyKey:r,signals:c.map(d=>d.input)});for(;i.length<Ye&&e.length>0;){let c=e[0];if(c.binding.socket!==n.binding.socket||c.binding.generation!==n.binding.generation||new TextEncoder().encode(JSON.stringify(o([...i,c]))).byteLength>pe)break;i.push(e.shift());}let s=i.length>1,a=Object.freeze(s?{...o(i),signals:Object.freeze(i.map(c=>c.input))}:{v:1,type:"signal.send",idempotencyKey:v("signal"),...n.input});if(new TextEncoder().encode(JSON.stringify(a)).byteLength>pe){n.reject(new Error("Signaling frame exceeds 64 KiB."));continue}this.dispatchSignalFrame(a,n.binding,i,s);}}async dispatchSignalFrame(e,n,i,r){try{await this.sendOperation(e,o=>this.assertSignalCurrent(n,o)),this.assertSignalCurrent(n,!1),i.forEach((o,s)=>o.resolve(r?`${e.idempotencyKey}:${s}`:e.idempotencyKey));}catch(o){for(let s of i)s.reject(o);}}async pollMessages(e){return this.pendingMessages.splice(0,this.pendingMessages.length)}watchFriendDevices(e,n){let i=[...new Set(e.map(a=>a.trim()).filter(Boolean))];if(i.length>25)throw new RangeError(`watchFriendDevices accepts at most ${25} unique friend IDs per runtime.`);for(let a of i)if(a.length>128||a.includes("/"))throw new TypeError('Friend user IDs must be 1-128 characters and cannot contain "/".');let r={value:false},o=new Map,s=[];n(new Map);for(let a of i){if(!a||a===this.options.getCurrentUserId())continue;let c=this.friendConnection(a);s.push(c.onDevicesChange(d=>{if(r.value)return;let u=d.filter(l=>l.online);o.set(a,u),n(new Map(o));}));}return ()=>{r.value=true;for(let a of s)a();for(let a of i)this.friendConnections.get(a)?.stopAuthActivity(),this.friendConnections.delete(a);}}waitForFriendDevice(e,n,i=1e4){let r=e.trim(),o=n.trim();return !r||!o?Promise.reject(new Error("Capability-authorized device observation requires user and device ids.")):new Promise((s,a)=>{let c=()=>{},d=false,u=f=>{d||(d=true,clearTimeout(l),c(),f.error?a(f.error):s(f.device));},l=setTimeout(()=>u({error:new Error(`Timed out waiting for capability-authorized device ${o}`)}),Math.max(1,i));c=this.watchFriendDevices([r],f=>{let w=(f.get(r)??[]).find(b=>b.deviceId===o&&b.online&&typeof b.ticket=="string"&&b.ticket.trim().startsWith("endpoint"));w&&u({device:w});}),d&&c();})}setFriendObservationIdentity(e){this.friendObservationPresence={localNodeId:e.localNodeId,ticket:e.ticket,online:true,ttlMs:e.ttlMs,metadata:e.metadata,deviceName:e.deviceName?.trim()||this.options.getDefaultDeviceName()};for(let n of this.friendConnections.values())this.activateFriendConnection(n,this.friendObservationPresence);}async updateFriendTicket(e){await this.ensureConnected(),await this.sendOperation({v:1,type:"device.patch",idempotencyKey:v("friend-ticket"),patch:{friendTicket:e??""}});}async handleScopeChange(){this.stopSocket(),this.credentialRevoked=false,this.reconnectCircuitOpen=false,this.reconnectAttempt=0,this.reconnectOutageStartedAtMs=null,this.appliedPresenceRevision=0,this.devices.clear(),this.emitDevices();}stopAuthActivity(){this.stopped=true,this.friendObservationPresence=null,this.reconnectOutageStartedAtMs=null,this.stopSocket(),this.rejectConnectionReadyWaiters(new h("Coordination activity stopped before capability admission completed.",false)),this.desiredExcludedPeers=[...this.initialExcludedPeers];for(let e of this.pendingAcks.values())clearTimeout(e.timer),e.resolve();this.pendingAcks.clear();for(let e of this.managedPublishQueue.splice(0))e.reject(new Error("[OpenRTC] Managed room activity stopped."));if(this.devices.clear(),this.pendingMessages.splice(0,this.pendingMessages.length),this.managedState){try{this.managedWasmClient?.__forgetManagedRoomGroup(this.managedAvenueKey());}catch{}this.managedState.close(),this.managedState=null;}this.managedInitialization=null,this.managedMessageListeners.clear(),this.roomAuthorityAssignmentExpiry&&clearTimeout(this.roomAuthorityAssignmentExpiry),this.roomAuthorityAssignmentExpiry=null,this.roomAuthorityAssignment=null,this.authorityAssignmentListeners.clear(),this.emitDevices();for(let e of this.roomConnections.values())e.stopAuthActivity();this.roomConnections.clear();for(let e of this.friendConnections.values())e.stopAuthActivity();this.friendConnections.clear();}usesCoordinationGateway(){return true}async joinCoordinationRoom(e,n,i){let r=e.trim().toUpperCase(),o=this.roomConnections.get(r);o||(o=new t({...this.options,avenueOverride:{kind:"room",id:r}}),o.setHostAvailability({available:this.hostAvailable,reason:"parent-avenue-created"}),this.roomConnections.set(r,o));try{await o.updatePresence(n,i,!0,5*6e4,void 0,this.options.getDefaultDeviceName());}catch(s){if(!(s instanceof h)||!s.retryable)throw s;await o.waitForConnectionReady();}}async leaveCoordinationRoom(e){let n=e.trim().toUpperCase(),i=this.roomConnections.get(n);i&&(await i.setOffline(this.options.getLocalDeviceId()).catch(()=>{}),i.stopAuthActivity(),this.roomConnections.delete(n));}async getCoordinationRoomMembers(e){return this.requireRoomConnection(e).snapshot().map(i=>this.roomMember(i))}watchCoordinationRoomMembers(e,n){return this.requireRoomConnection(e).onDevicesChange(r=>n(r.map(o=>this.roomMember(o))))}async ensureConnected(){if(this.credentialRevoked)throw new h("Coordination credential revoked.",false,"credential-revoked");if(this.connectPromise)return this.connectPromise;if(this.socket?.readyState===WebSocket.OPEN&&this.socketReady)return;if(!this.desiredPresence&&this.options.credentialPurpose!=="device-control")throw new Error("Coordination presence must be initialized before the gateway can connect.");if(!this.hostAvailable&&this.options.credentialPurpose!=="device-control")throw new h("Coordination reconnect is parked until the host is foregrounded and online.",true);if(this.reconnectCircuitOpen)throw new h("Coordination reconnect circuit is open until presence or scope changes.",false);if(this.reconnectTimer)throw new h("Coordination reconnect is already scheduled.",true);this.stopped=false;let e=this.serviceObservationGeneration,n=this.connect();this.connectPromise=n;try{await n;}catch(i){throw e===this.serviceObservationGeneration&&this.connectPromise===n&&this.scheduleReconnect(i),i}finally{this.connectPromise===n&&(this.connectPromise=null);}}async connect(){let e=this.serviceObservationGeneration,n=this.desiredPresence??this.controlPresence(),i=this.desiredPresenceRevision,r=()=>{if(e!==this.serviceObservationGeneration||this.stopped||this.credentialRevoked)throw new h("Coordination connection retired while minting an admission credential.",false)},o=async()=>{r();let s=await this.mintGatewayCredential(n,false);r(),await new Promise((a,c)=>{let d=new WebSocket(st(s.gatewayUrl,s.routeKey,s.protocolVersion),[nt,`${it}${s.token}`]);this.signalBatchMode="off",this.rejectQueuedSignals(new h("Signal connection replaced before dispatch.",false)),this.socket=d,this.pendingRosterPageSnapshot=null;let u=false,l=false,y=null,f=()=>{l||d.readyState!==WebSocket.OPEN||(l=true,this.socketReady=true,this.appliedPresenceRevision=Math.max(this.appliedPresenceRevision,this.desiredPresence?i:0),clearTimeout(w),this.reconnectAttempt=0,this.reconnectOutageStartedAtMs=null,this.scheduleAuthRefresh(s.expiresAtMs,s.protocolVersion),this.resolveConnectionReadyWaiters(),a());},w=setTimeout(()=>{d.close(4408,"authentication timeout"),y=new h("Coordination gateway authentication timed out.",true),c(y);},_);d.onopen=()=>{d.send(JSON.stringify({v:1,type:"auth",token:s.token,socketLiveness:"ping-v1",rosterDelivery:s.avenue.kind==="user"?"paged-v1":void 0,device:this.gatewayDevice(n)}));},d.onmessage=b=>{if(this.stopped||this.socket!==d||b.data==="pong")return;let m;try{m=JSON.parse(String(b.data));}catch{d.close(4400,"invalid gateway frame"),l||(clearTimeout(w),c(new Error("Coordination gateway returned an invalid frame.")));return}if(m.type==="roster.page"&&new TextEncoder().encode(String(b.data)).byteLength>64*1024){d.close(4400,"oversized roster page");return}if(m.type==="error"&&e===this.serviceObservationGeneration&&this.observeServiceError(m,s.avenue),this.stopped||this.socket!==d)return;if(m.type==="ready"&&!u&&this.socket===d&&(this.activeGrantToken=s.token,this.refillCredential={grant:s,ticket:n.ticket},this.activeGrantJti=me(s.token),this.activeAvenue=s.avenue,this.activeGrantExpiresAtMs=s.expiresAtMs,this.activeGrantProtocolVersion=s.protocolVersion,this.leaseRefreshMode=m.leaseRefreshMode??"off",this.signalBatchMode=m.signalBatchMode==="ordered-v1"?"ordered-v1":"off",u=true,this.keepaliveTimer&&clearInterval(this.keepaliveTimer),this.keepaliveTimer=setInterval(()=>{if(this.socket===d&&d.readyState===WebSocket.OPEN)try{d.send("ping");}catch{d.close(4408,"gateway keepalive failed");}},3e4)),m.type==="error"&&!l){y=new h(`Coordination gateway ${m.code}: ${m.message}`,m.retryable,m.code,m),clearTimeout(w),c(y),d.close(4403,m.code);return}this.handleFrame(m,d);let Ge=m.type==="roster.snapshot"||m.type==="roster.page"&&this.pendingRosterPageSnapshot===null||m.type==="membership.snapshot"||m.type==="membership.page"&&this.pendingMembershipPageSnapshot===null;u&&(this.options.credentialPurpose==="device-control"||Ge)&&f();},d.onerror=()=>{this.socket===d&&(this.signalBatchMode="off",this.rejectQueuedSignals(new h("Signal connection failed before dispatch.",false))),l||(clearTimeout(w),y??(y=new h("Coordination gateway connection failed.",true)),c(y));},d.onclose=b=>{clearTimeout(w);let m=this.socket===d;m&&this.keepaliveTimer&&(clearInterval(this.keepaliveTimer),this.keepaliveTimer=null),m&&b.code===4403&&(!y||x(y))&&this.stopForCredentialRevocation(new h("Coordination credential revoked.",false,"credential-revoked")),l||(y??(y=new h(`Coordination gateway closed (${b.code}) before its initial projection.`,b.code!==4401&&b.code!==4403)),c(y)),this.socket===d&&(this.pendingRosterPageSnapshot=null,this.socket=null,this.socketReady=false,this.signalBatchMode="off",this.rejectQueuedSignals(new h("Signal connection closed before dispatch.",false))),this.rejectPendingAcks("Coordination gateway connection closed.",d),this.rejectPendingAuthRefresh(new h("Coordination gateway closed during credential refresh.",b.code!==4401&&b.code!==4403),d),m&&!this.stopped&&this.desiredPresence&&b.code!==1e3&&!fe(y)&&this.scheduleReconnect(y??new h(`Coordination gateway closed (${b.code}).`,b.code!==4401));};});};try{await o();}catch(s){if(!fe(s))throw s;await o();}}async mintGatewayCredential(e,n){let i=this.serviceObservationGeneration,r=await this.resolveAvenue(),o={avenue:r,deviceId:this.options.getLocalDeviceId(),runtimeInstanceId:this.runtimeInstanceId,ticketFingerprint:await ot(e.ticket),purpose:this.options.credentialPurpose??"presence",idempotencyKey:v("credential")},s;if(i!==this.serviceObservationGeneration||this.stopped||this.credentialRevoked||!this.hostAvailable&&this.options.credentialPurpose!=="device-control")throw new h("Coordination credential admission retired before dispatch.",i===this.serviceObservationGeneration&&!this.stopped&&!this.credentialRevoked&&!this.hostAvailable);try{if(!this.options.gateway.grantProvider)throw new h("OpenRTC 2.0 coordination requires a v2 gateway grant provider.",!1);s=await this.options.gateway.grantProvider({...o,...n&&this.activeGrantToken?{refreshGrant:this.activeGrantToken}:{}});}catch(c){throw i===this.serviceObservationGeneration&&this.observeServiceError(c,r),c instanceof h?c:new h(c instanceof Error?c.message:"Coordination credential mint failed.",!ve(c),x(c)?"credential-revoked":void 0)}if(s.protocolVersion!==2)throw new h("Unsupported coordination gateway protocol.",false);let a=be(this.options.gateway.endpoint);if(be(s.gatewayUrl)!==a)throw new h("Coordination credential returned an unexpected gateway origin.",false);return s}observeServiceError(e,n){if(this.stopped||!this.options.gateway.onServiceError)return;let i=a(e,n);if(i)try{Promise.resolve(this.options.gateway.onServiceError(i)).catch(()=>{});}catch{}}handleFrame(e,n=this.socket){if(!(n&&n!==this.socket)){if(this.pendingRosterPageSnapshot&&(e.type==="presence.changed"||e.type==="roster.snapshot"||e.type==="membership.snapshot"||e.type==="membership.page"||e.type==="membership.changed"||e.type==="topology.lease")){this.pendingRosterPageSnapshot=null,n?.close(4400,"interleaved roster snapshot");return}if(e.type==="error"&&e.code==="credential-revoked"){let i=new h(`Coordination gateway ${e.code}: ${e.message}`,false,e.code);this.rejectPendingAcks(i.message,n??void 0),this.rejectPendingAuthRefresh(i,n??void 0),this.stopForCredentialRevocation(i);return}if(e.type==="auth.refreshed"){let i=this.pendingAuthRefresh;i&&i.socket===n&&(clearTimeout(i.timer),this.pendingAuthRefresh=null,this.pendingLeaseRefreshKey=null,this.updateLocalDeviceExpiry(e.expiresAtMs),this.scheduleAuthRefresh(e.expiresAtMs,this.activeGrantProtocolVersion),i.resolve());}else if(e.type==="lease.refreshed"){let i=this.pendingAuthRefresh;if(i&&i.socket===n&&e.idempotencyKey===this.pendingLeaseRefreshKey){if(!Number.isSafeInteger(e.expiresAtMs)||e.expiresAtMs<=Date.now()){this.rejectPendingAuthRefresh(new h("Coordination lease refresh is already expired or invalid.",false),n);return}clearTimeout(i.timer),this.pendingAuthRefresh=null,this.pendingLeaseRefreshKey=null,this.activeGrantExpiresAtMs=e.expiresAtMs,this.updateLocalDeviceExpiry(e.expiresAtMs),this.scheduleAuthRefresh(e.expiresAtMs,this.activeGrantProtocolVersion),i.resolve();}}else if(e.type==="roster.snapshot"){this.sparseMembers.clear(),this.sparseRoutes.clear(),this.sparseTopologyRevision=0,this.devices.clear();for(let i of e.devices)this.devices.set(i.deviceId,this.toDevice(i));this.emitDevices();}else if(e.type==="roster.page"){let i=this.activeAvenue?.kind==="user"&&/^[A-Za-z0-9:_-]{1,160}$/.test(e.snapshotId)&&Number.isSafeInteger(e.pageIndex)&&Number.isSafeInteger(e.pageCount)&&Number.isSafeInteger(e.deviceCount)&&e.pageIndex>=0&&e.pageIndex<e.pageCount&&e.pageCount>=1&&e.pageCount<=e.deviceCount&&e.deviceCount>=1&&e.deviceCount<=500&&Array.isArray(e.devices)&&e.devices.length>=1&&e.devices.length<=100&&e.devices.every(o=>o&&typeof o.deviceId=="string"&&/^[A-Za-z0-9_.:@-]{1,160}$/.test(o.deviceId))&&new Set(e.devices.map(o=>o.deviceId)).size===e.devices.length;e.pageIndex===0&&i&&this.pendingRosterPageSnapshot===null&&(this.pendingRosterPageSnapshot={snapshotId:e.snapshotId,nextPageIndex:0,pageCount:e.pageCount,deviceCount:e.deviceCount,devices:new Map});let r=this.pendingRosterPageSnapshot;if(!i||!r||r.snapshotId!==e.snapshotId||r.nextPageIndex!==e.pageIndex||r.pageCount!==e.pageCount||r.deviceCount!==e.deviceCount||r.devices.size+e.devices.length>r.deviceCount||e.devices.some(o=>r.devices.has(o.deviceId))){this.pendingRosterPageSnapshot=null,n?.close(4400,"invalid roster page");return}for(let o of e.devices)r.devices.set(o.deviceId,this.toDevice(o));if(r.nextPageIndex+=1,r.nextPageIndex===r.pageCount){if(r.devices.size!==r.deviceCount){this.pendingRosterPageSnapshot=null,n?.close(4400,"incomplete roster pages");return}this.sparseMembers.clear(),this.sparseRoutes.clear(),this.sparseTopologyRevision=0;let o=[...this.devices.keys()].filter(s=>!r.devices.has(s)).map(s=>({type:"removed",deviceId:s}));for(let[s,a]of r.devices)o.push({type:this.devices.has(s)?"modified":"added",device:a});this.devices.clear();for(let[s,a]of r.devices)this.devices.set(s,a);this.pendingRosterPageSnapshot=null,this.emitDeviceEvents(o),this.emitDevices();}}else if(e.type==="membership.snapshot"){this.pendingMembershipPageSnapshot=null,this.sparseMembers.clear(),this.sparseRoutes.clear(),this.sparseTopologyRevision=0;for(let i of e.members)this.sparseMembers.set(i.deviceId,i);this.rebuildSparseDevices();}else if(e.type==="membership.page"){let i=/^[A-Za-z0-9:_-]{1,160}$/.test(e.snapshotId)&&Number.isSafeInteger(e.pageIndex)&&Number.isSafeInteger(e.pageCount)&&Number.isSafeInteger(e.memberCount)&&e.pageIndex>=0&&e.pageCount>=2&&e.pageCount<=50&&e.pageIndex<e.pageCount&&e.memberCount>100&&e.memberCount<=5e3&&e.members.length>0&&e.members.length<=100;e.pageIndex===0&&i&&(this.pendingMembershipPageSnapshot={snapshotId:e.snapshotId,nextPageIndex:0,pageCount:e.pageCount,memberCount:e.memberCount,members:new Map});let r=this.pendingMembershipPageSnapshot;if(!(i&&r!==null&&r.snapshotId===e.snapshotId&&r.nextPageIndex===e.pageIndex&&r.pageCount===e.pageCount&&r.memberCount===e.memberCount&&e.members.every(s=>s.deviceId.length>0&&!r.members.has(s.deviceId)))||!r){n?.close(4400,"invalid membership page");return}for(let s of e.members)r.members.set(s.deviceId,s);if(r.nextPageIndex+=1,r.nextPageIndex===r.pageCount){if(r.members.size!==r.memberCount){n?.close(4400,"incomplete membership pages");return}this.sparseMembers.clear(),this.sparseRoutes.clear(),this.sparseTopologyRevision=0;for(let s of r.members.values())this.sparseMembers.set(s.deviceId,s);this.pendingMembershipPageSnapshot=null,this.rebuildSparseDevices();}}else if(e.type==="membership.changed")e.operation==="delete"?this.sparseMembers.delete(e.member.deviceId):this.sparseMembers.set(e.member.deviceId,e.member),this.rebuildSparseDevices();else if(e.type==="topology.lease")this.acceptTopologyLease(e.lease);else if(e.type==="authority.assignment")this.acceptAuthorityAssignment(e.assignment,e.signature);else if(e.type==="presence.changed"){if(e.operation==="delete")this.devices.delete(e.device.deviceId),this.emitDeviceEvents([{type:"removed",deviceId:e.device.deviceId}]);else {let i=this.devices.has(e.device.deviceId),r=this.toDevice(e.device);this.devices.set(r.deviceId,r),this.emitDeviceEvents([{type:i?"modified":"added",device:r}]);}this.emitDevices();}else if(e.type==="signal.received")this.pendingMessages.length>=tt&&this.pendingMessages.shift(),this.pendingMessages.push({senderId:e.senderDeviceId,targetId:this.options.getLocalDeviceId(),payload:e.payload,state:e.state,replyPayload:e.replyPayload,timestamp:e.createdAtMs,appTag:this.options.appTag});else if(e.type==="managed.prepare.page"||e.type==="managed.commit.chunk.received"||e.type==="managed.received")this.enqueueManagedWork(()=>this.handleManagedFrame(e));else if(e.type==="session.changed"){let i=e.operation==="delete"?[{type:"removed",sessionId:e.sessionId}]:[{type:"modified",session:{...e.session??{},connectionId:e.sessionId}}];for(let r of this.sessionStreams)r.enqueue(i);}else if(e.type==="ack"){let i=this.pendingAcks.get(e.idempotencyKey);i&&i.socket===n&&(clearTimeout(i.timer),this.pendingAcks.delete(e.idempotencyKey),i.resolve());}else if(e.type==="error"){if(this.pendingAuthRefresh?.socket===n&&(!e.idempotencyKey||e.idempotencyKey===this.pendingLeaseRefreshKey)){let r=this.pendingAuthRefresh;clearTimeout(r.timer),this.pendingAuthRefresh=null,this.pendingLeaseRefreshKey=null,r.reject(new h(`Coordination gateway ${e.code}: ${e.message}`,e.retryable,e.code,e));return}let i=e.idempotencyKey?this.pendingAcks.get(e.idempotencyKey):null;i&&i.socket===n&&(clearTimeout(i.timer),this.pendingAcks.delete(e.idempotencyKey),i.reject(new B(e.code,e.message,e.retryable,e)));}}}enqueueManagedWork(e){let n=this.managedActions.then(e);this.managedActions=n.catch(i=>{console.error("[OpenRTC] Managed room owner rejected a gateway frame:",i),this.socket?.close(4400,"managed room state invalid");});}async flushManagedPublishBatch(){let e=this.managedPublishQueue.splice(0,Je);if(e.length!==0)try{await this.ensureConnected(),await this.ensureManagedGroupInitialized();let n=this.roomArchitectureSnapshot,i=this.managedWasmClient,r=this.managedState;if(!n||n.effective!=="managed"||n.phase!=="settled"||this.roomEncryptionEpoch<1||!i||!r)throw new Error("[OpenRTC] Managed room encryption is not settled.");let o=[];for(let d of e){let u=await i.__sealManagedRoomPayload(this.managedAvenueKey(),BigInt(n.epoch),BigInt(this.roomEncryptionEpoch),d.input.messageId,d.input.channel,d.input.priority,d.input.zoneId,d.input.payload);o.push({item:d,sealedState:u.sealedState,envelope:{messageId:d.input.messageId,channel:d.input.channel,priority:d.input.priority,scope:d.input.zoneId?{kind:"zone",zoneId:d.input.zoneId}:{kind:"global"},ciphertext:u.payload}});}await r.persist(D(o[o.length-1].sealedState));let s=[],a=0,c=async()=>{if(s.length===0)return;let d=s;s=[],a=0,await this.sendOperation({v:1,type:"managed.publish",idempotencyKey:v("managed-publish"),architectureEpoch:n.epoch,encryptionEpoch:this.roomEncryptionEpoch,batch:d.map(({envelope:u})=>u)});for(let{item:u}of d)u.resolve();};for(let d of o){let u=d.envelope.ciphertext.length;s.length>0&&a+u>Qe&&await c(),s.push(d),a+=u;}await c();}catch(n){for(let i of e)i.reject(n);throw n}finally{this.managedPublishQueue.length>0&&!this.managedPublishScheduled&&(this.managedPublishScheduled=true,queueMicrotask(()=>{this.managedPublishScheduled=false,this.enqueueManagedWork(()=>this.flushManagedPublishBatch());}));}}managedAvenueKey(){let e=this.activeAvenue??this.options.avenueOverride;if(!e||e.kind!=="room"&&e.kind!=="space")throw new Error("[OpenRTC] Managed groups require an active room or space.");return `${e.kind}:${e.id}`}async ensureManagedGroupInitialized(){if(this.managedState)return;if(this.managedInitialization)return this.managedInitialization;let e=this.managedWasmClient;if(!e)throw new Error("[OpenRTC] This browser runtime has no managed-room Rust/WASM owner.");let n=this.managedAvenueKey(),i=(async()=>{let r=await this.managedStateProvider(this.options.appTag,this.options.getLocalDeviceId(),n),o=await e.__initManagedRoomGroup(n,this.options.getLocalDeviceId(),r.wrappingKey,r.sealedState);this.managedState=r,await this.executeManagedGroupActions([o]);})();this.managedInitialization=i;try{await i;}finally{this.managedInitialization===i&&(this.managedInitialization=null);}}async executeManagedGroupActions(e){for(let n of e)if(n.type==="persist-state"){let i=this.managedState;if(!i)throw new Error("[OpenRTC] Managed room state store is unavailable.");await i.persist(D(n.sealedState));}else n.type==="publish-key-package"?await this.sendOperation({v:1,type:"managed.key-package.publish",idempotencyKey:v("managed-key-package"),keyPackageHash:n.keyPackageHash,keyPackage:n.keyPackage}):n.type==="request-prepare-page"?await this.sendOperation({v:1,type:"managed.prepare.page.request",idempotencyKey:v("managed-prepare-page"),preparationId:n.preparationId,pageIndex:n.pageIndex}):n.type==="send-artifact-chunk"?await this.sendOperation({v:1,type:"managed.commit.chunk",idempotencyKey:v("managed-artifact"),...n.chunk}):n.type==="acknowledge-commit"&&await this.sendOperation({v:1,type:"managed.commit.ack",idempotencyKey:v("managed-commit-ack"),preparationId:n.preparationId,encryptionEpoch:n.encryptionEpoch,groupIdHash:n.groupIdHash});}async handleManagedFrame(e){await this.ensureManagedGroupInitialized();let n=this.managedWasmClient;if(!n)throw new Error("[OpenRTC] Managed room Rust/WASM owner is unavailable.");let i=this.managedAvenueKey();if(e.type==="managed.prepare.page"){await this.executeManagedGroupActions(await n.__handleManagedRoomPreparePage(i,e));return}if(e.type==="managed.commit.chunk.received"){await this.executeManagedGroupActions(await n.__handleManagedRoomArtifactChunk(i,e));return}let r=this.roomArchitectureSnapshot;if(!r||r.effective!=="managed"||r.phase!=="settled"||e.architectureEpoch!==r.epoch||e.encryptionEpoch!==this.roomEncryptionEpoch)throw new Error("[OpenRTC] Managed room delivery uses a stale room lease.");let o=[],s=null;for(let a of e.batch){let c=a.scope.kind==="zone"?a.scope.zoneId:void 0,d=await n.__openManagedRoomPayload(i,BigInt(e.architectureEpoch),BigInt(e.encryptionEpoch),a.messageId,a.channel,a.priority,c,D(a.ciphertext));s=d.sealedState,o.push({senderId:e.senderDeviceId,messageId:a.messageId,channel:a.channel,priority:a.priority,...c?{zoneId:c}:{},payload:D(d.payload)});}if(s){let a=this.managedState;if(!a)throw new Error("[OpenRTC] Managed room state store is unavailable.");await a.persist(D(s));}for(let a of o)for(let c of this.managedMessageListeners)c(a);}async sendOperation(e,n){this.budgetRenewalPromise&&await this.budgetRenewalPromise,n?.();let i=this.budgetRenewalEpoch;try{await this.sendOperationOnce(e);}catch(r){if(n?.(false),!(r instanceof B)||r.code!=="budget-renewal-required"&&r.code!==a$1.BUDGET_RENEWAL_REQUIRED||!r.retryable)throw r;this.budgetRenewalEpoch===i&&await this.renewBudget(),n?.(),await this.sendOperationOnce(e);}}async sendOperationOnce(e){let n=this.socket;if(!n||n.readyState!==WebSocket.OPEN||!this.socketReady)throw new Error("Coordination gateway is not connected.");await new Promise((i,r)=>{let o=setTimeout(()=>{this.pendingAcks.get(e.idempotencyKey)?.timer===o&&this.pendingAcks.delete(e.idempotencyKey),r(new Error("Coordination gateway acknowledgement timed out."));},_);this.pendingAcks.set(e.idempotencyKey,{socket:n,resolve:i,reject:r,timer:o});try{n.send(JSON.stringify(e));}catch(s){clearTimeout(o),this.pendingAcks.delete(e.idempotencyKey),r(s instanceof Error?s:new Error(String(s)));}});}async renewBudget(){if(this.budgetRenewalPromise)return this.budgetRenewalPromise;let e=this.refreshAuthentication(true,true).then(()=>{this.budgetRenewalEpoch+=1;});this.budgetRenewalPromise=e;try{await e;}finally{this.budgetRenewalPromise===e&&(this.budgetRenewalPromise=null);}}async resolveAvenue(){if(this.options.avenueOverride)return this.options.avenueOverride;if((this.options.discoveryMode??"space")==="space"){let n=await this.options.resolveSpaceNamespaceId();if(!n)throw new Error("Space namespace is not available for coordination.");return {kind:"space",id:n}}let e=this.options.getCurrentUserId();if(!e)throw new Error("Authenticated user is required for coordination.");return {kind:"user",id:e}}gatewayDevice(e){return {deviceId:this.options.getLocalDeviceId(),runtimeInstanceId:this.runtimeInstanceId,nodeId:e.localNodeId,deviceName:e.deviceName,platformType:this.options.getPlatformType(),ticket:e.ticket,metadata:e.metadata,excludedPeers:this.desiredExcludedPeers,online:e.online}}controlPresence(){if(this.options.credentialPurpose!=="device-control")throw new Error("Coordination presence must be initialized before the gateway can connect.");return {localNodeId:this.options.getLocalDeviceId(),ticket:`openrtc-device-control:${this.runtimeInstanceId}`,online:false,ttlMs:0,deviceName:this.options.getDefaultDeviceName()}}toDevice(e){return this.options.normalizeDevice({...e,appTag:this.options.appTag,lastSeenAt:e.updatedAtMs,expiresAt:e.expiresAtMs},e.deviceId)}rebuildSparseDevices(){this.devices.clear();for(let e of this.sparseMembers.values()){let n=this.sparseRoutes.get(e.deviceId),i=n?{...e,...n}:{...e,runtimeInstanceId:"",nodeId:"",ticket:""};this.devices.set(e.deviceId,this.toDevice(i));}this.emitDevices();}acceptTopologyLease(e){if(e.topologyRevision<=this.sparseTopologyRevision)return;let n=this.activeAvenue,i=[...e.active,...e.backups],r=i.map(l=>l.deviceId),o=e.schemaVersion===1||this.validArchitectureLease(e.architecture),s=e.schemaVersion===1||this.validGroupEncryptionLease(e.groupEncryption,e.architecture),a=e.schemaVersion===2&&e.architecture.effectiveMode==="authority",c=e.schemaVersion===2?e.admissionPeers:void 0,d=!a||this.peerAdmissionScope!==null&&this.peerAdmissionRuntime!==null&&Array.isArray(c)&&c.length<=50&&new Set(c.map(l=>l.deviceId)).size===c.length&&c.every(l=>this.sparseMembers.get(l.deviceId)?.online&&l.deviceId!==this.options.getLocalDeviceId()&&/^[0-9a-f]{64}$/.test(l.nodeId));if(!((e.schemaVersion===1||e.schemaVersion===2)&&o&&s&&d&&Number.isSafeInteger(e.topologyRevision)&&e.topologyRevision>0&&(this.sparseTopologyRevision===0?e.previousTopologyRevision===void 0:e.previousTopologyRevision===this.sparseTopologyRevision)&&e.grantJti===this.activeGrantJti&&n!==null&&e.avenue.kind===n.kind&&e.avenue.id===n.id&&Number.isSafeInteger(e.expiresAtMs)&&e.expiresAtMs>Date.now()&&e.expiresAtMs<=this.activeGrantExpiresAtMs&&e.active.length<=16&&e.backups.length<=4&&i.length<=20&&new Set(r).size===r.length&&i.every(l=>l.online&&this.sparseMembers.has(l.deviceId)&&l.deviceId!==this.options.getLocalDeviceId()&&l.nodeId.trim().length>0&&l.ticket.trim().length>0))){this.socket?.close(4400,"invalid topology lease");return}if(a)try{this.peerAdmissionRuntime.__updateScopePeerAdmission(this.peerAdmissionScope,++this.peerAdmissionRevision,e.expiresAtMs,JSON.stringify(c.map(l=>l.nodeId)));}catch{this.socket?.close(4400,"invalid peer admission lease");return}if(e.schemaVersion===2){e.groupEncryption&&(this.roomEncryptionEpoch=e.groupEncryption.epoch);let l={requested:e.architecture.requestedMode,effective:e.architecture.effectiveMode,epoch:e.architecture.epoch,phase:e.architecture.phase,reason:e.architecture.reason},y=JSON.stringify(l)!==JSON.stringify(this.roomArchitectureSnapshot);if(this.roomArchitectureSnapshot=l,y)for(let f of this.architectureListeners)f({...l});if(l.effective!=="authority"&&this.roomAuthorityAssignment){this.roomAuthorityAssignmentExpiry&&(clearTimeout(this.roomAuthorityAssignmentExpiry),this.roomAuthorityAssignmentExpiry=null),this.roomAuthorityAssignment=null;for(let f of this.authorityAssignmentListeners)f(null);}l.effective==="managed"&&this.enqueueManagedWork(()=>this.ensureManagedGroupInitialized());}this.sparseTopologyRevision=e.topologyRevision,this.sparseRoutes.clear();for(let l of e.active)this.sparseRoutes.set(l.deviceId,{...l,topologyRole:"active",topologyRevision:e.topologyRevision});for(let l of e.backups)this.sparseRoutes.set(l.deviceId,{...l,topologyRole:"backup",topologyRevision:e.topologyRevision});this.rebuildSparseDevices();}acceptAuthorityAssignment(e,n){let i=this.roomAuthorityAssignment,r=this.options.getLocalDeviceId(),o=[e.serviceId,e.subjectDeviceId,e.shardId,...e.priorityDeviceIds,...e.relevantEntityIds];if(i&&e.generation===i.generation&&e.revision===i.revision){if(JSON.stringify({serviceId:e.serviceId,generation:e.generation,revision:e.revision,shardId:e.shardId,priorityDeviceIds:e.priorityDeviceIds,relevantEntityIds:e.relevantEntityIds,issuedAtMs:e.issuedAtMs,expiresAtMs:e.expiresAtMs})===JSON.stringify(i))return;this.socket?.close(4400,"invalid authority assignment");return}if(!(e.policyVersion==="room-authority-assignment-v1"&&this.roomArchitectureSnapshot?.effective==="authority"&&e.subjectDeviceId===r&&Number.isSafeInteger(e.generation)&&e.generation>0&&Number.isSafeInteger(e.revision)&&e.revision>0&&Number.isSafeInteger(e.issuedAtMs)&&Number.isSafeInteger(e.expiresAtMs)&&e.issuedAtMs<=Date.now()+3e4&&e.expiresAtMs>Date.now()&&e.expiresAtMs-e.issuedAtMs<=12e4&&e.priorityDeviceIds.length<=8&&e.relevantEntityIds.length<=32&&new Set(e.priorityDeviceIds).size===e.priorityDeviceIds.length&&new Set(e.relevantEntityIds).size===e.relevantEntityIds.length&&o.every(c=>/^[A-Za-z0-9_.:@-]{1,160}$/.test(c))&&/^[A-Za-z0-9_-]{86}$/.test(n)&&(!i||e.generation>i.generation||e.generation===i.generation&&e.revision>i.revision))){this.socket?.close(4400,"invalid authority assignment");return}this.roomAuthorityAssignment=Object.freeze({serviceId:e.serviceId,generation:e.generation,revision:e.revision,shardId:e.shardId,priorityDeviceIds:Object.freeze([...e.priorityDeviceIds]),relevantEntityIds:Object.freeze([...e.relevantEntityIds]),issuedAtMs:e.issuedAtMs,expiresAtMs:e.expiresAtMs}),this.roomAuthorityAssignmentExpiry&&clearTimeout(this.roomAuthorityAssignmentExpiry),this.roomAuthorityAssignmentExpiry=setTimeout(()=>{if(this.roomAuthorityAssignmentExpiry=null,this.roomAuthorityAssignment?.expiresAtMs===e.expiresAtMs){this.roomAuthorityAssignment=null;for(let c of this.authorityAssignmentListeners)c(null);}},Math.max(0,e.expiresAtMs-Date.now()));for(let c of this.authorityAssignmentListeners)c(this.roomAuthorityAssignmentSnapshot());}roomAuthorityAssignmentSnapshot(){let e=this.roomAuthorityAssignment;return !e||e.expiresAtMs<=Date.now()?null:{...e,priorityDeviceIds:[...e.priorityDeviceIds],relevantEntityIds:[...e.relevantEntityIds]}}validArchitectureLease(e){let n=this.roomArchitectureSnapshot?.epoch??0,i=new Set(["auto","mesh","sparse","managed","authority"]),r=new Set(["mesh","sparse","managed","authority"]),o=new Set(["size","traffic","latency","cost","capacity","manual","recovery"]);return e.policyVersion==="room-architecture-v1"&&Number.isSafeInteger(e.epoch)&&e.epoch>0&&e.epoch>=n&&(e.epoch===n||n===0||e.previousArchitectureEpoch===n)&&i.has(e.requestedMode)&&r.has(e.effectiveMode)&&(e.phase==="settled"||e.phase==="preparing")&&o.has(e.reason)&&Number.isSafeInteger(e.heldCreditsMicrousd)&&e.heldCreditsMicrousd>=0&&Number.isSafeInteger(e.quoteExpiresAtMs)&&e.quoteExpiresAtMs>0&&(e.reservationId===void 0||/^[A-Za-z0-9:_-]{1,160}$/.test(e.reservationId))}validGroupEncryptionLease(e,n){if(!e)return n.effectiveMode!=="managed"||n.phase==="preparing";let i=this.roomEncryptionEpoch;return e.policyVersion==="room-mls-v1"&&Number.isSafeInteger(e.epoch)&&e.epoch>0&&e.epoch>=i&&(e.epoch===i||i===0||e.previousEncryptionEpoch===i)&&(e.phase==="preparing"||e.phase==="settled")&&(n.effectiveMode!=="managed"||n.phase!=="settled"||e.phase==="settled")&&/^[A-Za-z0-9_.:@-]{1,160}$/.test(e.committerDeviceId)&&/^[A-Za-z0-9_-]{43}$/.test(e.groupIdHash)}snapshot(e){return [...this.devices.values()].filter(n=>!e||n.nodeId!==e).sort((n,i)=>n.deviceId.localeCompare(i.deviceId))}emitDevices(){let e=this.snapshot();for(let n of this.deviceListeners)n(e);}emitDeviceEvents(e){for(let n of this.deviceStreams)n.enqueue(e);}updateLocalDeviceExpiry(e){let n=this.options.getLocalDeviceId(),i=this.devices.get(n);if(!i||i.expiresAt===e)return;let r={...i,expiresAt:e};this.devices.set(n,r),this.emitDeviceEvents([{type:"modified",device:r}]),this.emitDevices();}scheduleAuthRefresh(e,n){this.authRefreshTimer&&clearTimeout(this.authRefreshTimer);let i=e-Date.now(),r=n===2?$e:qe,o=i>r+1e3;this.authRefreshTimer=setTimeout(()=>{if(this.authRefreshTimer=null,this.stopped)return;if(!o){this.stopSocket(false),this.scheduleReconnect(new h("Coordination credential crossed a billing boundary.",true));return}(n===2&&this.leaseRefreshMode==="active"?this.refreshLease():this.refreshAuthentication()).catch(a=>{this.stopSocket(false),this.scheduleReconnect(a);});},o?i-r:Math.max(1e3,i+1e3));}refreshAuthentication(e=false,n=false){let i=`${n?"refill":e?"issue":"refresh"}\0${this.desiredPresence?.ticket??""}`,r=this.authenticationRefreshes.get(i);if(r)return r;let o=this.authenticationRefreshTail.catch(()=>{}).then(()=>this.performAuthenticationRefresh(e,n));this.authenticationRefreshTail=o,this.authenticationRefreshes.set(i,o);let s=()=>{this.authenticationRefreshes.get(i)===o&&this.authenticationRefreshes.delete(i);};return o.then(s,s),o}currentRefillCredential(e){let n=this.refillCredential;if(!n||n.ticket!==e||n.grant.token!==this.activeGrantToken||n.grant.protocolVersion!==2||n.grant.expiresAtMs<this.activeGrantExpiresAtMs)return null;let i=Se(n.grant.token);return i?.budget?.controlFunding?.recipeVersion!=="coordination-provider-control-v3"||!Number.isSafeInteger(i?.exp)||!Number.isSafeInteger(n.grant.expiresAtMs)||Math.min(n.grant.expiresAtMs,Number(i?.exp)*1e3)<=Date.now()+_?null:n.grant}async performAuthenticationRefresh(e,n=false){let i=this.socket,r=this.desiredPresence;if(!i||i.readyState!==WebSocket.OPEN||!this.socketReady||!r)throw new h("Coordination socket is unavailable for credential refresh.",true);if(this.pendingAuthRefresh)return this.pendingAuthRefresh.promise;let o=(n?this.currentRefillCredential(r.ticket):null)??await this.mintGatewayCredential(r,!e);if(this.socket!==i||i.readyState!==WebSocket.OPEN||!this.socketReady)throw new h("Coordination socket changed while minting a credential refresh.",true);let s,a,c=new Promise((u,l)=>{s=u,a=l;}),d=setTimeout(()=>{this.pendingAuthRefresh?.timer===d&&(this.pendingAuthRefresh=null),a(new h("Coordination credential refresh timed out.",true));},_);this.pendingAuthRefresh={socket:i,promise:c,resolve:s,reject:a,timer:d};try{i.send(JSON.stringify({v:1,type:"auth.refresh",token:o.token}));}catch(u){this.rejectPendingAuthRefresh(new h(u instanceof Error?u.message:"Coordination credential refresh send failed.",true),i);}await c,this.activeGrantToken=o.token,this.refillCredential={grant:o,ticket:r.ticket},this.activeGrantJti=me(o.token),this.activeAvenue=o.avenue,this.activeGrantExpiresAtMs=o.expiresAtMs,this.activeGrantProtocolVersion=o.protocolVersion;}refreshLease(){let e=`lease\0${this.desiredPresence?.ticket??""}`,n=this.authenticationRefreshes.get(e);if(n)return n;let i=this.authenticationRefreshTail.catch(()=>{}).then(()=>this.performLeaseRefresh());this.authenticationRefreshTail=i,this.authenticationRefreshes.set(e,i);let r=()=>{this.authenticationRefreshes.get(e)===i&&this.authenticationRefreshes.delete(e);};return i.then(r,r),i}async performLeaseRefresh(){let e=this.socket;if(!e||e.readyState!==WebSocket.OPEN||!this.socketReady)throw new h("Coordination socket is unavailable for lease refresh.",true);if(this.pendingAuthRefresh)return this.pendingAuthRefresh.promise;let n=v("lease"),i,r,o=new Promise((a,c)=>{i=a,r=c;}),s=setTimeout(()=>{this.pendingAuthRefresh?.timer===s&&(this.pendingAuthRefresh=null,this.pendingLeaseRefreshKey=null),r(new h("Coordination lease refresh timed out.",true));},_);this.pendingLeaseRefreshKey=n,this.pendingAuthRefresh={socket:e,promise:o,resolve:i,reject:r,timer:s};try{e.send(JSON.stringify({v:1,type:"lease.refresh",idempotencyKey:n}));}catch(a){this.rejectPendingAuthRefresh(new h(a instanceof Error?a.message:"Coordination lease refresh send failed.",true),e);}try{await o;}catch(a){if(this.stopped||x(a))throw a;await this.performAuthenticationRefresh(true);}}stopForCredentialRevocation(e){return x(e)?(this.credentialRevoked=true,this.reconnectCircuitOpen=true,this.stopAuthActivity(),true):false}scheduleReconnect(e){if(this.stopForCredentialRevocation(e)||this.reconnectTimer||this.reconnectCircuitOpen||this.stopped)return;if(!(e instanceof h?e.retryable:!ve(e))){this.reconnectCircuitOpen=true,this.rejectConnectionReadyWaiters(e instanceof Error?e:new h("Coordination reconnect circuit is open.",false));return}if(this.reconnectOutageStartedAtMs??(this.reconnectOutageStartedAtMs=Date.now()),!this.hostAvailable)return;let i=Math.min(this.reconnectAttempt,he),r=Date.now()-this.reconnectOutageStartedAtMs>=Xe,o=rt(r?Ze:d(i,250,Ve));this.reconnectAttempt=Math.min(i+1,he),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.ensureConnected().catch(s=>this.scheduleReconnect(s));},o);}stopSocket(e=true){this.serviceObservationGeneration+=1,this.signalBatchMode="off",this.rejectQueuedSignals(new h("Signal activity retired before dispatch.",false)),this.connectPromise=null,this.peerAdmissionScope&&this.peerAdmissionRuntime&&this.peerAdmissionRuntime.__updateScopePeerAdmission(this.peerAdmissionScope,++this.peerAdmissionRevision,0,"[]"),e&&this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.authRefreshTimer&&clearTimeout(this.authRefreshTimer),this.reconnectTimer=null,this.keepaliveTimer&&clearInterval(this.keepaliveTimer),this.keepaliveTimer=null,this.authRefreshTimer=null,this.leaseRefreshMode="off",this.pendingLeaseRefreshKey=null,this.rejectPendingAuthRefresh(new h("Coordination credential refresh was canceled.",true));let n=this.socket;this.socket=null,this.socketReady=false,this.activeGrantJti=null,this.refillCredential=null,this.activeAvenue=null,this.activeGrantExpiresAtMs=0,this.sparseRoutes.clear(),this.sparseTopologyRevision=0,this.pendingMembershipPageSnapshot=null,this.pendingRosterPageSnapshot=null,this.sparseMembers.size>0&&this.rebuildSparseDevices(),n?.close(1e3,"coordination session stopped");}waitForConnectionReady(){return this.socket?.readyState===WebSocket.OPEN&&this.socketReady?Promise.resolve():this.stopped||this.reconnectCircuitOpen?Promise.reject(new h("Coordination reconnect circuit is unavailable.",false)):new Promise((e,n)=>{this.connectionReadyWaiters.add({resolve:e,reject:n});})}resolveConnectionReadyWaiters(){for(let e of this.connectionReadyWaiters)e.resolve();this.connectionReadyWaiters.clear();}rejectConnectionReadyWaiters(e){for(let n of this.connectionReadyWaiters)n.reject(e);this.connectionReadyWaiters.clear();}rejectPendingAuthRefresh(e,n){let i=this.pendingAuthRefresh;!i||n&&i.socket!==n||(clearTimeout(i.timer),this.pendingAuthRefresh=null,this.pendingLeaseRefreshKey=null,i.reject(e));}rejectPendingAcks(e,n){for(let[i,r]of this.pendingAcks)n&&r.socket!==n||(clearTimeout(r.timer),r.reject(new Error(e)),this.pendingAcks.delete(i));}unscopedId(e){let n=e.split("::");return n.length===2?n[1]:e}requireRoomConnection(e){let n=e.trim().toUpperCase(),i=this.roomConnections.get(n);if(!i)throw new Error(`Room ${n} is not joined through the coordination gateway.`);return i}friendConnection(e){let n=this.friendConnections.get(e);n||(n=new t({...this.options,avenueOverride:{kind:"user",id:e}}),n.setHostAvailability({available:this.hostAvailable,reason:"parent-avenue-created"}),this.friendConnections.set(e,n));let i=this.desiredPresence??this.friendObservationPresence;return !n.desiredPresence&&i&&this.activateFriendConnection(n,i),n}activateFriendConnection(e,n){e.updatePresence(n.localNodeId,n.ticket,n.online,n.ttlMs,n.metadata,n.deviceName).catch(()=>{});}roomMember(e){return {nodeId:e.nodeId??e.deviceId,userId:e.userId??"",ticket:e.ticket,joinedAt:Number(e.createdAt??e.lastSeenAt??Date.now()),lastSeenAt:Number(e.lastSeenAt??Date.now()),expiresAt:typeof e.expiresAt=="number"?e.expiresAt:void 0}}};var j=class{constructor(e){this.provider=e;this.cached=null;this.inFlight=null;this.refreshTimer=null;this.refreshRetryUsed=false;this.listeners=new Set;}async get(e=false){if(!this.provider)throw new Error("[OpenRTC] Native coordination requires coordinationGateway.nativeTrustTokenProvider; obtain tokens through a trusted backend without shipping the developer secret.");let n=Date.now();if(!e&&this.cached&&this.cached.expiresAtMs>n+3e4)return this.cached;if(this.inFlight)return this.inFlight;let i=(async()=>{let r=await this.provider(e),o=r?.token?.trim()??"",s=Number(r?.expiresAtMs),a=Date.now();if(!o||!Number.isFinite(s)||s<=a+3e4)throw new Error("[OpenRTC] Native trust token provider returned no usable short-lived token.");let c={token:o,expiresAtMs:s};return this.cached=c,this.refreshRetryUsed=false,this.notify(c),this.scheduleRefresh(c),c})();this.inFlight=i;try{return await i}finally{this.inFlight===i&&(this.inFlight=null);}}invalidate(){this.cached=null,this.clearRefreshTimer(),this.notify(null);}clear(){this.invalidate(),this.listeners.clear();}subscribe(e,n){return this.listeners.add(e),this.cached&&this.cached.expiresAtMs>Date.now()&&(n?.emitCurrent!==false&&e(this.cached),this.scheduleRefresh(this.cached)),()=>{this.listeners.delete(e),this.listeners.size===0&&this.clearRefreshTimer();}}notify(e){for(let n of this.listeners)n(e);}scheduleRefresh(e){if(this.clearRefreshTimer(),this.listeners.size===0)return;let n=Math.max(0,e.expiresAtMs-Date.now()-3e4);this.refreshTimer=setTimeout(()=>{this.refreshTimer=null,this.get(true).catch(()=>{if(this.listeners.size===0||this.refreshRetryUsed){this.invalidate();return}this.refreshRetryUsed=true,this.refreshTimer=setTimeout(()=>{this.refreshTimer=null,this.get(true).catch(()=>this.invalidate());},15e3);});},n);}clearRefreshTimer(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}};var we=class{constructor(e){this.options=e;this.signaling=null;this.wasmClient=null;this.managedStateProvider=null;this.hostAvailability={available:true,reason:"initial"};this.nativeTrustTokens=e.gateway?new j(e.gateway.nativeTrustTokenProvider):null;}usesGateway(){return !!this.options.gateway}getSignaling(){if(this.options.signalingMode==="ticket-only")throw new Error('[openrtc] Managed signaling is disabled when signalingMode="ticket-only".');if(!this.options.gateway)throw new Error("[OpenRTC] Managed coordination requires coordinationGateway; the legacy direct Firebase data plane has been removed.");if(!this.signaling){this.signaling=new U({projectId:this.options.projectId,gateway:this.options.gateway,appTag:this.options.appTag,discoveryMode:this.options.discoveryMode,resolveSpaceNamespaceId:this.options.resolveSpaceNamespaceId,getCurrentUserId:this.options.getCurrentUserId,getAuthToken:this.options.getAuthToken,getAppCheckToken:this.options.getAppCheckToken,getLocalDeviceId:this.options.getLocalDeviceId,getDefaultDeviceName:this.options.getDefaultDeviceName,getPlatformType:this.options.getPlatformType,normalizeDevice:this.options.normalizeDevice,avenueOverride:this.options.avenueOverride,roomArchitecture:this.options.roomArchitecture,initialExcludedPeers:this.options.initialExcludedPeers,nativeTrustTokens:this.nativeTrustTokens});let e=this.signaling;this.managedStateProvider?e.setManagedRoomRuntime(this.wasmClient,this.managedStateProvider):e.setWasmClient(this.wasmClient),this.signaling.setHostAvailability?.(this.hostAvailability);}return this.signaling}setWasmClient(e){this.wasmClient=e,this.managedStateProvider=null,this.signaling?.setWasmClient(e);}setManagedRoomRuntime(e,n){this.wasmClient=e,this.managedStateProvider=n,this.signaling?.setManagedRoomRuntime(e,n);}setHostAvailability(e){this.hostAvailability=e,this.signaling?.setHostAvailability?.(e);}async reconnectAfterHostResume(){await this.signaling?.reconnectAfterHostResume?.();}async handleScopeChange(){await this.signaling?.handleScopeChange();}stopAuthActivity(){this.signaling?.stopAuthActivity();}async getNativeTrustToken(e=false){if(!this.nativeTrustTokens)throw new Error("[OpenRTC] Native trust tokens require a coordination gateway.");return this.nativeTrustTokens.get(e)}invalidateNativeTrustToken(){this.nativeTrustTokens?.invalidate();}subscribeNativeTrustToken(e,n){return this.nativeTrustTokens?.subscribe(e,n)??(()=>{})}};function at(){if(typeof globalThis<"u"&&globalThis.__OPENRTC_DEBUG__===true)return true;if(typeof localStorage<"u")try{return localStorage.getItem("openrtc:debug")==="1"}catch{return false}return false}function Y(t,e,n){if(at()){if(typeof n>"u"){console[t](e);return}console[t](e,n);}}function rn(t,e){Y("debug",t,e);}function on(t,e){Y("info",t,e);}function sn(t,e){Y("log",t,e);}function Ie(){return typeof window>"u"?false:!!(window.__TAURI_IPC__||window.__TAURI_INTERNALS__||window.__TAURI__||window.location.protocol==="tauri:"||window.location.hostname==="tauri.localhost")}var ct="[OpenRTC][teardown-trace]";function dt(){try{let t=globalThis;if(t.OPENRTC_TEARDOWN_TRACE===!0||t.localStorage?.getItem("OPENRTC_TEARDOWN_TRACE")==="1")return !0}catch{}return false}function dn(t,e={}){console.info(ct,{kind:t,ts:new Date().toISOString(),...e}),dt()&&console.info("[OpenRTC][teardown-trace:stack]",{kind:t,stack:new Error(`teardown: ${t}`).stack});}var z="trustedDevice",lt="plutonium:e2ee:identity:v1",ut="plutonium:e2ee:identity:session:v1",pt="openrtc-trust",E="identity",Te="transport-trust:v1",ht=2,Re="managed-room-keys",Ae="managed-room-state",gt=1,S=null,O=null;function R(t){let e=atob(t),n=new Uint8Array(e.length);for(let i=0;i<e.length;i+=1)n[i]=e.charCodeAt(i);return n}function N(t){let e="";for(let n=0;n<t.length;n+=1)e+=String.fromCharCode(t[n]);return btoa(e)}async function X(t){let e=await crypto.subtle.digest("SHA-256",t),n=new Uint8Array(e);return Array.from(n).map(i=>i.toString(16).padStart(2,"0")).join("")}function yt(){return typeof sessionStorage>"u"?null:sessionStorage}function mt(){if(!(typeof localStorage>"u"))try{localStorage.removeItem(lt);}catch{}}var F=null;async function Pe(){return F||(F=(async()=>{let t=globalThis.crypto?.subtle;if(!t||typeof t.generateKey!="function")return false;try{let e=await t.generateKey({name:"Ed25519"},!1,["sign","verify"]);return !!(e&&e.privateKey&&e.publicKey)}catch{return false}})(),F)}async function ft(t){let e=await crypto.subtle.exportKey("raw",t);return new Uint8Array(e)}function vt(){try{return typeof indexedDB<"u"?indexedDB:null}catch{return null}}function Ce(){let t=vt();return t?new Promise(e=>{let n;try{n=t.open(pt,ht);}catch{e(null);return}n.onupgradeneeded=()=>{let i=n.result;i.objectStoreNames.contains(E)||i.createObjectStore(E),i.objectStoreNames.contains(Re)||i.createObjectStore(Re),i.objectStoreNames.contains(Ae)||i.createObjectStore(Ae);},n.onsuccess=()=>e(n.result),n.onerror=()=>e(null),n.onblocked=()=>e(null);}):Promise.resolve(null)}async function bt(){let t=await Ce();if(!t)return null;try{return await new Promise(e=>{let r=t.transaction(E,"readonly").objectStore(E).get(Te);r.onsuccess=()=>{let o=r.result;e(o&&o.privateKey&&o.publicKey?o:null);},r.onerror=()=>e(null);})}catch{return null}finally{t.close();}}async function St(t){let e=await Ce();if(!e)return false;try{return await new Promise(n=>{let i=e.transaction(E,"readwrite");i.objectStore(E).put(t,Te),i.oncomplete=()=>n(!0),i.onerror=()=>n(!1),i.onabort=()=>n(!1);})}catch{return false}finally{e.close();}}async function Me(t,e){let n=await ft(t.publicKey),i=await X(n),r=t.privateKey;return {publicKey:n,fingerprint:i,backend:"webcrypto-nonextractable",durable:e,privateKey:r,async signChallenge(o){let s=await crypto.subtle.sign({name:"Ed25519"},r,R(o));return N(new Uint8Array(s))}}}function wt(t,e,n){let i=t.secretKey;return {publicKey:t.publicKey,secretKey:i,fingerprint:e,backend:"tweetnacl",durable:n,async signChallenge(r){return It(r,i)}}}function hn(t=32){let e=crypto.getRandomValues(new Uint8Array(t));return N(e)}function It(t,e){let n=G.sign.detached(R(t),e);return N(n)}function Rt(t,e,n){try{return G.sign.detached.verify(R(t),R(e),R(n))}catch{return false}}async function gn(t,e,n){let i=globalThis.crypto?.subtle;if(i&&typeof i.importKey=="function"&&typeof i.verify=="function")try{let r=await i.importKey("raw",R(n),{name:"Ed25519"},!1,["verify"]);return await i.verify({name:"Ed25519"},r,R(e),R(t))}catch{}return Rt(t,e,n)}function yn(t){return N(t)}function mn(t){if(!t||!t.trim())return null;try{let e=JSON.parse(t),n=e&&typeof e=="object"&&!Array.isArray(e)?e[z]:null;if(!n||typeof n!="object"||Array.isArray(n))return null;let i=n,r=typeof i.version=="number"?i.version:null,o=typeof i.identityPublicKey=="string"?i.identityPublicKey:null,s=typeof i.identityFingerprint=="string"?i.identityFingerprint:null;return !r||!o||!s?null:{version:r,identityPublicKey:o,identityFingerprint:s}}catch{return null}}async function At(){let t=await Et().catch(()=>null);return t?{version:gt,identityPublicKey:N(t.publicKey),identityFingerprint:t.fingerprint}:null}async function fn(t){let e=await At();if(!e)return t??void 0;let n=typeof t=="string"?t.trim():"";if(!n)return JSON.stringify({[z]:e});try{let i=JSON.parse(n);if(i&&typeof i=="object"&&!Array.isArray(i))return JSON.stringify({...i,[z]:e})}catch{}return JSON.stringify({metadata:t,[z]:e})}function Tt(){if(typeof window>"u")return null;let t=window.__TAURI_INTERNALS__;return !t||typeof t.invoke!="function"?null:t.invoke.bind(t)}async function Pt(){if(typeof window>"u")return null;let t=Tt();if(!Ie()&&!t)return null;if(!t)throw new Error("[OpenRTC] Tauri transport trust requires the native signing provider, but Tauri invoke is unavailable.");try{let e=await t("openrtc_get_transport_trust_identity"),n=R(e.publicKeyBase64);if(n.byteLength!==G.sign.publicKeyLength)throw new Error("native transport trust public key has an invalid length");let i=await X(n);if(e.fingerprint!==i)throw new Error("native transport trust fingerprint does not match its public key");return {publicKey:n,fingerprint:i,backend:"native-provider",durable:!0,async signChallenge(r){return t("openrtc_sign_transport_trust_challenge",{challenge:r})}}}catch(e){let n=new Error("[OpenRTC] native transport trust provider failed; refusing WebCrypto fallback in Tauri.");throw n.cause=e,n}}function Ct(){let t=yt();t&&t.removeItem(ut);}async function Mt(){if(mt(),Ct(),S)return S;let t=await Pt();if(t)return S=t,S;if(await Pe()){let e=await bt();if(e)return S=await Me(e,true),S}return null}async function Et(t={}){let e=i=>{if(t.ephemeral===true&&i?.durable)throw new Error("Cannot replace an active durable transport identity with an ephemeral identity.");if(t.ephemeral===false&&i&&!i.durable)throw new Error("Persistent transport identity requires durable storage before session startup.");return i};if(S)return e(S);if(O)return e(await O);let n=(async()=>{if(t.ephemeral!==true){let i=await Mt();if(i)return i}return kt(t)})();O=n;try{return e(await n)}finally{O===n&&(O=null);}}async function kt(t){if(S)return S;let e=t.ephemeral===true;if(await Pe())try{let n=await crypto.subtle.generateKey({name:"Ed25519"},!1,["sign","verify"]),i=!1;return e||(i=await St(n)),S=await Me(n,i),S}catch{}if(!e)return console.warn("[OpenRTC][TRUST] Managed transport trust requires WebCrypto Ed25519 or native keychain; refusing extractable fallback storage"),null;try{let n=G.sign.keyPair(),i=await X(b(n.publicKey));return S=wt(n,i,!1),S}catch{return null}}var _t={managedSession:{nativeStartRetryWindowMs:12e4,nativeStartRetryMinDelayMs:400,nativeStartRetryMaxDelayMs:5e3,deviceStatusRefreshDebounceMs:50},browserAutoConnect:{scanDebounceMs:150,retryCooldownMs:2e3,settleGuardMs:1e4,retryMaxMs:8e3,nonInitiatorBaseGraceMs:2e3,nonInitiatorMaxGraceMs:16e3},nativeIpc:{authRequiredWaitMs:15e3,defaultBoundedCommandTimeoutMs:15e3,connectionEventSubscribeWindowMs:15e3,connectionEventRetryMinDelayMs:250,connectionEventRetryMaxDelayMs:1e3,tauriIpcNegativeCacheMs:2e3},browserIdentity:{ephemeralDeviceIdTtlMs:6e4}};function bn(){return _t}var Dt={adapter:"browser-wasm",productMaturity:{boundedRooms:"stable",serviceNodes:"preview",offlineEdge:"support-only",broadcast:"preview"},signaling:{coordinationGateway:true,nativeIpc:false,managedPresence:true},transport:{irohQuic:false,irohLan:false,webRtc:true,moq:true,ble:false,wasm:true},nativeProtocols:{productAlpn:false,irohDocs:false,irohBlobs:false,irohGossip:false},lifecycle:{managedSession:true,autoConnect:true,manualDisconnect:true,connectionStateEvents:true,peerSessions:true},transfers:{explicitFilePath:false,explicitFileData:true,history:false},fallback:{wasm:false}},xt={adapter:"native-ipc",productMaturity:{boundedRooms:"stable",serviceNodes:"unavailable",offlineEdge:"unavailable",broadcast:"unavailable"},signaling:{coordinationGateway:true,nativeIpc:true,managedPresence:true},transport:{irohQuic:true,irohLan:false,webRtc:false,moq:false,ble:false,wasm:false},nativeProtocols:{productAlpn:true,irohDocs:true,irohBlobs:true,irohGossip:true},lifecycle:{managedSession:true,autoConnect:true,manualDisconnect:true,connectionStateEvents:true,peerSessions:true},transfers:{explicitFilePath:true,explicitFileData:true,history:true},fallback:{wasm:false}};function Ee(t){return {adapter:t.adapter,productMaturity:t.productMaturity?{...t.productMaturity}:void 0,signaling:{...t.signaling},transport:{...t.transport},nativeProtocols:{...t.nativeProtocols},lifecycle:{...t.lifecycle},transfers:{...t.transfers},fallback:{...t.fallback}}}function wn(t=globalThis){let e=Ee(Dt),n=typeof t?.RTCPeerConnection=="function";return e.transport.webRtc=n,e}function K(t){return t?.compiled===true&&t.enabled===true}function In(t,e=false){let n=Ee(xt),i=t?.transport;return n.productMaturity={...n.productMaturity,...t?.productMaturity},i&&(n.transport.irohQuic=K(i.irohQuic),n.transport.irohLan=K(i.irohLan),n.transport.webRtc=K(i.webRtc),n.transport.moq=K(i.moq),n.transport.ble=K(i.ble)),n.transport.wasm=false,n.fallback.wasm=e,n}function Rn(t){return {environment:t.adapter==="native-ipc"||t.adapter==="tauri-ipc"?"native":t.adapter==="browser-wasm"?"web":"unknown",productMaturity:t.productMaturity?{...t.productMaturity}:void 0,transports:{quic:t.transport.irohQuic,irohRelay:t.transport.irohQuic||t.adapter==="browser-wasm",irohLan:t.transport.irohLan,webRtc:t.transport.webRtc,moq:t.transport.moq,ble:t.transport.ble},lifecycle:{...t.lifecycle},storage:{localFileSystem:t.transfers.explicitFilePath,transferHistory:t.transfers.history},nativeProtocols:{...t.nativeProtocols}}}function ke(t){if(t.errorCode)return t;let e=t.error||t.readinessReason;if(!e)return t;let n=c(e);return {...t,errorCode:n.errorCode,retryable:n.retryable,errorPlane:n.errorPlane}}function k(t){return !t||typeof t!="object"?{}:t instanceof Map?Object.fromEntries(t):t}function Z(t){let e=k(t),n=k(e.device);if(!Object.keys(n).length)return e;let i={...n,...e};return delete i.device,i}function p(t,...e){for(let n of e){let i=t[n];if(typeof i=="string"&&i.trim().length>0)return i}}function I(t,...e){for(let n of e){let i=t[n];if(typeof i=="boolean")return i}}function g(t,...e){for(let n of e){let i=t[n];if(typeof i=="number"&&Number.isFinite(i))return i}}function P(t){if(typeof t=="number"&&Number.isFinite(t))return t;if(t instanceof Date){let e=t.getTime();return Number.isFinite(e)?e:void 0}if(typeof t=="string"){let e=Date.parse(t);return Number.isFinite(e)?e:void 0}if(t&&typeof t=="object"){let e=t;if(typeof e.toMillis=="function"){let i=e.toMillis();return Number.isFinite(i)?i:void 0}let n=typeof e.seconds=="number"?e.seconds:typeof e._seconds=="number"?e._seconds:void 0;if(n!==void 0&&Number.isFinite(n)){let i=typeof e.nanoseconds=="number"?e.nanoseconds:typeof e._nanoseconds=="number"?e._nanoseconds:0;return n*1e3+Math.floor((Number.isFinite(i)?i:0)/1e6)}}}function ee(...t){let e=t.map(P).filter(n=>typeof n=="number"&&Number.isFinite(n));return e.length?Math.max(...e):void 0}function te(t){if(typeof t!="string")return;let e=t.trim().toLowerCase();return e==="online"||e==="idle"||e==="offline"?e:void 0}function _e(t){let e=te("presenceStatus"in t?t.presenceStatus:void 0),n="presenceUpdatedAt"in t?P(t.presenceUpdatedAt):void 0,i="presenceExpiresAt"in t?P(t.presenceExpiresAt):void 0,r=n??ee(t.lastSeenAt,t.updatedAt,t.createdAt),o=i??P(t.expiresAt),s=e;s||(t.online?r!==void 0&&r+3e5<=Date.now()?s="idle":s="online":s="offline");let a=typeof t.ticket=="string"?t.ticket.trim():"",c="connectable"in t&&typeof t.connectable=="boolean"?t.connectable:s==="online"&&a.length>0;return {presenceStatus:s,presenceUpdatedAt:r,presenceExpiresAt:o,connectable:c}}function De(t){return l(t)}function C(t,...e){return De(p(t,...e))}function H(t){if(!Array.isArray(t))return;let e=Array.from(new Set(t.map(De).filter(n=>!!n)));return e.length?e:void 0}function xe(t){let e=k(t),n={webrtc:g(e,"webrtc"),iroh:g(e,"iroh"),irohLan:g(e,"irohLan","iroh_lan"),irohRelay:g(e,"irohRelay","iroh_relay"),ble:g(e,"ble"),moq:g(e,"moq")};return Object.values(n).some(i=>i!==void 0)?n:void 0}function Mn(t){return (t.discoveryMode??"space")==="space"&&typeof t.apiKey=="string"&&t.apiKey.trim().length>0&&typeof t.spaceKey=="string"&&t.spaceKey.trim().length>0}function En(t,e,n){return n?true:(typeof t.appTag=="string"?t.appTag:typeof t.tag=="string"?t.tag:void 0)===e}function Ot(t,e){let n=Z(t),i=p(n,"deviceId","device_id")||e||"",r=p(n,"nodeId","node_id")||"",o=p(n,"ticket")||"";return {deviceId:i,deviceName:p(n,"deviceName","device_name")||"Unknown Device",online:!!n.online,ticket:o,friendTicket:p(n,"friendTicket","friend_ticket"),presenceStatus:te(p(n,"presenceStatus","presence_status","livenessStatus","liveness_status")),presenceUpdatedAt:g(n,"presenceUpdatedAt","presence_updated_at")??ee(n.presenceUpdatedAt,n.presence_updated_at,n.lastSeenAt,n.last_seen_at,n.updatedAt,n.updated_at,n.createdAt,n.created_at),presenceExpiresAt:g(n,"presenceExpiresAt","presence_expires_at")??P(n.presenceExpiresAt??n.presence_expires_at)??P(n.expiresAt??n.expires_at),connectable:I(n,"connectable"),kind:p(n,"kind"),nodeId:r||void 0,devicePublicKeyJwk:n.devicePublicKeyJwk??n.device_public_key_jwk,platformType:p(n,"platformType","platform_type"),capabilities:n.capabilities||void 0,sessionId:p(n,"sessionId","session_id"),userId:p(n,"userId","user_id"),lastSeenAt:n.lastSeenAt??n.last_seen_at,expiresAt:n.expiresAt??n.expires_at,createdAt:n.createdAt??n.created_at,updatedAt:n.updatedAt??n.updated_at,metadata:p(n,"metadata"),excludedPeers:W(n.excludedPeers??n.excluded_peers),availableTransports:H(n.availableTransports??n.available_transports),transports:H(n.transports),topologyRole:n.topologyRole==="active"||n.topologyRole==="backup"?n.topologyRole:void 0,topologyRevision:Number.isSafeInteger(n.topologyRevision)&&Number(n.topologyRevision)>0?Number(n.topologyRevision):void 0}}function W(t){return Array.isArray(t)?[...new Set(t.filter(e=>typeof e=="string").map(e=>e.trim()).filter(Boolean))]:[]}function Gt(t){let e=_e(t);return {...t,...e,connectionStatus:"connectionStatus"in t&&typeof t.connectionStatus=="string"?t.connectionStatus:t.online?"online":"disconnected",settledReady:"settledReady"in t&&typeof t.settledReady=="boolean"?t.settledReady:false,readinessState:"readinessState"in t&&typeof t.readinessState=="string"?t.readinessState:void 0,readinessReason:"readinessReason"in t&&typeof t.readinessReason=="string"?t.readinessReason:void 0,peerHealth:"peerHealth"in t&&typeof t.peerHealth=="string"?t.peerHealth:"unknown",peerId:"peerId"in t&&typeof t.peerId=="string"?t.peerId:void 0,promotionEligible:"promotionEligible"in t&&typeof t.promotionEligible=="boolean"?t.promotionEligible:true,scopes:"scopes"in t?W(t.scopes):[],connectionId:"connectionId"in t&&typeof t.connectionId=="string"?t.connectionId:void 0,deviceIdHint:"deviceIdHint"in t&&typeof t.deviceIdHint=="string"?t.deviceIdHint:void 0,transportStableId:"transportStableId"in t&&typeof t.transportStableId=="number"?t.transportStableId:"transportStableId"in t?t.transportStableId??null:void 0,transportGeneration:"transportGeneration"in t&&typeof t.transportGeneration=="number"?t.transportGeneration:void 0,routeGeneration:"routeGeneration"in t&&typeof t.routeGeneration=="number"?t.routeGeneration:void 0,activeTransport:"activeTransport"in t?t.activeTransport:void 0,parallelTransport:"parallelTransport"in t?t.parallelTransport:void 0,availableTransports:"availableTransports"in t?H(t.availableTransports):"transports"in t?H(t.transports):void 0,latencyMs:"latencyMs"in t&&typeof t.latencyMs=="number"?t.latencyMs:void 0,latencyByTransport:"latencyByTransport"in t?xe(t.latencyByTransport):void 0}}function L(t,e){return e===void 0?true:e===null?t==null:t==null||t===e}function Oe(t,e){let n=L(t.connectionId,e.connectionId)&&L(t.nodeId,e.nodeId)&&L(t.transportStableId,e.transportStableId)&&L(t.transportGeneration,e.transportGeneration)&&L(t.routeGeneration,e.routeGeneration),i=(r,o)=>r!==void 0?r:n?o:void 0;return {inheritsSnapshot:n,fields:{connectionId:i(e.connectionId??void 0,t.connectionId),transportStableId:i(e.transportStableId,t.transportStableId),transportGeneration:i(e.transportGeneration,t.transportGeneration),routeGeneration:i(e.routeGeneration,t.routeGeneration),activeTransport:i(e.activeTransport,t.activeTransport),parallelTransport:i(e.parallelTransport,t.parallelTransport),latencyMs:n?t.latencyMs:void 0,latencyByTransport:n?t.latencyByTransport:void 0}}}var Nt={connectionId:void 0,transportStableId:null,transportGeneration:void 0,routeGeneration:void 0,activeTransport:void 0,parallelTransport:void 0,latencyMs:void 0,latencyByTransport:void 0};function Kt(t,e,n){let i=Oe(t,{connectionId:e.activeConnectionId,nodeId:e.nodeId,transportStableId:e.transportStableId,transportGeneration:e.transportGeneration,routeGeneration:e.routeGeneration,activeTransport:e.activeTransport,parallelTransport:e.parallelTransport}),r=n?n({connectionId:e.activeConnectionId??void 0,deviceId:e.deviceId??void 0,deviceIdHint:e.deviceIdHint??void 0,nodeId:e.nodeId??void 0}):t.promotionEligible??true;if(!r)return {...t,peerHealth:e.health??t.peerHealth,peerId:e.peerId??t.peerId,promotionEligible:r,scopes:e.scopes?.length?[...e.scopes]:t.scopes,nodeId:e.nodeId===void 0?t.nodeId:e.nodeId??void 0,deviceIdHint:e.deviceIdHint??t.deviceIdHint,...i.fields,readinessReason:e.readinessReason??t.readinessReason};let o=e.status??t.connectionStatus,s=typeof o=="string"?o.trim().toLowerCase():"",a=s==="failed"||s==="closed"||s==="disconnected",d=typeof e.readinessState=="string"&&e.readinessState.trim().length>0?e.readinessState==="routable":e.settledReady===true,u=t.settledReady===true||t.readinessState==="routable";if(i.inheritsSnapshot&&u&&!a&&!d)return {...t,peerHealth:e.health??t.peerHealth,peerId:e.peerId??t.peerId,promotionEligible:r,scopes:e.scopes?.length?[...e.scopes]:t.scopes,nodeId:e.nodeId===void 0?t.nodeId:e.nodeId??void 0,deviceIdHint:e.deviceIdHint??t.deviceIdHint,...i.fields,readinessReason:e.readinessReason??t.readinessReason};let l=a?false:d,y=d&&!a&&(s==="connecting"||s==="connected")?"connected":o,f=d?"routable":e.readinessState??(i.inheritsSnapshot?t.readinessState:void 0),w=l?e.readinessReason??"peer-session-settled":e.readinessReason??(i.inheritsSnapshot?t.readinessReason:void 0);return {...t,connectionStatus:y,settledReady:l,readinessState:f,readinessReason:w,peerHealth:e.health??t.peerHealth,peerId:e.peerId??t.peerId,promotionEligible:r,scopes:e.scopes?.length?[...e.scopes]:t.scopes,nodeId:e.nodeId===void 0?t.nodeId:e.nodeId??void 0,deviceIdHint:e.deviceIdHint??t.deviceIdHint,...i.fields}}function Lt(t,e){let n=Oe(t,{connectionId:e.connectionId,nodeId:e.nodeId,transportStableId:e.transportStableId,transportGeneration:e.transportGeneration,routeGeneration:e.routeGeneration,activeTransport:e.activeTransport,parallelTransport:e.parallelTransport});if(e.promotionEligible===false)return {...t,peerHealth:e.health??t.peerHealth,peerId:e.peerId??t.peerId,promotionEligible:false,nodeId:e.nodeId??t.nodeId,deviceIdHint:e.deviceIdHint??t.deviceIdHint,...n.fields,scopes:e.scopes?.length?[...e.scopes]:t.scopes};let i=e.status??t.connectionStatus,r=typeof i=="string"?i.trim().toLowerCase():"",o=r==="failed"||r==="closed"||r==="disconnected",s=t.settledReady===true||t.readinessState==="routable",a=e.routable===false;if(n.inheritsSnapshot&&s&&o&&!a)return {...t,peerHealth:t.peerHealth??e.health,peerId:t.peerId??e.peerId,promotionEligible:e.promotionEligible??t.promotionEligible??true,connectionId:t.connectionId??e.connectionId,deviceIdHint:t.deviceIdHint??e.deviceIdHint,scopes:t.scopes?.length?t.scopes:e.scopes??t.scopes};if(s&&o)return {...t,connectionStatus:i,settledReady:false,readinessState:void 0,readinessReason:e.error??t.readinessReason,peerHealth:e.health??t.peerHealth,peerId:e.peerId??t.peerId,promotionEligible:e.promotionEligible??t.promotionEligible??true,deviceIdHint:e.deviceIdHint??t.deviceIdHint,...Nt,scopes:e.scopes?.length?[...e.scopes]:t.scopes};let c=e.routable===true||e.protocolState==="routable";if(n.inheritsSnapshot&&s&&!o&&!c)return {...t,peerHealth:t.peerHealth??e.health,peerId:t.peerId??e.peerId,promotionEligible:e.promotionEligible??t.promotionEligible??true,connectionId:t.connectionId??e.connectionId,deviceIdHint:t.deviceIdHint??e.deviceIdHint,transportStableId:t.transportStableId??e.transportStableId,transportGeneration:t.transportGeneration??e.transportGeneration,routeGeneration:t.routeGeneration??e.routeGeneration,activeTransport:t.activeTransport??e.activeTransport,parallelTransport:t.parallelTransport===void 0?e.parallelTransport:t.parallelTransport,scopes:t.scopes?.length?t.scopes:e.scopes??t.scopes};let d=e.transportState==="connected"&&e.health==="healthy",u=o?false:c,l=!o&&(c||d)&&(r==="connecting"||r==="connected"||e.transportState==="connected")?"connected":i,y=u?"routable":(e.routable===false&&e.protocolState?e.protocolState:void 0)??(n.inheritsSnapshot?t.readinessState:void 0)??(e.status==="connecting"?e.transportState==="connected"?"transport-only":"connecting":void 0),f=u?(n.inheritsSnapshot?t.readinessReason:void 0)??(e.routable===true?"peer-projection-routable":void 0):(e.routable===false&&e.error?e.error:void 0)??(n.inheritsSnapshot?t.readinessReason:void 0)??(e.status==="connecting"?e.transportState==="connected"?"peer-projection-transport-ready":"peer-projection-connecting":void 0);return {...t,connectionStatus:l,settledReady:u,readinessState:y,readinessReason:f,peerHealth:e.health??t.peerHealth,peerId:e.peerId??t.peerId,promotionEligible:e.promotionEligible??t.promotionEligible??true,nodeId:e.nodeId??t.nodeId,deviceIdHint:e.deviceIdHint??t.deviceIdHint,...n.fields,scopes:e.scopes?.length?[...e.scopes]:t.scopes}}function Ht(t){let{device:e,session:n=null,peer:i=null,isPromotionEligible:r}=t,o=Gt(e);return n&&(o=Kt(o,n,r)),i&&(o=Lt(o,i)),ke(o)}function kn(t){let e=Z(t),n=Ot(e),i=te(p(e,"presenceStatus","presence_status","livenessStatus","liveness_status")),r=_e({...n,...i?{presenceStatus:i}:{},presenceUpdatedAt:g(e,"presenceUpdatedAt","presence_updated_at")??ee(e.presenceUpdatedAt,e.presence_updated_at,e.lastSeenAt,e.last_seen_at,e.updatedAt,e.updated_at,e.createdAt,e.created_at),presenceExpiresAt:g(e,"presenceExpiresAt","presence_expires_at")??P(e.presenceExpiresAt??e.presence_expires_at)??P(e.expiresAt??e.expires_at),connectable:I(e,"connectable")}),o={...n,...r,connectionStatus:p(e,"connectionStatus","connection_status")||"disconnected",settledReady:I(e,"settledReady","settled_ready")??false,readinessState:p(e,"readinessState","readiness_state")??void 0,readinessReason:p(e,"readinessReason","readiness_reason")??void 0,peerHealth:p(e,"peerHealth","peer_health")||"unknown",peerId:p(e,"peerId","peer_id"),scopes:W(e.scopes),connectionId:p(e,"connectionId","connection_id"),deviceIdHint:p(e,"deviceIdHint","device_id_hint"),transportStableId:g(e,"transportStableId","activeTransportStableId","active_transport_stable_id")??void 0,transportGeneration:g(e,"transportGeneration","transport_generation")??void 0,routeGeneration:g(e,"routeGeneration","route_generation")??void 0,activeTransport:C(e,"activeTransport","active_transport"),parallelTransport:C(e,"parallelTransport","parallel_transport")??null,availableTransports:H(e.availableTransports??e.available_transports),latencyMs:g(e,"latencyMs","latency_ms"),latencyByTransport:xe(e.latencyByTransport??e.latency_by_transport)};return Ht({device:o})}function _n(t){let e=Z(t);return ke({peerId:p(e,"peerId","peer_id")||"",deviceId:p(e,"deviceId","device_id"),deviceIdHint:p(e,"deviceIdHint","device_id_hint"),nodeId:p(e,"nodeId","node_id"),activeConnectionId:p(e,"activeConnectionId","active_connection_id"),candidates:Array.isArray(e.candidates)?e.candidates.filter(n=>typeof n=="string"):Array.isArray(e.candidateConnectionIds)?e.candidateConnectionIds.filter(n=>typeof n=="string"):Array.isArray(e.candidate_connection_ids)?e.candidate_connection_ids.filter(n=>typeof n=="string"):[],status:p(e,"status")||"disconnected",health:p(e,"health")||"unknown",settledReady:I(e,"settledReady","settled_ready")??false,readinessState:p(e,"readinessState","readiness_state")??void 0,transportStableId:g(e,"transportStableId","activeTransportStableId","active_transport_stable_id")??void 0,transportGeneration:g(e,"transportGeneration","transport_generation")??void 0,routeGeneration:g(e,"routeGeneration","route_generation")??void 0,activeTransport:C(e,"activeTransport","active_transport"),parallelTransport:C(e,"parallelTransport","parallel_transport")??null,replacementPending:I(e,"replacementPending","replacement_pending")??void 0,logicalSessionTerminal:I(e,"logicalSessionTerminal","logical_session_terminal")??false,lastTransitionAtMs:g(e,"lastTransitionAtMs","lastLifecycleTransitionAtMs","last_lifecycle_transition_at_ms")??void 0,readinessReason:p(e,"readinessReason","readiness_reason")??void 0,transitionCount:g(e,"transitionCount","transition_count")??void 0,connectTransitions:g(e,"connectTransitions","connectingTransitionCount","connecting_transition_count")??void 0,replacementCount:g(e,"replacementCount","replacement_count")??void 0,retireCount:g(e,"retireCount","retire_count")??void 0,lastDisconnectReason:p(e,"lastDisconnectReason","last_disconnect_reason")??void 0,lastReconnectReason:p(e,"lastReconnectReason","last_reconnect_reason")??void 0,scopes:Array.isArray(e.scopes)?e.scopes.filter(n=>typeof n=="string"):[],lastSeenAtMs:typeof e.lastSeenAtMs=="number"?e.lastSeenAtMs:typeof e.last_seen_at_ms=="number"?e.last_seen_at_ms:0,error:p(e,"error"),errorCode:p(e,"errorCode","error_code")??void 0,retryable:I(e,"retryable")??void 0,errorPlane:p(e,"errorPlane","error_plane")??void 0})}function Dn(t){let e=k(t);return {connectionId:typeof e.connectionId=="string"?e.connectionId:"",nodeId:typeof e.nodeId=="string"?e.nodeId:null,deviceId:typeof e.deviceId=="string"?e.deviceId:null,deviceIdHint:typeof e.deviceIdHint=="string"?e.deviceIdHint:null,endpointId:typeof e.endpointId=="string"?e.endpointId:null,transportGeneration:typeof e.transportGeneration=="number"?e.transportGeneration:0,routeGeneration:typeof e.routeGeneration=="number"?e.routeGeneration:void 0,transportStableId:typeof e.transportStableId=="number"?e.transportStableId:null,transportSource:typeof e.transportSource=="string"?e.transportSource:null,lastTransportChangeAtMs:typeof e.lastTransportChangeAtMs=="number"?e.lastTransportChangeAtMs:0,lastRouteChangeAtMs:typeof e.lastRouteChangeAtMs=="number"?e.lastRouteChangeAtMs:void 0,state:typeof e.state=="string"?e.state:"pending",statusReason:typeof e.statusReason=="string"?e.statusReason:null,transitionCount:typeof e.transitionCount=="number"?e.transitionCount:void 0,connectTransitions:typeof e.connectTransitions=="number"?e.connectTransitions:void 0,replacementCount:typeof e.replacementCount=="number"?e.replacementCount:void 0,retireCount:typeof e.retireCount=="number"?e.retireCount:void 0,lastDisconnectReason:typeof e.lastDisconnectReason=="string"?e.lastDisconnectReason:void 0,lastReconnectReason:typeof e.lastReconnectReason=="string"?e.lastReconnectReason:void 0,createdAtMs:typeof e.createdAtMs=="number"?e.createdAtMs:0,updatedAtMs:typeof e.updatedAtMs=="number"?e.updatedAtMs:0}}function xn(t){let e=k(t);return {peerId:typeof e.peerId=="string"?e.peerId:null,deviceId:typeof e.deviceId=="string"?e.deviceId:null,deviceIdHint:typeof e.deviceIdHint=="string"?e.deviceIdHint:null,nodeId:typeof e.nodeId=="string"?e.nodeId:null}}function Bt(t){switch(t){case "connected":return "connected";case "connecting":return "connecting";case "failed":return "failed";default:return "closed"}}function On(t){let e=t.activeConnectionId||t.candidates[0]||null;if(!e)return null;let n=Bt(t.status),i=n==="connected"?"connected":n==="connecting"?"connecting":"closed",r=n==="connected"?t.settledReady?"routable":"transport-only":n==="connecting"?"connecting":"closed";return {connectionId:e,deviceId:t.deviceId??null,deviceIdHint:t.deviceIdHint??null,remoteNodeId:t.nodeId??null,state:n,transportState:i,protocolState:r,routable:!!t.settledReady,readinessState:t.readinessState,readinessReason:t.readinessReason,transportGeneration:t.transportGeneration,routeGeneration:t.routeGeneration,transportStableId:t.transportStableId,activeTransport:t.activeTransport,parallelTransport:t.parallelTransport??null,replacementInProgress:t.replacementPending,logicalSessionTerminal:t.logicalSessionTerminal===true,lastTransitionAtMs:t.lastTransitionAtMs,transitionCount:t.transitionCount,connectTransitions:t.connectTransitions,replacementCount:t.replacementCount,retireCount:t.retireCount,lastDisconnectReason:t.lastDisconnectReason??void 0,lastReconnectReason:t.lastReconnectReason??void 0,updatedAt:t.lastSeenAtMs,error:t.error??void 0}}function Ut(t){if(!t||typeof t!="object")return null;let e=t;return ["acceptedWriteObjects","acceptedWriteBytes","completedReceivedObjects","completedReceivedBytes"].every(i=>typeof e[i]=="number"&&Number.isSafeInteger(e[i])&&e[i]>=0)?Object.freeze({acceptedWriteObjects:e.acceptedWriteObjects,acceptedWriteBytes:e.acceptedWriteBytes,completedReceivedObjects:e.completedReceivedObjects,completedReceivedBytes:e.completedReceivedBytes}):null}function Gn(t){let e=k(t),n=p(e,"connectionId","connection_id");if(!n)return null;let i=p(e,"state")||"connecting",r=g(e,"createdAt","created_at")??g(e,"updatedAt","updated_at")??Date.now(),o=g(e,"updatedAt","updated_at")??r;return {connectionId:n,deviceId:p(e,"deviceId","device_id"),deviceIdHint:p(e,"deviceIdHint","device_id_hint"),remoteNodeId:p(e,"remoteNodeId","remote_node_id"),state:i,transportState:p(e,"transportState","transport_state")??(i==="connected"?"connected":i==="connecting"?"connecting":"closed"),protocolState:p(e,"protocolState","protocol_state")??(i==="connected"?"routable":i==="connecting"?"connecting":"closed"),routable:I(e,"routable")??false,scopes:W(e.scopes),logicalSessionTerminal:I(e,"logicalSessionTerminal","logical_session_terminal")??false,readinessState:p(e,"readinessState","readiness_state")??void 0,readinessReason:p(e,"readinessReason","readiness_reason")??void 0,transportGeneration:g(e,"transportGeneration","transport_generation")??void 0,routeGeneration:g(e,"routeGeneration","route_generation")??void 0,transportStableId:g(e,"transportStableId","activeTransportStableId","active_transport_stable_id")??void 0,activeTransport:C(e,"activeTransport","active_transport"),parallelTransport:C(e,"parallelTransport","parallel_transport")??null,latencyMs:g(e,"latencyMs","latency_ms")??null,carrier:C(e,"carrier")??null,metricsSampledAtMs:g(e,"metricsSampledAtMs","metrics_sampled_at_ms")??null,moqObjectQuantities:Ut(e.moqObjectQuantities??e.moq_object_quantities),replacementInProgress:I(e,"replacementInProgress","replacement_in_progress")??void 0,lastTransitionAtMs:g(e,"lastTransitionAtMs","lastLifecycleTransitionAtMs","last_lifecycle_transition_at_ms")??void 0,transitionCount:g(e,"transitionCount","transition_count")??void 0,connectTransitions:g(e,"connectTransitions","connectingTransitionCount","connecting_transition_count")??void 0,replacementCount:g(e,"replacementCount","replacement_count")??void 0,retireCount:g(e,"retireCount","retire_count")??void 0,lastDisconnectReason:p(e,"lastDisconnectReason","last_disconnect_reason")??void 0,lastReconnectReason:p(e,"lastReconnectReason","last_reconnect_reason")??void 0,error:p(e,"error")??void 0,createdAt:r,updatedAt:o}}function Nn(t,e){return t?t.connectionId===e.connectionId&&(t.deviceId??null)===(e.deviceId??null)&&(t.deviceIdHint??null)===(e.deviceIdHint??null)&&(t.remoteNodeId??null)===(e.remoteNodeId??null)&&t.state===e.state&&(t.transportState??null)===(e.transportState??null)&&(t.protocolState??null)===(e.protocolState??null)&&!!t.routable==!!e.routable&&JSON.stringify(t.scopes??[])===JSON.stringify(e.scopes??[])&&(t.activeTransport??null)===(e.activeTransport??null)&&(t.parallelTransport??null)===(e.parallelTransport??null)&&(t.transportStableId??null)===(e.transportStableId??null)&&(t.transportGeneration??null)===(e.transportGeneration??null)&&(t.routeGeneration??null)===(e.routeGeneration??null)&&!!t.replacementInProgress==!!e.replacementInProgress&&!!t.logicalSessionTerminal==!!e.logicalSessionTerminal&&(t.transitionCount??null)===(e.transitionCount??null)&&(t.connectTransitions??null)===(e.connectTransitions??null)&&(t.replacementCount??null)===(e.replacementCount??null)&&(t.retireCount??null)===(e.retireCount??null)&&(t.lastDisconnectReason??null)===(e.lastDisconnectReason??null)&&(t.lastReconnectReason??null)===(e.lastReconnectReason??null)&&(t.error??null)===(e.error??null):false}
2
+ export{Z as A,Mn as B,En as C,Ot as D,Ht as E,kn as F,_n as G,Dn as H,xn as I,On as J,Gn as K,Nn as L,ce as a,Ne as b,Ke as c,jt as d,zt as e,we as f,at as g,rn as h,on as i,sn as j,Ie as k,dn as l,hn as m,gn as n,yn as o,mn as p,fn as q,Et as r,_t as s,bn as t,Dt as u,xt as v,Ee as w,wn as x,In as y,Rn as z};
@@ -0,0 +1 @@
1
+ var w="3.0.1";function R(t,o){if(t)try{Promise.resolve(t(o)).catch(()=>{});}catch{}}var y=new Set(["transport-healthy","missing-active-transport","native-main-route-pending","session-admission-pending","application-crypto-key-pending","application-crypto-confirmation-pending","bounded-health-confirmation-pending","authoritative-device-binding-pending","device-offline","manual-disconnect","waiting-for-transport","transport-attached-awaiting-readiness-confirmation","transport-connected-health-check-pending","readiness-confirmation-timed-out","transport-closed","connection-failed"]),_=new Set(["user-device","persistent","trusted-device","ticket","room","space","share","drive-grant"]),O=new Set(["connected","connecting","disconnected","failed","closed"]),P=new Set(["unknown","pending","admitted","rejected","expired"]),x=new Set(["iroh","iroh-quic","iroh-lan","iroh-relay","webrtc","moq","ble"]),g=t=>Number.isSafeInteger(t)&&t>=0?t:null;function k(t,o={}){let a=o.maxEvents??256;if(!Number.isInteger(a)||a<1||a>1024)throw new RangeError("Diagnostic maxEvents must be an integer between 1 and 1024");let h=Date.now(),S=performance.now(),r=new Map,c=new Map,d=[],D=0,f=0,p=false,v=false,b=(s,n)=>{let e=Object.freeze({sequence:++D,timestampMs:Date.now(),elapsedMs:performance.now()-S,level:n.hasError||n.state==="failed"?"warn":n.ready?"info":"debug",name:s,peer:Object.freeze({...n,scopeKinds:Object.freeze([...n.scopeKinds])})});d.length===a&&(d.shift(),f++),d.push(e),R(o.logger,e);},E=t(s=>{if(p)return;let n=new Map;for(let e of s){let i=r.get(e.peerId);if(!i){if(r.size===64){v=true;continue}i=`peer-${r.size+1}`,r.set(e.peerId,i);}let m=e.readinessReason==="manual disconnect"?"manual-disconnect":e.readinessReason,l={peerRef:i,state:O.has(e.status)?e.status:"unknown",admission:e.admissionState&&P.has(e.admissionState)?e.admissionState:"unknown",ready:e.settledReady===true,readinessCode:m&&y.has(m)?m:"unclassified",scopeKinds:[...new Set(e.scopes.map(u=>u.split(":",1)[0]).map(u=>_.has(u)?u:"custom"))].sort(),transportGeneration:g(e.transportGeneration),routeGeneration:g(e.routeGeneration),transportStableId:g(e.transportStableId??void 0),transport:e.activeTransport&&x.has(e.activeTransport)?e.activeTransport:"unknown",hasError:!!e.error};n.set(i,l),JSON.stringify(c.get(i))!==JSON.stringify(l)&&b("peer.changed",l);}for(let[e,i]of c)n.has(e)||b("peer.removed",{...i,ready:false,state:"disconnected"});c=n;});return {snapshot:()=>({schemaVersion:1,sdkVersion:w,startedAtMs:h,stopped:p,droppedEvents:f,peerLimitReached:v,events:d.map(s=>({...s,peer:{...s.peer,scopeKinds:[...s.peer.scopeKinds]}}))}),stop:()=>{p||(p=true,E(),r.clear(),c.clear());}}}export{w as a,R as b,k as c};