@xyo-network/service-kit-xl1 0.2.2 → 0.3.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 (66) hide show
  1. package/README.md +64 -0
  2. package/dist/browser/createFleetAuthority.d.ts +11 -1
  3. package/dist/browser/createFleetAuthority.d.ts.map +1 -1
  4. package/dist/browser/fleetForeign.d.ts +5 -0
  5. package/dist/browser/fleetForeign.d.ts.map +1 -0
  6. package/dist/browser/fleetHistory.d.ts +37 -0
  7. package/dist/browser/fleetHistory.d.ts.map +1 -0
  8. package/dist/browser/fleetHistoryCache.d.ts +22 -0
  9. package/dist/browser/fleetHistoryCache.d.ts.map +1 -0
  10. package/dist/browser/fleetMeter.d.ts +26 -0
  11. package/dist/browser/fleetMeter.d.ts.map +1 -0
  12. package/dist/browser/fleetPage.d.ts +5 -0
  13. package/dist/browser/fleetPage.d.ts.map +1 -0
  14. package/dist/browser/fleetProfile.d.ts +13 -0
  15. package/dist/browser/fleetProfile.d.ts.map +1 -0
  16. package/dist/browser/fleetProjection.d.ts +1 -0
  17. package/dist/browser/fleetProjection.d.ts.map +1 -1
  18. package/dist/browser/fleetQuery.d.ts +8 -0
  19. package/dist/browser/fleetQuery.d.ts.map +1 -0
  20. package/dist/browser/fleetQuerySelection.d.ts +3 -0
  21. package/dist/browser/fleetQuerySelection.d.ts.map +1 -0
  22. package/dist/browser/fleetReaders.d.ts +10 -0
  23. package/dist/browser/fleetReaders.d.ts.map +1 -0
  24. package/dist/browser/fleetRequests.d.ts +3 -0
  25. package/dist/browser/fleetRequests.d.ts.map +1 -0
  26. package/dist/browser/fleetScope.d.ts +4 -0
  27. package/dist/browser/fleetScope.d.ts.map +1 -0
  28. package/dist/browser/fleetSelectedPayloadSource.d.ts +4 -0
  29. package/dist/browser/fleetSelectedPayloadSource.d.ts.map +1 -0
  30. package/dist/browser/index.d.ts +5 -0
  31. package/dist/browser/index.d.ts.map +1 -1
  32. package/dist/browser/index.mjs +769 -92
  33. package/dist/browser/index.mjs.map +4 -4
  34. package/dist/node/createFleetAuthority.d.ts +11 -1
  35. package/dist/node/createFleetAuthority.d.ts.map +1 -1
  36. package/dist/node/fleetForeign.d.ts +5 -0
  37. package/dist/node/fleetForeign.d.ts.map +1 -0
  38. package/dist/node/fleetHistory.d.ts +37 -0
  39. package/dist/node/fleetHistory.d.ts.map +1 -0
  40. package/dist/node/fleetHistoryCache.d.ts +22 -0
  41. package/dist/node/fleetHistoryCache.d.ts.map +1 -0
  42. package/dist/node/fleetMeter.d.ts +26 -0
  43. package/dist/node/fleetMeter.d.ts.map +1 -0
  44. package/dist/node/fleetPage.d.ts +5 -0
  45. package/dist/node/fleetPage.d.ts.map +1 -0
  46. package/dist/node/fleetProfile.d.ts +13 -0
  47. package/dist/node/fleetProfile.d.ts.map +1 -0
  48. package/dist/node/fleetProjection.d.ts +1 -0
  49. package/dist/node/fleetProjection.d.ts.map +1 -1
  50. package/dist/node/fleetQuery.d.ts +8 -0
  51. package/dist/node/fleetQuery.d.ts.map +1 -0
  52. package/dist/node/fleetQuerySelection.d.ts +3 -0
  53. package/dist/node/fleetQuerySelection.d.ts.map +1 -0
  54. package/dist/node/fleetReaders.d.ts +10 -0
  55. package/dist/node/fleetReaders.d.ts.map +1 -0
  56. package/dist/node/fleetRequests.d.ts +3 -0
  57. package/dist/node/fleetRequests.d.ts.map +1 -0
  58. package/dist/node/fleetScope.d.ts +4 -0
  59. package/dist/node/fleetScope.d.ts.map +1 -0
  60. package/dist/node/fleetSelectedPayloadSource.d.ts +4 -0
  61. package/dist/node/fleetSelectedPayloadSource.d.ts.map +1 -0
  62. package/dist/node/index.d.ts +5 -0
  63. package/dist/node/index.d.ts.map +1 -1
  64. package/dist/node/index.mjs +769 -92
  65. package/dist/node/index.mjs.map +4 -4
  66. package/package.json +12 -12
@@ -5,14 +5,14 @@ import {
5
5
  verifyFleetPayload
6
6
  } from "@xyo-network/service-kit-protocol";
7
7
  import {
8
- AddressZod,
8
+ AddressZod as AddressZod4,
9
9
  FleetControlSchema,
10
10
  FleetMemberSchema,
11
11
  FleetPublicationScopeSchema,
12
12
  FleetPublicationScopeZod,
13
13
  FleetSchema,
14
14
  FleetZod,
15
- HashZod
15
+ HashZod as HashZod5
16
16
  } from "@xyo-network/service-kit-schemas";
17
17
  import {
18
18
  createXl1FinalizedPublicationEvidence
@@ -81,26 +81,263 @@ function operationControl(signal, timeoutMs, startedAt) {
81
81
  }
82
82
  var fleetNow = now;
83
83
 
84
- // src/fleetProjection.ts
85
- function nextPublisherProjection(result) {
86
- const { publicationBlock: projectionBlock, ...original } = result;
84
+ // src/fleetHistory.ts
85
+ function historicalPublisherCandidates(controls) {
86
+ const candidates = /* @__PURE__ */ new Map();
87
+ for (const fact of controls) {
88
+ const payload = fact.payload;
89
+ if (payload.operation !== "grant-publisher" || candidates.has(fact.root)) continue;
90
+ candidates.set(fact.root, Object.freeze({
91
+ controlRoot: fact.root,
92
+ controlBlock: fact.block,
93
+ fleetRoot: payload.fleetRoot,
94
+ memberRoot: payload.memberRoot,
95
+ scopeRoot: payload.scopeRoot,
96
+ publisherAddress: payload.publisherAddress,
97
+ ...payload.expiresAtBlock !== void 0 && { expiresAtBlock: payload.expiresAtBlock }
98
+ }));
99
+ }
100
+ return Object.freeze(candidates.values().toArray());
101
+ }
102
+ function historicalPublisherResult(result, controls, fleetRoot) {
87
103
  const context2 = {
88
- ...original,
89
- projection: "pending-N+1",
90
- projectionBlock
104
+ anchor: result.anchor,
105
+ assurance: result.assurance,
106
+ chainId: result.chainId,
107
+ genesisRoot: result.genesisRoot,
108
+ historyScope: result.historyScope,
109
+ network: result.network,
110
+ owner: result.owner,
111
+ selection: "historical-ever-granted-discovery-only",
112
+ ...result.resources !== void 0 && { resources: result.resources },
113
+ ...fleetRoot !== void 0 && { fleetRoot }
91
114
  };
92
- if (result.status === "authorized" || result.status === "absent") {
115
+ return result.status === "complete" ? Object.freeze({
116
+ ...context2,
117
+ ...result.scopeCompleteness !== void 0 && { scopeCompleteness: result.scopeCompleteness },
118
+ status: "complete",
119
+ correspondence: result.correspondence,
120
+ coveredRange: result.coveredRange,
121
+ history: result.history,
122
+ candidates: historicalPublisherCandidates(controls)
123
+ }) : Object.freeze({
124
+ ...context2,
125
+ status: result.status,
126
+ code: result.code
127
+ });
128
+ }
129
+
130
+ // src/fleetMeter.ts
131
+ var encoder = new TextEncoder();
132
+ function spend(budget, bytes) {
133
+ budget.bytes += bytes;
134
+ if (budget.bytes > budget.maximum) throw new RangeError("Declaration response exceeds its reserved allowance");
135
+ }
136
+ function text(budget, value) {
137
+ if (value.length > budget.maximum - budget.bytes) throw new RangeError("Declaration text exceeds its reserved allowance");
138
+ spend(budget, encoder.encode(JSON.stringify(value)).byteLength);
139
+ }
140
+ function compositeSnapshot(value, budget, depth) {
141
+ const array = Array.isArray(value);
142
+ if (Object.getPrototypeOf(value) !== (array ? Array.prototype : Object.prototype)) throw new TypeError("Declaration response requires plain JSON");
143
+ if (array && value.length > budget.limits.maxNodes - budget.nodes) throw new RangeError("Declaration response exceeds node bounds");
144
+ const keys = Reflect.ownKeys(value);
145
+ const expected = array ? Array.from({ length: value.length }, (_, index) => String(index)) : keys;
146
+ if (array && (keys.length !== value.length + 1 || keys.at(-1) !== "length")) throw new TypeError("Declaration arrays require dense own slots");
147
+ if (expected.length > budget.limits.maxNodes - budget.nodes) throw new RangeError("Declaration response exceeds node bounds");
148
+ spend(budget, 2);
149
+ const entries = expected.map((key, index) => {
150
+ if (typeof key !== "string" || key === "__proto__") throw new TypeError("Declaration keys require plain strings");
151
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
152
+ if (descriptor?.enumerable !== true || !("value" in descriptor)) throw new TypeError("Declaration accessors are unsupported");
153
+ if (index > 0) spend(budget, 1);
154
+ if (!array) {
155
+ text(budget, key);
156
+ spend(budget, 1);
157
+ }
158
+ return [key, jsonSnapshot(descriptor.value, budget, depth + 1)];
159
+ });
160
+ return Object.freeze(array ? entries.map(([, item]) => item) : Object.fromEntries(entries));
161
+ }
162
+ function jsonSnapshot(value, budget, depth = 0) {
163
+ if (++budget.nodes > budget.limits.maxNodes || depth > budget.limits.maxDepth) throw new RangeError("Declaration response exceeds structure bounds");
164
+ if (value === null || typeof value === "boolean" || typeof value === "number") {
165
+ if (typeof value === "number" && !Number.isFinite(value)) throw new TypeError("Declaration response requires finite JSON");
166
+ spend(budget, JSON.stringify(value).length);
167
+ return value;
168
+ }
169
+ if (typeof value === "string") {
170
+ text(budget, value);
171
+ return value;
172
+ }
173
+ if (typeof value !== "object" || budget.ancestors.has(value)) throw new TypeError("Declaration response requires acyclic own-data JSON");
174
+ budget.ancestors.add(value);
175
+ try {
176
+ return compositeSnapshot(value, budget, depth);
177
+ } finally {
178
+ budget.ancestors.delete(value);
179
+ }
180
+ }
181
+ function logicalJsonSnapshot(value, maximum, limits) {
182
+ const budget = {
183
+ bytes: 0,
184
+ nodes: 0,
185
+ maximum,
186
+ limits,
187
+ ancestors: /* @__PURE__ */ new WeakSet()
188
+ };
189
+ const snapshot = jsonSnapshot(value, budget);
190
+ return { value: snapshot, bytes: budget.bytes };
191
+ }
192
+ var FleetMeter = class {
193
+ #ceiling;
194
+ #closed = false;
195
+ #declarations = 0;
196
+ #limits;
197
+ #native = 0;
198
+ #reserved = 0;
199
+ constructor(ceiling, limits) {
200
+ this.#ceiling = ceiling;
201
+ this.#limits = limits;
202
+ }
203
+ close() {
204
+ this.#closed = true;
205
+ }
206
+ native(bytes) {
207
+ if (bytes === void 0 || !Number.isSafeInteger(bytes) || bytes < 0) throw new FleetAuthorityError("conflict", "native-resources");
208
+ this.#native += bytes;
209
+ if (this.#native + this.#declarations + this.#reserved > this.#ceiling) throw new FleetAuthorityError("resource-limit", "aggregate-bytes");
210
+ }
211
+ async read(get, roots, options) {
212
+ const allowance = Math.min(options?.maxBodyBytes ?? this.#limits.maxBodyBytes, this.remaining());
213
+ this.#reserved += allowance;
214
+ const response = await get(roots, {
215
+ ...options,
216
+ signal: options?.signal ?? new AbortController().signal,
217
+ maxBodyBytes: allowance
218
+ });
219
+ if (this.#closed || options?.signal !== void 0 && aborted(options.signal)) throw new FleetAuthorityError("incomplete", "declaration-late");
220
+ if (!Array.isArray(response) || response.length > this.#limits.maxCandidatesPerSeed) throw new FleetAuthorityError("resource-limit", "declaration-response");
221
+ const budget = {
222
+ bytes: 0,
223
+ nodes: 0,
224
+ maximum: allowance,
225
+ limits: this.#limits,
226
+ ancestors: /* @__PURE__ */ new WeakSet()
227
+ };
228
+ const snapshot = jsonSnapshot(response, budget);
229
+ this.#reserved -= allowance;
230
+ this.#declarations += budget.bytes;
231
+ return snapshot;
232
+ }
233
+ remaining() {
234
+ const remaining = this.#ceiling - this.#native - this.#declarations - this.#reserved;
235
+ if (this.#closed || remaining <= 0) throw new FleetAuthorityError("resource-limit", "aggregate-bytes");
236
+ return remaining;
237
+ }
238
+ resources() {
239
+ const decodedBytes = this.#native + this.#declarations;
93
240
  return Object.freeze({
94
- ...context2,
95
- status: result.status === "authorized" ? "projected-granted" : "projected-absent",
96
- coveredRange: Object.freeze({ fromBlockNumber: 0, toBlockNumber: result.anchor.blockNumber })
241
+ decodedBytes,
242
+ chargedBytes: decodedBytes + this.#reserved,
243
+ nativeDecodedBytes: this.#native,
244
+ declarationDecodedBytes: this.#declarations,
245
+ declarationReservedBytes: this.#reserved
97
246
  });
98
247
  }
99
- return Object.freeze(context2);
248
+ };
249
+ function chargeNativeResources(meter, resources) {
250
+ meter?.native(resources?.decodedBytes);
100
251
  }
101
252
 
102
- // src/createFleetAuthority.ts
103
- var b4Families = Object.freeze([FleetSchema, FleetMemberSchema, FleetPublicationScopeSchema, FleetControlSchema]);
253
+ // src/fleetHistoryCache.ts
254
+ function snapshotFleetVerifiedHistory(input) {
255
+ if (input === void 0) return;
256
+ if (input === null || typeof input !== "object" || Object.getPrototypeOf(input) !== Object.prototype || Reflect.ownKeys(input).length !== 2) throw new TypeError("Select strict verified owner-history bounds");
257
+ const values = Object.fromEntries(["maxBytes", "maxOwners"].map((key) => {
258
+ const slot = Object.getOwnPropertyDescriptor(input, key);
259
+ if (slot?.enumerable !== true || !("value" in slot) || typeof slot.value !== "number" || !Number.isSafeInteger(slot.value) || slot.value <= 0) throw new TypeError("Select positive own-data history bounds");
260
+ return [key, slot.value];
261
+ }));
262
+ if (values.maxOwners > 16 || values.maxBytes > 128 * 1024 * 1024) throw new RangeError("Verified history storage exceeds its bounded profile");
263
+ return Object.freeze(values);
264
+ }
265
+ var encoder2 = new TextEncoder();
266
+ var decoder = new TextDecoder("utf-8", { fatal: true });
267
+ var VerifiedFleetHistory = class {
268
+ #bytes = 0;
269
+ #entries = /* @__PURE__ */ new Map();
270
+ #limits;
271
+ #maxDepth;
272
+ constructor(limits, maxDepth) {
273
+ this.#limits = limits;
274
+ this.#maxDepth = maxDepth;
275
+ }
276
+ get(owner) {
277
+ const entry = this.#entries.get(owner);
278
+ if (entry === void 0) return;
279
+ this.#entries.delete(owner);
280
+ this.#entries.set(owner, entry);
281
+ const decoded = JSON.parse(decoder.decode(entry.data));
282
+ return logicalJsonSnapshot(decoded, this.#limits.maxBytes, { maxDepth: this.#maxDepth, maxNodes: this.#limits.maxBytes }).value;
283
+ }
284
+ publish(input) {
285
+ const prior = this.#entries.get(input.owner);
286
+ if (prior !== void 0) {
287
+ if (prior.anchor.blockNumber > input.anchor.blockNumber) return;
288
+ if (prior.anchor.blockNumber === input.anchor.blockNumber && prior.anchor.blockRoot !== input.anchor.blockRoot) throw new FleetAuthorityError("conflict", "history-anchor");
289
+ }
290
+ let snapshot;
291
+ try {
292
+ snapshot = logicalJsonSnapshot(input, this.#limits.maxBytes, { maxDepth: this.#maxDepth, maxNodes: this.#limits.maxBytes });
293
+ } catch {
294
+ throw new FleetAuthorityError("resource-limit", "history-bytes");
295
+ }
296
+ while (this.#bytes + snapshot.bytes > this.#limits.maxBytes || this.#entries.size >= this.#limits.maxOwners) {
297
+ const oldest = this.#entries.keys().next().value;
298
+ if (oldest === void 0) throw new FleetAuthorityError("resource-limit", "history-bytes");
299
+ this.#bytes -= this.#entries.get(oldest).data.byteLength;
300
+ this.#entries.delete(oldest);
301
+ }
302
+ const data = encoder2.encode(JSON.stringify(snapshot.value));
303
+ if (data.byteLength !== snapshot.bytes) throw new FleetAuthorityError("conflict", "history-size");
304
+ const replacing = this.#entries.get(input.owner);
305
+ if (replacing !== void 0) this.#bytes -= replacing.data.byteLength;
306
+ this.#entries.set(input.owner, { anchor: input.anchor, data });
307
+ this.#bytes += data.byteLength;
308
+ }
309
+ };
310
+
311
+ // src/fleetScope.ts
312
+ import { HashZod as HashZod3 } from "@xyo-network/service-kit-schemas";
313
+
314
+ // src/fleetForeign.ts
315
+ import { AddressZod, HashZod } from "@xyo-network/service-kit-schemas";
316
+
317
+ // src/fleetProfile.ts
318
+ import {
319
+ snapshotFinalizedForeignTransactions,
320
+ snapshotFinalizedForkLineage,
321
+ snapshotFinalizedVerifiedPrefix
322
+ } from "@xyo-network/xl1-sdk/protocol-sdk/finalized-publication";
323
+
324
+ // src/fleetQuerySelection.ts
325
+ import { snapshotFinalizedQuerySelection } from "@xyo-network/xl1-sdk/protocol-sdk/finalized-publication";
326
+ function snapshotFleetQuerySelection(input) {
327
+ const selection = snapshotFinalizedQuerySelection(input);
328
+ if (selection !== input) throw new TypeError("Native query selection snapshot must preserve the exact policy");
329
+ return selection;
330
+ }
331
+
332
+ // src/fleetSelectedPayloadSource.ts
333
+ import { snapshotFinalizedSelectedPayloadSource } from "@xyo-network/xl1-sdk/protocol-sdk/finalized-publication";
334
+ function snapshotFleetSelectedPayloadSource(input, maxSourceUrlBytes) {
335
+ const captured = snapshotFinalizedSelectedPayloadSource(input, maxSourceUrlBytes);
336
+ if (input !== void 0 && captured === void 0) throw new TypeError("Selected payload source snapshot must preserve the requested selection");
337
+ return captured;
338
+ }
339
+
340
+ // src/fleetProfile.ts
104
341
  function ownRecord(input, required, optional = []) {
105
342
  if (input === null || typeof input !== "object" || Object.getPrototypeOf(input) !== Object.prototype) throw new TypeError("Use a strict own-data profile/request");
106
343
  const keys = Reflect.ownKeys(input);
@@ -111,15 +348,26 @@ function ownRecord(input, required, optional = []) {
111
348
  return [key, descriptor.value];
112
349
  }));
113
350
  }
114
- function finiteProfile(input, keys) {
351
+ function finiteProfile(input, keys, largeBytes = false) {
115
352
  const values = ownRecord(input, keys);
116
- if (Object.values(values).some((value) => typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0 || value > 2147483647)) throw new RangeError("Every finite positive bound is required");
353
+ if (Object.entries(values).some(([key, value]) => typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0 || value > 2147483647 && !(largeBytes && key === "maxAggregateBytes"))) throw new RangeError("Every finite positive bound is required");
117
354
  return Object.freeze(values);
118
355
  }
119
356
  function pinProfile(input) {
120
- const profile = ownRecord(input, ["evidence", "foldLimits", "limits", "resolutionLimits", "seeds"]);
121
- const evidence = ownRecord(profile.evidence, ["assurance", "chainId", "genesisRoot", "limits", "network", "source"]);
122
- const source = ownRecord(evidence.source, ["bodyBaseUrl", "finalizedBaseUrl", "headUrl"], ["fetch"]);
357
+ const profile = ownRecord(input, ["evidence", "foldLimits", "limits", "resolutionLimits", "seeds"], ["verifiedHistory"]);
358
+ const evidence = ownRecord(profile.evidence, ["assurance", "chainId", "genesisRoot", "limits", "network", "source"], ["forkLineage", "verifiedPrefix", "foreignTransactions", "querySelection"]);
359
+ const source = ownRecord(evidence.source, ["bodyBaseUrl", "finalizedBaseUrl", "headUrl"], ["fetch", "blockFrames", "selectedPayloadSource"]);
360
+ const forkLineage = snapshotFinalizedForkLineage(evidence.forkLineage, evidence.chainId);
361
+ const blockFrames = source.blockFrames === void 0 ? void 0 : pinBlockFrames(source.blockFrames);
362
+ const verifiedPrefix = pinVerifiedPrefix(evidence.verifiedPrefix);
363
+ const foreignTransactions = snapshotFinalizedForeignTransactions(evidence.foreignTransactions);
364
+ if (foreignTransactions !== void 0 && (forkLineage === void 0 || blockFrames === void 0 || verifiedPrefix === void 0)) {
365
+ throw new TypeError("Foreign transaction exclusion requires explicit fork, frame and verified-prefix profiles");
366
+ }
367
+ if (verifiedPrefix !== void 0 && (forkLineage === void 0 || blockFrames === void 0)) throw new TypeError("Verified native prefix requires explicit fork and original-block frame profiles");
368
+ const querySelection = snapshotFleetQuerySelection(evidence.querySelection);
369
+ const verifiedHistory = snapshotFleetVerifiedHistory(profile.verifiedHistory);
370
+ if (verifiedHistory !== void 0 && verifiedPrefix === void 0) throw new TypeError("Verified owner history requires native verified-prefix support");
123
371
  const evidenceLimits = finiteProfile(evidence.limits, [
124
372
  "maxAggregateBytes",
125
373
  "maxBlocks",
@@ -133,11 +381,20 @@ function pinProfile(input) {
133
381
  "maxSourceUrlBytes",
134
382
  "perCallTimeoutMs",
135
383
  "totalTimeoutMs"
136
- ]);
384
+ ], verifiedPrefix !== void 0);
385
+ const selectedPayloadSource = snapshotFleetSelectedPayloadSource(source.selectedPayloadSource, evidenceLimits.maxSourceUrlBytes);
137
386
  const fixedEvidence = Object.freeze({
138
387
  ...evidence,
139
388
  limits: evidenceLimits,
140
- source: Object.freeze(source)
389
+ ...forkLineage !== void 0 && { forkLineage },
390
+ ...verifiedPrefix !== void 0 && { verifiedPrefix },
391
+ ...foreignTransactions !== void 0 && { foreignTransactions },
392
+ ...querySelection !== void 0 && { querySelection },
393
+ source: Object.freeze({
394
+ ...source,
395
+ ...blockFrames !== void 0 && { blockFrames },
396
+ ...selectedPayloadSource !== void 0 && { selectedPayloadSource }
397
+ })
141
398
  });
142
399
  const limits = finiteProfile(profile.limits, [
143
400
  "maxBlocks",
@@ -164,22 +421,349 @@ function pinProfile(input) {
164
421
  limits,
165
422
  foldLimits,
166
423
  resolutionLimits,
424
+ verifiedHistory,
167
425
  seeds: profile.seeds
168
426
  };
169
427
  }
170
- function pinRequest(input, next = false) {
171
- const values = ownRecord(input, ["anchor", "owner", "publicationBlock"], ["fleetRoot", "signal"]);
172
- const anchor = ownRecord(values.anchor, ["blockNumber", "blockRoot"]);
173
- HashZod.parse(anchor.blockRoot);
174
- AddressZod.parse(values.owner);
175
- if (values.fleetRoot !== void 0) HashZod.parse(values.fleetRoot);
176
- if (!Number.isSafeInteger(anchor.blockNumber) || anchor.blockNumber < 0 || anchor.blockNumber >= Number.MAX_SAFE_INTEGER || typeof values.publicationBlock !== "number" || !Number.isSafeInteger(values.publicationBlock) || values.publicationBlock < 0 || (next ? values.publicationBlock !== anchor.blockNumber + 1 : values.publicationBlock > anchor.blockNumber)) throw new RangeError("Select an exact publication height within the anchor");
177
- return Object.freeze({
178
- ...values,
179
- anchor: Object.freeze(anchor),
180
- signal: captureSignal(values.signal)
181
- });
428
+ function pinBlockFrames(input) {
429
+ const frames = ownRecord(input, ["indexBaseUrl", "maxStep"]);
430
+ if (typeof frames.indexBaseUrl !== "string" || frames.indexBaseUrl.length === 0 || typeof frames.maxStep !== "number" || !Number.isSafeInteger(frames.maxStep) || frames.maxStep < 0 || frames.maxStep > 3) throw new TypeError("Select a bounded original-block frame source");
431
+ return Object.freeze({ indexBaseUrl: frames.indexBaseUrl, maxStep: frames.maxStep });
432
+ }
433
+ function pinVerifiedPrefix(input) {
434
+ if (input === void 0) return snapshotFinalizedVerifiedPrefix(input);
435
+ const fields = ownRecord(input, ["maxEntries", "maxBytes"], ["shareKey"]);
436
+ const captured = snapshotFinalizedVerifiedPrefix(fields);
437
+ if (captured === void 0 || captured.maxEntries !== fields.maxEntries || captured.maxBytes !== fields.maxBytes || Reflect.get(captured, "shareKey") !== fields.shareKey) throw new TypeError("Native verified-prefix snapshot must preserve its exact selection");
438
+ return captured;
439
+ }
440
+
441
+ // src/fleetForeign.ts
442
+ function field(input, key) {
443
+ if (input === null || typeof input !== "object") throw new FleetAuthorityError("conflict", "scan-foreign-header");
444
+ const slot = Object.getOwnPropertyDescriptor(input, key);
445
+ if (slot?.enumerable !== true || !("value" in slot)) throw new FleetAuthorityError("conflict", "scan-foreign-header");
446
+ return slot.value;
447
+ }
448
+ function position(value) {
449
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
450
+ }
451
+ function validateSlots(header) {
452
+ const hashes = field(header.transaction, "payload_hashes");
453
+ const schemas = field(header.transaction, "payload_schemas");
454
+ if (!Array.isArray(hashes) || !Array.isArray(schemas) || !Array.isArray(header.payloads) || hashes.length !== schemas.length || hashes.length !== header.payloads.length) throw new FleetAuthorityError("conflict", "scan-foreign-slots");
455
+ for (let index = 0; index < hashes.length; index++) {
456
+ const hash = field(hashes, String(index));
457
+ const schema = field(schemas, String(index));
458
+ const slot = ownRecord(field(header.payloads, String(index)), ["payloadOrdinal", "payloadRoot", "schema", "selected"]);
459
+ if (typeof schema !== "string" || schema.length === 0 || !HashZod.safeParse(hash).success || slot.payloadOrdinal !== index || slot.payloadRoot !== hash || slot.schema !== schema || slot.selected !== false) throw new FleetAuthorityError("conflict", "scan-foreign-slots");
460
+ }
461
+ }
462
+ function validateDomain(header, profile) {
463
+ const ancestors = profile.evidence.forkLineage?.map((edge) => edge.parentChainId) ?? [];
464
+ if (header.network !== profile.evidence.network || header.genesisRoot !== profile.evidence.genesisRoot || header.carryingChainId !== profile.evidence.chainId || header.chainId === profile.evidence.chainId || !ancestors.includes(header.chainId) || header.reason !== "verified-ancestor-domain-not-authority" || field(header.transaction, "chain") !== header.chainId || field(header.transaction, "from") !== header.signer || !AddressZod.safeParse(header.signer).success || !HashZod.safeParse(header.blockRoot).success || !HashZod.safeParse(header.transactionRoot).success) throw new FleetAuthorityError("conflict", "scan-foreign-domain");
465
+ }
466
+ function validateHeader(input, page, profile, from, to) {
467
+ const header = ownRecord(input, [
468
+ "network",
469
+ "chainId",
470
+ "genesisRoot",
471
+ "blockNumber",
472
+ "blockRoot",
473
+ "transactionRoot",
474
+ "transactionIndex",
475
+ "transactionPayloadOrdinal",
476
+ "signer",
477
+ "transaction",
478
+ "payloads",
479
+ "carryingChainId",
480
+ "reason"
481
+ ]);
482
+ validateDomain(header, profile);
483
+ if (!position(header.blockNumber) || header.blockNumber < from || header.blockNumber > to || !position(header.transactionIndex) || !position(header.transactionPayloadOrdinal) || header.transactionPayloadOrdinal < header.transactionIndex) throw new FleetAuthorityError("conflict", "scan-foreign-position");
484
+ if (page.blockClocks.every((clock) => !(clock.blockNumber === header.blockNumber && clock.blockRoot === header.blockRoot && clock.chainId === header.carryingChainId)) || page.headers.some((ordinary) => ordinary.blockNumber === header.blockNumber && ordinary.transactionIndex === header.transactionIndex)) {
485
+ throw new FleetAuthorityError("conflict", "scan-foreign-correspondence");
486
+ }
487
+ validateSlots(header);
488
+ return {
489
+ block: header.blockNumber,
490
+ index: header.transactionIndex,
491
+ ordinal: header.transactionPayloadOrdinal
492
+ };
493
+ }
494
+ function validateForeignHeaders(page, profile, from, to) {
495
+ const result = page;
496
+ if (profile.evidence.foreignTransactions === void 0) {
497
+ if (result.foreignTransactionHeaders !== void 0) throw new FleetAuthorityError("conflict", "scan-foreign-profile");
498
+ return 0;
499
+ }
500
+ if (!Array.isArray(result.foreignTransactionHeaders) || result.foreignTransactionHeaders.length > profile.evidence.limits.maxRoots) throw new FleetAuthorityError("conflict", "scan-foreign-headers");
501
+ let previous;
502
+ for (let index = 0; index < result.foreignTransactionHeaders.length; index++) {
503
+ const header = validateHeader(field(result.foreignTransactionHeaders, String(index)), page, profile, from, to);
504
+ if (previous !== void 0 && (header.block < previous.block || header.block === previous.block && (header.index <= previous.index || header.ordinal <= previous.ordinal))) throw new FleetAuthorityError("conflict", "scan-foreign-order");
505
+ previous = header;
506
+ }
507
+ return result.foreignTransactionHeaders.length;
508
+ }
509
+
510
+ // src/fleetQuery.ts
511
+ import { AddressZod as AddressZod2, HashZod as HashZod2 } from "@xyo-network/service-kit-schemas";
512
+ var grade = "verified-block-committed-query-selection";
513
+ var encoder3 = new TextEncoder();
514
+ function fail(code = "scan-query-exclusion") {
515
+ throw new FleetAuthorityError("conflict", code);
516
+ }
517
+ function spend2(budget, nodes, bytes = 0) {
518
+ budget.nodes += nodes;
519
+ budget.bytes += bytes;
520
+ if (budget.nodes > budget.profile.evidence.limits.maxDecodedNodes || budget.bytes > budget.profile.evidence.limits.maxAggregateBytes) {
521
+ throw new FleetAuthorityError("resource-limit", "scan-query-metadata");
522
+ }
523
+ }
524
+ function field2(input, key) {
525
+ const slot = input !== null && typeof input === "object" ? Object.getOwnPropertyDescriptor(input, key) : void 0;
526
+ return slot?.enumerable === true && "value" in slot ? slot.value : fail();
527
+ }
528
+ function position2(input) {
529
+ return typeof input === "number" && Number.isSafeInteger(input) && input >= 0;
530
+ }
531
+ function dense(input, maximum, budget) {
532
+ if (!Array.isArray(input) || input.length > maximum || Reflect.ownKeys(input).length !== input.length + 1) return fail();
533
+ spend2(budget, input.length + 1);
534
+ for (let i = 0; i < input.length; i++) field2(input, String(i));
535
+ return input;
536
+ }
537
+ function strings(input, budget, address = false) {
538
+ const values = dense(input, budget.profile.evidence.limits.maxRoots, budget);
539
+ for (const value of values) {
540
+ if (typeof value !== "string" || value.length === 0 || value.length > budget.profile.evidence.limits.maxResponseBytes || address && !AddressZod2.safeParse(value).success) return fail();
541
+ spend2(budget, 0, encoder3.encode(value).byteLength);
542
+ }
543
+ return values;
544
+ }
545
+ function scopeMatches(input, expected, budget) {
546
+ const keys = ["authorizers", "chainIds", "schemas"].filter((key) => expected[key] !== void 0);
547
+ const snapshot = ownRecord(input, keys);
548
+ for (const key of keys) {
549
+ const selected = snapshot[key];
550
+ if (!Array.isArray(selected) || selected.length !== expected[key].length) fail("scan-query-request");
551
+ const values = strings(selected, budget, key !== "schemas");
552
+ if (values.some((value, index) => value !== expected[key][index])) fail("scan-query-request");
553
+ }
554
+ }
555
+ function chainAt(profile, block) {
556
+ let chain = profile.evidence.chainId;
557
+ const lineage = profile.evidence.forkLineage ?? [];
558
+ for (const edge of lineage) {
559
+ if (block > edge.forkedAtBlockNumber) break;
560
+ chain = edge.parentChainId;
561
+ }
562
+ return chain;
563
+ }
564
+ function occupiedPositions(page, budget) {
565
+ const occupied = /* @__PURE__ */ new Set();
566
+ for (const rows of [page.headers, page.occurrences, page.foreignTransactionHeaders ?? []]) {
567
+ for (const row of dense(rows, budget.profile.evidence.limits.maxRoots, budget)) {
568
+ const block = field2(row, "blockNumber");
569
+ const index = field2(row, "transactionIndex");
570
+ const ordinal = field2(row, "transactionPayloadOrdinal");
571
+ if (!position2(block) || !position2(index) || !position2(ordinal)) fail();
572
+ occupied.add(`${block}:index:${index}`);
573
+ occupied.add(`${block}:ordinal:${ordinal}`);
574
+ }
575
+ }
576
+ return occupied;
577
+ }
578
+ function clockRows(page, budget) {
579
+ const clocks = /* @__PURE__ */ new Map();
580
+ for (const row of dense(page.blockClocks, budget.profile.evidence.limits.maxBlocks, budget)) {
581
+ const block = field2(row, "blockNumber");
582
+ if (!position2(block) || clocks.has(block)) fail("scan-query-clock");
583
+ clocks.set(block, row);
584
+ }
585
+ return clocks;
586
+ }
587
+ function validateClock(row, clocks, profile) {
588
+ const clock = clocks.get(row.blockNumber);
589
+ if (clock === void 0 || field2(clock, "network") !== profile.evidence.network || field2(clock, "genesisRoot") !== profile.evidence.genesisRoot || field2(clock, "blockRoot") !== row.blockRoot || field2(clock, "chainId") !== row.carryingChainId) fail("scan-query-clock");
590
+ const time = field2(clock, "time");
591
+ if (field2(time, "status") === "authenticated" && (field2(time, "payloadOrdinal") === row.transactionPayloadOrdinal || field2(time, "payloadRoot") === row.transactionRoot)) fail("scan-query-time");
592
+ }
593
+ function validatePosition(row, profile, from, to) {
594
+ if (!position2(row.blockNumber) || row.blockNumber < from || row.blockNumber > to || !position2(row.transactionIndex) || !position2(row.transactionPayloadOrdinal) || row.transactionPayloadOrdinal < row.transactionIndex || row.carryingChainId !== chainAt(profile, row.blockNumber) || !AddressZod2.safeParse(row.declaredChainId).success || !AddressZod2.safeParse(row.declaredFrom).success || !HashZod2.safeParse(row.blockRoot).success || !HashZod2.safeParse(row.transactionRoot).success) fail();
595
+ }
596
+ function validateRecord(input, expected, profile, from, to, clocks, occupied, budget) {
597
+ const row = ownRecord(input, [
598
+ "blockNumber",
599
+ "blockRoot",
600
+ "carryingChainId",
601
+ "transactionIndex",
602
+ "transactionPayloadOrdinal",
603
+ "transactionRoot",
604
+ "declaredChainId",
605
+ "declaredFrom",
606
+ "declaredAddresses",
607
+ "declaredPayloadSchemas",
608
+ "reason",
609
+ "requestSnapshot"
610
+ ]);
611
+ spend2(budget, 12);
612
+ validatePosition(row, profile, from, to);
613
+ const addresses = strings(row.declaredAddresses, budget, true);
614
+ const schemas = strings(row.declaredPayloadSchemas, budget);
615
+ if (addresses.length === 0 || new Set(addresses).size !== addresses.length) fail();
616
+ scopeMatches(row.requestSnapshot, expected, budget);
617
+ const claimed = /* @__PURE__ */ new Set([row.declaredFrom, ...addresses]);
618
+ const noAuthorizer = expected.authorizers?.every((value) => !claimed.has(value)) === true;
619
+ const noSchema = expected.schemas?.every((value) => !schemas.includes(value)) === true;
620
+ const reason = noAuthorizer ? "no-requested-authorizer" : noSchema ? "no-requested-schema" : void 0;
621
+ if (reason === void 0 || row.reason !== reason) fail("scan-query-reason");
622
+ const indexKey = `${row.blockNumber}:index:${row.transactionIndex}`;
623
+ const ordinalKey = `${row.blockNumber}:ordinal:${row.transactionPayloadOrdinal}`;
624
+ if (occupied.has(indexKey) || occupied.has(ordinalKey)) fail("scan-query-overlap");
625
+ occupied.add(indexKey);
626
+ occupied.add(ordinalKey);
627
+ if (pageExcluded(profile, row.blockNumber, from, to)) fail("scan-query-excluded-chain");
628
+ validateClock(row, clocks, profile);
629
+ return {
630
+ block: row.blockNumber,
631
+ index: row.transactionIndex,
632
+ ordinal: row.transactionPayloadOrdinal
633
+ };
634
+ }
635
+ function pageExcluded(profile, block, from, to) {
636
+ return profile.evidence.verifiedPrefix !== void 0 && profile.evidence.forkLineage?.some((edge) => block >= from && block <= to && block <= edge.forkedAtBlockNumber) === true;
637
+ }
638
+ function validateQueryExclusions(page, profile, from, to, expectedScope) {
639
+ const result = page;
640
+ if (profile.evidence.querySelection === void 0) {
641
+ if (result.blockCommittedQueryExclusions !== void 0 || result.scopeCompleteness === grade) fail("scan-query-profile");
642
+ return;
643
+ }
644
+ try {
645
+ if (expectedScope === void 0 || expectedScope.headersOnly !== void 0 || expectedScope.authorizers === void 0 && expectedScope.schemas === void 0 || [expectedScope.authorizers, expectedScope.chainIds, expectedScope.schemas].some((values) => values?.length === 0) || result.scopeCompleteness !== grade) fail("scan-query-grade");
646
+ const budget = {
647
+ nodes: 0,
648
+ bytes: 0,
649
+ profile
650
+ };
651
+ scopeMatches(page.scope, expectedScope, budget);
652
+ const rows = dense(result.blockCommittedQueryExclusions, profile.evidence.limits.maxRoots, budget);
653
+ const occupied = occupiedPositions(page, budget);
654
+ const clocks = clockRows(page, budget);
655
+ let previous;
656
+ for (const row of rows) {
657
+ const current = validateRecord(row, expectedScope, profile, from, to, clocks, occupied, budget);
658
+ if (previous !== void 0 && (current.block < previous.block || current.block === previous.block && (current.index <= previous.index || current.ordinal <= previous.ordinal))) fail("scan-query-order");
659
+ previous = current;
660
+ }
661
+ return grade;
662
+ } catch (error) {
663
+ if (error instanceof FleetAuthorityError) throw error;
664
+ return fail();
665
+ }
666
+ }
667
+
668
+ // src/fleetScope.ts
669
+ function validateRange(input, expected, profile) {
670
+ const range = ownRecord(input, ["chainId", "fromBlockNumber", "fromBlockRoot", "toBlockNumber", "toBlockRoot"]);
671
+ const {
672
+ edge,
673
+ first,
674
+ last
675
+ } = expected;
676
+ if (range.chainId !== edge.parentChainId || range.chainId === profile.evidence.chainId || range.fromBlockNumber !== first || range.toBlockNumber !== last || !HashZod3.safeParse(range.fromBlockRoot).success || !HashZod3.safeParse(range.toBlockRoot).success || first === 0 && range.fromBlockRoot !== profile.evidence.genesisRoot || last === edge.forkedAtBlockNumber && range.toBlockRoot !== edge.forkedAtBlockRoot || first === last && range.fromBlockRoot !== range.toBlockRoot) throw new FleetAuthorityError("conflict", "scan-exclusions");
677
+ }
678
+ function validateGrade(actual, query, foreign) {
679
+ if (query !== void 0) return;
680
+ if (actual !== "verified-native-header-selection-with-domain-exclusions" && foreign > 0) throw new FleetAuthorityError("conflict", "scan-foreign-grade");
681
+ const legacy = ["verified-native-header-selection", "verified-native-header-selection-with-chain-exclusions", "verified-native-header-selection-with-domain-exclusions"];
682
+ if (!legacy.includes(actual)) throw new FleetAuthorityError("conflict", "scan-scope-mode");
683
+ }
684
+ function validateScopeMode(page, profile, from, to, expectedScope) {
685
+ const query = validateQueryExclusions(page, profile, from, to, expectedScope);
686
+ const foreign = validateForeignHeaders(page, profile, from, to);
687
+ const result = page;
688
+ validateGrade(result.scopeCompleteness, query, foreign);
689
+ if (result.scopeCompleteness === "verified-native-header-selection" || query !== void 0 && (profile.evidence.forkLineage === void 0 || profile.evidence.verifiedPrefix === void 0)) {
690
+ if (result.excludedChainRanges !== void 0 && result.excludedChainRanges.length > 0) throw new FleetAuthorityError("conflict", "scan-exclusions");
691
+ return query;
692
+ }
693
+ const lineage = profile.evidence.forkLineage;
694
+ if (lineage === void 0 || profile.evidence.verifiedPrefix === void 0 || !Array.isArray(result.excludedChainRanges)) throw new FleetAuthorityError("conflict", "scan-scope-mode");
695
+ const expected = lineage.map((edge, index) => ({
696
+ edge,
697
+ first: Math.max(from, (lineage[index + 1]?.forkedAtBlockNumber ?? -1) + 1),
698
+ last: Math.min(to, edge.forkedAtBlockNumber)
699
+ })).filter(({ first, last }) => first <= last).toReversed();
700
+ if (query === void 0 && (result.scopeCompleteness === "verified-native-header-selection-with-domain-exclusions" ? foreign : expected.length) === 0 || result.excludedChainRanges.length !== expected.length) throw new FleetAuthorityError("conflict", "scan-exclusion-coverage");
701
+ for (const [index, range] of result.excludedChainRanges.entries()) validateRange(range, expected[index], profile);
702
+ return query;
703
+ }
704
+
705
+ // src/fleetPage.ts
706
+ function nativeFailure(page) {
707
+ const statuses = ["cancelled", "deadline", "conflict", "unsupported", "resource-limit"];
708
+ const status = statuses.includes(page.status) ? page.status : "incomplete";
709
+ return new FleetAuthorityError(status, `native-${page.issues[0]?.code ?? page.status}`);
710
+ }
711
+ function validateForkPage(page, profile, request) {
712
+ const clock = page.anchorClock;
713
+ if (page.scope.chainIds?.length !== 1 || page.scope.chainIds[0] !== profile.evidence.chainId || clock?.chainId !== profile.evidence.chainId || clock.network !== profile.evidence.network || clock.genesisRoot !== profile.evidence.genesisRoot || clock.blockNumber !== request.anchor.blockNumber || clock.blockRoot !== request.anchor.blockRoot) throw new FleetAuthorityError("conflict", "scan-current-chain");
714
+ }
715
+ function validateFleetPage(page, profile, request, from, to, scope) {
716
+ const actual = [
717
+ page.network,
718
+ page.chainId,
719
+ page.genesisRoot,
720
+ page.anchor.blockNumber,
721
+ page.anchor.blockRoot,
722
+ page.assurance,
723
+ page.requestedRange.fromBlockNumber,
724
+ page.requestedRange.toBlockNumber
725
+ ];
726
+ const expected = [
727
+ profile.evidence.network,
728
+ profile.evidence.chainId,
729
+ profile.evidence.genesisRoot,
730
+ request.anchor.blockNumber,
731
+ request.anchor.blockRoot,
732
+ "source-trusted-finalized-replay",
733
+ from,
734
+ to
735
+ ];
736
+ if (actual.some((value, index) => value !== expected[index])) throw new FleetAuthorityError("conflict", "scan-binding");
737
+ if (profile.evidence.querySelection !== void 0 && page.status !== "complete") throw nativeFailure(page);
738
+ const basis = validateScopeMode(page, profile, from, to, scope);
739
+ if (page.scope.authorizers?.length !== 1 || page.scope.authorizers[0] !== request.owner || page.scope.schemas?.length !== scope.schemas.length || page.scope.schemas.some((family, index) => family !== scope.schemas[index])) throw new FleetAuthorityError("conflict", "scan-scope");
740
+ if (page.status !== "complete") throw nativeFailure(page);
741
+ if (profile.evidence.forkLineage !== void 0) validateForkPage(page, profile, request);
742
+ if (page.coveredRange?.fromBlockNumber !== from || page.coveredRange.toBlockNumber !== to || page.continuation !== void 0 || page.issues.length > 0) {
743
+ throw new FleetAuthorityError("incomplete", "scan-coverage");
744
+ }
745
+ return basis;
746
+ }
747
+
748
+ // src/fleetProjection.ts
749
+ function nextPublisherProjection(result) {
750
+ const { publicationBlock: projectionBlock, ...original } = result;
751
+ const context2 = {
752
+ ...original,
753
+ projection: "pending-N+1",
754
+ projectionBlock
755
+ };
756
+ if (result.status === "authorized" || result.status === "absent") {
757
+ return Object.freeze({
758
+ ...context2,
759
+ status: result.status === "authorized" ? "projected-granted" : "projected-absent",
760
+ coveredRange: Object.freeze({ fromBlockNumber: 0, toBlockNumber: result.anchor.blockNumber })
761
+ });
762
+ }
763
+ return Object.freeze(context2);
182
764
  }
765
+
766
+ // src/fleetReaders.ts
183
767
  function pinReaders(seeds, profile) {
184
768
  if (!Array.isArray(seeds) || seeds.length === 0 || seeds.length > profile.resolutionLimits.maxSeeds) throw new RangeError("Explicit bounded root readers required");
185
769
  const ids = /* @__PURE__ */ new Set();
@@ -195,7 +779,7 @@ function pinReaders(seeds, profile) {
195
779
  return Object.freeze({ id: seed.id, reader: Object.freeze({ get }) });
196
780
  }));
197
781
  }
198
- function capacityReaders(seeds, state, maximum, capacity) {
782
+ function capacityReaders(seeds, state, maximum, capacity, meter) {
199
783
  return Object.freeze(seeds.map((seed) => Object.freeze({
200
784
  id: seed.id,
201
785
  reader: Object.freeze({
@@ -206,7 +790,7 @@ function capacityReaders(seeds, state, maximum, capacity) {
206
790
  }
207
791
  state.active++;
208
792
  try {
209
- return await seed.reader.get(...args);
793
+ return await (meter === void 0 ? seed.reader.get(...args) : meter.read(seed.reader.get.bind(seed.reader), ...args));
210
794
  } finally {
211
795
  state.active--;
212
796
  }
@@ -214,6 +798,26 @@ function capacityReaders(seeds, state, maximum, capacity) {
214
798
  })
215
799
  })));
216
800
  }
801
+
802
+ // src/fleetRequests.ts
803
+ import { AddressZod as AddressZod3, HashZod as HashZod4 } from "@xyo-network/service-kit-schemas";
804
+ function pinRequest(input, next = false) {
805
+ const values = ownRecord(input, ["anchor", "owner", "publicationBlock"], ["fleetRoot", "signal", "maxAggregateBytes"]);
806
+ const anchor = ownRecord(values.anchor, ["blockNumber", "blockRoot"]);
807
+ HashZod4.parse(anchor.blockRoot);
808
+ AddressZod3.parse(values.owner);
809
+ if (values.maxAggregateBytes !== void 0 && (typeof values.maxAggregateBytes !== "number" || !Number.isSafeInteger(values.maxAggregateBytes) || values.maxAggregateBytes <= 0)) throw new RangeError("Select a finite positive aggregate request ceiling");
810
+ if (values.fleetRoot !== void 0) HashZod4.parse(values.fleetRoot);
811
+ if (!Number.isSafeInteger(anchor.blockNumber) || anchor.blockNumber < 0 || anchor.blockNumber >= Number.MAX_SAFE_INTEGER || typeof values.publicationBlock !== "number" || !Number.isSafeInteger(values.publicationBlock) || values.publicationBlock < 0 || (next ? values.publicationBlock !== anchor.blockNumber + 1 : values.publicationBlock > anchor.blockNumber)) throw new RangeError("Select an exact publication height within the anchor");
812
+ return Object.freeze({
813
+ ...values,
814
+ anchor: Object.freeze(anchor),
815
+ signal: captureSignal(values.signal)
816
+ });
817
+ }
818
+
819
+ // src/createFleetAuthority.ts
820
+ var b4Families = Object.freeze([FleetSchema, FleetMemberSchema, FleetPublicationScopeSchema, FleetControlSchema]);
217
821
  function context(profile, request) {
218
822
  return Object.freeze({
219
823
  assurance: "source-trusted-finalized-replay",
@@ -229,38 +833,8 @@ function context(profile, request) {
229
833
  function positionAfter(left, right) {
230
834
  return left.blockNumber > right.blockNumber || left.blockNumber === right.blockNumber && (left.transactionIndex > right.transactionIndex || left.transactionIndex === right.transactionIndex && left.payloadOrdinal > right.payloadOrdinal);
231
835
  }
232
- function nativeFailure(page) {
233
- const statuses = ["cancelled", "deadline", "conflict", "unsupported", "resource-limit"];
234
- const status = statuses.includes(page.status) ? page.status : "incomplete";
235
- return new FleetAuthorityError(status, `native-${page.issues[0]?.code ?? page.status}`);
236
- }
237
- function validatePage(page, profile, request, from, to) {
238
- const actual = [
239
- page.network,
240
- page.chainId,
241
- page.genesisRoot,
242
- page.anchor.blockNumber,
243
- page.anchor.blockRoot,
244
- page.assurance,
245
- page.requestedRange.fromBlockNumber,
246
- page.requestedRange.toBlockNumber
247
- ];
248
- const expected = [
249
- profile.evidence.network,
250
- profile.evidence.chainId,
251
- profile.evidence.genesisRoot,
252
- request.anchor.blockNumber,
253
- request.anchor.blockRoot,
254
- "source-trusted-finalized-replay",
255
- from,
256
- to
257
- ];
258
- if (actual.some((value, index) => value !== expected[index])) throw new FleetAuthorityError("conflict", "scan-binding");
259
- if (page.scopeCompleteness !== "verified-native-header-selection" || page.scope.authorizers?.length !== 1 || page.scope.authorizers[0] !== request.owner || page.scope.schemas?.length !== b4Families.length || page.scope.schemas.some((family, index) => family !== b4Families[index])) throw new FleetAuthorityError("conflict", "scan-scope");
260
- if (page.status !== "complete") throw nativeFailure(page);
261
- if (page.coveredRange?.fromBlockNumber !== from || page.coveredRange.toBlockNumber !== to || page.continuation !== void 0 || page.issues.length > 0) {
262
- throw new FleetAuthorityError("incomplete", "scan-coverage");
263
- }
836
+ function scanCeiling(meter, maximum) {
837
+ return meter === void 0 ? {} : { maxAggregateBytes: Math.min(maximum, meter.remaining()) };
264
838
  }
265
839
  function createFleetAuthority(input) {
266
840
  const profile = pinProfile(input);
@@ -268,6 +842,8 @@ function createFleetAuthority(input) {
268
842
  const readState = { active: 0 };
269
843
  const seeds = pinReaders(profile.seeds, profile);
270
844
  let activeCalls = 0;
845
+ const historyDepth = Math.min(2147483647, Math.max(profile.evidence.limits.maxDecodedDepth, profile.resolutionLimits.maxDepth) + 8);
846
+ const history = profile.verifiedHistory === void 0 ? void 0 : new VerifiedFleetHistory(profile.verifiedHistory, historyDepth);
271
847
  async function resolved(root, family, work) {
272
848
  work.control.assertActive();
273
849
  const cached = work.roots.get(root);
@@ -294,23 +870,31 @@ function createFleetAuthority(input) {
294
870
  if (family !== FleetControlSchema) work.declarations.set(root, Object.freeze({ root, payload: result.payload }));
295
871
  return result.payload;
296
872
  }
297
- async function scan(request, control) {
873
+ async function scan(request, work, fromBlockNumber = 0) {
874
+ const { control, meter } = work;
298
875
  if (request.anchor.blockNumber + 1 > profile.limits.maxBlocks) throw new FleetAuthorityError("resource-limit", "history-blocks");
299
876
  const occurrences = [];
300
- let pages = 0;
301
- for (let from = 0; from <= request.anchor.blockNumber; ) {
877
+ for (let from = fromBlockNumber; from <= request.anchor.blockNumber; ) {
302
878
  control.assertActive();
303
- if (++pages > profile.limits.maxPages) throw new FleetAuthorityError("resource-limit", "scan-pages");
879
+ if (++work.pages.count > profile.limits.maxPages) throw new FleetAuthorityError("resource-limit", "scan-pages");
304
880
  const to = Math.min(request.anchor.blockNumber, from + profile.evidence.limits.maxBlocks - 1);
881
+ const scope = Object.freeze({
882
+ authorizers: Object.freeze([request.owner]),
883
+ schemas: b4Families,
884
+ ...profile.evidence.forkLineage !== void 0 && { chainIds: Object.freeze([profile.evidence.chainId]) }
885
+ });
305
886
  const page = await evidence.scanScoped({
306
887
  anchor: request.anchor,
307
888
  fromBlockNumber: from,
308
889
  toBlockNumber: to,
309
890
  signal: control.signal,
310
- scope: { authorizers: [request.owner], schemas: b4Families }
891
+ ...scanCeiling(meter, profile.evidence.limits.maxAggregateBytes),
892
+ scope
311
893
  });
894
+ chargeNativeResources(meter, page.resources);
312
895
  control.assertActive();
313
- validatePage(page, profile, request, from, to);
896
+ const basis = validateFleetPage(page, profile, request, from, to, scope);
897
+ if (basis !== void 0) work.queryBasis.scopeCompleteness = basis;
314
898
  for (const fact of page.occurrences) {
315
899
  const previous = occurrences.at(-1);
316
900
  if (fact.network !== profile.evidence.network || fact.chainId !== profile.evidence.chainId || fact.genesisRoot !== profile.evidence.genesisRoot || fact.signer !== request.owner || !b4Families.includes(fact.schema) || fact.blockNumber < from || fact.blockNumber > to || previous !== void 0 && !positionAfter(fact, previous)) throw new FleetAuthorityError("conflict", "occurrence-binding-order");
@@ -367,8 +951,7 @@ function createFleetAuthority(input) {
367
951
  if (roots.size > profile.limits.maxFleets) throw new FleetAuthorityError("resource-limit", "fleets");
368
952
  return { roots, controls };
369
953
  }
370
- async function enumerateWork(request, work) {
371
- const occurrences = await scan(request, work.control);
954
+ async function foldWork(request, work, occurrences) {
372
955
  const { roots, controls } = await collect(request, work, occurrences);
373
956
  const views = [];
374
957
  for (const root of roots) {
@@ -405,7 +988,10 @@ function createFleetAuthority(input) {
405
988
  assurance: "source-trusted-finalized-replay"
406
989
  }));
407
990
  }
408
- return Object.freeze({
991
+ const basis = work.queryBasis.scopeCompleteness;
992
+ if (profile.evidence.querySelection === void 0 !== (basis === void 0)) throw new FleetAuthorityError("conflict", "history-query-basis");
993
+ const result = Object.freeze({
994
+ ...basis !== void 0 && { scopeCompleteness: basis },
409
995
  ...context(profile, request),
410
996
  status: "complete",
411
997
  correspondence: "native-sdk-verified",
@@ -413,44 +999,112 @@ function createFleetAuthority(input) {
413
999
  coveredRange: Object.freeze({ fromBlockNumber: 0, toBlockNumber: request.anchor.blockNumber }),
414
1000
  views: Object.freeze(views)
415
1001
  });
1002
+ return { result, controls };
1003
+ }
1004
+ function restore(entry, work) {
1005
+ const expected = profile.evidence.querySelection === void 0 ? void 0 : "verified-block-committed-query-selection";
1006
+ if (entry.scopeCompleteness !== expected) throw new FleetAuthorityError("conflict", "history-query-policy");
1007
+ if (entry.scopeCompleteness !== void 0) work.queryBasis.scopeCompleteness = entry.scopeCompleteness;
1008
+ for (const [root, payload] of entry.roots) {
1009
+ if (!work.roots.has(root) && work.roots.size >= profile.limits.maxRootReads) throw new FleetAuthorityError("resource-limit", "root-reads");
1010
+ work.roots.set(root, payload);
1011
+ if (payload.schema !== FleetControlSchema) work.declarations.set(root, Object.freeze({ root, payload }));
1012
+ }
1013
+ }
1014
+ async function replayWork(request, work) {
1015
+ const prior = history?.get(request.owner);
1016
+ let occurrences;
1017
+ if (prior === void 0) occurrences = await scan(request, work);
1018
+ else {
1019
+ restore(prior, work);
1020
+ const sameHeight = request.anchor.blockNumber === prior.anchor.blockNumber;
1021
+ if (sameHeight && request.anchor.blockRoot !== prior.anchor.blockRoot) throw new FleetAuthorityError("conflict", "history-anchor");
1022
+ if (sameHeight) occurrences = prior.occurrences;
1023
+ else if (request.anchor.blockNumber < prior.anchor.blockNumber) {
1024
+ await scan(request, work, request.anchor.blockNumber);
1025
+ occurrences = prior.occurrences.filter((fact) => fact.blockNumber <= request.anchor.blockNumber);
1026
+ } else {
1027
+ await scan({ ...request, anchor: prior.anchor }, work, prior.anchor.blockNumber);
1028
+ occurrences = [...prior.occurrences, ...await scan(request, work, prior.anchor.blockNumber + 1)];
1029
+ }
1030
+ }
1031
+ if (occurrences.length > profile.limits.maxOccurrences) throw new FleetAuthorityError("resource-limit", "occurrences");
1032
+ if (history !== void 0 && (prior === void 0 || request.anchor.blockNumber > prior.anchor.blockNumber)) {
1033
+ const completeRequest = {
1034
+ ...request,
1035
+ fleetRoot: void 0,
1036
+ publicationBlock: request.anchor.blockNumber + 1
1037
+ };
1038
+ const complete = await foldWork(completeRequest, work, occurrences);
1039
+ work.control.assertActive();
1040
+ history.publish({
1041
+ owner: request.owner,
1042
+ anchor: request.anchor,
1043
+ occurrences,
1044
+ roots: work.roots.entries().toArray(),
1045
+ ...complete.result.scopeCompleteness !== void 0 && { scopeCompleteness: complete.result.scopeCompleteness }
1046
+ });
1047
+ if (request.fleetRoot === void 0 && request.publicationBlock === completeRequest.publicationBlock) return complete;
1048
+ }
1049
+ return await foldWork(request, work, occurrences);
1050
+ }
1051
+ async function enumerateWork(request, work) {
1052
+ const replay = await replayWork(request, work);
1053
+ return replay.result;
416
1054
  }
417
1055
  async function execute(request, startedAt, operation) {
418
1056
  const control = operationControl(request.signal, profile.limits.totalTimeoutMs, startedAt);
419
1057
  let admitted = false;
1058
+ let meter;
420
1059
  try {
1060
+ const bound = BigInt(profile.limits.maxPages) * BigInt(profile.evidence.limits.maxAggregateBytes) + BigInt(profile.limits.maxRootReads) * BigInt(profile.resolutionLimits.maxSeeds) * BigInt(profile.resolutionLimits.maxBodyBytes);
1061
+ if (request.maxAggregateBytes !== void 0 || profile.evidence.verifiedPrefix !== void 0) {
1062
+ meter = new FleetMeter(request.maxAggregateBytes ?? Number(bound > BigInt(Number.MAX_SAFE_INTEGER) ? BigInt(Number.MAX_SAFE_INTEGER) : bound), profile.resolutionLimits);
1063
+ }
1064
+ if (request.maxAggregateBytes !== void 0 && BigInt(request.maxAggregateBytes) > bound) throw new FleetAuthorityError("resource-limit", "aggregate-ceiling");
421
1065
  control.assertActive();
422
1066
  if (activeCalls >= profile.limits.maxConcurrentCalls) throw new FleetAuthorityError("resource-limit", "composition-capacity");
423
1067
  activeCalls++;
424
1068
  admitted = true;
425
1069
  const capacity = { limited: false };
426
- return await operation({
1070
+ const result = await operation({
427
1071
  control,
1072
+ ...meter !== void 0 && { meter },
428
1073
  roots: /* @__PURE__ */ new Map(),
1074
+ pages: { count: 0 },
1075
+ queryBasis: {},
429
1076
  declarations: /* @__PURE__ */ new Map(),
430
1077
  capacity,
431
- seeds: capacityReaders(seeds, readState, profile.limits.maxConcurrentReads, capacity)
1078
+ seeds: capacityReaders(seeds, readState, profile.limits.maxConcurrentReads, capacity, meter)
432
1079
  });
1080
+ return meter === void 0 ? result : Object.freeze({ ...result, resources: meter.resources() });
433
1081
  } catch (error) {
434
1082
  const failure = error instanceof FleetAuthorityError ? error : new FleetAuthorityError("incomplete", "composition-source");
435
1083
  return Object.freeze({
436
1084
  ...context(profile, request),
437
1085
  status: failure.status,
438
- code: failure.code
1086
+ code: failure.code,
1087
+ ...meter !== void 0 && { resources: meter.resources() }
439
1088
  });
440
1089
  } finally {
441
1090
  if (admitted) activeCalls--;
1091
+ meter?.close();
442
1092
  control.dispose();
443
1093
  }
444
1094
  }
445
1095
  async function publisherWork(request, scopeRoot, publisherAddress, work) {
1096
+ const retained = history?.get(request.owner);
1097
+ if (retained !== void 0) restore(retained, work);
446
1098
  const scope = FleetPublicationScopeZod.parse(await resolved(scopeRoot, FleetPublicationScopeSchema, work));
447
1099
  const result = await enumerateWork({ ...request, fleetRoot: scope.fleetRoot }, work);
1100
+ const basis = result.scopeCompleteness === void 0 ? {} : { scopeCompleteness: result.scopeCompleteness };
448
1101
  const view = result.views[0];
449
1102
  const matches = view?.fleetActive ? view.grants.filter((grant2) => grant2.scopeRoot === scopeRoot && grant2.publisherAddress === publisherAddress) : [];
450
1103
  if (matches.length > 1) throw new FleetAuthorityError("conflict", "publisher-ambiguity");
451
1104
  const grant = matches[0];
452
1105
  return grant === void 0 ? Object.freeze({
453
1106
  ...context(profile, request),
1107
+ ...basis,
454
1108
  status: "absent",
455
1109
  correspondence: "native-sdk-verified",
456
1110
  history: "complete-genesis-to-anchor",
@@ -458,6 +1112,7 @@ function createFleetAuthority(input) {
458
1112
  publisherAddress
459
1113
  }) : Object.freeze({
460
1114
  ...context(profile, request),
1115
+ ...basis,
461
1116
  status: "authorized",
462
1117
  correspondence: "native-sdk-verified",
463
1118
  history: "complete-genesis-to-anchor",
@@ -474,30 +1129,49 @@ function createFleetAuthority(input) {
474
1129
  const request = pinRequest(inputRequest);
475
1130
  return await execute(request, startedAt, (work) => enumerateWork(request, work));
476
1131
  },
1132
+ async enumerateHistoricalPublishers(inputRequest) {
1133
+ const startedAt = fleetNow();
1134
+ const values = ownRecord(inputRequest, ["anchor", "owner"], ["fleetRoot", "signal", "maxAggregateBytes"]);
1135
+ const anchor = ownRecord(values.anchor, ["blockNumber", "blockRoot"]);
1136
+ const request = pinRequest({
1137
+ ...values,
1138
+ anchor,
1139
+ publicationBlock: anchor.blockNumber + 1
1140
+ }, true);
1141
+ let controls = [];
1142
+ const result = await execute(request, startedAt, async (work) => {
1143
+ const replay = await replayWork(request, work);
1144
+ controls = replay.controls;
1145
+ return replay.result;
1146
+ });
1147
+ return historicalPublisherResult(result, controls, request.fleetRoot);
1148
+ },
477
1149
  async resolvePublisher(inputRequest) {
478
1150
  const startedAt = fleetNow();
479
- const values = ownRecord(inputRequest, ["anchor", "owner", "publicationBlock", "publisherAddress", "scopeRoot"], ["signal"]);
480
- const publisherAddress = AddressZod.parse(values.publisherAddress);
481
- const scopeRoot = HashZod.parse(values.scopeRoot);
1151
+ const values = ownRecord(inputRequest, ["anchor", "owner", "publicationBlock", "publisherAddress", "scopeRoot"], ["signal", "maxAggregateBytes"]);
1152
+ const publisherAddress = AddressZod4.parse(values.publisherAddress);
1153
+ const scopeRoot = HashZod5.parse(values.scopeRoot);
482
1154
  const request = pinRequest({
483
1155
  anchor: values.anchor,
484
1156
  owner: values.owner,
485
1157
  publicationBlock: values.publicationBlock,
486
- ...values.signal !== void 0 && { signal: values.signal }
1158
+ ...values.signal !== void 0 && { signal: values.signal },
1159
+ ...values.maxAggregateBytes !== void 0 && { maxAggregateBytes: values.maxAggregateBytes }
487
1160
  });
488
1161
  return await execute(request, startedAt, (work) => publisherWork(request, scopeRoot, publisherAddress, work));
489
1162
  },
490
1163
  async projectNextPublisher(inputRequest) {
491
1164
  const startedAt = fleetNow();
492
- const values = ownRecord(inputRequest, ["anchor", "owner", "publisherAddress", "scopeRoot"], ["signal"]);
1165
+ const values = ownRecord(inputRequest, ["anchor", "owner", "publisherAddress", "scopeRoot"], ["signal", "maxAggregateBytes"]);
493
1166
  const anchor = ownRecord(values.anchor, ["blockNumber", "blockRoot"]);
494
- const publisherAddress = AddressZod.parse(values.publisherAddress);
495
- const scopeRoot = HashZod.parse(values.scopeRoot);
1167
+ const publisherAddress = AddressZod4.parse(values.publisherAddress);
1168
+ const scopeRoot = HashZod5.parse(values.scopeRoot);
496
1169
  const request = pinRequest({
497
1170
  anchor,
498
1171
  owner: values.owner,
499
1172
  publicationBlock: anchor.blockNumber + 1,
500
- ...values.signal !== void 0 && { signal: values.signal }
1173
+ ...values.signal !== void 0 && { signal: values.signal },
1174
+ ...values.maxAggregateBytes !== void 0 && { maxAggregateBytes: values.maxAggregateBytes }
501
1175
  }, true);
502
1176
  const result = await execute(request, startedAt, (work) => publisherWork(request, scopeRoot, publisherAddress, work));
503
1177
  return nextPublisherProjection(result);
@@ -559,18 +1233,18 @@ function endpointPolicy(value) {
559
1233
  return value;
560
1234
  }
561
1235
  function parsedEndpoint(value, policyValue) {
562
- const text = endpointText(value);
1236
+ const text2 = endpointText(value);
563
1237
  const policy = endpointPolicy(policyValue);
564
1238
  let parsed;
565
1239
  try {
566
- parsed = new URL(text);
1240
+ parsed = new URL(text2);
567
1241
  } catch {
568
1242
  throw new TypeError("endpoint must be an unambiguous absolute HTTP(S) URL");
569
1243
  }
570
1244
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || parsed.hostname === "" || parsed.username !== "" || parsed.password !== "") {
571
1245
  throw new TypeError("endpoint must be an unambiguous absolute HTTP(S) URL");
572
1246
  }
573
- const inputWithoutTrailingSlashes = text.replace(/\/+$/u, "");
1247
+ const inputWithoutTrailingSlashes = text2.replace(/\/+$/u, "");
574
1248
  const parsedWithoutTrailingSlashes = parsed.href.replace(/\/+$/u, "");
575
1249
  if (parsedWithoutTrailingSlashes !== inputWithoutTrailingSlashes) {
576
1250
  throw new TypeError("endpoint must not require URL normalization");
@@ -642,6 +1316,9 @@ async function createXl1DataLakeSeed(options) {
642
1316
  }
643
1317
  export {
644
1318
  createFleetAuthority,
645
- createXl1DataLakeSeed
1319
+ createXl1DataLakeSeed,
1320
+ snapshotFleetQuerySelection,
1321
+ snapshotFleetSelectedPayloadSource,
1322
+ snapshotFleetVerifiedHistory
646
1323
  };
647
1324
  //# sourceMappingURL=index.mjs.map