@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
@@ -0,0 +1,616 @@
1
+ /**
2
+ * Owner dispatch: join, admission, `authorize`, projection, `man`
3
+ * (brief §1.3, §1.5, §1.12, §2) — slice C.
4
+ *
5
+ * ## The authenticated origin is an argument, never a field
6
+ *
7
+ * {@link StoreOwner.receive} takes the **authenticated originating
8
+ * peer** as a parameter, and there is no way to name a caller inside a
9
+ * store frame at all (§2's shapes have no originator field). That is
10
+ * the whole of §1.3's rule expressed as a signature: the identity comes
11
+ * from the session the bytes arrived on, which the transport
12
+ * authenticated — `LeafEvent::StreamData.peer_node` on the Rust side,
13
+ * `LeafStream.peerNode` in the package — and a dispatcher cannot read
14
+ * it off the payload because the payload does not carry one.
15
+ *
16
+ * A caller could still *lie to this function*, so the contract is
17
+ * stated where it is enforceable: whoever calls `receive` must pass the
18
+ * peer the transport proved, and the store's own entry points will
19
+ * (slice G). Nothing here can make a wrong argument right, and
20
+ * pretending otherwise is the mistake this module refuses to make.
21
+ *
22
+ * ## What is here, and what is deliberately not
23
+ *
24
+ * Here: `join` admission, handle binding and re-checking, `authorize`
25
+ * for the read request, the audience projection, and the `man` + `snap`
26
+ * emission that follows. Refusals for the paths that reach those.
27
+ *
28
+ * Not here: `act`/`in`/`res` and the ledger (slice E), `aud`/`resume`
29
+ * transitions (slice F), `delta` emission (slice D). Those kinds are
30
+ * refused `not-ready` or `invalid-data` rather than half-implemented,
31
+ * and the refusal says which layer owns them.
32
+ */
33
+ import { Assembly, AssemblyTable } from './assembly.js';
34
+ import type { JsonValue } from './json.js';
35
+ import { type Outcome } from './ledger.js';
36
+ import type { AccessRequest, ActionContext, Cancel, ActionSpec, InputSpec, Parse, StoreDefinition } from './types.js';
37
+ import { type Hex } from './wire.js';
38
+ /** Actions in flight per owner, against the pending bound (§2). */
39
+ export declare const MAX_PENDING_ACTIONS = 32;
40
+ /** Handles one owner will hold (brief §2). */
41
+ export declare const MAX_HANDLES = 256;
42
+ /** How long a handle lives without an accepted authenticated message. */
43
+ export declare const HANDLE_LEASE_MS = 60000;
44
+ /** What the owner needs from its host. */
45
+ export interface OwnerDeps<S extends object, A extends ActionSpec, I extends InputSpec> {
46
+ readonly definition: StoreDefinition<S, A, I>;
47
+ /**
48
+ * WHICH store of this definition this owner is — the address a
49
+ * joiner names in `join.store`.
50
+ *
51
+ * A node may host several stores of one definition (a lobby and a
52
+ * match; three worlds in a harness), every host store on that node
53
+ * receives every frame, and a `join` names no handle. So without
54
+ * this, the store that answers a join is whichever listener
55
+ * happened to be registered first — and a caller asking for B got
56
+ * A's document, A's handle and A's state mutated by its actions.
57
+ * Found by review: two COLD stores, join the second, and the first
58
+ * answers.
59
+ */
60
+ readonly store: string;
61
+ /**
62
+ * The owner's policy. Receives the **authenticated** caller, because
63
+ * that is the only identity this module will ever hand it.
64
+ */
65
+ authorize(request: AccessRequest<A, I>): boolean;
66
+ /**
67
+ * The audience projection: what this caller may see. Returning the
68
+ * whole state is a decision, not a default — `empty()` is what
69
+ * absence looks like.
70
+ *
71
+ * Computed once per DISTINCT audience and shared by every handle
72
+ * carrying it. Exactly one of `project` and {@link projectFor} is
73
+ * given.
74
+ */
75
+ project?(state: S, audience: readonly string[]): S;
76
+ /**
77
+ * The per-player projection: what THIS player may see — their own
78
+ * hand, their own fog of war. Handed the authenticated peer with the
79
+ * audience it reads.
80
+ *
81
+ * Computed once per distinct (peer, audience) pair, so its cost per
82
+ * change grows with the number of players, where `project`'s grows
83
+ * with the number of distinct audiences. That is inherent: a view
84
+ * that depends on who is looking has to be taken for each of them.
85
+ */
86
+ projectFor?(state: S, viewer: Viewer): S;
87
+ /**
88
+ * The one hook for things that happen to players: `join`, `leave`,
89
+ * `area`. Runs on the host as a transaction with the player as
90
+ * `context.peer`, exactly like an action handler — so it can
91
+ * `setState` (a starting inventory on join) — and its changes reach
92
+ * every replica. Synchronous; a throw discards its writes.
93
+ */
94
+ onEvent?(event: StoreEvent, context: ActionContext<S>): void;
95
+ /**
96
+ * Development warnings: a store that sends everything to everyone
97
+ * without saying so, a projection the state validator refuses. Off
98
+ * unless given; never on by default in production.
99
+ */
100
+ warn?(message: string): void;
101
+ /**
102
+ * Which area a player is in, for `area` events: any string (a zone,
103
+ * a room, a grid cell), or `null` for none. Read-only; called after
104
+ * changes, for each present player.
105
+ */
106
+ areaOf?(state: S, peer: string): string | null;
107
+ /** The admissible frame size, derived from the transport (§1.9). */
108
+ readonly maxEventBytes: number;
109
+ /** Monotone clock, milliseconds. */
110
+ now(): number;
111
+ /** 32 lowercase hex. Unguessable: a handle is a capability. */
112
+ newHandle(): Hex;
113
+ /** 16 lowercase hex, one per owner incarnation. */
114
+ newIncarnation(): Hex;
115
+ /**
116
+ * Whether a projection can be taken right now.
117
+ *
118
+ * A host that is mid-frame, or whose world is being rebuilt, answers
119
+ * `false` and the control is DEFERRED rather than refused (§1.8) — a
120
+ * control is never answered `not-ready`.
121
+ */
122
+ canProject(): boolean;
123
+ /**
124
+ * The action handlers, one per declared action.
125
+ *
126
+ * Each runs inside ONE synchronous transaction: it stages writes
127
+ * through its context and returns the output, or throws to reject.
128
+ * A throw is an `action-rejected` outcome that is RETAINED (§1.10),
129
+ * not an absent one.
130
+ */
131
+ readonly actions: ActionHandlers<S, A>;
132
+ /** The latest-value input handlers. Fire-and-forget, no reply. */
133
+ readonly inputs: InputHandlers<S, I>;
134
+ }
135
+ /** Why a player left, as `onEvent` hears it. */
136
+ export type LeaveReason =
137
+ /** The player closed their handle. */
138
+ 'left'
139
+ /** Its lease ran out: a closed tab, a lost connection. */
140
+ | 'expired'
141
+ /** `authorize` stopped granting its read: a kick, a revoked permission. */
142
+ | 'refused'
143
+ /** Its view could not be delivered (too large, or `project` failed). */
144
+ | 'dropped';
145
+ /**
146
+ * What happened to a player, for the host's single `onEvent` hook.
147
+ *
148
+ * - `join`: a player arrived — their first subscription, or the host's
149
+ * own player (`hostPlayer`). Per player, not per connection.
150
+ * - `leave`: their last subscription ended, and why.
151
+ * - `area`: `areaOf(state, peer)` gave a different answer than it last
152
+ * did for them (`from` is `null` the first time).
153
+ */
154
+ export type StoreEvent = {
155
+ readonly type: 'join';
156
+ readonly peer: string;
157
+ readonly audience: readonly string[];
158
+ } | {
159
+ readonly type: 'leave';
160
+ readonly peer: string;
161
+ readonly reason: LeaveReason;
162
+ } | {
163
+ readonly type: 'area';
164
+ readonly peer: string;
165
+ readonly from: string | null;
166
+ readonly to: string | null;
167
+ };
168
+ /** How many hook runs one drain may perform before it stops (see `drainEvents`). */
169
+ export declare const MAX_EVENT_ROUNDS = 256;
170
+ /** Who a per-player projection is for. */
171
+ export interface Viewer {
172
+ /** The authenticated peer, 16 lowercase hex — as `context.peer`. */
173
+ readonly peer: string;
174
+ /** The audience this handle reads. */
175
+ readonly audience: readonly string[];
176
+ }
177
+ /** One handler per declared action. */
178
+ export type ActionHandlers<S extends object, A extends ActionSpec> = {
179
+ readonly [K in keyof A]: (input: A[K]['input'], context: ActionContext<S>) => A[K]['output'];
180
+ };
181
+ /** One handler per declared input. */
182
+ export type InputHandlers<S extends object, I extends InputSpec> = {
183
+ readonly [K in keyof I]: (input: I[K], context: ActionContext<S>) => void;
184
+ };
185
+ /** One admitted subscription. */
186
+ export interface OwnerHandle {
187
+ readonly h: Hex;
188
+ readonly inc: Hex;
189
+ /** The authenticated peer this handle is bound to (§1.3). */
190
+ readonly peer: string;
191
+ readonly audience: readonly string[];
192
+ /** Highest generation allocated for this handle; monotone (§1.7a). */
193
+ readonly generation: number;
194
+ /**
195
+ * The revision this replica's view is at: its installation's, then
196
+ * each delta's `r`. A delta's `base` is THIS, not the owner's previous
197
+ * revision — a replica whose view did not change on a commit was sent
198
+ * nothing and is still here, and a `base` it never had is a gap.
199
+ */
200
+ readonly revision: number;
201
+ /** Its interest set; `null` when it declared none (sees every entity). */
202
+ readonly interest: readonly string[] | null;
203
+ /** Last accepted authenticated message, for the lease. */
204
+ readonly lastSeen: number;
205
+ }
206
+ /** A frame the owner wants sent, and to whom. */
207
+ export interface Outbound {
208
+ readonly peer: string;
209
+ readonly h: Hex | null;
210
+ readonly frame: string;
211
+ }
212
+ /** What one inbound frame produced. */
213
+ export interface Dispatched {
214
+ readonly out: readonly Outbound[];
215
+ /** A stable, countable refusal reason, when the frame was refused. */
216
+ readonly refused: string | null;
217
+ /**
218
+ * The rest of an action whose request binding needed a digest.
219
+ *
220
+ * §1.10 puts one `await` in the ledger path, for inputs too large to
221
+ * retain verbatim. Rather than make every join and `alive` async to
222
+ * serve that one case, the synchronous answer comes back immediately
223
+ * and the remainder is handed over explicitly. A transport sends
224
+ * `out`, then sends the deferred result's `out` when it settles.
225
+ *
226
+ * `null` on every other path, which is all of them but one.
227
+ */
228
+ readonly deferred: Promise<Dispatched> | null;
229
+ }
230
+ interface Counters {
231
+ [reason: string]: number;
232
+ }
233
+ /**
234
+ * The owner half of the store protocol.
235
+ *
236
+ * Holds no transport: frames come in as text with an authenticated
237
+ * peer, and go out as text addressed to a peer. That is what lets the
238
+ * whole of slice C be exercised without a network.
239
+ */
240
+ export declare class StoreOwner<S extends object, A extends ActionSpec, I extends InputSpec> {
241
+ #private;
242
+ private readonly deps;
243
+ private readonly handles;
244
+ private readonly counters;
245
+ private readonly chunkBytes;
246
+ private readonly incarnation;
247
+ /**
248
+ * The authoritative document.
249
+ *
250
+ * The owner's state IS a store: one place that validates, reconciles,
251
+ * counts revisions and runs a handler's synchronous transaction.
252
+ * Keeping a second copy beside it would give handler writes and
253
+ * `commit` two truths to disagree about.
254
+ */
255
+ private readonly core;
256
+ /** Digest computations in flight, against the pending bound (§2). */
257
+ private pending;
258
+ private readonly ledgers;
259
+ /**
260
+ * One pending projection per handle (§1.8).
261
+ *
262
+ * A newer control REPLACES the pending one rather than queueing
263
+ * behind it, which is what keeps this a bound rather than a buffer.
264
+ */
265
+ private readonly deferred;
266
+ /** The revision every installed view is at, before the commit. */
267
+ private revisionBeforeCommit;
268
+ constructor(deps: OwnerDeps<S, A, I>);
269
+ /** Whether projections depend on the peer (`projectFor`, or an `owner` rule). */
270
+ private readonly perPlayer;
271
+ /** The definition's declared rules, compiled; `null` when it declares none. */
272
+ private readonly visibility;
273
+ /** Development warnings already given, so each is said once. */
274
+ private readonly warned;
275
+ private warnOnce;
276
+ /** The key under which two handles are certain to receive the same projection. */
277
+ private viewKey;
278
+ /**
279
+ * Views whose change was projected from the changed entities alone
280
+ * (`sparseInterestDiff`). Not a refusal, so not in {@link snapshotCounters}.
281
+ */
282
+ get sparseViews(): number;
283
+ private sparseViewCount;
284
+ /** Counters a host can report. Every refusal moves exactly one. */
285
+ snapshotCounters(): Readonly<Counters>;
286
+ /** Live handles, for a host's own bounds reporting. */
287
+ get handleCount(): number;
288
+ /** The handle record, for a test or a host's introspection. */
289
+ handle(h: Hex): OwnerHandle | undefined;
290
+ /**
291
+ * Replace the authoritative state, as `setState` does.
292
+ *
293
+ * Inside an open transaction the write JOINS it (`applySnapshot`
294
+ * stages) and the delta emission is DEFERRED to that transaction's
295
+ * commit (#5): `decide`/`input` diff the committed before/after at
296
+ * the transaction's end and ship exactly one delta, and a rollback
297
+ * ships nothing at all. Emitting here would put a staged-world
298
+ * delta on the wire that no rollback retracts.
299
+ */
300
+ commit(next: S): Dispatched;
301
+ /**
302
+ * Write entities of one declared collection, as `setEntities` does:
303
+ * each changed entity validated by its per-entity parser, no
304
+ * whole-document validation. Same transaction and delta rules as
305
+ * {@link commit}.
306
+ */
307
+ commitEntities(collection: string, changes: Readonly<Record<string, unknown>>): Dispatched;
308
+ /**
309
+ * Tell every installed handle what changed (§1.9).
310
+ *
311
+ * Per audience, because a delta of the raw state would ship what a
312
+ * projection exists to withhold: the previous and current
313
+ * projections are both taken and the difference between THOSE is
314
+ * what goes out. The previous one is recomputed from the previous
315
+ * state rather than retained per handle — one projection can be a
316
+ * megabyte, and keeping one per handle is 256 of them.
317
+ *
318
+ * When a delta would not fit the message budget the owner allocates
319
+ * a new generation instead and sends a manifest: an owner-initiated
320
+ * replacement, admissible at a `ready` replica (§1.8).
321
+ */
322
+ private propagate;
323
+ /** The authoritative document, for a host's own reads. */
324
+ getState(): S;
325
+ /**
326
+ * Subscribe to the authoritative document.
327
+ *
328
+ * The owner's own code watches the state it serves — a host renders
329
+ * from this, and an action's commit is the same revision its
330
+ * subscribers see.
331
+ */
332
+ subscribe(listener: (state: S, previous: S) => void): Cancel;
333
+ /** The current authoritative revision. */
334
+ get currentRevision(): number;
335
+ /**
336
+ * The host's own player: whether `peer` may read `audience`.
337
+ *
338
+ * The same `authorize` call a `join` makes. There is no handle, no
339
+ * lease and no ledger — the host's player has no wire to lose a
340
+ * frame on and no request to replay — but there is the policy.
341
+ */
342
+ localRead(peer: string, audience: readonly string[]): boolean;
343
+ /** The host's own player: the projection a replica of `audience` receives. */
344
+ localView(peer: string, audience: readonly string[], interest?: readonly string[] | null): S | null;
345
+ /**
346
+ * The host's own player: one action, through the ladder a replica's
347
+ * `act` takes after the wire — known name, `authorize`, then one
348
+ * transaction that parses the input, runs the handler and validates
349
+ * the output, and a result that must fit the message budget a
350
+ * replica would have received it in.
351
+ *
352
+ * `input` is what `parseStoreJson` produced from the caller's value,
353
+ * so the handler sees exactly what it would see from a replica.
354
+ */
355
+ localAct(name: string, input: JsonValue, peer: string): {
356
+ readonly outcome: Outcome;
357
+ readonly dispatched: Dispatched;
358
+ };
359
+ /**
360
+ * The host's own player: one latest-value input, through the same
361
+ * ladder as a replica's `in` after the wire. No sequence: a local
362
+ * call cannot arrive out of order.
363
+ */
364
+ localInput(name: string, input: JsonValue, peer: string): Dispatched;
365
+ /**
366
+ * Dispatch one inbound frame.
367
+ *
368
+ * `peer` is the **authenticated** originating caller — see the module
369
+ * note. It is not read from `frame`, and no frame can carry one.
370
+ */
371
+ receive(frame: string, peer: string, now?: number): Dispatched;
372
+ /**
373
+ * One action (§1.10).
374
+ *
375
+ * The ladder: gameplay readiness, then the sequence, then the
376
+ * ledger's disposition, then — only for a genuinely new request —
377
+ * `authorize` and one synchronous transaction.
378
+ *
379
+ * The digest path is the one place this module awaits. Everything
380
+ * decided before the await is discarded and decided again after it:
381
+ * the handle may have expired, the policy may have been revoked, and
382
+ * the ledger may have retained this very sequence while the digest
383
+ * was computing.
384
+ */
385
+ private action;
386
+ /**
387
+ * The ledger's decision, and the execution it may authorize.
388
+ *
389
+ * Synchronous from here on: no `await` may appear below this line,
390
+ * because the transaction it enters is synchronous by construction
391
+ * and a permission checked before a wait can have been revoked
392
+ * during it.
393
+ */
394
+ private decide;
395
+ /** One latest-value input (§1.11). Fire and forget: no reply, ever. */
396
+ private input;
397
+ /** A `res` for a result, a `no` for a retained refusal. */
398
+ private reply;
399
+ private permitsAction;
400
+ private permitsInput;
401
+ /** The lease is renewed by an accepted message, refusals excepted. */
402
+ private renew;
403
+ /**
404
+ * Everything that belongs to one handle, gone together.
405
+ *
406
+ * §2: the ledger goes with the handle. That is what makes a replay
407
+ * after eviction `closed` rather than `result-expired` — the owner
408
+ * no longer knows the sequence existed — and it is what keeps the
409
+ * ledger table bounded by live handles instead of by the owner's
410
+ * lifetime.
411
+ */
412
+ private forget;
413
+ /** Peers present as players: a handle installed, or a local player. */
414
+ private readonly present;
415
+ private readonly localPlayers;
416
+ private readonly pendingEvents;
417
+ private readonly areas;
418
+ private areasAt;
419
+ /** Set by `farewell`: a closing store raises no more events. */
420
+ private ending;
421
+ private get wantsEvents();
422
+ private isPresent;
423
+ /** Queue `join` / `leave` when a peer's presence actually flips. */
424
+ private presenceChanged;
425
+ /**
426
+ * The host's own player arriving or going (`hostPlayer`). It has no
427
+ * handle, but it is a player: `onEvent` hears it like any other.
428
+ */
429
+ localPresence(peer: string, joined: boolean, audience?: readonly string[], reason?: LeaveReason): void;
430
+ /** Queue `area` events for present players whose area moved. */
431
+ private detectAreas;
432
+ /**
433
+ * Run `onEvent` for everything queued, each as its own transaction,
434
+ * and return what those transactions changed for the replicas.
435
+ *
436
+ * Called by the host AFTER the frame that caused the events has been
437
+ * dispatched — never inside it — so a hook never runs in the middle
438
+ * of a projection pass. A hook that throws discards its writes, as a
439
+ * handler's do, and is counted. A hook whose writes cause more events
440
+ * (a teleport on join) is served in the same drain, up to a bound, so
441
+ * two hooks cannot ping-pong forever.
442
+ */
443
+ drainEvents(): Dispatched;
444
+ /** Listeners told when the set of installed handles changes. */
445
+ private readonly membership;
446
+ private membershipChanged;
447
+ /**
448
+ * Be told when a handle is installed or forgotten — join, leave,
449
+ * expiry, a policy refusal, closure. Synchronous, inside the frame
450
+ * that caused it: a listener reads {@link peers} and must not call
451
+ * back into the owner.
452
+ */
453
+ onMembership(listener: () => void): Cancel;
454
+ /** The distinct authenticated peers with an installed handle. */
455
+ peers(): readonly string[];
456
+ /**
457
+ * Re-ask `authorize` for every installed read, now.
458
+ *
459
+ * The delta feed re-authorizes before shipping, but only when there
460
+ * is a change to ship: a policy that revokes a peer (a kick) would
461
+ * otherwise leave it subscribed until the next commit. A refused
462
+ * handle is forgotten with the same unsolicited `closed` the feed
463
+ * sends, so the replica rejoins and its join is answered
464
+ * `forbidden`.
465
+ */
466
+ reauthorize(): Dispatched;
467
+ /**
468
+ * Emit the projections that were deferred, now that one can be
469
+ * taken.
470
+ *
471
+ * Completion **revalidates**: a handle can die between the deferral
472
+ * and the availability, and an expired one never acquires a pending
473
+ * projection in the first place (§1.8).
474
+ */
475
+ resumeDeferred(now?: number): Dispatched;
476
+ /** Projections waiting on availability, for a host's bounds report. */
477
+ get deferredCount(): number;
478
+ /** Ledgers held, for a host's own bounds reporting (§2). */
479
+ get ledgerCount(): number;
480
+ /** An accepted frame's reply. */
481
+ private accept;
482
+ /**
483
+ * Expire handles whose lease has run out (§2).
484
+ *
485
+ * Reports the PEER with the handle, because §1.6's expiry notice is
486
+ * addressed to a caller and the handle is gone by the time anyone
487
+ * could look it up. A host that cannot reach that peer sends
488
+ * nothing; no tombstone is retained to announce later.
489
+ */
490
+ sweep(now: number): readonly {
491
+ readonly h: Hex;
492
+ readonly peer: string;
493
+ }[];
494
+ /**
495
+ * Say goodbye, once, to every replica this owner is serving.
496
+ *
497
+ * §1.6's doctrine is that a caller learns why rather than inferring
498
+ * it from silence, and it was applied to EXPIRY (`sweep`) and not
499
+ * to closure: a host that closed took its answer with it, so every
500
+ * bound replica's next write reached a store that no longer
501
+ * existed and the caller's only signal was a deadline — the
502
+ * `indeterminate` "the store did not answer before the deadline",
503
+ * measured over the real transport.
504
+ *
505
+ * The code is `owner-lost`, not `closed`, and the difference is
506
+ * the whole semantics: `closed` is the expiry notice and the
507
+ * replica REJOINS on it, which after a close would either hang or
508
+ * silently attach the caller to a SUCCESSOR's different document
509
+ * under the same handle. `owner-lost` is terminal — this
510
+ * incarnation held the document and is gone — so the replica's
511
+ * view is cleared, `ready()` rejects, and rejoining is the
512
+ * caller's decision to make explicitly.
513
+ *
514
+ * Every handle is forgotten here, so the frames are a one-shot:
515
+ * a second call has nothing to say.
516
+ */
517
+ farewell(): readonly Outbound[];
518
+ /** This owner's incarnation, which every manifest carries. */
519
+ get incarnationHex(): Hex;
520
+ /**
521
+ * Admit a join.
522
+ *
523
+ * Order matters and is the ladder's: **the store address first**,
524
+ * because it decides whether this owner may answer at all; then
525
+ * definition identity and version, which are loud for the store
526
+ * they ARE addressed to; then capacity, `authorize`, and only then
527
+ * a handle. Nothing is allocated before the policy has ruled, so a
528
+ * refused caller costs one counter and no state.
529
+ *
530
+ * This summary is written out in full because it was wrong for one
531
+ * commit — it still listed the definition first, ten lines above
532
+ * the code that had just been reordered, in the rung whose
533
+ * position was the point of the change.
534
+ */
535
+ private join;
536
+ /**
537
+ * Allocate the next generation and emit `man` + every `snap`.
538
+ *
539
+ * Returns `null` when the projection cannot be carried, so the caller
540
+ * decides what to do with the handle rather than this function
541
+ * guessing.
542
+ */
543
+ private install;
544
+ /**
545
+ * One read decision, for the join and for every later read.
546
+ *
547
+ * A throwing policy is a refusal, never an admission.
548
+ */
549
+ private permitsRead;
550
+ /** A handle from the application's allocator, or null if it threw. */
551
+ private newHandle;
552
+ /** The definition's interest collections and their key functions. */
553
+ private get interestFns();
554
+ /** An entity's interest key; a key function that throws or returns a non-string means "no key": always delivered. */
555
+ private interestKey;
556
+ /** A view narrowed to the entities an interest set covers. */
557
+ private filterInterest;
558
+ /**
559
+ * The commit's raw entity change, or `null` when this commit cannot be
560
+ * projected entity by entity.
561
+ *
562
+ * It can when the host projects only by DECLARED rules (no `project` /
563
+ * `projectFor`, which see the whole document), and every root key the
564
+ * commit changed is a collection declared in both `interest` and
565
+ * `entities`, and is an entity map on both sides. Declared rules are
566
+ * path patterns, so an entity's visibility is the same in a document
567
+ * holding only the changed entities; and `entities` is the contract that
568
+ * an entity is valid on its own, so its projection is validated by the
569
+ * per-entity parser instead of `state` over the whole view.
570
+ */
571
+ private entityDelta;
572
+ /**
573
+ * One view's change from the changed entities alone: O(changed) per
574
+ * view instead of two whole-world projections, a whole-view validation
575
+ * and a scan of every id. Returns `undefined` for anything it cannot
576
+ * answer exactly as `interestDiff` over full projections would (a rule
577
+ * hiding a whole collection, a projected entity its parser refuses),
578
+ * and the caller takes the full path.
579
+ */
580
+ private sparseInterestDiff;
581
+ /** One view's change, split for interest: the rest of the document, and per-entity changes with their keys. */
582
+ private interestDiff;
583
+ /** The ops one handle receives for a split diff. */
584
+ private interestOps;
585
+ /**
586
+ * A new interest set: the entities entering it arrive, the ones leaving
587
+ * go, in one delta — the view never blanks — and then `ok`.
588
+ *
589
+ * Interest is a filter, not a permission: nothing here asks `authorize`,
590
+ * because the audience (which is) is unchanged and every entity sent
591
+ * was already readable under it.
592
+ */
593
+ private interestChange;
594
+ /**
595
+ * The audience projection, validated by the definition.
596
+ *
597
+ * A projection that does not satisfy `state()` is the owner's bug and
598
+ * must not be shipped as a snapshot, so it becomes `empty()` — the
599
+ * value that represents absence — rather than the full state.
600
+ */
601
+ private project;
602
+ /**
603
+ * Re-check the binding for every message (§1.3).
604
+ *
605
+ * Returns a countable reason instead of a handle when the handle is
606
+ * unknown, expired, or bound to a different authenticated peer — and
607
+ * the three are **one** refusal on the wire, so a refusal cannot
608
+ * disclose that a handle exists (§2).
609
+ */
610
+ private bind;
611
+ private no;
612
+ private refuse;
613
+ }
614
+ /** Re-exported so a host can hold assemblies without another import. */
615
+ export { Assembly, AssemblyTable };
616
+ export type { Parse };