@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,50 @@
1
+ /**
2
+ * The store's JSON parser: step 2 of the frozen ladder (brief §1.12).
3
+ *
4
+ * `JSON.parse` cannot implement that step. It accepts duplicate keys
5
+ * and silently keeps the last one, it has no depth bound, and — the one
6
+ * that matters most — `JSON.parse('1e999')` returns `Infinity`, so
7
+ * "numbers finite" is not a property it gives you. A protocol that
8
+ * digests or compares values cannot have two spellings of one value,
9
+ * and it cannot have a value that is not a number.
10
+ *
11
+ * So the ladder's second rung is a real parser:
12
+ *
13
+ * - depth ≤ {@link MAX_JSON_DEPTH}, counting objects and arrays;
14
+ * - **duplicate keys refused**, not resolved;
15
+ * - every number finite, and spelled by the JSON grammar (no `NaN`,
16
+ * `Infinity`, `+1`, `.5`, `1.`, `01`, or hex);
17
+ * - objects built with **null prototypes**, so no parsed document can
18
+ * introduce a `__proto__` key that later traversal would follow;
19
+ * - trailing content refused.
20
+ *
21
+ * It returns a refusal rather than throwing: the caller counts it and
22
+ * answers `invalid-data`, and no mutation has happened by then.
23
+ */
24
+ /** Depth bound for a store message (brief §1.12). */
25
+ export declare const MAX_JSON_DEPTH = 16;
26
+ /** A parsed JSON document. Objects have null prototypes. */
27
+ export type JsonValue = null | boolean | number | string | JsonValue[] | JsonObject;
28
+ /** A parsed JSON object: own properties only, no prototype. */
29
+ export interface JsonObject {
30
+ [key: string]: JsonValue;
31
+ }
32
+ /** Why a document was refused, and where. */
33
+ export interface JsonFailure {
34
+ readonly ok: false;
35
+ readonly reason: JsonRefusal;
36
+ /** Byte offset into the text, for the counter's detail. */
37
+ readonly at: number;
38
+ }
39
+ export type JsonRefusal = 'empty' | 'unexpected-token' | 'unexpected-end' | 'trailing-content' | 'depth-exceeded' | 'duplicate-key' | 'number-not-finite' | 'number-grammar' | 'string-control-char' | 'string-escape' | 'literal';
40
+ export type JsonResult = {
41
+ readonly ok: true;
42
+ readonly value: JsonValue;
43
+ } | JsonFailure;
44
+ /**
45
+ * Parse one JSON document under the store's rules.
46
+ *
47
+ * The bounds are checked while scanning, not afterwards, so a depth
48
+ * bomb costs its prefix and nothing more.
49
+ */
50
+ export declare function parseStoreJson(text: string): JsonResult;
@@ -0,0 +1,283 @@
1
+ /**
2
+ * The store's JSON parser: step 2 of the frozen ladder (brief §1.12).
3
+ *
4
+ * `JSON.parse` cannot implement that step. It accepts duplicate keys
5
+ * and silently keeps the last one, it has no depth bound, and — the one
6
+ * that matters most — `JSON.parse('1e999')` returns `Infinity`, so
7
+ * "numbers finite" is not a property it gives you. A protocol that
8
+ * digests or compares values cannot have two spellings of one value,
9
+ * and it cannot have a value that is not a number.
10
+ *
11
+ * So the ladder's second rung is a real parser:
12
+ *
13
+ * - depth ≤ {@link MAX_JSON_DEPTH}, counting objects and arrays;
14
+ * - **duplicate keys refused**, not resolved;
15
+ * - every number finite, and spelled by the JSON grammar (no `NaN`,
16
+ * `Infinity`, `+1`, `.5`, `1.`, `01`, or hex);
17
+ * - objects built with **null prototypes**, so no parsed document can
18
+ * introduce a `__proto__` key that later traversal would follow;
19
+ * - trailing content refused.
20
+ *
21
+ * It returns a refusal rather than throwing: the caller counts it and
22
+ * answers `invalid-data`, and no mutation has happened by then.
23
+ */
24
+ /** Depth bound for a store message (brief §1.12). */
25
+ export const MAX_JSON_DEPTH = 16;
26
+ class Refused extends Error {
27
+ reason;
28
+ at;
29
+ constructor(reason, at) {
30
+ super(reason);
31
+ this.reason = reason;
32
+ this.at = at;
33
+ }
34
+ }
35
+ /**
36
+ * Parse one JSON document under the store's rules.
37
+ *
38
+ * The bounds are checked while scanning, not afterwards, so a depth
39
+ * bomb costs its prefix and nothing more.
40
+ */
41
+ export function parseStoreJson(text) {
42
+ const parser = new Parser(text);
43
+ try {
44
+ const value = parser.document();
45
+ return { ok: true, value };
46
+ }
47
+ catch (error) {
48
+ if (error instanceof Refused) {
49
+ return { ok: false, reason: error.reason, at: error.at };
50
+ }
51
+ throw error;
52
+ }
53
+ }
54
+ class Parser {
55
+ src;
56
+ i = 0;
57
+ constructor(src) {
58
+ this.src = src;
59
+ }
60
+ document() {
61
+ this.skipWhitespace();
62
+ if (this.i >= this.src.length)
63
+ throw new Refused('empty', this.i);
64
+ const value = this.value(0);
65
+ this.skipWhitespace();
66
+ if (this.i !== this.src.length)
67
+ throw new Refused('trailing-content', this.i);
68
+ return value;
69
+ }
70
+ value(depth) {
71
+ const c = this.src.charCodeAt(this.i);
72
+ switch (c) {
73
+ case 123 /* Code.OpenBrace */:
74
+ return this.object(depth + 1);
75
+ case 91 /* Code.OpenBracket */:
76
+ return this.array(depth + 1);
77
+ case 34 /* Code.Quote */:
78
+ return this.string();
79
+ default:
80
+ break;
81
+ }
82
+ if (c === 45 /* Code.Minus */ || (c >= 48 /* Code.Zero */ && c <= 57 /* Code.Nine */))
83
+ return this.number();
84
+ if (this.src.startsWith('true', this.i)) {
85
+ this.i += 4;
86
+ return true;
87
+ }
88
+ if (this.src.startsWith('false', this.i)) {
89
+ this.i += 5;
90
+ return false;
91
+ }
92
+ if (this.src.startsWith('null', this.i)) {
93
+ this.i += 4;
94
+ return null;
95
+ }
96
+ // `NaN`, `Infinity`, `-Infinity` and `undefined` all land here: they
97
+ // are not JSON, and accepting them is how a non-finite number gets
98
+ // in without going through the number grammar.
99
+ throw new Refused(Number.isNaN(c) ? 'unexpected-end' : 'literal', this.i);
100
+ }
101
+ object(depth) {
102
+ if (depth > MAX_JSON_DEPTH)
103
+ throw new Refused('depth-exceeded', this.i);
104
+ this.i += 1; // '{'
105
+ const out = Object.create(null);
106
+ this.skipWhitespace();
107
+ if (this.peek() === 125 /* Code.CloseBrace */) {
108
+ this.i += 1;
109
+ return out;
110
+ }
111
+ for (;;) {
112
+ this.skipWhitespace();
113
+ if (this.peek() !== 34 /* Code.Quote */)
114
+ throw new Refused('unexpected-token', this.i);
115
+ const at = this.i;
116
+ const key = this.string();
117
+ // Own-property lookup: a document containing `__proto__` must be
118
+ // refused as a duplicate only if it really repeats, never because
119
+ // the draft object inherited something.
120
+ if (Object.prototype.hasOwnProperty.call(out, key)) {
121
+ throw new Refused('duplicate-key', at);
122
+ }
123
+ this.skipWhitespace();
124
+ if (this.peek() !== 58 /* Code.Colon */)
125
+ throw new Refused('unexpected-token', this.i);
126
+ this.i += 1;
127
+ this.skipWhitespace();
128
+ out[key] = this.value(depth);
129
+ this.skipWhitespace();
130
+ const sep = this.peek();
131
+ if (sep === 44 /* Code.Comma */) {
132
+ this.i += 1;
133
+ continue;
134
+ }
135
+ if (sep === 125 /* Code.CloseBrace */) {
136
+ this.i += 1;
137
+ return out;
138
+ }
139
+ throw new Refused(sep === -1 ? 'unexpected-end' : 'unexpected-token', this.i);
140
+ }
141
+ }
142
+ array(depth) {
143
+ if (depth > MAX_JSON_DEPTH)
144
+ throw new Refused('depth-exceeded', this.i);
145
+ this.i += 1; // '['
146
+ const out = [];
147
+ this.skipWhitespace();
148
+ if (this.peek() === 93 /* Code.CloseBracket */) {
149
+ this.i += 1;
150
+ return out;
151
+ }
152
+ for (;;) {
153
+ this.skipWhitespace();
154
+ out.push(this.value(depth));
155
+ this.skipWhitespace();
156
+ const sep = this.peek();
157
+ if (sep === 44 /* Code.Comma */) {
158
+ this.i += 1;
159
+ continue;
160
+ }
161
+ if (sep === 93 /* Code.CloseBracket */) {
162
+ this.i += 1;
163
+ return out;
164
+ }
165
+ throw new Refused(sep === -1 ? 'unexpected-end' : 'unexpected-token', this.i);
166
+ }
167
+ }
168
+ string() {
169
+ this.i += 1; // '"'
170
+ let out = '';
171
+ for (;;) {
172
+ if (this.i >= this.src.length)
173
+ throw new Refused('unexpected-end', this.i);
174
+ const c = this.src.charCodeAt(this.i);
175
+ if (c === 34 /* Code.Quote */) {
176
+ this.i += 1;
177
+ return out;
178
+ }
179
+ if (c === 92 /* Code.Backslash */) {
180
+ out += this.escape();
181
+ continue;
182
+ }
183
+ // Raw control characters are not permitted in a JSON string; a
184
+ // parser that accepts them accepts two spellings of one value.
185
+ if (c < 32 /* Code.Space */)
186
+ throw new Refused('string-control-char', this.i);
187
+ out += this.src[this.i];
188
+ this.i += 1;
189
+ }
190
+ }
191
+ escape() {
192
+ this.i += 1;
193
+ const c = this.src[this.i];
194
+ this.i += 1;
195
+ switch (c) {
196
+ case '"':
197
+ return '"';
198
+ case '\\':
199
+ return '\\';
200
+ case '/':
201
+ return '/';
202
+ case 'b':
203
+ return '\b';
204
+ case 'f':
205
+ return '\f';
206
+ case 'n':
207
+ return '\n';
208
+ case 'r':
209
+ return '\r';
210
+ case 't':
211
+ return '\t';
212
+ case 'u': {
213
+ const hex = this.src.slice(this.i, this.i + 4);
214
+ if (!/^[0-9a-fA-F]{4}$/.test(hex))
215
+ throw new Refused('string-escape', this.i);
216
+ this.i += 4;
217
+ return String.fromCharCode(Number.parseInt(hex, 16));
218
+ }
219
+ default:
220
+ throw new Refused('string-escape', this.i - 1);
221
+ }
222
+ }
223
+ number() {
224
+ const start = this.i;
225
+ if (this.peek() === 45 /* Code.Minus */)
226
+ this.i += 1;
227
+ // Integer part: `0` alone, or a non-zero digit followed by digits.
228
+ if (this.peek() === 48 /* Code.Zero */) {
229
+ this.i += 1;
230
+ if (this.isDigit(this.peek()))
231
+ throw new Refused('number-grammar', start);
232
+ }
233
+ else if (this.isDigit(this.peek())) {
234
+ while (this.isDigit(this.peek()))
235
+ this.i += 1;
236
+ }
237
+ else {
238
+ throw new Refused('number-grammar', start);
239
+ }
240
+ if (this.peek() === 46 /* Code.Dot */) {
241
+ this.i += 1;
242
+ if (!this.isDigit(this.peek()))
243
+ throw new Refused('number-grammar', start);
244
+ while (this.isDigit(this.peek()))
245
+ this.i += 1;
246
+ }
247
+ const e = this.src[this.i];
248
+ if (e === 'e' || e === 'E') {
249
+ this.i += 1;
250
+ const sign = this.peek();
251
+ if (sign === 43 /* Code.Plus */ || sign === 45 /* Code.Minus */)
252
+ this.i += 1;
253
+ if (!this.isDigit(this.peek()))
254
+ throw new Refused('number-grammar', start);
255
+ while (this.isDigit(this.peek()))
256
+ this.i += 1;
257
+ }
258
+ const value = Number(this.src.slice(start, this.i));
259
+ // `1e999` is grammatical JSON and is not a number. This is the check
260
+ // `JSON.parse` does not do.
261
+ if (!Number.isFinite(value))
262
+ throw new Refused('number-not-finite', start);
263
+ return value;
264
+ }
265
+ isDigit(c) {
266
+ return c >= 48 /* Code.Zero */ && c <= 57 /* Code.Nine */;
267
+ }
268
+ peek() {
269
+ if (this.i >= this.src.length)
270
+ return -1;
271
+ return this.src.charCodeAt(this.i);
272
+ }
273
+ skipWhitespace() {
274
+ for (;;) {
275
+ const c = this.peek();
276
+ if (c === 32 /* Code.Space */ || c === 9 /* Code.Tab */ || c === 10 /* Code.LF */ || c === 13 /* Code.CR */) {
277
+ this.i += 1;
278
+ continue;
279
+ }
280
+ return;
281
+ }
282
+ }
283
+ }
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Slice E — the action ledger (§1.10).
3
+ *
4
+ * The rule the whole module exists for: **a sequence number identifies
5
+ * one request, not a slot.** A retained `s` replayed with the same
6
+ * request returns the same outcome; replayed with a *different* request
7
+ * it is refused and the retained entry is left alone. Without that, a
8
+ * caller could overwrite the record of what it asked for.
9
+ *
10
+ * ## Why a rejection is retained
11
+ *
12
+ * Authorization denial and a handler throw both retain an entry. If a
13
+ * refusal were simply absent, a later policy change would turn an
14
+ * earlier refusal into an execution of the same sequence — the same
15
+ * request succeeding the second time because the record of its refusal
16
+ * was not kept.
17
+ *
18
+ * ## Why the floor exists, and what it cannot say
19
+ *
20
+ * The window is bounded three ways (count, bytes, age), and eviction
21
+ * happens in `s` order so an entry is never dropped while a lower one
22
+ * is retained. The floor is the highest evicted `s`: at or below it the
23
+ * owner knows a sequence has been used but no longer knows the outcome,
24
+ * which is `result-expired` — explicitly NOT a claim that it did or did
25
+ * not commit. A handle that is gone is a different answer again
26
+ * (`closed`), because then the owner does not even know the sequence
27
+ * existed.
28
+ *
29
+ * ## The binding, and the one `await`
30
+ *
31
+ * The request binding is a canonical `name \x1f json` string, retained
32
+ * verbatim while it is small and as a SHA-256 when it is not. The small
33
+ * form is the common case and has no `await` at all, which is the point:
34
+ * the asynchronous path is the only one where the handle, the policy and
35
+ * the ledger can change under the request, and it is the only one that
36
+ * has to revalidate.
37
+ */
38
+ import type { JsonObject, JsonValue } from './json.js';
39
+ import { type Decimal, type Hex } from './wire.js';
40
+ import type { StoreErrorCode } from './errors.js';
41
+ /** Outcomes retained per handle (§2). */
42
+ export declare const LEDGER_MAX_ENTRIES = 32;
43
+ /** Bytes retained per handle (§2). */
44
+ export declare const LEDGER_MAX_BYTES: number;
45
+ /** How long an outcome is retained (§2). */
46
+ export declare const LEDGER_MAX_AGE_MS = 60000;
47
+ /** Above this, a binding is retained as its digest rather than verbatim. */
48
+ export declare const BINDING_INLINE_MAX_BYTES = 2048;
49
+ /** The highest sequence a handle can reach. It does not wrap. */
50
+ export declare const MAX_SEQUENCE: bigint;
51
+ /**
52
+ * What a request was, in the form the ledger keeps.
53
+ *
54
+ * The form is recorded with the value so a 2 KiB boundary crossing
55
+ * cannot make two encodings of one request compare unequal.
56
+ */
57
+ export interface RequestBinding {
58
+ readonly form: 'inline' | 'digest';
59
+ readonly value: string;
60
+ }
61
+ /** What happened, in the form a replay can reproduce. */
62
+ export type Outcome = {
63
+ readonly kind: 'result';
64
+ readonly out: JsonObject;
65
+ } | {
66
+ readonly kind: 'refusal';
67
+ readonly code: StoreErrorCode;
68
+ };
69
+ /** What the owner should do with an arriving `act`. */
70
+ export type Disposition =
71
+ /** Never seen, above the floor: run it. */
72
+ {
73
+ readonly kind: 'execute';
74
+ }
75
+ /** Retained, same request: reply the retained outcome under a new envelope. */
76
+ | {
77
+ readonly kind: 'replay';
78
+ readonly outcome: Outcome;
79
+ }
80
+ /** Retained, DIFFERENT request under the same sequence. */
81
+ | {
82
+ readonly kind: 'conflict';
83
+ }
84
+ /** Used, evicted: the outcome is no longer known. */
85
+ | {
86
+ readonly kind: 'expired';
87
+ }
88
+ /** The counter is exhausted; a fresh handle is the only way on. */
89
+ | {
90
+ readonly kind: 'exhausted';
91
+ };
92
+ /**
93
+ * The canonical form of one request.
94
+ *
95
+ * Object keys sort ascending by UTF-16 code unit, there is no
96
+ * insignificant whitespace, and numbers are rendered by
97
+ * `Number.prototype.toString` — exact for every value the store admits,
98
+ * because §1.12 already refuses `NaN`, `Infinity` and duplicate keys,
99
+ * and identifiers needing full integer precision are strings by §1.1.
100
+ *
101
+ * Only the owner computes this and only the owner compares it: it never
102
+ * crosses the wire, so self-consistency is what matters.
103
+ */
104
+ export declare function canonicalRequest(name: string, input: JsonValue): string;
105
+ /** How many bytes a canonical form occupies. */
106
+ export declare function canonicalBytes(canonical: string): number;
107
+ /** Whether this binding needs the asynchronous digest path. */
108
+ export declare function needsDigest(canonical: string): boolean;
109
+ /** The binding for a small canonical form. Synchronous by construction. */
110
+ export declare function inlineBinding(canonical: string): RequestBinding;
111
+ /**
112
+ * The binding for a large canonical form.
113
+ *
114
+ * The caller must treat the `await` as a boundary: no authorization
115
+ * decision and no transaction context may cross it (§1.10).
116
+ */
117
+ export declare function digestBinding(canonical: string): Promise<RequestBinding>;
118
+ /**
119
+ * One handle's outcomes.
120
+ *
121
+ * Keyed by sequence, bounded by count, bytes and age, evicted in `s`
122
+ * order so the floor can only ever describe a contiguous prefix.
123
+ */
124
+ export declare class HandleLedger {
125
+ #private;
126
+ private readonly maxEntries;
127
+ private readonly maxBytes;
128
+ private readonly maxAgeMs;
129
+ constructor(maxEntries?: number, maxBytes?: number, maxAgeMs?: number);
130
+ get floor(): Decimal;
131
+ get size(): number;
132
+ get bytesHeld(): number;
133
+ /**
134
+ * What to do with `(s, binding)`.
135
+ *
136
+ * Pure: it moves nothing, so the owner can call it before the
137
+ * transaction and — on the digest path — again after the `await`.
138
+ */
139
+ disposition(s: bigint, binding: RequestBinding, now: number): Disposition;
140
+ /**
141
+ * Retain an outcome.
142
+ *
143
+ * A refusal is retained exactly like a result: that is what stops a
144
+ * policy change from turning an earlier denial into a later
145
+ * execution of the same sequence.
146
+ */
147
+ retain(s: bigint, binding: RequestBinding, outcome: Outcome, now: number): void;
148
+ /** Drop everything past its age, advancing the floor. */
149
+ expire(now: number): void;
150
+ private evict;
151
+ private drop;
152
+ private ordered;
153
+ }
154
+ /**
155
+ * Latest-value inputs (§1.11).
156
+ *
157
+ * Monotone per `(handle, name)`: a sequence at or below the last seen
158
+ * one is dropped and counted. There is no retention, no replay and no
159
+ * gap recovery, and **loss does not imply a successor** — a dropped
160
+ * input may be the last one, so the game must tolerate a missing final
161
+ * input. The coalescing design invites the opposite assumption, which
162
+ * is why it is stated here beside the code.
163
+ */
164
+ export declare class InputSequences {
165
+ #private;
166
+ /** How many inputs this handle has dropped as stale. */
167
+ get dropped(): number;
168
+ /** Whether this input is newer than the last for its name. */
169
+ admit(name: string, s: bigint): boolean;
170
+ /** The last admitted sequence for a name, or null. */
171
+ latest(name: string): Decimal | null;
172
+ }
173
+ /** Per-handle ledger state, created on demand. */
174
+ export declare class LedgerTable {
175
+ #private;
176
+ ledger(h: Hex): HandleLedger;
177
+ inputs(h: Hex): InputSequences;
178
+ /**
179
+ * Forget a handle's ledger.
180
+ *
181
+ * §2: the ledger goes with the handle, which is why a replay after
182
+ * eviction is `closed` and not `result-expired` — the owner no
183
+ * longer knows the sequence existed.
184
+ */
185
+ forget(h: Hex): void;
186
+ get size(): number;
187
+ }