openrtc 0.1.3 → 0.2.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 (41) hide show
  1. package/LICENSE +92 -0
  2. package/README.md +73 -9
  3. package/dist/DelegatingRuntimeAdapter-BxOcVIx_.d.ts +201 -0
  4. package/dist/{IpcRuntimeAdapter-CT-W0Mtp.d.ts → IpcRuntimeAdapter-U5AEH0jn.d.ts} +6 -2
  5. package/dist/auth/index.js +1 -1
  6. package/dist/auth/internal.js +1 -1
  7. package/dist/chunk-7DN33VUQ.js +1 -0
  8. package/dist/chunk-BLOEZIFJ.js +1 -0
  9. package/dist/chunk-FQETZQPW.js +2 -0
  10. package/dist/chunk-IUHUYHNZ.js +1 -0
  11. package/dist/chunk-UBEE42VU.js +2 -0
  12. package/dist/chunk-UPO23UMZ.js +3 -0
  13. package/dist/chunk-WNJE3MJF.js +1 -0
  14. package/dist/{factories-0TxDPMeu.d.ts → framing-lxzHEuSr.d.ts} +479 -226
  15. package/dist/index.d.ts +201 -7
  16. package/dist/index.js +2 -1
  17. package/dist/openrtc_bg.wasm +0 -0
  18. package/dist/runtime/WasmRuntimeAdapter.d.ts +2 -1
  19. package/dist/runtime/WasmRuntimeAdapter.js +1 -1
  20. package/dist/runtime/index.d.ts +213 -392
  21. package/dist/runtime/index.js +1 -1
  22. package/dist/runtime/tauri.d.ts +5 -6
  23. package/dist/runtime/tauri.js +1 -1
  24. package/dist/transport/index.d.ts +11 -0
  25. package/dist/transport/index.js +1 -0
  26. package/dist/{DelegatingRuntimeAdapter-CW8d78dZ.d.ts → types-D0fRvUbN.d.ts} +222 -171
  27. package/env/index.d.ts +64 -0
  28. package/env/index.mjs +230 -0
  29. package/package.json +29 -18
  30. package/dist/chunk-26POO5PL.js +0 -4
  31. package/dist/chunk-4MH42GUI.js +0 -2
  32. package/dist/chunk-D54VGRRH.js +0 -1
  33. package/dist/chunk-DIQYFAGL.js +0 -2
  34. package/dist/chunk-PZ25OCVG.js +0 -2
  35. package/dist/chunk-UVASANPG.js +0 -1
  36. package/wasm/README.md +0 -64
  37. package/wasm/openrtc.d.ts +0 -320
  38. package/wasm/openrtc.js +0 -2290
  39. package/wasm/openrtc_bg.wasm +0 -0
  40. package/wasm/openrtc_bg.wasm.d.ts +0 -113
  41. package/wasm/package.json +0 -16
@@ -1 +1 @@
1
- export{f as DriveGrantActorError,i as DriveGrantActorHandle,j as DriveGrantActorRegistry,k as RuntimeClient,b as RuntimeConnectionController,f as ScopedConnectionActorError,i as ScopedConnectionActorHandle,j as ScopedConnectionActorRegistry,e as clog,d as correlationForDriveGrantScope,m as createIpcClient,l as createWasmClient,g as driveGrantConnectionKey,h as driveGrantConnectionKeyToString,c as renderCorrelationFields,g as scopedConnectionKey,h as scopedConnectionKeyToString}from'../chunk-26POO5PL.js';export{a as WasmRuntimeAdapter}from'../chunk-D54VGRRH.js';export{b as TauriRuntimeAdapter,a as createTauriIpcBridge}from'../chunk-UVASANPG.js';export{b as IpcRuntimeAdapter}from'../chunk-DIQYFAGL.js';export{r as BROWSER_WASM_RUNTIME_CAPABILITIES,s as NATIVE_IPC_RUNTIME_CAPABILITIES,p as OPENRTC_RUNTIME_POLICY,t as cloneRuntimeCapabilities,q as getRuntimePolicy,i as logOpenRtcTeardownTrace}from'../chunk-PZ25OCVG.js';import'../chunk-4MH42GUI.js';
1
+ export{y as RuntimeClient,h as RuntimeConnectionController,l as ScopedConnectionActorError,o as ScopedConnectionActorHandle,p as ScopedConnectionActorRegistry,k as clog,w as concatRuntimeBytes,j as correlationForDriveGrantScope,A as createIpcClient,v as createRuntimeJsonFrameDecoder,r as createRuntimeU32BEFrameDecoder,z as createWasmClient,t as decodeRuntimeJsonPayload,u as encodeRuntimeJsonFrame,s as encodeRuntimeJsonPayload,q as encodeRuntimeU32BEFrame,B as isRuntimeDeviceActive,D as isRuntimeDeviceConnectable,C as isRuntimeDeviceRoutable,x as readRuntimeU32BE,i as renderCorrelationFields,m as scopedConnectionKey,n as scopedConnectionKeyToString}from'../chunk-UPO23UMZ.js';export{a as WasmRuntimeAdapter}from'../chunk-IUHUYHNZ.js';export{b as TauriRuntimeAdapter,a as createTauriIpcBridge}from'../chunk-7DN33VUQ.js';export{h as IpcRuntimeAdapter,e as classifyNativeIpcFailure,f as isNativeIpcCommandUnavailable}from'../chunk-UBEE42VU.js';export{s as BROWSER_WASM_RUNTIME_CAPABILITIES,t as NATIVE_IPC_RUNTIME_CAPABILITIES,q as OPENRTC_RUNTIME_POLICY,u as cloneRuntimeCapabilities,r as getRuntimePolicy,i as logOpenRtcTeardownTrace,c as openRtcDebug,b as openRtcDebugEnabled,d as openRtcDebugInfo,e as openRtcDebugLog,v as runtimeCapabilitiesFromNativeStatus,w as runtimeCapabilityProfile}from'../chunk-WNJE3MJF.js';import'../chunk-FQETZQPW.js';import'../chunk-BLOEZIFJ.js';
@@ -1,7 +1,6 @@
1
- import { N as NativeIpcBridgeOptions, I as IpcRuntimeAdapter, P as PlutoIpcBridge } from '../IpcRuntimeAdapter-CT-W0Mtp.js';
2
- import '../DelegatingRuntimeAdapter-CW8d78dZ.js';
3
-
4
- type TauriBridgeOptions = NativeIpcBridgeOptions;
1
+ import { I as IpcRuntimeAdapter, N as NativeIpcBridgeOptions, P as PlutoIpcBridge } from '../IpcRuntimeAdapter-U5AEH0jn.js';
2
+ import '../types-D0fRvUbN.js';
3
+ import '../DelegatingRuntimeAdapter-BxOcVIx_.js';
5
4
 
6
5
  /**
7
6
  * @deprecated Native Tauri support now lives in the first-party `openrtc-tauri` package.
@@ -13,8 +12,8 @@ declare function createTauriIpcBridge(): PlutoIpcBridge;
13
12
  * Removal target: OpenRTC 0.2.0. This shim remains for one compatibility cycle.
14
13
  */
15
14
  declare class TauriRuntimeAdapter extends IpcRuntimeAdapter {
16
- constructor(options: TauriBridgeOptions);
15
+ constructor(options: NativeIpcBridgeOptions);
17
16
  }
18
- type TauriRuntimeAdapterOptions = TauriBridgeOptions;
17
+ type TauriRuntimeAdapterOptions = NativeIpcBridgeOptions;
19
18
 
20
19
  export { TauriRuntimeAdapter, type TauriRuntimeAdapterOptions, createTauriIpcBridge };
@@ -1 +1 @@
1
- export{b as TauriRuntimeAdapter,a as createTauriIpcBridge}from'../chunk-UVASANPG.js';import'../chunk-DIQYFAGL.js';import'../chunk-PZ25OCVG.js';import'../chunk-4MH42GUI.js';
1
+ export{b as TauriRuntimeAdapter,a as createTauriIpcBridge}from'../chunk-7DN33VUQ.js';import'../chunk-UBEE42VU.js';import'../chunk-WNJE3MJF.js';import'../chunk-FQETZQPW.js';import'../chunk-BLOEZIFJ.js';
@@ -0,0 +1,11 @@
1
+ import { n as ProtocolName } from '../types-D0fRvUbN.js';
2
+
3
+ declare const TRANSPORT_LABELS: readonly ProtocolName[];
4
+ declare function normalizeTransportLabel(value: unknown): ProtocolName | undefined;
5
+ declare function isIrohBaseTransportLabel(value: unknown): boolean;
6
+ declare function isDirectIrohTransportLabel(value: unknown): boolean;
7
+ declare function isOptionalTransportLabel(value: unknown): boolean;
8
+ declare function isWebRtcTransportLabel(value: unknown): boolean;
9
+ declare function isIndependentTransportLabel(value: unknown): boolean;
10
+
11
+ export { ProtocolName, TRANSPORT_LABELS, isDirectIrohTransportLabel, isIndependentTransportLabel, isIrohBaseTransportLabel, isOptionalTransportLabel, isWebRtcTransportLabel, normalizeTransportLabel };
@@ -0,0 +1 @@
1
+ export{a as TRANSPORT_LABELS,d as isDirectIrohTransportLabel,g as isIndependentTransportLabel,c as isIrohBaseTransportLabel,e as isOptionalTransportLabel,f as isWebRtcTransportLabel,b as normalizeTransportLabel}from'../chunk-BLOEZIFJ.js';
@@ -5,32 +5,59 @@ interface AppLimits {
5
5
  maxRooms: number;
6
6
  /** Max members per room. -1 = unlimited. */
7
7
  maxMembersPerRoom: number;
8
- /** Max active devices across all provisioned personal spaces for this app. -1 = unlimited. */
8
+ /** Max active devices across all provisioned spaces for this app. -1 = unlimited. */
9
9
  maxPersonalDevices: number;
10
10
  }
11
11
  interface PlutoRTCConfiguration extends RTCConfiguration {
12
12
  iceServers?: RTCIceServer[];
13
13
  privacyMode?: boolean;
14
14
  useTurn?: boolean;
15
+ /** Prefer host/srflx ICE candidates and upgrade aggressively on LAN. */
16
+ lanMode?: boolean;
17
+ }
18
+ interface LocalPeerSnapshot {
19
+ nodeId: string;
20
+ discoveredAtMs: number;
21
+ localReachable: boolean;
15
22
  }
16
23
  interface PlutoMoQConfiguration {
17
24
  relayUrl?: string;
18
25
  }
19
26
  interface PlutoIrohConfiguration {
20
27
  relayOnly?: boolean;
28
+ relayTransportPolicy?: 'auto' | 'quicRequired' | 'websocketRequired';
21
29
  persistenceMode?: 'persistent' | 'ephemeral';
30
+ /** Enable native iroh mDNS LAN discovery (native runtimes only). */
31
+ localDiscovery?: boolean;
32
+ /** When false, listen for LAN peers without advertising this endpoint. */
33
+ localDiscoveryMode?: 'active' | 'passive';
34
+ }
35
+ interface PlutoBleConfiguration {
36
+ /** Enable native BLE discovery + transport (native runtimes only). */
37
+ enabled?: boolean;
38
+ /** Timeout for a single BLE connection attempt. */
39
+ connectTimeoutMs?: number;
40
+ /** Preferred retry budget for native BLE connection establishment. */
41
+ retryAttempts?: number;
42
+ /** Backoff between BLE retry attempts. */
43
+ retryBackoffMs?: number;
22
44
  }
23
45
  interface TurnCredentials {
24
46
  iceServers?: RTCIceServer[];
25
47
  }
26
48
  type TurnCredentialsProvider = () => Promise<TurnCredentials | null | undefined>;
27
- type DiscoveryMode = 'personal' | 'user-scoped';
49
+ type DiscoveryMode = 'space' | 'user-scoped';
28
50
  type AuthMode = 'external' | 'anonymous' | 'required';
29
51
  type SignalingMode = 'hosted' | 'ticket-only';
30
52
  type RoomCreationMode = 'client-open' | 'client-auth' | 'server-only';
31
53
  type EndpointKind = 'device' | 'ephemeral';
32
54
  type PeerLifecycleStatus = 'disconnected' | 'connecting' | 'connected' | 'failed' | 'closed';
33
55
  type PeerHealth = 'unknown' | 'healthy' | 'suspect' | 'stale';
56
+ type DevicePresenceStatus = 'online' | 'idle' | 'offline';
57
+ type PeerLifecycleStage = 'discovered' | 'dialing' | 'base-connected' | 'admitted' | 'protocol-ready' | 'upgrading' | 'webrtc-ready' | 'degraded' | 'reconnecting' | 'closed';
58
+ type PeerBaseTransportState = 'unknown' | 'connecting' | 'connected' | 'degraded' | 'closed';
59
+ type PeerAdmissionState = 'unknown' | 'pending' | 'admitted' | 'rejected' | 'expired';
60
+ type PeerWebRtcState = 'unknown' | 'disabled' | 'connecting' | 'transport-open' | 'route-probing' | 'ready' | 'failed' | 'closed';
34
61
  /**
35
62
  * Lifecycle label attached to a projected peer while the runtime tracks local ownership.
36
63
  *
@@ -62,15 +89,30 @@ interface ChannelDescriptor {
62
89
  signalingPolicy?: ChannelSignalingPolicy;
63
90
  description?: string;
64
91
  }
65
- type ProtocolName = 'iroh' | 'iroh-quic' | 'iroh-relay' | 'webrtc' | 'moq';
92
+ type ProtocolName = 'iroh' | 'iroh-quic' | 'iroh-relay' | 'iroh-lan' | 'ble' | 'webrtc' | 'webrtc-lan' | 'moq';
66
93
  type ProtocolMaturity = 'stable' | 'experimental' | 'unsupported';
94
+ type ProtocolBaseName = 'iroh' | 'webrtc' | 'moq';
95
+ type ProtocolImplementationKind = 'plugin' | 'native' | 'path-label';
96
+ type ProtocolLocality = 'nearby' | 'direct-internet' | 'relay' | 'mixed';
67
97
  interface ProtocolCapability {
68
98
  protocol: ProtocolName;
99
+ baseProtocol: ProtocolBaseName;
100
+ implementation: ProtocolImplementationKind;
101
+ locality: ProtocolLocality;
69
102
  maturity: ProtocolMaturity;
103
+ preferredRank: number;
104
+ browser: boolean;
105
+ native: boolean;
70
106
  available: boolean;
71
107
  reason?: string;
72
108
  }
73
109
  type ProtocolCapabilityMap = Record<ProtocolName, ProtocolCapability>;
110
+ /** Space discovery always uses namespace-scoped Firebase tokens. */
111
+ type SpaceAuthMode = 'scoped-token';
112
+ type SpaceTokenProvider = () => Promise<{
113
+ customToken: string;
114
+ uid?: string;
115
+ } | null | undefined>;
74
116
  interface ClientOptions {
75
117
  /**
76
118
  * API key issued from the Pluto developer dashboard (https://api.openrtc.app/developer).
@@ -78,26 +120,30 @@ interface ClientOptions {
78
120
  */
79
121
  apiKey?: string;
80
122
  /**
81
- * Explicitly opt in to the legacy shared hosted fallback when no apiKey is provided.
123
+ * Discovery avenue for this runtime.
82
124
  *
83
- * This should only be used for controlled demos/tests. Production integrations
84
- * should always provide an API key.
85
- */
86
- allowAnonymousHostedDefaults?: boolean;
87
- /**
88
- * Discovery mode for this app. Defaults to 'personal'.
89
- * - 'personal': No user accounts. Devices share a spaceKey to discover each other.
90
- * - 'user-scoped': Developer mints tokens for their users. Devices scoped per user.
125
+ * Set this explicitly in new apps:
126
+ * - `space`: a small live shared namespace backed by scoped space tokens.
127
+ * - `user-scoped`: a signed-in user's durable owned-device roster.
91
128
  *
92
- * Set in the developer dashboard. The server validates this against the app's plan.
129
+ * Rooms and ticket/share grants are separate layers. Do not use `space`
130
+ * as a generic account device list, and do not expect `user-scoped`
131
+ * discovery to show other users unless a room or explicit grant connects them.
93
132
  */
94
133
  discoveryMode?: DiscoveryMode;
95
134
  /**
96
- * Space key for 'personal' discovery mode. Acts as a shared secret that scopes
97
- * device discovery without requiring user authentication. Devices with the same
98
- * spaceKey + apiKey will see each other.
135
+ * Shared space name for `space` discovery mode. Use this for lightweight
136
+ * lobbies, demos, cursors, and other live-only collaboration surfaces.
137
+ * This is the beginner-facing name for `spaceKey`; if both are set,
138
+ * `spaceKey` wins.
139
+ */
140
+ space?: string;
141
+ /**
142
+ * Compatibility name for `space`. The SDK derives a namespace from
143
+ * apiKey + spaceKey, then authenticates with spaceTokenProvider.
99
144
  *
100
- * Only used when discoveryMode is 'personal'. Ignored for managed modes.
145
+ * Prefer `space` in public app code. Only used when discoveryMode is
146
+ * `space`; ignored for user-scoped discovery.
101
147
  */
102
148
  spaceKey?: string;
103
149
  /**
@@ -106,6 +152,11 @@ interface ClientOptions {
106
152
  */
107
153
  sessionToken?: string;
108
154
  authMode?: AuthMode;
155
+ /**
156
+ * Allows first-party demos to use hosted defaults when an API key is omitted.
157
+ * Product apps should pass an API key.
158
+ */
159
+ allowAnonymousHostedDefaults?: boolean;
109
160
  signalingMode?: SignalingMode;
110
161
  projectId?: string;
111
162
  storagePrefix?: string;
@@ -130,16 +181,48 @@ interface ClientOptions {
130
181
  transports?: {
131
182
  iroh?: boolean | PlutoIrohConfiguration;
132
183
  webrtc?: boolean | PlutoRTCConfiguration;
184
+ ble?: boolean | PlutoBleConfiguration;
133
185
  moq?: boolean | PlutoMoQConfiguration;
134
186
  };
135
187
  transportPriority?: ProtocolName[];
188
+ /** Subscribe to native LAN peer discovery events. */
189
+ onLocalPeer?: (peer: LocalPeerSnapshot) => void;
136
190
  disableIrohFallback?: boolean;
191
+ /**
192
+ * Optional application-layer payload envelope. When configured, OpenRTC
193
+ * protects public message/media payload bytes before they are handed to
194
+ * iroh, WebRTC, or MoQ and opens them before app callbacks fire.
195
+ */
196
+ applicationCrypto?: ApplicationPayloadCrypto;
197
+ /**
198
+ * When manual `applicationCrypto` is not set, peers must negotiate an
199
+ * ephemeral X25519 ECDH key during transport handshake. Disabling is not
200
+ * supported in secure deployments.
201
+ */
202
+ automaticApplicationKeyAgreement?: boolean;
203
+ /**
204
+ * @internal Overrides orphan drift grace windows for tests and diagnostics.
205
+ */
206
+ orphanReconciliationGrace?: {
207
+ tsConnectionMs?: number;
208
+ rustRecordMs?: number;
209
+ };
210
+ /**
211
+ * Mints a namespace-scoped Firebase custom token for space discovery.
212
+ * Required when `discoveryMode` is `space` and `space`/`spaceKey` is set.
213
+ * Use `spaceToken(...)` for browser demos and simple static sites.
214
+ */
215
+ spaceTokenProvider?: SpaceTokenProvider;
137
216
  }
138
217
  interface Device {
139
218
  deviceId: string;
140
219
  deviceName: string;
141
220
  online: boolean;
142
221
  ticket: string;
222
+ presenceStatus?: DevicePresenceStatus;
223
+ presenceUpdatedAt?: number;
224
+ presenceExpiresAt?: number;
225
+ connectable?: boolean;
143
226
  kind?: EndpointKind | string;
144
227
  nodeId?: string;
145
228
  platformType?: string;
@@ -159,6 +242,8 @@ interface Device {
159
242
  updatedAt?: any;
160
243
  metadata?: string;
161
244
  excludedPeers?: string[];
245
+ availableTransports?: ProtocolName[];
246
+ transports?: ProtocolName[];
162
247
  }
163
248
  interface PeerState {
164
249
  peerId: string;
@@ -173,13 +258,22 @@ interface PeerState {
173
258
  platformType?: string;
174
259
  status: PeerLifecycleStatus;
175
260
  health: PeerHealth;
261
+ lifecycleStage?: PeerLifecycleStage;
262
+ generation?: number;
263
+ baseTransportState?: PeerBaseTransportState;
264
+ admissionState?: PeerAdmissionState;
176
265
  transportState?: string;
177
266
  protocolState?: string;
267
+ webrtcState?: PeerWebRtcState;
178
268
  routable?: boolean;
179
269
  activeTransportStableId?: number | null;
180
270
  transportGeneration?: number;
181
271
  activeTransport?: ProtocolName;
272
+ fallbackTransport?: ProtocolName | null;
182
273
  parallelTransport?: ProtocolName | null;
274
+ manualDisconnect?: boolean;
275
+ lastAuthoritativeEventAt?: number;
276
+ lastTransientEventAt?: number;
183
277
  promotionEligible?: boolean;
184
278
  scopes: PeerScope[];
185
279
  lastSeenAt?: number;
@@ -218,6 +312,7 @@ interface NativeConnectResult {
218
312
  deviceIdHint?: string | null;
219
313
  remoteNodeId?: string | null;
220
314
  state: string;
315
+ approvedScope?: string | null;
221
316
  }
222
317
  interface BackendPeerBiStream {
223
318
  readable: ReadableStream<Uint8Array>;
@@ -260,6 +355,8 @@ interface SignalingEnvelope {
260
355
  name?: string;
261
356
  senderId: string;
262
357
  targetId: string;
358
+ senderUserId?: string;
359
+ targetUserId?: string;
263
360
  state?: string;
264
361
  payload: string;
265
362
  replyPayload?: string;
@@ -353,6 +450,14 @@ interface ManagedDeviceConnectOptions {
353
450
  onConnected?: (device: Device) => void | Promise<void>;
354
451
  }
355
452
  interface DeviceStatusSnapshot extends Device {
453
+ /**
454
+ * Presence/liveness for the roster entry. This is separate from
455
+ * `connectionStatus`, which describes the runtime route to the peer.
456
+ */
457
+ presenceStatus: DevicePresenceStatus;
458
+ presenceUpdatedAt?: number;
459
+ presenceExpiresAt?: number;
460
+ connectable: boolean;
356
461
  connectionStatus: PeerLifecycleStatus | 'online';
357
462
  settledReady?: boolean;
358
463
  readinessState?: string;
@@ -367,6 +472,7 @@ interface DeviceStatusSnapshot extends Device {
367
472
  transportGeneration?: number;
368
473
  activeTransport?: ProtocolName;
369
474
  parallelTransport?: ProtocolName | null;
475
+ availableTransports?: ProtocolName[];
370
476
  }
371
477
  interface ManagedConnectionRecord {
372
478
  connectionId: string;
@@ -473,11 +579,21 @@ interface ExplicitFileDataSendParams {
473
579
  send: (message: unknown) => Promise<void>;
474
580
  deviceId?: string;
475
581
  remoteNodeId?: string;
582
+ requireApplicationCrypto?: boolean;
583
+ getUpgradeState?: () => string;
584
+ isWebRtcApplicationRouteReady?: () => boolean;
585
+ sendOnWebRTC?: (data: Uint8Array) => Promise<void>;
586
+ getWebRTCTransport?: () => {
587
+ getBufferedAmount?: () => number;
588
+ waitForDrain?: (lowWaterMark: number) => Promise<void>;
589
+ } | null;
476
590
  };
477
591
  remoteNodeId?: string;
478
592
  file: File;
479
593
  transferId: string;
480
594
  channelId?: string;
595
+ applicationCrypto?: ApplicationPayloadCrypto;
596
+ requireApplicationCrypto?: boolean;
481
597
  }
482
598
  interface ISignalingBackend {
483
599
  currentUser: RuntimeIdentity | null;
@@ -537,19 +653,18 @@ interface ISignalingBackend {
537
653
  }): Promise<string | null>;
538
654
  getEndpointTicket?(): Promise<string>;
539
655
  openPeerBi?(id: string, timeoutMs?: number): Promise<BackendPeerBiStream>;
656
+ openPeerNativeBi?(id: string, label: string, timeoutMs?: number): Promise<BackendPeerBiStream>;
540
657
  openPeerUni?(id: string, timeoutMs?: number): Promise<BackendPeerUniStream>;
541
658
  connectToDevice?(params: {
542
659
  deviceId?: string | null;
543
660
  endpointTicket: string;
544
661
  }): Promise<NativeConnectResult>;
545
662
  /**
546
- * Optional backchannel so a backend (e.g. WasmBridge) can access the core
547
- * Client after Client.setSignalingBackend() has been called. This lets the
548
- * backend trigger Client.connect() for peers it dials directly (e.g. via
549
- * the WASM auto-connect path) so the TS Connection/upgrade state machine
550
- * stays in lockstep with the Rust transport.
663
+ * Optional backchannel so a backend (e.g. WasmBridge) can access the narrow
664
+ * facade surface needed to escalate runtime transport dials into registered
665
+ * TS connections.
551
666
  */
552
- setCoreClient?(client: unknown): void;
667
+ setCoreClient?(client: CoreClientBridgeHost | null): void;
553
668
  disconnectDevice?(deviceId: string): Promise<void>;
554
669
  setAutoConnectExcluded?(deviceId: string, excluded: boolean): Promise<void>;
555
670
  isConnected(nodeId: string): Promise<boolean>;
@@ -560,30 +675,110 @@ interface ISignalingBackend {
560
675
  getTransferHistory?(limit?: number): Promise<Array<[string, unknown]>>;
561
676
  deleteTransferJob?(jobId: string): Promise<void>;
562
677
  }
678
+ interface CoreClientBridgeHost {
679
+ connect(ticket: string, timeoutMs?: number, expectedDeviceId?: string | null, channelId?: string, options?: {
680
+ admissionAlreadyPresented?: boolean;
681
+ approvedScope?: string | null;
682
+ }): Promise<{
683
+ remoteNodeId?: string | null;
684
+ deviceId?: string | null;
685
+ } | unknown>;
686
+ waitForApplicationCryptoForPeer?(peerId?: string, timeoutMs?: number): Promise<unknown>;
687
+ hasApplicationRouteForPeer?(connectionId?: string, remoteNodeId?: string): boolean;
688
+ }
563
689
  interface SignalingOptions {
564
690
  apiKey?: string;
565
- allowAnonymousHostedDefaults?: boolean;
566
691
  authMode?: AuthMode;
567
692
  projectId?: string;
568
693
  storagePrefix?: string;
569
694
  nodeIdPersistence?: 'persistent' | 'ephemeral';
570
695
  }
571
696
  interface TransportContext {
572
- sendMoQ: (data: Uint8Array) => Promise<void>;
697
+ sendMoQ: (data: Uint8Array, options?: {
698
+ alreadyProtected?: boolean;
699
+ }) => Promise<void>;
573
700
  priorities: ProtocolName[];
574
701
  disableIrohFallback: boolean;
575
702
  isMoQReady: () => boolean;
703
+ isMoQDataReady?: () => boolean;
576
704
  runtimeFlow?: 'default' | 'ticket-only';
577
705
  readerCloseStrategy?: 'cancel' | 'release-lock';
578
706
  }
707
+ interface ApplicationPayloadCrypto {
708
+ /**
709
+ * When true, incoming application payloads that are not encrypted by this
710
+ * envelope are dropped before app callbacks fire.
711
+ */
712
+ requireEncrypted?: boolean;
713
+ protectPayload: (typeId: number, payload: Uint8Array) => Uint8Array;
714
+ openPayload: (expectedTypeId: number, payload: Uint8Array) => Uint8Array | null;
715
+ }
716
+ interface ApplicationCryptoBiStream {
717
+ send: WritableStream<Uint8Array>;
718
+ recv: ReadableStream<Uint8Array>;
719
+ endpoint_id?: string;
720
+ }
721
+ interface ApplicationCryptoStreamTools {
722
+ readonly typeId: number;
723
+ protectFrame: (payload: Uint8Array) => Uint8Array;
724
+ openFrame: (payload: Uint8Array) => Uint8Array | null;
725
+ createOutboundTransform: () => TransformStream<Uint8Array, Uint8Array>;
726
+ createInboundTransform: () => TransformStream<Uint8Array, Uint8Array>;
727
+ wrapReadable: (readable: ReadableStream<Uint8Array>) => ReadableStream<Uint8Array>;
728
+ wrapWritable: (writable: WritableStream<Uint8Array>) => WritableStream<Uint8Array>;
729
+ wrapBiStream: <T extends ApplicationCryptoBiStream>(stream: T) => T;
730
+ }
731
+ interface ApplicationPayloadReadinessOptions {
732
+ /**
733
+ * When provided, a connection is considered ready only once its active
734
+ * application route is one of these transports.
735
+ */
736
+ preferredTransports?: ProtocolName[];
737
+ /**
738
+ * If a preferred upgraded route cannot be established, allow the connection's
739
+ * proven application route to carry payloads instead of remaining pending.
740
+ */
741
+ allowFallbackAfterPreferredTransportFailure?: boolean;
742
+ }
743
+ interface ApplicationPayloadRouteOptions extends ApplicationPayloadReadinessOptions {
744
+ /**
745
+ * Include the parallel/fallback transport in diagnostic route listings.
746
+ * Normal app payload probes should leave this disabled so they measure the
747
+ * route OpenRTC would actually prefer for application data.
748
+ */
749
+ includeFallbackTransports?: boolean;
750
+ }
751
+ interface ApplicationPayloadSendOptions extends ApplicationPayloadRouteOptions {
752
+ }
579
753
  interface ConnectionOptions {
580
754
  reliable?: boolean;
581
- rtcConfig?: RTCConfiguration;
755
+ rtcConfig?: PlutoRTCConfiguration;
582
756
  transportContext?: TransportContext;
757
+ applicationCrypto?: ApplicationPayloadCrypto;
758
+ /** Framing used by the underlying iroh control stream. */
759
+ controlFrameMode?: 'typed' | 'native-main';
760
+ /**
761
+ * When true, public application payload sends wait for applicationCrypto to
762
+ * be installed and fail closed if key negotiation never completes.
763
+ * Internal handshake/control frames are sent through a separate control path.
764
+ */
765
+ requireApplicationCrypto?: boolean;
766
+ applicationCryptoWaitMs?: number;
583
767
  onTransportStatusChange?: (status: {
584
768
  activeTransport: ProtocolName;
585
769
  parallelTransport?: ProtocolName | null;
586
770
  }) => void;
771
+ /**
772
+ * Fired when the WebRTC data plane has proven a ping/pong round trip but the
773
+ * mandatory application crypto route is not installed yet. Connection owns
774
+ * transport proof; Client owns the application-route handshake recovery.
775
+ */
776
+ onApplicationRouteMissing?: (event: {
777
+ connectionId: string;
778
+ remoteNodeId: string;
779
+ reason: 'webrtc-heartbeat-before-crypto';
780
+ negotiationId?: string | null;
781
+ }) => void;
587
782
  }
588
783
  interface JoinRequest {
589
784
  id: string;
@@ -592,148 +787,4 @@ interface JoinRequest {
592
787
  state: 'pending' | 'accepted' | 'rejected';
593
788
  }
594
789
 
595
- type AuthContext = {
596
- userId: string;
597
- token?: string | null;
598
- refreshToken?: string | null;
599
- customToken?: string | null;
600
- tokenProvider?: (forceRefresh?: boolean) => Promise<string | null>;
601
- expiresAtMs?: number | null;
602
- };
603
-
604
- type RuntimeAdapterKind = 'browser-wasm' | 'native-ipc' | 'tauri-ipc' | 'unknown';
605
- interface RuntimeCapabilities {
606
- adapter: RuntimeAdapterKind;
607
- signaling: {
608
- firestore: boolean;
609
- nativeIpc: boolean;
610
- rtdbPresence: boolean;
611
- };
612
- transport: {
613
- irohQuic: boolean;
614
- webRtcUpgrade: boolean;
615
- nativeWebRtc: boolean;
616
- wasm: boolean;
617
- };
618
- lifecycle: {
619
- managedSession: boolean;
620
- autoConnect: boolean;
621
- manualDisconnect: boolean;
622
- connectionStateEvents: boolean;
623
- peerSessions: boolean;
624
- };
625
- transfers: {
626
- explicitFilePath: boolean;
627
- explicitFileData: boolean;
628
- history: boolean;
629
- };
630
- fallback: {
631
- wasm: boolean;
632
- };
633
- }
634
- declare const BROWSER_WASM_RUNTIME_CAPABILITIES: RuntimeCapabilities;
635
- declare const NATIVE_IPC_RUNTIME_CAPABILITIES: RuntimeCapabilities;
636
- declare function cloneRuntimeCapabilities(capabilities: RuntimeCapabilities): RuntimeCapabilities;
637
-
638
- interface WasmBridgeOptions {
639
- apiKey?: string;
640
- discoveryMode?: DiscoveryMode;
641
- spaceKey?: string;
642
- authMode?: AuthMode;
643
- signalingMode?: SignalingMode;
644
- projectId?: string;
645
- storagePrefix?: string;
646
- nodeIdPersistence?: 'persistent' | 'ephemeral';
647
- deviceName?: string;
648
- turnCredentialsProvider?: () => Promise<{
649
- iceServers?: RTCIceServer[];
650
- } | null | undefined>;
651
- }
652
-
653
- declare abstract class DelegatingRuntimeAdapter implements ISignalingBackend {
654
- protected readonly backend: ISignalingBackend;
655
- protected constructor(backend: ISignalingBackend);
656
- get currentUser(): RuntimeIdentity | null;
657
- setAuthContext(context: AuthContext | null): Promise<void> | void;
658
- signInAnonymously(): Promise<void>;
659
- signInWithPluto(): Promise<void>;
660
- signOut(): Promise<void>;
661
- stopAuthScopedActivity(): Promise<void>;
662
- getTurnCredentials(): Promise<any>;
663
- updatePresence(localNodeId: string, ticketStr: string, isOnline: boolean, ttlMs: number, metadata?: string): Promise<void>;
664
- setOffline(localNodeId: string): Promise<void>;
665
- cleanupStaleDevices(): Promise<void>;
666
- searchDevices(excludeNodeId?: string): Promise<Device[]>;
667
- listDevicesWithStatus(): Promise<DeviceStatusSnapshot[]>;
668
- getPeerSession(id: string): Promise<PeerSessionSnapshot | null>;
669
- listPeerSessions(): Promise<PeerSessionSnapshot[]>;
670
- waitForSettledPeer(id: string, timeoutMs?: number): Promise<PeerSessionSnapshot | null>;
671
- resolvePeerIdentity(id: string): Promise<ResolvedPeerIdentity>;
672
- resolvePeerConnectionRecords(id: string): Promise<ManagedConnectionRecord[]>;
673
- updateDevice(deviceId: string, updates: {
674
- deviceName?: string;
675
- capabilities?: Device['capabilities'];
676
- metadata?: string;
677
- }): Promise<void>;
678
- deleteDevice(deviceId: string): Promise<void>;
679
- onDevicesChange(callback: (devices: Device[]) => void, excludeNodeId?: string): () => void;
680
- onAuthChange(callback: (user: RuntimeIdentity | null) => void): () => void;
681
- checkForSSOToken(): Promise<void>;
682
- waitForAuth(): Promise<void>;
683
- sendMessage(targetId: string, payload: string, state?: string, replyPayload?: string): Promise<string>;
684
- pollMessages(targetId: string): Promise<SignalingEnvelope[]>;
685
- subscribeDevices(userId: string): Promise<ReadableStream<DeviceEvent[]>>;
686
- startAutoConnect(userId: string, localDeviceId: string): void;
687
- startPresenceLoop(userId: string, localNodeId: string, deviceName: string, ticket: string, metadata?: string): void;
688
- createSession(session: SignalingSession): Promise<void>;
689
- updateSession(sessionId: string, updateData: any): Promise<void>;
690
- subscribeSessions(localDeviceId: string): Promise<ReadableStream<SessionEvent[]>>;
691
- forceReconnectSnapshot(): void;
692
- getLocalDeviceId(): Promise<string | null>;
693
- getLocalDeviceInfo(): Promise<LocalDeviceInfo | null>;
694
- updateLocalDeviceName(deviceName: string): Promise<LocalDeviceInfo | null>;
695
- startManagedSessionNative(options: {
696
- userId: string;
697
- deviceName?: string;
698
- localDeviceId?: string | null;
699
- metadata?: string;
700
- autoConnect?: boolean;
701
- presence?: boolean;
702
- }): Promise<NativeManagedSessionStartResult>;
703
- getManagedNodeId(options?: {
704
- initializeIfMissing?: boolean;
705
- }): Promise<string | null>;
706
- startPresenceLoopOnce(userId: string, localNodeId: string, deviceName: string, ticket: string, metadata?: string): Promise<void>;
707
- startAutoConnectOnce(userId: string, localDeviceId: string): Promise<void>;
708
- getEndpointTicket(): Promise<string>;
709
- getEndpointTicketWithToken(scope: GrantScope, maxConnections: number): Promise<string | null>;
710
- registerSessionToken(token: string, scope: GrantScope, maxConnections: number): Promise<void>;
711
- revokeSessionTokensByScope(scope: GrantScope): Promise<string[]>;
712
- openPeerBi(id: string, timeoutMs?: number): Promise<BackendPeerBiStream>;
713
- openPeerBiTransportOnly(id: string, timeoutMs?: number): Promise<BackendPeerBiStream>;
714
- openPeerUni(id: string, timeoutMs?: number): Promise<BackendPeerUniStream>;
715
- connectToDevice(params: {
716
- deviceId?: string | null;
717
- endpointTicket: string;
718
- }): Promise<NativeConnectResult>;
719
- disconnectDevice(deviceId: string): Promise<void>;
720
- isConnected(nodeId: string): Promise<boolean>;
721
- getConnectionStates(): Promise<BackendConnectionState[]>;
722
- onConnectionStateChange(callback: (state: BackendConnectionState) => void): Promise<() => void> | (() => void);
723
- sendExplicitFilePath(connectionId: string, filePath: string, transferId?: string): Promise<string>;
724
- sendExplicitFileData(params: ExplicitFileDataSendParams): Promise<void>;
725
- getTransferHistory(limit?: number): Promise<Array<[string, unknown]>>;
726
- deleteTransferJob(jobId: string): Promise<void>;
727
- getRuntimeCapabilities(): RuntimeCapabilities;
728
- onIncomingNativeMessage(callback: (connectionId: string, remoteNodeId: string | null, message: any) => void): Promise<() => void>;
729
- unwrap(): ISignalingBackend;
730
- /**
731
- * Forward setCoreClient() to the inner backend if it implements it. This
732
- * lets the core Client inject a reference into backends (e.g. WasmBridge)
733
- * that need to escalate transport-level dials into full Client.connect()
734
- * handshakes.
735
- */
736
- setCoreClient(client: unknown): void;
737
- }
738
-
739
- export { type AuthContext as A, type BackendConnectionState as B, type ConnectDeviceResult as C, DelegatingRuntimeAdapter as D, type ExplicitFileDataSendParams as E, type RoomCreationMode as F, type GrantScope as G, type ScanningLoopOptions as H, type IncomingStreamChannelMetadata as I, type JoinRoomOptions as J, type ScanningLoopHandle as K, type LocalDeviceInfo as L, type ManagedDeviceConnectOptions as M, type NativeConnectResult as N, type RuntimeBootstrapOptions as O, type PeerSessionSnapshot as P, type RuntimeBootstrapResult as Q, type ResolvedPeerIdentity as R, type SignalingMode as S, type JoinRequest as T, BROWSER_WASM_RUNTIME_CAPABILITIES as U, NATIVE_IPC_RUNTIME_CAPABILITIES as V, type WasmBridgeOptions as W, cloneRuntimeCapabilities as X, type ConnectDeviceHooks as a, type ConnectDeviceOptions as b, type RuntimeCapabilities as c, type AppLimits as d, type AuthMode as e, type DiscoveryMode as f, type ProtocolCapability as g, type ProtocolCapabilityMap as h, type ProtocolName as i, type RuntimeAdapterKind as j, type ClientOptions as k, type ChannelDescriptor as l, type Device as m, type SignalingSession as n, type RuntimeIdentity as o, type DeviceStatusSnapshot as p, type PeerState as q, type PeerHealth as r, type RoomMember as s, type PeerScope as t, type PeerLifecycleStatus as u, type ConnectionOptions as v, type ISignalingBackend as w, type ManagedConnectionRecord as x, type SignalingOptions as y, type SignalingEnvelope as z };
790
+ export type { PeerHealth as $, AuthMode as A, BackendPeerBiStream as B, ClientOptions as C, DiscoveryMode as D, ExplicitFileDataSendParams as E, ProtocolImplementationKind as F, GrantScope as G, ProtocolLocality as H, ISignalingBackend as I, SpaceAuthMode as J, SignalingOptions as K, LocalDeviceInfo as L, ManagedConnectionRecord as M, NativeManagedSessionStartResult as N, JoinRoomOptions as O, PeerSessionSnapshot as P, RoomMember as Q, RuntimeIdentity as R, SignalingMode as S, IncomingStreamChannelMetadata as T, RoomCreationMode as U, ScanningLoopOptions as V, ScanningLoopHandle as W, RuntimeBootstrapOptions as X, RuntimeBootstrapResult as Y, PeerState as Z, PeerScope as _, Device as a, ChannelDescriptor as a0, JoinRequest as a1, ConnectionOptions as a2, ManagedDeviceConnectOptions as a3, PeerLifecycleStatus as a4, DeviceStatusSnapshot as b, ResolvedPeerIdentity as c, SignalingEnvelope as d, DeviceEvent as e, SignalingSession as f, SessionEvent as g, BackendPeerUniStream as h, NativeConnectResult as i, BackendConnectionState as j, ConnectDeviceResult as k, ConnectDeviceHooks as l, ConnectDeviceOptions as m, ProtocolName as n, ProtocolCapability as o, ProtocolCapabilityMap as p, ApplicationPayloadCrypto as q, ApplicationCryptoStreamTools as r, SpaceTokenProvider as s, AppLimits as t, ApplicationCryptoBiStream as u, ApplicationPayloadReadinessOptions as v, ApplicationPayloadRouteOptions as w, ApplicationPayloadSendOptions as x, DevicePresenceStatus as y, ProtocolBaseName as z };