openrtc 2.6.0 → 2.8.0

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 (60) hide show
  1. package/dist/{Connection-CQdRHqjO.d.ts → Connection-DnZeUt3p.d.ts} +2 -0
  2. package/dist/{DelegatingRuntimeAdapter-B8ubDv86.d.ts → DelegatingRuntimeAdapter-DtNdkP9H.d.ts} +2 -2
  3. package/dist/{IpcRuntimeAdapter-D4vIpOre.d.ts → IpcRuntimeAdapter-BSartqkw.d.ts} +2 -2
  4. package/dist/{WasmBridge-W3GRBTTZ.js → WasmBridge-IQLHKJJN.js} +1 -1
  5. package/dist/{assembly-D9vP5Q6M.d.ts → assembly-CKGAvY3a.d.ts} +2 -2
  6. package/dist/{capabilities-BgxJVk9q.d.ts → capabilities-CsnXfI4b.d.ts} +1 -1
  7. package/dist/{chunk-DOI7F3VQ.js → chunk-4KY4I6W5.js} +1 -1
  8. package/dist/chunk-AUICRD2W.js +2 -0
  9. package/dist/chunk-DIDBQEGI.js +2 -0
  10. package/dist/chunk-HDGSSJGQ.js +2 -0
  11. package/dist/{chunk-HQ6ANBIU.js → chunk-JQBYZHKY.js} +1 -1
  12. package/dist/{chunk-VFDCIEP6.js → chunk-UBLYBL3O.js} +1 -1
  13. package/dist/chunk-UPWTSOR7.js +2 -0
  14. package/dist/{chunk-FQB3VTOC.js → chunk-VGG7KR7S.js} +1 -1
  15. package/dist/{chunk-5KN6YOM6.js → chunk-VRZUDBPK.js} +1 -1
  16. package/dist/{chunk-V7E4OUN5.js → chunk-ZYGBXYTT.js} +1 -1
  17. package/dist/controlPlane-GRIKNHDP.js +1 -0
  18. package/dist/coreClient.d.ts +3 -3
  19. package/dist/deviceKey-XXY72BIM.js +1 -0
  20. package/dist/index.d.ts +6 -6
  21. package/dist/index.js +1 -1
  22. package/dist/{ipcFactory-ZEHQMCEM.js → ipcFactory-IJJTGM23.js} +1 -1
  23. package/dist/native.d.ts +5 -5
  24. package/dist/native.js +1 -1
  25. package/dist/node.d.ts +6 -6
  26. package/dist/node.js +2 -2
  27. package/dist/{openrtc-R6EPOY3N.js → openrtc-PR74PMIZ.js} +1 -1
  28. package/dist/openrtc_bg.wasm +0 -0
  29. package/dist/{room-Z6F46KMH.js → room-XOMUNWSD.js} +1 -1
  30. package/dist/runtime/WasmRuntimeAdapter.d.ts +3 -3
  31. package/dist/runtime/WasmRuntimeAdapter.js +1 -1
  32. package/dist/runtime/device-status.d.ts +1 -1
  33. package/dist/runtime/factories.d.ts +5 -5
  34. package/dist/runtime/factories.js +1 -1
  35. package/dist/runtime/index.d.ts +10 -9
  36. package/dist/runtime/index.js +1 -1
  37. package/dist/server-browser.d.ts +4 -4
  38. package/dist/server.d.ts +4 -4
  39. package/dist/server.js +1 -1
  40. package/dist/service-node.d.ts +4 -4
  41. package/dist/service-node.js +1 -1
  42. package/dist/testing/native.d.ts +4 -4
  43. package/dist/testing/native.js +1 -1
  44. package/dist/testing.d.ts +7 -4
  45. package/dist/testing.js +1 -1
  46. package/dist/transport/index.d.ts +2 -2
  47. package/dist/{types-jxyrOzCw.d.ts → types-CJ5FGAyJ.d.ts} +5 -1
  48. package/native/darwin-arm64/openrtc-node-host +0 -0
  49. package/native/darwin-arm64/openrtc-node-host.manifest.json +4 -4
  50. package/native/darwin-x64/openrtc-node-host +0 -0
  51. package/native/darwin-x64/openrtc-node-host.manifest.json +4 -4
  52. package/native/linux-x64/openrtc-node-host +0 -0
  53. package/native/linux-x64/openrtc-node-host.manifest.json +4 -4
  54. package/package.json +2 -1
  55. package/dist/chunk-BEYBIRAN.js +0 -2
  56. package/dist/chunk-C7UBBRYW.js +0 -2
  57. package/dist/chunk-GQWHEDGU.js +0 -2
  58. package/dist/chunk-NDR2ANQB.js +0 -2
  59. package/dist/controlPlane-T3TOHY3D.js +0 -1
  60. package/dist/deviceKey-EIMDBAQS.js +0 -1
@@ -287,6 +287,8 @@ interface DeviceProfile {
287
287
  }
288
288
  interface ManagedOptions {
289
289
  platform: SessionPlatform;
290
+ /** Browser transport identity persistence; native host authority is unchanged. */
291
+ browserTrustPersistence?: 'session' | 'persistent';
290
292
  sessionKind?: SessionKind;
291
293
  scope?: string | null;
292
294
  autoConnectPolicy?: AutoConnectPolicy;
@@ -1,5 +1,5 @@
1
- import { O as DiscoveryMode, Q as AuthMode, T as SignalingMode, U as ClientOptions, V as ExplicitFileDataSendParams, W as ISignalingBackend, X as RuntimeIdentity, H as AuthContext, Y as RoomMember, Z as Device, _ as DeviceStatusSnapshot, k as PeerSessionSnapshot, n as ResolvedPeerIdentity, $ as ManagedConnectionRecord, a0 as SignalingEnvelope, a1 as DeviceEvent, a2 as DesiredPeerProjection, a3 as SignalingSession, a4 as SessionEvent, a5 as LocalDeviceInfo, a6 as NativeManagedSessionStartResult, g as ProtocolName, G as GrantScope, a7 as BackendPeerBiStream, a8 as BackendPeerUniStream, a9 as PortableMediaPublish, aa as PortableMediaPublicationStart, ab as PortableMediaSample, ac as PortableMediaChunk, ad as PortableMediaControl, ae as NativeConnectParams, af as NativeConnectResult, ag as BackendConnectionState, ah as NativePeerDataEvent } from './Connection-CQdRHqjO.js';
2
- import { R as RuntimeCapabilities } from './capabilities-BgxJVk9q.js';
1
+ import { O as DiscoveryMode, Q as AuthMode, T as SignalingMode, U as ClientOptions, V as ExplicitFileDataSendParams, W as ISignalingBackend, X as RuntimeIdentity, H as AuthContext, Y as RoomMember, Z as Device, _ as DeviceStatusSnapshot, k as PeerSessionSnapshot, n as ResolvedPeerIdentity, $ as ManagedConnectionRecord, a0 as SignalingEnvelope, a1 as DeviceEvent, a2 as DesiredPeerProjection, a3 as SignalingSession, a4 as SessionEvent, a5 as LocalDeviceInfo, a6 as NativeManagedSessionStartResult, g as ProtocolName, G as GrantScope, a7 as BackendPeerBiStream, a8 as BackendPeerUniStream, a9 as PortableMediaPublish, aa as PortableMediaPublicationStart, ab as PortableMediaSample, ac as PortableMediaChunk, ad as PortableMediaControl, ae as NativeConnectParams, af as NativeConnectResult, ag as BackendConnectionState, ah as NativePeerDataEvent } from './Connection-DnZeUt3p.js';
2
+ import { R as RuntimeCapabilities } from './capabilities-CsnXfI4b.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-B8ubDv86.js';
1
+ import { R as RuntimeBridgeOptions, D as DelegatingRuntimeAdapter } from './DelegatingRuntimeAdapter-DtNdkP9H.js';
2
2
  import { P as PlutoIpcBridge } from './ipc-DgzKqHH3.js';
3
- import { S as ServiceErrorObservation, ag as BackendConnectionState, ah as NativePeerDataEvent, Z as Device } from './Connection-CQdRHqjO.js';
3
+ import { S as ServiceErrorObservation, ag as BackendConnectionState, ah as NativePeerDataEvent, Z as Device } from './Connection-DnZeUt3p.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-V7E4OUN5.js';import'./chunk-AYHD4X2R.js';import'./chunk-GQWHEDGU.js';import'./chunk-XMYBBLYK.js';import'./chunk-OT7IPLZE.js';import'./chunk-OWKAJPOI.js';import'./chunk-ISTROQQJ.js';import'./chunk-CNAW5BZ3.js';import'./chunk-CCCYE3XN.js';import'./chunk-4R5BLX2U.js';import'./chunk-JPBW67B3.js';import'./chunk-2GX6GB6L.js';
1
+ export{b as WasmBridge,a as loadBrowserWasmRuntimeModule}from'./chunk-ZYGBXYTT.js';import'./chunk-AYHD4X2R.js';import'./chunk-UPWTSOR7.js';import'./chunk-XMYBBLYK.js';import'./chunk-OT7IPLZE.js';import'./chunk-OWKAJPOI.js';import'./chunk-ISTROQQJ.js';import'./chunk-CNAW5BZ3.js';import'./chunk-CCCYE3XN.js';import'./chunk-4R5BLX2U.js';import'./chunk-JPBW67B3.js';import'./chunk-2GX6GB6L.js';
@@ -1,5 +1,5 @@
1
- import { h as RuntimePeerState, s as ConnectionState, l as PeerReadiness, i as PeerConnectOptions, j as Connection, I as IncomingStream, G as GrantScope, K as RuntimeClientOptions, W as ISignalingBackend, ay as RuntimeAuthIdentity, H as AuthContext, g as ProtocolName, L as LocalDeviceInfo, A as DeviceProfile, al as BrowserProtocolStore, am as NamespaceDescriptor, an as IrohMutationReceipt, ao as IrohDocEntry, q as RuntimeDevice, M as ManagedOptions, v as ManagedSession, D as DeviceStatus, y as ConnectDeviceHooks, z as ConnectDeviceOptions, x as ConnectDeviceResult, w as DeviceConnectOptions, $ as ManagedConnectionRecord, k as PeerSessionSnapshot, n as ResolvedPeerIdentity, az as RuntimeSession, aA as AppLimits, J as JoinRoomOptions, F as RuntimeRoomMember, aB as ConnectionTarget, p as ScopedChannelOptions, r as ScopedLogicalChannel, o as PeerStreamOptions, ae as NativeConnectParams, af as NativeConnectResult, B as RawConnection, C as ChannelDescriptor, V as ExplicitFileDataSendParams, aC as PresenceLoopOptions, b as RoomArchitectureSnapshot, c as RoomAuthorityAssignment, m as RuntimePeerHealth, t as ReadinessOptions, u as ConnectionEvent } from './Connection-CQdRHqjO.js';
2
- import { R as RuntimeCapabilities, C as CapabilityProfile } from './capabilities-BgxJVk9q.js';
1
+ import { h as RuntimePeerState, s as ConnectionState, l as PeerReadiness, i as PeerConnectOptions, j as Connection, I as IncomingStream, G as GrantScope, K as RuntimeClientOptions, W as ISignalingBackend, ay as RuntimeAuthIdentity, H as AuthContext, g as ProtocolName, L as LocalDeviceInfo, A as DeviceProfile, al as BrowserProtocolStore, am as NamespaceDescriptor, an as IrohMutationReceipt, ao as IrohDocEntry, q as RuntimeDevice, M as ManagedOptions, v as ManagedSession, D as DeviceStatus, y as ConnectDeviceHooks, z as ConnectDeviceOptions, x as ConnectDeviceResult, w as DeviceConnectOptions, $ as ManagedConnectionRecord, k as PeerSessionSnapshot, n as ResolvedPeerIdentity, az as RuntimeSession, aA as AppLimits, J as JoinRoomOptions, F as RuntimeRoomMember, aB as ConnectionTarget, p as ScopedChannelOptions, r as ScopedLogicalChannel, o as PeerStreamOptions, ae as NativeConnectParams, af as NativeConnectResult, B as RawConnection, C as ChannelDescriptor, V as ExplicitFileDataSendParams, aC as PresenceLoopOptions, b as RoomArchitectureSnapshot, c as RoomAuthorityAssignment, m as RuntimePeerHealth, t as ReadinessOptions, u as ConnectionEvent } from './Connection-DnZeUt3p.js';
2
+ import { R as RuntimeCapabilities, C as CapabilityProfile } from './capabilities-CsnXfI4b.js';
3
3
 
4
4
  /**
5
5
  * Coalesced peer reconciliation scheduler and full reconcile orchestration.
@@ -1,4 +1,4 @@
1
- import { g as ProtocolName, f as RouteOptimization } from './Connection-CQdRHqjO.js';
1
+ import { g as ProtocolName, f as RouteOptimization } from './Connection-DnZeUt3p.js';
2
2
 
3
3
  type RuntimeAdapterKind = 'browser-wasm' | 'native-ipc' | 'tauri-ipc' | 'unknown';
4
4
  type CapabilityMaturity = 'stable' | 'preview' | 'support-only' | 'unavailable';
@@ -1,2 +1,2 @@
1
- import {j,d as d$1,c}from'./chunk-HQ6ANBIU.js';var E=/^[A-Za-z0-9_.:@-]+$/,P=/^[A-Za-z0-9_-]{43}$/,C=/^[A-Za-z0-9_.:@-]+$/,k=/^[A-Za-z0-9._-]+$/,x=120*6e4,A=new TextEncoder;function d(r,e,t=160){let n=r.trim();if(!n||n.length>t||!E.test(n))throw new TypeError(`[OpenRTC] ${e} is invalid.`);return n}function h(r,e,t=Number.MAX_SAFE_INTEGER){if(!Number.isSafeInteger(r)||r<1||r>t)throw new RangeError(`[OpenRTC] ${e} must be a positive safe integer.`);return r}function K(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}async function g(r,e){let t=await r.publicJwk();if(t.kty!=="OKP"||t.crv!=="Ed25519"||typeof t.x!="string"||!P.test(t.x)||t.d!==void 0)throw new TypeError(`[OpenRTC] ${e} must return an Ed25519 public JWK.`);return {kty:"OKP",crv:"Ed25519",x:t.x}}async function y(r,e,t){let n=await r.sign(e);if(!(n instanceof Uint8Array)||n.byteLength!==64)throw new TypeError(`[OpenRTC] ${t} returned an invalid Ed25519 signature.`);return K(n)}function T(r){if(!/^pk_(?:live|test)_[A-Za-z0-9]+$/.test(r))throw new TypeError("[OpenRTC] apiKey is invalid.");return `app_${r.slice(-16)}`}function u(r){return r!==null&&typeof r=="object"&&!Array.isArray(r)?r:null}function v(r,e,t,n){if(typeof r!="string"||r.length<1||r.length>t||r!==r.trim()||n&&!n.test(r))throw new Error(`[OpenRTC] authority service grant ${e} is invalid.`);return r}function O(r){let e=v(r,"gatewayUrl",2048),t;try{t=new URL(e);}catch{throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.")}let n=t.protocol==="http:"&&["127.0.0.1","localhost","::1"].includes(t.hostname.toLowerCase());if(t.protocol!=="https:"&&!n||t.username||t.password||t.search||t.hash)throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.");return e}function N(r,e){let t=u(r),n=u(t?.avenue),i=u(t?.roomAuthority),a=u(i?.assignmentPublicKeyJwk),c=Date.now(),o=t?.expiresAtMs,s=t?.maxPeers;if(!t||t.protocolVersion!==2||t.architecture!=="authority"||n?.kind!=="room"||n.id!==e.roomId||i?.serviceId!==e.serviceId||i.generation!==e.generation||!Array.isArray(i.shardIds)||i.shardIds.length!==e.shardIds.length||i.shardIds.some((m,l)=>m!==e.shardIds[l])||a?.kty!=="OKP"||a.crv!=="Ed25519"||a.x!==e.assignmentPublicKeyX||!Number.isSafeInteger(o)||o<=c||o>c+x||!Number.isSafeInteger(s)||s<1||s>e.maxPeers)throw new Error("[OpenRTC] authority service grant response is inconsistent.");return {protocolVersion:2,gatewayUrl:O(t.gatewayUrl),routeKey:v(t.routeKey,"routeKey",256,C),token:v(t.token,"token",24e3,k),expiresAtMs:o,avenue:{kind:"room",id:e.roomId},maxPeers:s,architecture:"authority",roomAuthority:{serviceId:e.serviceId,generation:e.generation,shardIds:[...e.shardIds],assignmentPublicKeyJwk:{kty:"OKP",crv:"Ed25519",x:e.assignmentPublicKeyX}}}}var p=class{constructor(e){if(this.apiKey=e.apiKey,this.applicationTag=T(e.apiKey),typeof e.grantIssuer!="function")throw new TypeError("[OpenRTC] ServiceNode requires a browser-safe grantIssuer.");if(this.grantIssuer=e.grantIssuer,this.serviceId=d(e.serviceId,"serviceId",80),this.generation=h(e.generation,"generation"),this.shardIds=[...new Set(e.shardIds.map(t=>d(t,"shardId",80)))].sort(),this.shardIds.length<1||this.shardIds.length>64||this.shardIds.length!==e.shardIds.length)throw new RangeError("[OpenRTC] shardIds must contain 1..64 unique identifiers.");this.deviceId=d(e.deviceId,"deviceId"),this.deviceSigner=e.deviceSigner,this.assignmentSigner=e.assignmentSigner;}async requestGrant(e){let t=d(e.roomId,"roomId"),n=d(e.runtimeInstanceId,"runtimeInstanceId");if(!P.test(e.ticketFingerprint))throw new TypeError("[OpenRTC] ticketFingerprint is invalid.");e.maxPeers!==void 0&&h(e.maxPeers,"maxPeers",50);let i=await g(this.assignmentSigner,"assignmentSigner.publicJwk()"),a=await g(this.deviceSigner,"deviceSigner.publicJwk()"),c=crypto.randomUUID().replace(/-/g,""),o=Math.floor(Date.now()/1e3),s=["openrtc:v2:authority-service-grant",this.applicationTag,t,this.serviceId,String(this.generation),this.shardIds.join(","),i.x,n,c,o].join(":"),m={avenue:{kind:"room",id:t},serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyJwk:i,deviceId:this.deviceId,runtimeInstanceId:n,ticketFingerprint:e.ticketFingerprint,deviceProof:{publicKeyJwk:a,nonce:c,issuedAt:o,signature:await y(this.deviceSigner,A.encode(s),"deviceSigner.sign()")},...e.maxPeers===void 0?{}:{maxPeers:e.maxPeers},...e.refreshGrant?{refreshGrant:e.refreshGrant}:{},features:e.features??{}},l=`authority_${crypto.randomUUID().replace(/-/g,"")}`,R=await this.grantIssuer({apiKey:this.apiKey,idempotencyKey:l,body:m});return N(R,{roomId:t,serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyX:i.x,maxPeers:e.maxPeers??50})}async devicePublicKey(){return g(this.deviceSigner,"deviceSigner.publicJwk()")}async assignmentPublicKey(){return g(this.assignmentSigner,"assignmentSigner.publicJwk()")}async signDeviceBytes(e){return y(this.deviceSigner,e,"deviceSigner.sign()")}async signAssignment(e){let t=e.ttlMs??6e4;h(t,"ttlMs",2*6e4);let n=d(e.shardId,"shardId",80);if(!this.shardIds.includes(n))throw new RangeError("[OpenRTC] assignment shard is not owned by this service.");let i=e.priorityDeviceIds??[],a=e.relevantEntityIds??[];if(i.length>8||a.length>32)throw new RangeError("[OpenRTC] assignment exceeds the 8-edge or 32-entity bound.");let c=Date.now(),o={policyVersion:"room-authority-assignment-v1",serviceId:this.serviceId,generation:this.generation,revision:h(e.revision,"revision"),subjectDeviceId:d(e.subjectDeviceId,"subjectDeviceId"),shardId:n,priorityDeviceIds:i.map(s=>d(s,"priorityDeviceId")),relevantEntityIds:a.map(s=>d(s,"relevantEntityId")),issuedAtMs:c,expiresAtMs:c+t};if(new Set(o.priorityDeviceIds).size!==o.priorityDeviceIds.length||new Set(o.relevantEntityIds).size!==o.relevantEntityIds.length)throw new RangeError("[OpenRTC] assignment identifiers must be unique.");return {assignment:o,signature:await y(this.assignmentSigner,A.encode(JSON.stringify(o)),"assignmentSigner.sign()")}}},I=class{constructor(e,t,n){this.room=e;this.authority=t;this.onClosed=n;this.releaseRuntimeAlias=d$1(this,e);}get kind(){return this.room.kind}get id(){return this.room.id}get peers(){return this.room.peers}get channels(){return this.room.channels}get diagnostics(){return this.room.diagnostics}get closed(){return this.room.closed}get membership(){return this.room.membership}state(e){return this.room.state(e)}channel(e){return this.room.channel(e)}onConnection(e){return this.room.onConnection(e)}architecture(){return this.room.architecture()}onArchitectureChanged(e){return this.room.onArchitectureChanged(e)}authorityAssignment(){return this.room.authorityAssignment()}onAuthorityAssignmentChanged(e){return this.room.onAuthorityAssignmentChanged(e)}leave(){return this.retire(()=>this.room.leave())}close(){return this.retire(()=>this.room.close())}async publishAssignment(e){let t=await this.authority.signAssignment(e);return await c(this.room).advanced.runtime.publishAuthorityAssignment(t),t.assignment}retire(e){return this.retirement??(this.retirement=e().finally(()=>{this.releaseRuntimeAlias(),this.onClosed();}))}},S=class{constructor(e){this.options=e;this.rooms=new Map;this.connectionListeners=new Set;this.connectionCleanups=new Map;this.closed=false;if("secretKey"in e)throw new TypeError("[OpenRTC] ServiceNode never accepts secretKey; delegate short-lived grants.");this.authority=new p(e);}listen(e){if(this.closed)throw new Error("[OpenRTC] ServiceNode is closed.");let t=d(e,"roomId"),n=this.rooms.get(t);if(n)return n.promise;let i={};return i.promise=this.openRoom(t,()=>this.evictRoom(t,i)).catch(a=>{throw this.evictRoom(t,i),a}),this.rooms.set(t,i),i.promise}onConnection(e){if(this.connectionListeners.add(e),this.connectionListeners.size===1)for(let[t,n]of this.rooms)n.promise.then(i=>this.attachConnectionListener(t,i),()=>{});return ()=>{if(this.connectionListeners.delete(e),this.connectionListeners.size===0){for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();}}}async close(){if(this.closed)return;this.closed=true;for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();let e=await Promise.allSettled([...this.rooms.values()].map(t=>t.promise));await Promise.all(e.flatMap(t=>t.status==="fulfilled"?[t.value.close()]:[])),this.rooms.clear(),this.connectionListeners.clear();}async openRoom(e,t){let n=await this.options.client.devices.localId();if(n!==this.options.deviceId)throw new Error("[OpenRTC] ServiceNode deviceId must match the client installation.");let[i,a]=await Promise.all([this.authority.devicePublicKey(),this.authority.assignmentPublicKey()]),c=await j(this.options.client,{roomId:e,serviceId:this.options.serviceId,generation:this.options.generation,shardIds:this.options.shardIds,deviceId:n,maxPeers:this.options.maxPeers,irohRelay:this.options.irohRelay!==false,devicePublicKeyX:i.x,assignmentPublicKeyX:a.x,deviceSign:s=>this.authority.signDeviceBytes(s),grantProvider:async s=>{if(s.avenue.kind!=="room"||s.avenue.id!==e)throw new Error("[OpenRTC] ServiceNode grant request escaped its room.");if(s.deviceId!==n)throw new Error("[OpenRTC] ServiceNode grant request escaped its device.");return this.authority.requestGrant({roomId:e,runtimeInstanceId:s.runtimeInstanceId,ticketFingerprint:s.ticketFingerprint,maxPeers:this.options.maxPeers,refreshGrant:s.refreshGrant,features:{irohRelay:this.options.irohRelay!==false}})}}),o=new I(c,this.authority,t);return this.attachConnectionListener(e,o),o}evictRoom(e,t){this.rooms.get(e)===t&&(this.rooms.delete(e),this.connectionCleanups.get(e)?.(),this.connectionCleanups.delete(e));}attachConnectionListener(e,t){this.closed||this.connectionListeners.size===0||this.connectionCleanups.has(e)||this.connectionCleanups.set(e,t.onConnection(n=>{for(let i of this.connectionListeners)i({room:t,connection:n});}));}};
1
+ import {j,d as d$1,c}from'./chunk-JQBYZHKY.js';var E=/^[A-Za-z0-9_.:@-]+$/,P=/^[A-Za-z0-9_-]{43}$/,C=/^[A-Za-z0-9_.:@-]+$/,k=/^[A-Za-z0-9._-]+$/,x=120*6e4,A=new TextEncoder;function d(r,e,t=160){let n=r.trim();if(!n||n.length>t||!E.test(n))throw new TypeError(`[OpenRTC] ${e} is invalid.`);return n}function h(r,e,t=Number.MAX_SAFE_INTEGER){if(!Number.isSafeInteger(r)||r<1||r>t)throw new RangeError(`[OpenRTC] ${e} must be a positive safe integer.`);return r}function K(r){let e="";for(let t of r)e+=String.fromCharCode(t);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}async function g(r,e){let t=await r.publicJwk();if(t.kty!=="OKP"||t.crv!=="Ed25519"||typeof t.x!="string"||!P.test(t.x)||t.d!==void 0)throw new TypeError(`[OpenRTC] ${e} must return an Ed25519 public JWK.`);return {kty:"OKP",crv:"Ed25519",x:t.x}}async function y(r,e,t){let n=await r.sign(e);if(!(n instanceof Uint8Array)||n.byteLength!==64)throw new TypeError(`[OpenRTC] ${t} returned an invalid Ed25519 signature.`);return K(n)}function T(r){if(!/^pk_(?:live|test)_[A-Za-z0-9]+$/.test(r))throw new TypeError("[OpenRTC] apiKey is invalid.");return `app_${r.slice(-16)}`}function u(r){return r!==null&&typeof r=="object"&&!Array.isArray(r)?r:null}function v(r,e,t,n){if(typeof r!="string"||r.length<1||r.length>t||r!==r.trim()||n&&!n.test(r))throw new Error(`[OpenRTC] authority service grant ${e} is invalid.`);return r}function O(r){let e=v(r,"gatewayUrl",2048),t;try{t=new URL(e);}catch{throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.")}let n=t.protocol==="http:"&&["127.0.0.1","localhost","::1"].includes(t.hostname.toLowerCase());if(t.protocol!=="https:"&&!n||t.username||t.password||t.search||t.hash)throw new Error("[OpenRTC] authority service grant gatewayUrl is invalid.");return e}function N(r,e){let t=u(r),n=u(t?.avenue),i=u(t?.roomAuthority),a=u(i?.assignmentPublicKeyJwk),c=Date.now(),o=t?.expiresAtMs,s=t?.maxPeers;if(!t||t.protocolVersion!==2||t.architecture!=="authority"||n?.kind!=="room"||n.id!==e.roomId||i?.serviceId!==e.serviceId||i.generation!==e.generation||!Array.isArray(i.shardIds)||i.shardIds.length!==e.shardIds.length||i.shardIds.some((m,l)=>m!==e.shardIds[l])||a?.kty!=="OKP"||a.crv!=="Ed25519"||a.x!==e.assignmentPublicKeyX||!Number.isSafeInteger(o)||o<=c||o>c+x||!Number.isSafeInteger(s)||s<1||s>e.maxPeers)throw new Error("[OpenRTC] authority service grant response is inconsistent.");return {protocolVersion:2,gatewayUrl:O(t.gatewayUrl),routeKey:v(t.routeKey,"routeKey",256,C),token:v(t.token,"token",24e3,k),expiresAtMs:o,avenue:{kind:"room",id:e.roomId},maxPeers:s,architecture:"authority",roomAuthority:{serviceId:e.serviceId,generation:e.generation,shardIds:[...e.shardIds],assignmentPublicKeyJwk:{kty:"OKP",crv:"Ed25519",x:e.assignmentPublicKeyX}}}}var p=class{constructor(e){if(this.apiKey=e.apiKey,this.applicationTag=T(e.apiKey),typeof e.grantIssuer!="function")throw new TypeError("[OpenRTC] ServiceNode requires a browser-safe grantIssuer.");if(this.grantIssuer=e.grantIssuer,this.serviceId=d(e.serviceId,"serviceId",80),this.generation=h(e.generation,"generation"),this.shardIds=[...new Set(e.shardIds.map(t=>d(t,"shardId",80)))].sort(),this.shardIds.length<1||this.shardIds.length>64||this.shardIds.length!==e.shardIds.length)throw new RangeError("[OpenRTC] shardIds must contain 1..64 unique identifiers.");this.deviceId=d(e.deviceId,"deviceId"),this.deviceSigner=e.deviceSigner,this.assignmentSigner=e.assignmentSigner;}async requestGrant(e){let t=d(e.roomId,"roomId"),n=d(e.runtimeInstanceId,"runtimeInstanceId");if(!P.test(e.ticketFingerprint))throw new TypeError("[OpenRTC] ticketFingerprint is invalid.");e.maxPeers!==void 0&&h(e.maxPeers,"maxPeers",50);let i=await g(this.assignmentSigner,"assignmentSigner.publicJwk()"),a=await g(this.deviceSigner,"deviceSigner.publicJwk()"),c=crypto.randomUUID().replace(/-/g,""),o=Math.floor(Date.now()/1e3),s=["openrtc:v2:authority-service-grant",this.applicationTag,t,this.serviceId,String(this.generation),this.shardIds.join(","),i.x,n,c,o].join(":"),m={avenue:{kind:"room",id:t},serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyJwk:i,deviceId:this.deviceId,runtimeInstanceId:n,ticketFingerprint:e.ticketFingerprint,deviceProof:{publicKeyJwk:a,nonce:c,issuedAt:o,signature:await y(this.deviceSigner,A.encode(s),"deviceSigner.sign()")},...e.maxPeers===void 0?{}:{maxPeers:e.maxPeers},...e.refreshGrant?{refreshGrant:e.refreshGrant}:{},features:e.features??{}},l=`authority_${crypto.randomUUID().replace(/-/g,"")}`,R=await this.grantIssuer({apiKey:this.apiKey,idempotencyKey:l,body:m});return N(R,{roomId:t,serviceId:this.serviceId,generation:this.generation,shardIds:this.shardIds,assignmentPublicKeyX:i.x,maxPeers:e.maxPeers??50})}async devicePublicKey(){return g(this.deviceSigner,"deviceSigner.publicJwk()")}async assignmentPublicKey(){return g(this.assignmentSigner,"assignmentSigner.publicJwk()")}async signDeviceBytes(e){return y(this.deviceSigner,e,"deviceSigner.sign()")}async signAssignment(e){let t=e.ttlMs??6e4;h(t,"ttlMs",2*6e4);let n=d(e.shardId,"shardId",80);if(!this.shardIds.includes(n))throw new RangeError("[OpenRTC] assignment shard is not owned by this service.");let i=e.priorityDeviceIds??[],a=e.relevantEntityIds??[];if(i.length>8||a.length>32)throw new RangeError("[OpenRTC] assignment exceeds the 8-edge or 32-entity bound.");let c=Date.now(),o={policyVersion:"room-authority-assignment-v1",serviceId:this.serviceId,generation:this.generation,revision:h(e.revision,"revision"),subjectDeviceId:d(e.subjectDeviceId,"subjectDeviceId"),shardId:n,priorityDeviceIds:i.map(s=>d(s,"priorityDeviceId")),relevantEntityIds:a.map(s=>d(s,"relevantEntityId")),issuedAtMs:c,expiresAtMs:c+t};if(new Set(o.priorityDeviceIds).size!==o.priorityDeviceIds.length||new Set(o.relevantEntityIds).size!==o.relevantEntityIds.length)throw new RangeError("[OpenRTC] assignment identifiers must be unique.");return {assignment:o,signature:await y(this.assignmentSigner,A.encode(JSON.stringify(o)),"assignmentSigner.sign()")}}},I=class{constructor(e,t,n){this.room=e;this.authority=t;this.onClosed=n;this.releaseRuntimeAlias=d$1(this,e);}get kind(){return this.room.kind}get id(){return this.room.id}get peers(){return this.room.peers}get channels(){return this.room.channels}get diagnostics(){return this.room.diagnostics}get closed(){return this.room.closed}get membership(){return this.room.membership}state(e){return this.room.state(e)}channel(e){return this.room.channel(e)}onConnection(e){return this.room.onConnection(e)}architecture(){return this.room.architecture()}onArchitectureChanged(e){return this.room.onArchitectureChanged(e)}authorityAssignment(){return this.room.authorityAssignment()}onAuthorityAssignmentChanged(e){return this.room.onAuthorityAssignmentChanged(e)}leave(){return this.retire(()=>this.room.leave())}close(){return this.retire(()=>this.room.close())}async publishAssignment(e){let t=await this.authority.signAssignment(e);return await c(this.room).advanced.runtime.publishAuthorityAssignment(t),t.assignment}retire(e){return this.retirement??(this.retirement=e().finally(()=>{this.releaseRuntimeAlias(),this.onClosed();}))}},S=class{constructor(e){this.options=e;this.rooms=new Map;this.connectionListeners=new Set;this.connectionCleanups=new Map;this.closed=false;if("secretKey"in e)throw new TypeError("[OpenRTC] ServiceNode never accepts secretKey; delegate short-lived grants.");this.authority=new p(e);}listen(e){if(this.closed)throw new Error("[OpenRTC] ServiceNode is closed.");let t=d(e,"roomId"),n=this.rooms.get(t);if(n)return n.promise;let i={};return i.promise=this.openRoom(t,()=>this.evictRoom(t,i)).catch(a=>{throw this.evictRoom(t,i),a}),this.rooms.set(t,i),i.promise}onConnection(e){if(this.connectionListeners.add(e),this.connectionListeners.size===1)for(let[t,n]of this.rooms)n.promise.then(i=>this.attachConnectionListener(t,i),()=>{});return ()=>{if(this.connectionListeners.delete(e),this.connectionListeners.size===0){for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();}}}async close(){if(this.closed)return;this.closed=true;for(let t of this.connectionCleanups.values())t();this.connectionCleanups.clear();let e=await Promise.allSettled([...this.rooms.values()].map(t=>t.promise));await Promise.all(e.flatMap(t=>t.status==="fulfilled"?[t.value.close()]:[])),this.rooms.clear(),this.connectionListeners.clear();}async openRoom(e,t){let n=await this.options.client.devices.localId();if(n!==this.options.deviceId)throw new Error("[OpenRTC] ServiceNode deviceId must match the client installation.");let[i,a]=await Promise.all([this.authority.devicePublicKey(),this.authority.assignmentPublicKey()]),c=await j(this.options.client,{roomId:e,serviceId:this.options.serviceId,generation:this.options.generation,shardIds:this.options.shardIds,deviceId:n,maxPeers:this.options.maxPeers,irohRelay:this.options.irohRelay!==false,devicePublicKeyX:i.x,assignmentPublicKeyX:a.x,deviceSign:s=>this.authority.signDeviceBytes(s),grantProvider:async s=>{if(s.avenue.kind!=="room"||s.avenue.id!==e)throw new Error("[OpenRTC] ServiceNode grant request escaped its room.");if(s.deviceId!==n)throw new Error("[OpenRTC] ServiceNode grant request escaped its device.");return this.authority.requestGrant({roomId:e,runtimeInstanceId:s.runtimeInstanceId,ticketFingerprint:s.ticketFingerprint,maxPeers:this.options.maxPeers,refreshGrant:s.refreshGrant,features:{irohRelay:this.options.irohRelay!==false}})}}),o=new I(c,this.authority,t);return this.attachConnectionListener(e,o),o}evictRoom(e,t){this.rooms.get(e)===t&&(this.rooms.delete(e),this.connectionCleanups.get(e)?.(),this.connectionCleanups.delete(e));}attachConnectionListener(e,t){this.closed||this.connectionListeners.size===0||this.connectionCleanups.has(e)||this.connectionCleanups.set(e,t.onConnection(n=>{for(let i of this.connectionListeners)i({room:t,connection:n});}));}};
2
2
  export{p as a,S as b};
@@ -0,0 +1,2 @@
1
+ function c(t){let r=new Uint8Array(t),e="";for(let n of r)e+=String.fromCharCode(n);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function g(t){let r=JSON.stringify({crv:t.crv,kty:t.kty,x:t.x});return c(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(r)))}function p(){return c(crypto.getRandomValues(new Uint8Array(24)).buffer)}async function y(){return typeof indexedDB>"u"?null:new Promise((t,r)=>{let e=indexedDB.open("openrtc-v2-device-keys",1);e.onupgradeneeded=()=>{e.result.objectStoreNames.contains("keys")||e.result.createObjectStore("keys");},e.onsuccess=()=>t(e.result),e.onerror=()=>r(e.error);})}async function f(t){let r=await y().catch(()=>null);if(!r)throw new Error("[OpenRTC] Persistent browser identity storage is unavailable.");try{return await new Promise((e,n)=>{let s=r.transaction("keys","readonly").objectStore("keys").get(t);s.onsuccess=()=>e(s.result??null),s.onerror=()=>n(s.error);})}finally{r.close();}}async function w(t,r){let e=await y().catch(()=>null);if(!e)throw new Error("[OpenRTC] Persistent browser identity storage is unavailable.");try{return await new Promise((n,s)=>{let o=e.transaction("keys","readwrite"),a=r;o.oncomplete=()=>n(a),o.onabort=()=>s(o.error??new Error("[OpenRTC] Persistent browser identity storage transaction aborted."));let u=o.objectStore("keys"),i=u.get(t);i.onerror=()=>s(i.error),i.onsuccess=()=>{if(i.result!==void 0&&i.result!==null){a=i.result;return}let l=u.put(r,t);l.onerror=()=>s(l.error);};})}finally{e.close();}}async function b(t){let r=await y().catch(()=>null);if(r)try{await new Promise((e,n)=>{let s=r.transaction("keys","readwrite").objectStore("keys").delete(t);s.onsuccess=()=>e(),s.onerror=()=>n(s.error);});}finally{r.close();}}async function v(t){let r=await f(t);if(r)return r;let e=await crypto.subtle.generateKey({name:"Ed25519"},false,["sign","verify"]);return w(t,e)}async function d(t){let r=await crypto.subtle.exportKey("jwk",t.publicKey),e=await g(r);return {publicKeyJwk:r,thumbprint:e,async sign(n){return c(await crypto.subtle.sign({name:"Ed25519"},t.privateKey,n))},async proof(n){let s=p(),o=Math.floor(Date.now()/1e3),a=await crypto.subtle.sign({name:"Ed25519"},t.privateKey,new TextEncoder().encode(n(s,o)));return {publicKeyJwk:r,signature:c(a),nonce:s,issuedAt:o}}}}async function P(){return d(await crypto.subtle.generateKey({name:"Ed25519"},false,["sign","verify"]))}var K={persistence:"persistent",async getOrCreate(t){return d(await v(t))},delete:b};function m(){let t=new Map,r=new Map;return {persistence:"session",getOrCreate(e){let n=t.get(e);return n||(n=P(),t.set(e,n)),n},async delete(e){t.delete(e),r.delete(e);},async readSecureRecord(e,n){return r.get(e)?.get(n)??null},async writeSecureRecord(e,n,s){let o=r.get(e);o||(o=new Map,r.set(e,o)),o.set(n,s);},async deleteSecureRecord(e,n){r.get(e)?.delete(n);}}}
2
+ export{g as a,P as b,K as c,m as d};