@net-mesh/browser 0.37.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 (110) hide show
  1. package/CHANGELOG.md +517 -0
  2. package/LICENSE-APACHE +190 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +666 -0
  5. package/dist/async-queue.d.ts +26 -0
  6. package/dist/async-queue.js +62 -0
  7. package/dist/credential.d.ts +70 -0
  8. package/dist/credential.js +95 -0
  9. package/dist/errors.d.ts +400 -0
  10. package/dist/errors.js +726 -0
  11. package/dist/events.d.ts +232 -0
  12. package/dist/events.js +298 -0
  13. package/dist/identity.d.ts +40 -0
  14. package/dist/identity.js +78 -0
  15. package/dist/index.bundle.js +2 -0
  16. package/dist/index.d.ts +38 -0
  17. package/dist/index.js +46 -0
  18. package/dist/leader/events.d.ts +111 -0
  19. package/dist/leader/events.js +116 -0
  20. package/dist/leader/index.d.ts +14 -0
  21. package/dist/leader/index.js +11 -0
  22. package/dist/leader/session.d.ts +539 -0
  23. package/dist/leader/session.js +770 -0
  24. package/dist/leader/wasm.d.ts +123 -0
  25. package/dist/leader/wasm.js +39 -0
  26. package/dist/lobby.d.ts +183 -0
  27. package/dist/lobby.js +504 -0
  28. package/dist/local.d.ts +80 -0
  29. package/dist/local.js +160 -0
  30. package/dist/net_leaf.d.ts +1494 -0
  31. package/dist/net_leaf.js +3753 -0
  32. package/dist/net_leaf_bg.wasm +0 -0
  33. package/dist/net_leaf_bg.wasm.d.ts +137 -0
  34. package/dist/netcode/client.d.ts +102 -0
  35. package/dist/netcode/client.js +296 -0
  36. package/dist/netcode/clock.d.ts +45 -0
  37. package/dist/netcode/clock.js +54 -0
  38. package/dist/netcode/host.d.ts +118 -0
  39. package/dist/netcode/host.js +276 -0
  40. package/dist/netcode/index.d.ts +19 -0
  41. package/dist/netcode/index.js +14 -0
  42. package/dist/netcode/interpolate.d.ts +50 -0
  43. package/dist/netcode/interpolate.js +100 -0
  44. package/dist/netcode/wire.d.ts +125 -0
  45. package/dist/netcode/wire.js +117 -0
  46. package/dist/node.d.ts +908 -0
  47. package/dist/node.js +1085 -0
  48. package/dist/org.d.ts +412 -0
  49. package/dist/org.js +567 -0
  50. package/dist/peer-driver.d.ts +117 -0
  51. package/dist/peer-driver.js +224 -0
  52. package/dist/store/assembly.d.ts +176 -0
  53. package/dist/store/assembly.js +325 -0
  54. package/dist/store/chunker.d.ts +83 -0
  55. package/dist/store/chunker.js +190 -0
  56. package/dist/store/core.d.ts +136 -0
  57. package/dist/store/core.js +477 -0
  58. package/dist/store/definition.d.ts +23 -0
  59. package/dist/store/definition.js +83 -0
  60. package/dist/store/errors.d.ts +77 -0
  61. package/dist/store/errors.js +94 -0
  62. package/dist/store/host.d.ts +247 -0
  63. package/dist/store/host.js +675 -0
  64. package/dist/store/index.d.ts +50 -0
  65. package/dist/store/index.js +40 -0
  66. package/dist/store/interest.d.ts +40 -0
  67. package/dist/store/interest.js +77 -0
  68. package/dist/store/inventory.d.ts +81 -0
  69. package/dist/store/inventory.js +140 -0
  70. package/dist/store/join.d.ts +118 -0
  71. package/dist/store/join.js +724 -0
  72. package/dist/store/json.d.ts +50 -0
  73. package/dist/store/json.js +283 -0
  74. package/dist/store/ledger.d.ts +187 -0
  75. package/dist/store/ledger.js +292 -0
  76. package/dist/store/owner.d.ts +616 -0
  77. package/dist/store/owner.js +1711 -0
  78. package/dist/store/patch.d.ts +70 -0
  79. package/dist/store/patch.js +166 -0
  80. package/dist/store/player.d.ts +65 -0
  81. package/dist/store/player.js +261 -0
  82. package/dist/store/replica.d.ts +187 -0
  83. package/dist/store/replica.js +740 -0
  84. package/dist/store/state.d.ts +42 -0
  85. package/dist/store/state.js +165 -0
  86. package/dist/store/types.d.ts +200 -0
  87. package/dist/store/types.js +25 -0
  88. package/dist/store/visibility.d.ts +118 -0
  89. package/dist/store/visibility.js +282 -0
  90. package/dist/store/wire.d.ts +309 -0
  91. package/dist/store/wire.js +834 -0
  92. package/dist/stream.d.ts +174 -0
  93. package/dist/stream.js +238 -0
  94. package/dist/three/index.d.ts +109 -0
  95. package/dist/three/index.js +130 -0
  96. package/dist/udp-probe.d.ts +159 -0
  97. package/dist/udp-probe.js +245 -0
  98. package/dist/wasm.d.ts +642 -0
  99. package/dist/wasm.js +98 -0
  100. package/dist/world/border.d.ts +84 -0
  101. package/dist/world/border.js +99 -0
  102. package/dist/world/handoff.d.ts +187 -0
  103. package/dist/world/handoff.js +222 -0
  104. package/dist/world/index.d.ts +13 -0
  105. package/dist/world/index.js +9 -0
  106. package/dist/world/link.d.ts +179 -0
  107. package/dist/world/link.js +476 -0
  108. package/dist/world/regions.d.ts +154 -0
  109. package/dist/world/regions.js +314 -0
  110. package/package.json +72 -0
package/dist/wasm.d.ts ADDED
@@ -0,0 +1,642 @@
1
+ /**
2
+ * The wasm-bindgen boundary, described in TypeScript.
3
+ *
4
+ * These are the *only* shapes this package assumes about
5
+ * `net-mesh-leaf`. They are snake_case because that is what
6
+ * `wasm-bindgen` emits from Rust method names; every camelCase name a
7
+ * consumer sees is added by {@link BrowserNode} one layer up. Keeping
8
+ * the boundary in one file means a change on the Rust side breaks
9
+ * compilation here, at the seam, instead of somewhere in the middle of
10
+ * the wrapper.
11
+ */
12
+ /**
13
+ * `LeafNode.connect`'s argument, exactly as the Rust side reads it
14
+ * (`wasm.rs`: `credentialB64`, `bootstrapUrl?`, `origin`,
15
+ * `iceServers?`, `entitySecretHex?`, `noiseSecretHex?`).
16
+ */
17
+ export interface LeafWasmConnectOptions {
18
+ /** The bootstrap credential, base64. */
19
+ credentialB64: string;
20
+ /**
21
+ * The anchor's HTTPS bootstrap endpoint. Optional: the credential
22
+ * carries one, and this overrides it when present.
23
+ */
24
+ bootstrapUrl?: string;
25
+ /** The origin this node belongs to — the identity's trust boundary. */
26
+ origin: string;
27
+ /**
28
+ * Extra ICE servers, when the page wants them.
29
+ *
30
+ * Real `RTCIceServer` objects: `urls` a string or an array of
31
+ * them, plus `username`/`credential` for TURN. Rust parses this
32
+ * shape (`wasm.rs: parse_ice_servers`) and refuses anything else
33
+ * — a bare URL string included — rather than dropping it.
34
+ */
35
+ iceServers?: readonly RTCIceServer[];
36
+ /** Custodial Ed25519 entity secret, 32 bytes of hex. */
37
+ entitySecretHex?: string;
38
+ /**
39
+ * Custodial Noise X25519 static secret, 32 bytes of hex. The Rust
40
+ * side reads it only when `entitySecretHex` is also present.
41
+ */
42
+ noiseSecretHex?: string;
43
+ }
44
+ /** How a stream behaves. Mirrors the leaf's two stream profiles. */
45
+ export type StreamReliability = 'reliable' | 'fireAndForget';
46
+ /** `open_stream`'s argument. */
47
+ export interface LeafWasmStreamOptions {
48
+ reliability: StreamReliability;
49
+ /** A human label for logs. */
50
+ label?: string;
51
+ /**
52
+ * Used verbatim when present, so a stream can match a publish
53
+ * contract a native handler dispatches on. Decimal or `0x`-hex,
54
+ * and a **string** because a `u64` does not survive a JS number.
55
+ */
56
+ streamId?: string;
57
+ /**
58
+ * Likewise verbatim: the `u16` channel hash the stream rides.
59
+ *
60
+ * A **number**, which is what Rust reads. It was declared a
61
+ * string here while `wasm.rs` read it with `as_f64`, so every
62
+ * typed caller that obeyed this file got hash 0 — silently, on
63
+ * the wrong channel. Out of `0..=65535` is now an error, not a
64
+ * saturating cast.
65
+ */
66
+ channelHash?: number;
67
+ /**
68
+ * The node the stream addresses: **16 hex digits**, the spelling
69
+ * `node_id_hex()` hands out and the four §9 peer methods take.
70
+ * Absent, the stream addresses the anchor — the behaviour every
71
+ * caller had before this option existed.
72
+ *
73
+ * A decimal id is refused rather than accepted as a second
74
+ * spelling, exactly as `connectPeer` refuses one.
75
+ */
76
+ peer?: string;
77
+ /**
78
+ * **Ride the lossy carrier** — for high-rate state where only the newest
79
+ * value matters (positions, inputs). With `reliability: 'fireAndForget'`
80
+ * only; `true` with `'reliable'` throws.
81
+ *
82
+ * Every stream normally shares one ordered, fully retransmitted
83
+ * DataChannel, so one lost packet delays everything behind it. A lossy
84
+ * stream's packets ride a second, unordered channel with no
85
+ * retransmits: each arrives promptly or not at all, and none delays
86
+ * anything else. A packet that would queue behind a backed-up buffer is
87
+ * dropped instead (it would be stale on arrival). The receiver sees a
88
+ * fire-and-forget stream as always: gaps are skipped and anything older
89
+ * than what it already delivered is dropped — the newest value wins.
90
+ *
91
+ * Direct `connect()` nodes only for now: {@link MeshSession.openStream}
92
+ * refuses it. A peer or anchor that opens no lossy channel still gets
93
+ * the packets, on the reliable one.
94
+ */
95
+ lossy?: boolean;
96
+ }
97
+ /**
98
+ * What a stream's `on_message` callback receives from Rust.
99
+ *
100
+ * The wasm boundary hands over **the node's `stream_data` event
101
+ * JSON string**, the same text `on_event` delivers, filtered to this
102
+ * stream's id:
103
+ *
104
+ * ```json
105
+ * {"type":"stream_data","stream_id":"9","seq":"1","payload":"AQI="}
106
+ * ```
107
+ *
108
+ * `stream_id`/`seq` are decimal `u64` strings, `payload` is padded
109
+ * base64. {@link LeafStream} decodes it, which is where the promise
110
+ * of `Uint8Array` is kept; this declaration states what actually
111
+ * arrives. Before Stage 5's repair it said `Uint8Array` and the
112
+ * string was handed to pages verbatim.
113
+ *
114
+ * `Uint8Array` is admitted as already-decoded payload for a host
115
+ * that supplies its own {@link LeafWasmStreamLike} — the wrapper is
116
+ * a public type — and it is what keeps the plain-bytes path honest
117
+ * in the ABI probes.
118
+ */
119
+ export type StreamCallbackPayload = string | Uint8Array;
120
+ /** The stream object `open_stream` returns. */
121
+ export interface LeafWasmStream {
122
+ /** Synchronous on the Rust side: one payload, one packet, no framing. */
123
+ send(payload: Uint8Array): void;
124
+ on_message(callback: (event: StreamCallbackPayload) => void): void;
125
+ is_reliable(): boolean;
126
+ /** 16 lowercase hex digits. The event JSON's `stream_id` is the same id in decimal. */
127
+ stream_id_hex(): string;
128
+ /**
129
+ * The peer this stream addresses, 16 lowercase hex digits — the
130
+ * same spelling as {@link LeafWasmStream.stream_id_hex} on
131
+ * purpose, so peer and id are reconciled against their decimal
132
+ * event fields by one idiom rather than two. The event JSON's
133
+ * `peer_node` is this value in decimal.
134
+ *
135
+ * **Why the wrapper needs it:** a stream id is an application
136
+ * label scoped to a session, so two streams to two peers under one
137
+ * id is the ordinary case, not a collision. The callback delivers
138
+ * the NODE-WIDE event vector, so without the peer a wrapper's
139
+ * filter admits the other peer's payload (R4-10).
140
+ *
141
+ * **Required**, on both this and the proxied handle: the leaf
142
+ * implements it on both, so a consumer never has to know which kind
143
+ * of stream it holds to filter by peer. A host-supplied wrapper
144
+ * that genuinely has no peer to report is handled by the wrapper's
145
+ * own `identity: 'optional'` construction (`stream.ts`), not by
146
+ * making the boundary lie about what the leaf exposes.
147
+ */
148
+ peer_node_hex(): string;
149
+ /**
150
+ * Which incarnation of that peer's session this stream belongs to,
151
+ * exact decimal — the event JSON's `incarnation`, same spelling.
152
+ *
153
+ * Provenance, not identity: the filter is `(peer, stream id)`.
154
+ * Send-side staleness is fenced by the leaf itself, and a replaced
155
+ * session retires its receive cursors, so no frame reaches a
156
+ * wrapper under a dead incarnation. Declared because this file is
157
+ * the record of the boundary the leaf actually exposes.
158
+ */
159
+ incarnation(): string;
160
+ close(): void;
161
+ }
162
+ /**
163
+ * The stream object a **session**'s `open_stream` resolves to.
164
+ *
165
+ * `send` is a promise because on a follower the packet is put on the
166
+ * wire by another tab, and `on_message` delivers the same event JSON,
167
+ * so one decoder serves both.
168
+ *
169
+ * **It is not otherwise identical, and the difference matters.** The
170
+ * real `ProxyStream` exports no `peer_node_hex` or `incarnation`
171
+ * (`leaf/src/leader_session.rs`), which is why they are optional
172
+ * here — and why a proxied stream's peer filter in `stream.ts` is
173
+ * inert: `peerId` reads `null` and admission falls back to the stream
174
+ * id alone. That is the cross-peer admixture the direct path fixed,
175
+ * still open for followers (S7 brief §4a). The optionality is a
176
+ * faithful declaration of today's ABI, not an invitation to rely on
177
+ * it: a consumer that needs the peer must not accept a proxied
178
+ * stream until the accessor exists.
179
+ */
180
+ export interface LeafWasmProxyStream {
181
+ send(payload: Uint8Array): Promise<void>;
182
+ on_message(callback: (event: StreamCallbackPayload) => void): void;
183
+ is_reliable(): boolean;
184
+ stream_id_hex(): string;
185
+ /**
186
+ * As {@link LeafWasmStream.peer_node_hex}, and **required**.
187
+ *
188
+ * It was optional, and `ProxyStream` did not implement it, so a
189
+ * proxied stream's peer filter went inert and admitted any peer's
190
+ * frame under a matching id. The declaration is required now
191
+ * because the implementation exists on both handles; a consumer
192
+ * must not have to know which kind of stream it holds to filter by
193
+ * peer.
194
+ */
195
+ peer_node_hex(): string;
196
+ /** As {@link LeafWasmStream.incarnation}. */
197
+ incarnation(): string;
198
+ close(): void;
199
+ }
200
+ /** Either stream object, since the wrapper serves both. */
201
+ export type LeafWasmStreamLike = LeafWasmStream | LeafWasmProxyStream;
202
+ /**
203
+ * The caller attribution one handler invocation receives: the crate's
204
+ * `to_json` JSON **string** (the `on_event` convention), camelCase
205
+ * keys verbatim {@link OrgCaller}'s, `entity` as 64 hex digits. Parsed
206
+ * once in the wrapper by {@link parseOrgCaller}.
207
+ */
208
+ export type LeafWasmOrgCaller = string;
209
+ /** The credential set one org call presents. Byte fields must be real `Uint8Array`s. */
210
+ export interface LeafWasmOrgCredentials {
211
+ /** The caller's membership certificate, its 156-byte wire form. */
212
+ membership: Uint8Array;
213
+ /** The dispatcher grant, its wire form. */
214
+ dispatcher: Uint8Array;
215
+ /** The capability grant, its wire form, when the call carries one. */
216
+ capabilityGrant?: Uint8Array;
217
+ /** The org the caller acts as. */
218
+ actingOrg: string;
219
+ /** The org that owns the provider. */
220
+ providerOwnerOrg: string;
221
+ /** The provider, exactly as the call addresses it. */
222
+ provider: string;
223
+ /** Proof freshness bound, seconds. */
224
+ proofTtlSecs?: number;
225
+ }
226
+ /** `call_org*`'s options object. */
227
+ export interface LeafWasmOrgCallOptions {
228
+ credentials: LeafWasmOrgCredentials;
229
+ /**
230
+ * The call's deadline, milliseconds.
231
+ */
232
+ deadlineMs?: number;
233
+ /**
234
+ * Initial response-direction flow-control window, **chunk
235
+ * credits** — one credit permits one item frame (the wire header's
236
+ * unit). NOT bytes.
237
+ */
238
+ streamWindowInitial?: number;
239
+ /**
240
+ * Initial request-direction flow-control window, **chunk credits**
241
+ * (as {@link LeafWasmOrgCallOptions.streamWindowInitial}).
242
+ */
243
+ requestWindowInitial?: number;
244
+ }
245
+ /** `serve_org*`'s options object. */
246
+ export interface LeafWasmOrgServeOptions {
247
+ /** The org that owns the provider side of every admitted call. */
248
+ ownerOrg: string;
249
+ }
250
+ /**
251
+ * Which authority admits a served call: `'same-org'` (owner-org
252
+ * traffic only) or `'granted'` (capability grants too). Anything else
253
+ * is a loud refusal at registration.
254
+ */
255
+ export type LeafWasmOrgAccess = 'same-org' | 'granted';
256
+ /**
257
+ * One terminal item's typed error, exactly as it crosses: the frozen
258
+ * `kind` vocabulary plus its fields. `message` is the Display text,
259
+ * verbatim.
260
+ */
261
+ export interface LeafWasmOrgTerminalError {
262
+ kind: string;
263
+ message?: string;
264
+ coarse?: string;
265
+ /** Exact decimal u64 — never a JS number. */
266
+ generation?: string;
267
+ status?: number;
268
+ deadlineMs?: number;
269
+ }
270
+ /**
271
+ * What `OrgByteStreamHandle.next()` resolves — the leaf's three item
272
+ * objects (`org_stream_item` / `org_stream_end` /
273
+ * `org_stream_end_value` / `org_stream_end_error` in
274
+ * `leaf/src/wasm.rs`), verbatim. The `done` arm carries `value` when
275
+ * the terminal carries a final body (the completion frame's non-empty
276
+ * body): `{ done: true, value }`, never both `value` and `error`.
277
+ */
278
+ export type LeafWasmOrgByteItem = {
279
+ done: false;
280
+ value: Uint8Array;
281
+ } | {
282
+ done: true;
283
+ value?: Uint8Array;
284
+ error?: LeafWasmOrgTerminalError;
285
+ };
286
+ /**
287
+ * What `OrgRequestStreamHandle.next()` resolves. No error arm: a
288
+ * handler-side request stream's termination is observed ONLY through
289
+ * `retired()`.
290
+ */
291
+ export type LeafWasmOrgRequestItem = {
292
+ done: false;
293
+ value: Uint8Array;
294
+ } | {
295
+ done: true;
296
+ value?: undefined;
297
+ };
298
+ /** The response half of an org call, as a raw handle. */
299
+ export interface LeafWasmOrgByteStreamHandle {
300
+ next(): Promise<LeafWasmOrgByteItem>;
301
+ /** Drop this caller handle: at most one CANCEL leaves per handle. */
302
+ cancel(): void;
303
+ }
304
+ /** A client-streaming upload, as a raw handle. */
305
+ export interface LeafWasmOrgUploadCallHandle {
306
+ send(payload: Uint8Array): Promise<void>;
307
+ finish(): Promise<Uint8Array>;
308
+ cancel(): void;
309
+ }
310
+ /**
311
+ * A duplex call, as a raw handle: the sink verbs are inline (the
312
+ * caller-side sink has `finish_sending`/`cancel` and NO `retired` —
313
+ * it differs from the serve-side {@link LeafWasmOrgResponseSinkHandle},
314
+ * which has `close`/`retired` and no `finish_sending`).
315
+ */
316
+ export interface LeafWasmOrgDuplexCallHandle {
317
+ send(payload: Uint8Array): Promise<void>;
318
+ finish_sending(): Promise<void>;
319
+ cancel(): void;
320
+ stream(): LeafWasmOrgByteStreamHandle;
321
+ }
322
+ /** The response sink a streaming/duplex **handler** receives. */
323
+ export interface LeafWasmOrgResponseSinkHandle {
324
+ send(payload: Uint8Array): Promise<void>;
325
+ close(): Promise<void>;
326
+ /** Resolves with exactly one of the seven retire verdict strings. */
327
+ retired(): Promise<string>;
328
+ }
329
+ /** The request stream a client-streaming/duplex **handler** receives. */
330
+ export interface LeafWasmOrgRequestStreamHandle {
331
+ next(): Promise<LeafWasmOrgRequestItem>;
332
+ /** Resolves with exactly one of the seven retire verdict strings. */
333
+ retired(): Promise<string>;
334
+ }
335
+ /** One serve registration, as a raw handle. */
336
+ export interface LeafWasmOrgServeHandle {
337
+ service(): string;
338
+ /**
339
+ * Unregister AND retire: every live protected call this
340
+ * registration admitted is retired with its exact terminal, and new
341
+ * openings on the service are refused. NOT the public path's
342
+ * let-existing-calls-finish behavior.
343
+ */
344
+ close(): void;
345
+ }
346
+ /** The trampoline `serve_org` hands the leaf for one unary call. */
347
+ export type LeafWasmOrgUnaryHandler = (caller: LeafWasmOrgCaller, request: Uint8Array) => Promise<Uint8Array>;
348
+ /** The trampoline `serve_org_streaming` hands the leaf. */
349
+ export type LeafWasmOrgStreamingHandler = (caller: LeafWasmOrgCaller, request: Uint8Array, sink: LeafWasmOrgResponseSinkHandle) => Promise<void>;
350
+ /** The trampoline `serve_org_client_stream` hands the leaf. */
351
+ export type LeafWasmOrgClientStreamHandler = (caller: LeafWasmOrgCaller, requests: LeafWasmOrgRequestStreamHandle) => Promise<Uint8Array>;
352
+ /** The trampoline `serve_org_duplex` hands the leaf. */
353
+ export type LeafWasmOrgDuplexHandler = (caller: LeafWasmOrgCaller, requests: LeafWasmOrgRequestStreamHandle, sink: LeafWasmOrgResponseSinkHandle) => Promise<void>;
354
+ /** The node object `LeafNode.connect` resolves to. */
355
+ export interface LeafWasmNode {
356
+ node_id_hex(): string;
357
+ /** The anchor's node id, 16 lowercase hex digits. */
358
+ anchor_id_hex(): string;
359
+ /**
360
+ * This node's origin hash, 16 lowercase hex digits — the value its
361
+ * packet headers carry and the one a receiver checks an event
362
+ * payload's `EventMeta.origin_hash` against.
363
+ */
364
+ origin_hash_hex(): string;
365
+ /**
366
+ * Run the enrollment exchange. `connect` awaits it internally after
367
+ * the handshake; the explicit method exists so a caller can drive or
368
+ * observe the step. Until a leaf is enrolled the anchor keeps the
369
+ * peer provisional and §12 refuses everything above the transport.
370
+ */
371
+ enroll(): Promise<void>;
372
+ /**
373
+ * Whether the anchor has admitted this leaf. `false` means the
374
+ * session is still §12-provisional and every call will die on its
375
+ * deadline, which is a very different fact from a slow anchor.
376
+ */
377
+ is_enrolled(): boolean;
378
+ call(service: string, payload: Uint8Array, timeout_ms?: number): Promise<Uint8Array>;
379
+ call_org(service: string, payload: Uint8Array, options: LeafWasmOrgCallOptions): Promise<Uint8Array>;
380
+ call_org_streaming(service: string, payload: Uint8Array, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgByteStreamHandle>;
381
+ call_org_client_stream(service: string, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgUploadCallHandle>;
382
+ call_org_duplex(service: string, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgDuplexCallHandle>;
383
+ /**
384
+ * Serve the four shapes. The handler is invoked with `(caller,
385
+ * request[, requests][, sink])` per shape and returns a promise the
386
+ * leaf awaits; a rejection is the typed refusal text.
387
+ */
388
+ serve_org(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgUnaryHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
389
+ serve_org_streaming(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgStreamingHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
390
+ serve_org_client_stream(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgClientStreamHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
391
+ serve_org_duplex(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgDuplexHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
392
+ subscribe(channel: string): Promise<void>;
393
+ publish(channel: string, payload: Uint8Array): Promise<void>;
394
+ /**
395
+ * Open a stream on this node.
396
+ *
397
+ * **Throws on a closed node.** `Inner::admit` fences every
398
+ * outbound operation once `close()` (or a leadership retirement)
399
+ * has run, with the `LeafError::Session` Display
400
+ * `session: the node is closed: it no longer holds this origin's
401
+ * identity` — so the refusal arrives as a `SessionError` through
402
+ * `fromWasmError` rather than as a silent dead handle. Declared
403
+ * here because it is the contract `BrowserNode.openStream` relies
404
+ * on instead of adding a second fence of its own; the text is
405
+ * pinned against `leaf/src/wasm.rs` by
406
+ * `tests/abi_real_package.mjs`.
407
+ */
408
+ open_stream(options: LeafWasmStreamOptions): LeafWasmStream;
409
+ announce(capabilities: string[]): Promise<void>;
410
+ /**
411
+ * A JSON array of `{ node_id, entity_id, capabilities, rtc_addr,
412
+ * noise_pubkey, version }`.
413
+ */
414
+ query(capability: string): Promise<string>;
415
+ /**
416
+ * Sign and send a `0x0D02` signalling envelope to `peer` through the
417
+ * control plane — no session with `peer` needed.
418
+ *
419
+ * `dialog_hex` is the attempt's id, 16 lowercase hex digits — the
420
+ * same spelling {@link LeafWasmNode.peer_offer} resolves to and the
421
+ * `*_in` forms take. A number would not do: `DialogId` is a `u64`
422
+ * minted from the full CSPRNG range, and one carried through a JS
423
+ * number comes back rounded (`as f64 as u64`), so ~511 of every 512
424
+ * minted dialogs would name no attempt at all.
425
+ *
426
+ * Both id arguments cross as STRINGS, verbatim — {@link idArg} is
427
+ * the marshaling. A non-string is refused
428
+ * "is not a peer id" / "is not a dialog id" at the binding rather
429
+ * than coerced, and rather than reaching `wasm-bindgen`'s String
430
+ * marshaling at all: a JS number here corrupts `passStringToWasm0`
431
+ * (panicking `assert!(old_size > 0)` in `__wbindgen_realloc`) and
432
+ * kills the call before any parser runs — finding #52's
433
+ * engine-marshaling failure, on every peer spelling alike.
434
+ */
435
+ signal(peer_hex: string, dialog_hex: string, kind: string, payload: Uint8Array): Promise<void>;
436
+ /**
437
+ * Offer a direct browser ↔ browser connection to `peer` (plan §9
438
+ * steps 2–3). Resolves to the dialog id, 16 lowercase hex digits.
439
+ *
440
+ * Takes a peer id. The SDP is created, signed and sent inside the
441
+ * leaf; the relayed session it rides comes up first if it is not
442
+ * already there.
443
+ */
444
+ peer_offer(peer_hex: string): Promise<string>;
445
+ /**
446
+ * The live attempt's dialog when `peer` is already a healthy direct
447
+ * pair (session installed, no relay entry, transport open), else
448
+ * `undefined`. What makes `connectPeer` idempotent: a second offer
449
+ * would replace — and close — the working link.
450
+ */
451
+ peer_direct_dialog(peer_hex: string): string | undefined;
452
+ /**
453
+ * Answer the offer `peer` sent, from the **verified envelope** that
454
+ * arrived — not from anything the caller supplies. Resolves to the
455
+ * dialog id the offerer minted.
456
+ */
457
+ peer_accept_offer(peer_hex: string): Promise<string>;
458
+ /**
459
+ * Service `peer`'s attempt once: apply its answer, trickle local
460
+ * candidates as signed envelopes, apply the ones it sent, and
461
+ * evaluate the attempt's deadline.
462
+ *
463
+ * Resolves to JSON: `{"dialog","state","sent","applied","answered",
464
+ * "direct","remainingMs"}`, plus `"candidateError"` when the engine
465
+ * refused a trickled line. `state` is `gathering | open |
466
+ * iceTimeout | udpBlocked | failed`; `failed` is the attempt's
467
+ * terminal transition for a channel that opened and a session that
468
+ * never installed. `dialog` is the attempt CURRENTLY live for the
469
+ * peer, so a caller whose dialog id no longer matches was
470
+ * superseded.
471
+ */
472
+ peer_candidate(peer_hex: string): Promise<string>;
473
+ /**
474
+ * Run the Noise handshake with `peer` over the direct DataChannel
475
+ * (§9 step 4), in the offerer's role. Resolves to the dialog id it
476
+ * ran for, 16 lowercase hex digits.
477
+ *
478
+ * **A peer id and nothing else.** A page that could supply a Noise
479
+ * key could supply any key, so the peer's static key comes from its
480
+ * signature-verified announcement and the PSK from the credential.
481
+ *
482
+ * The resolved dialog is what makes a stale caller's success
483
+ * legible: it is the attempt the handshake actually ran for, not
484
+ * the one the caller was holding.
485
+ */
486
+ peer_handshake(peer_hex: string): Promise<string>;
487
+ /**
488
+ * {@link LeafWasmNode.peer_candidate}, for a caller that names the
489
+ * dialog it is driving.
490
+ *
491
+ * Refused when that dialog is not the live one, **before** the
492
+ * attempt is serviced — so a request issued for an attempt that has
493
+ * since been replaced cannot drive its replacement. The shared
494
+ * drive loop uses this form on both surfaces.
495
+ */
496
+ peer_candidate_in(peer_hex: string, dialog_hex: string): Promise<string>;
497
+ /**
498
+ * {@link LeafWasmNode.peer_handshake}, for a caller that names the
499
+ * dialog it is driving. Refused on a mismatch, before the Noise
500
+ * wait — the longest await on this surface, and the one whose
501
+ * session must belong to the attempt that negotiated the channel.
502
+ */
503
+ peer_handshake_in(peer_hex: string, dialog_hex: string): Promise<string>;
504
+ /** Every counter as JSON; `u64`s are decimal strings. */
505
+ counters_json(): string;
506
+ /**
507
+ * The RTC transport's `RtcStats` as JSON, in the NATIVE field
508
+ * names, plus a `not_applicable` object mapping each native field
509
+ * a leaf has no meaning for to the reason it has none.
510
+ */
511
+ rtc_stats_json(): string;
512
+ /**
513
+ * Install the `online` listener for the network-change re-attempt
514
+ * trigger. Idempotent; the ICE `disconnected` → `failed` watcher
515
+ * is already on every peer connection.
516
+ */
517
+ arm_network_retry(): void;
518
+ /** The re-attempt owner's ledger as JSON. */
519
+ retry_report(): string;
520
+ /** One JSON-string event per call. Registered once per node. */
521
+ on_event(callback: (eventJson: string) => void): void;
522
+ /**
523
+ * Close the node: every session, every channel, every pending
524
+ * call.
525
+ *
526
+ * After it, nothing is delivered and every outbound operation is
527
+ * refused — which is why `BrowserNode.close` closes the
528
+ * streams it handed out **before** calling this, rather than
529
+ * leaving their handles to be retired through a node that would
530
+ * only report the attempt as a failure.
531
+ */
532
+ close(): void;
533
+ }
534
+ /**
535
+ * The module `wasm-bindgen --target web` generates.
536
+ *
537
+ * `MeshSession` is typed as `unknown` here on purpose: §8's
538
+ * leader/follower boundary lives in `src/leader/wasm.ts`, which owns
539
+ * its shape. This file keeps only what the direct surface needs, so
540
+ * the two cannot drift into two spellings of one contract.
541
+ */
542
+ export interface LeafWasmModule {
543
+ /**
544
+ * The generated initialiser. Instantiates the `.wasm` next to the
545
+ * glue unless given a path or module.
546
+ */
547
+ default?: (init?: {
548
+ module_or_path: string | URL;
549
+ }) => Promise<unknown>;
550
+ LeafNode: {
551
+ connect(options: LeafWasmConnectOptions): Promise<LeafWasmNode>;
552
+ /**
553
+ * The ICE servers a `connect()` with these options would hand
554
+ * the `RTCPeerConnection`, as JSON:
555
+ * `[{"urls":["stun:host:3478"],"username":"u","credential":"c"}]`.
556
+ *
557
+ * Static and pure, so the ABI it reports can be asserted
558
+ * against the real built wasm without an anchor — which is the
559
+ * only reason the `RTCIceServer[]` drop went unnoticed. Throws
560
+ * the same typed error `connect()` would.
561
+ *
562
+ * Optional because {@link loadLeafWasm} will happily load a glue
563
+ * built before this existed; `tests/abi_real_package.mjs`
564
+ * asserts the shipped one has it.
565
+ */
566
+ effective_ice_servers?(options: LeafWasmConnectOptions): string;
567
+ /**
568
+ * The largest payload one packet carries: the wire's
569
+ * `MAX_EVENT_SIZE`, which is `MAX_PAYLOAD_SIZE` minus the event
570
+ * frame's 4-byte length prefix.
571
+ *
572
+ * An application that must keep a message inside one packet
573
+ * reads it from here rather than hardcoding a figure. The packet
574
+ * cap is **not** this number, and treating it as available data
575
+ * bytes overruns by the prefix.
576
+ *
577
+ * Optional for the same reason `effective_ice_servers` is: glue
578
+ * built before this existed still loads, and
579
+ * `tests/abi_real_package.mjs` asserts the shipped one has it.
580
+ */
581
+ maxEventBytes?(): number;
582
+ /**
583
+ * What an `open_stream()` with these options would ask the node
584
+ * for, as JSON: `{"reliability":"reliable","label":"app",
585
+ * "streamId":"0000000000000009","channelHash":7,
586
+ * "peer":"00366d403ce19dac"}`, `streamId` `null` when unpinned,
587
+ * `channelHash` `null` when absent, `peer` `null` when the
588
+ * stream addresses the anchor.
589
+ *
590
+ * The same reader `MeshSession.open_stream` uses, so one
591
+ * assertion covers the direct and the leader-proxied surface —
592
+ * which is also why `peer` appears here: the proxied surface
593
+ * refuses that option by name, and this is where a page can see
594
+ * what the leaf made of it.
595
+ *
596
+ * Optional for the same reason as the reader above.
597
+ */
598
+ effective_stream_options?(options: LeafWasmStreamOptions): string;
599
+ };
600
+ /**
601
+ * §8's surface, refined by `src/leader/wasm.ts`. Absent from a
602
+ * bundle built before Stage 5 slice 3.
603
+ */
604
+ MeshSession?: unknown;
605
+ }
606
+ /** Where the wasm comes from. */
607
+ export interface WasmSource {
608
+ /**
609
+ * An already-imported module. The escape hatch for bundlers, for
610
+ * tests, and for a page that wants to control instantiation.
611
+ */
612
+ wasm?: LeafWasmModule;
613
+ /**
614
+ * A specifier or URL to `import()`. Defaults to `./net_leaf.js`
615
+ * resolved against this module, i.e. the glue `npm run build`
616
+ * copies next to the entry point.
617
+ */
618
+ wasmModule?: string;
619
+ /** The `.wasm` to instantiate. Defaults to the glue's own sibling. */
620
+ wasmUrl?: string | URL;
621
+ }
622
+ /** Resolve and instantiate the leaf wasm described by `source`. */
623
+ export declare function loadLeafWasm(source?: WasmSource): Promise<LeafWasmModule>;
624
+ /**
625
+ * One id argument of {@link LeafWasmNode.signal} as it crosses the
626
+ * wasm seam: a string passes through VERBATIM, and anything else is
627
+ * refused by the parsers' own names before it can reach the boundary.
628
+ *
629
+ * Refused, never coerced, and either alternative is fatal. A JS
630
+ * number cannot carry a `u64` id losslessly (`as f64 as u64`
631
+ * re-spells 511 of every 512 minted dialogs) — and a non-string must
632
+ * never reach `wasm-bindgen`'s String marshaling at all: it corrupts
633
+ * there, panicking `assert!(old_size > 0)` inside
634
+ * `passStringToWasm0`'s `__wbindgen_realloc`, and the call dies
635
+ * before `parse_peer_id` runs (finding #52's repro, on every peer
636
+ * spelling alike). The refusal carries the parser's name — "is not a
637
+ * peer id" / "is not a dialog id", as `name` picks — so a page that
638
+ * classifies a refusal by its text reads this one as the refusal it
639
+ * is. Peer before dialog at the call sites, the order
640
+ * `LeafNode::signal` parses in.
641
+ */
642
+ export declare function idArg(value: unknown, name: 'peer' | 'dialog'): string;