@opendatalabs/personal-server-ts-lite 1.34.2 → 1.35.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.
- package/dist/additions-crypto.d.ts +1 -1
- package/dist/additions-crypto.d.ts.map +1 -1
- package/dist/additions-crypto.js +16 -6
- package/dist/additions-crypto.js.map +1 -1
- package/dist/additions-protocol.d.ts +9 -1
- package/dist/additions-protocol.d.ts.map +1 -1
- package/dist/additions-protocol.js.map +1 -1
- package/dist/additions-session.d.ts +2 -0
- package/dist/additions-session.d.ts.map +1 -1
- package/dist/additions-session.js +29 -4
- package/dist/additions-session.js.map +1 -1
- package/dist/additions-transport.d.ts +10 -2
- package/dist/additions-transport.d.ts.map +1 -1
- package/dist/additions-transport.js +143 -48
- package/dist/additions-transport.js.map +1 -1
- package/dist/additions-worker.bundle.js +538 -101
- package/dist/additions-worker.js +45 -24
- package/dist/additions-worker.js.map +1 -1
- package/dist/browser-runtime.d.ts +23 -0
- package/dist/browser-runtime.d.ts.map +1 -1
- package/dist/browser-runtime.js +38 -1
- package/dist/browser-runtime.js.map +1 -1
- package/dist/canonical-persistence.d.ts +53 -0
- package/dist/canonical-persistence.d.ts.map +1 -0
- package/dist/canonical-persistence.js +13 -0
- package/dist/canonical-persistence.js.map +1 -0
- package/dist/canonical-store.d.ts +395 -0
- package/dist/canonical-store.d.ts.map +1 -0
- package/dist/canonical-store.js +1807 -0
- package/dist/canonical-store.js.map +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +154 -1
- package/dist/client.js.map +1 -1
- package/dist/diagnostics.d.ts +3 -0
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +9 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/history-probe-worker.bundle.js +31216 -0
- package/dist/history-probe.worker.d.ts +35 -0
- package/dist/history-probe.worker.d.ts.map +1 -0
- package/dist/history-probe.worker.js +160 -0
- package/dist/history-probe.worker.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-store.d.ts.map +1 -1
- package/dist/mcp-store.js +109 -19
- package/dist/mcp-store.js.map +1 -1
- package/dist/oura-import.d.ts +2 -0
- package/dist/oura-import.d.ts.map +1 -0
- package/dist/oura-import.js +3 -0
- package/dist/oura-import.js.map +1 -0
- package/dist/replication-coordinator-state.d.ts +19 -0
- package/dist/replication-coordinator-state.d.ts.map +1 -0
- package/dist/replication-coordinator-state.js +20 -0
- package/dist/replication-coordinator-state.js.map +1 -0
- package/dist/replication-door.d.ts +17 -0
- package/dist/replication-door.d.ts.map +1 -0
- package/dist/replication-door.js +23 -0
- package/dist/replication-door.js.map +1 -0
- package/dist/replication-engine.d.ts +49 -0
- package/dist/replication-engine.d.ts.map +1 -0
- package/dist/replication-engine.js +589 -0
- package/dist/replication-engine.js.map +1 -0
- package/dist/replication-host.d.ts +92 -0
- package/dist/replication-host.d.ts.map +1 -0
- package/dist/replication-host.js +135 -0
- package/dist/replication-host.js.map +1 -0
- package/dist/replication-ports.d.ts +194 -0
- package/dist/replication-ports.d.ts.map +1 -0
- package/dist/replication-ports.js +58 -0
- package/dist/replication-ports.js.map +1 -0
- package/dist/replication-runtime.d.ts +64 -0
- package/dist/replication-runtime.d.ts.map +1 -0
- package/dist/replication-runtime.js +79 -0
- package/dist/replication-runtime.js.map +1 -0
- package/dist/replication-storage.d.ts +42 -0
- package/dist/replication-storage.d.ts.map +1 -0
- package/dist/replication-storage.js +173 -0
- package/dist/replication-storage.js.map +1 -0
- package/dist/runtime.d.ts +20 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +80 -1
- package/dist/runtime.js.map +1 -1
- package/dist/state.d.ts +1 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js.map +1 -1
- package/dist/storage.d.ts +15 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +352 -146
- package/dist/storage.js.map +1 -1
- package/dist/sync.d.ts +8 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +25 -7
- package/dist/sync.js.map +1 -1
- package/package.json +8 -4
|
@@ -24051,12 +24051,12 @@ function describe(description) {
|
|
|
24051
24051
|
return ch2;
|
|
24052
24052
|
}
|
|
24053
24053
|
// @__NO_SIDE_EFFECTS__
|
|
24054
|
-
function meta(
|
|
24054
|
+
function meta(metadata2) {
|
|
24055
24055
|
const ch2 = new $ZodCheck({ check: "meta" });
|
|
24056
24056
|
ch2._zod.onattach = [
|
|
24057
24057
|
(inst) => {
|
|
24058
24058
|
const existing = globalRegistry.get(inst) ?? {};
|
|
24059
|
-
globalRegistry.add(inst, { ...existing, ...
|
|
24059
|
+
globalRegistry.add(inst, { ...existing, ...metadata2 });
|
|
24060
24060
|
}
|
|
24061
24061
|
];
|
|
24062
24062
|
ch2._zod.check = () => {
|
|
@@ -29642,6 +29642,288 @@ var DerivativeStatusSchema = external_exports.object({
|
|
|
29642
29642
|
retryAfterSeconds: nullable2(external_exports.number())
|
|
29643
29643
|
});
|
|
29644
29644
|
|
|
29645
|
+
// ../core/dist/sync/tombstone.js
|
|
29646
|
+
var TOMBSTONE_DATA_HASH_LABEL = "vana.data-point.tombstone.v1";
|
|
29647
|
+
var TOMBSTONE_METADATA_HASH_LABEL = "vana.data-point.tombstone.metadata.v1";
|
|
29648
|
+
var TOMBSTONE_DATA_HASH = keccak256(stringToHex(TOMBSTONE_DATA_HASH_LABEL));
|
|
29649
|
+
var TOMBSTONE_METADATA_HASH = keccak256(stringToHex(TOMBSTONE_METADATA_HASH_LABEL));
|
|
29650
|
+
function isTombstoneRecord(record2) {
|
|
29651
|
+
return record2.dataHash.toLowerCase() === TOMBSTONE_DATA_HASH && record2.metadataHash.toLowerCase() === TOMBSTONE_METADATA_HASH;
|
|
29652
|
+
}
|
|
29653
|
+
|
|
29654
|
+
// ../core/dist/sync/data-point-id.js
|
|
29655
|
+
function computeDataPointId(ownerAddress, scope) {
|
|
29656
|
+
return keccak256(encodeAbiParameters([
|
|
29657
|
+
{ name: "ownerAddress", type: "address" },
|
|
29658
|
+
{ name: "scope", type: "string" }
|
|
29659
|
+
], [ownerAddress.toLowerCase(), scope]));
|
|
29660
|
+
}
|
|
29661
|
+
|
|
29662
|
+
// ../core/dist/lineage/lineage.js
|
|
29663
|
+
var LINEAGE_KEY = "$lineage";
|
|
29664
|
+
var BYTES32_HEX = /^0x[0-9a-fA-F]{64}$/;
|
|
29665
|
+
function isRecord2(value) {
|
|
29666
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
29667
|
+
}
|
|
29668
|
+
var StoredLineageMalformedError = class extends Error {
|
|
29669
|
+
constructor(detail) {
|
|
29670
|
+
super(`Stored $lineage is malformed: ${detail}`);
|
|
29671
|
+
this.name = "StoredLineageMalformedError";
|
|
29672
|
+
}
|
|
29673
|
+
};
|
|
29674
|
+
function readStoredLineage(data) {
|
|
29675
|
+
if (!isRecord2(data) || !(LINEAGE_KEY in data))
|
|
29676
|
+
return null;
|
|
29677
|
+
const value = data[LINEAGE_KEY];
|
|
29678
|
+
if (!isRecord2(value)) {
|
|
29679
|
+
throw new StoredLineageMalformedError("not an object");
|
|
29680
|
+
}
|
|
29681
|
+
const sources = value.sources;
|
|
29682
|
+
if (!Array.isArray(sources) || !sources.every((id) => typeof id === "string" && BYTES32_HEX.test(id))) {
|
|
29683
|
+
throw new StoredLineageMalformedError("sources is not a list of bytes32 ids");
|
|
29684
|
+
}
|
|
29685
|
+
if (typeof value.writtenAt !== "string") {
|
|
29686
|
+
throw new StoredLineageMalformedError("writtenAt is not a string");
|
|
29687
|
+
}
|
|
29688
|
+
return {
|
|
29689
|
+
sources: sources.map((id) => id.toLowerCase()),
|
|
29690
|
+
writtenAt: value.writtenAt
|
|
29691
|
+
};
|
|
29692
|
+
}
|
|
29693
|
+
|
|
29694
|
+
// ../core/dist/storage/adapters/interface.js
|
|
29695
|
+
var StoredBlobConflictError = class extends Error {
|
|
29696
|
+
key;
|
|
29697
|
+
constructor(key) {
|
|
29698
|
+
super(`Storage key ${key} already holds different bytes`);
|
|
29699
|
+
this.key = key;
|
|
29700
|
+
this.name = "StoredBlobConflictError";
|
|
29701
|
+
}
|
|
29702
|
+
};
|
|
29703
|
+
|
|
29704
|
+
// ../core/dist/publication/publish.js
|
|
29705
|
+
var NeedsFencedPublicationError = class extends Error {
|
|
29706
|
+
scope;
|
|
29707
|
+
reason;
|
|
29708
|
+
retryable;
|
|
29709
|
+
code = "NEEDS_FENCED_PUBLICATION";
|
|
29710
|
+
constructor(scope, reason, retryable = true) {
|
|
29711
|
+
super(`Needs fenced publication for ${scope}: ${reason}`);
|
|
29712
|
+
this.scope = scope;
|
|
29713
|
+
this.reason = reason;
|
|
29714
|
+
this.retryable = retryable;
|
|
29715
|
+
this.name = "NeedsFencedPublicationError";
|
|
29716
|
+
}
|
|
29717
|
+
};
|
|
29718
|
+
var sameHash = (a2, b2) => a2.toLowerCase() === b2.toLowerCase();
|
|
29719
|
+
function metadata(scope, collectedAt, sizeBytes) {
|
|
29720
|
+
return keccak256(stringToHex(JSON.stringify({ scope, collectedAt, sizeBytes })));
|
|
29721
|
+
}
|
|
29722
|
+
async function publishVersion(options) {
|
|
29723
|
+
const { envelope, storageAdapter } = options;
|
|
29724
|
+
const { scope } = envelope;
|
|
29725
|
+
const password = Array.from(deriveScopeKey(options.masterKey, scope), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
29726
|
+
const plaintext = new TextEncoder().encode(JSON.stringify(envelope));
|
|
29727
|
+
const lineage = readStoredLineage(envelope.data);
|
|
29728
|
+
function candidate(env, bytes, hash3) {
|
|
29729
|
+
return {
|
|
29730
|
+
dataHash: hash3,
|
|
29731
|
+
metadataHash: metadata(scope, env.collectedAt, bytes.byteLength),
|
|
29732
|
+
sizeBytes: bytes.byteLength,
|
|
29733
|
+
lineage: readStoredLineage(env.data)
|
|
29734
|
+
};
|
|
29735
|
+
}
|
|
29736
|
+
return publishPreparedVersion({
|
|
29737
|
+
...options,
|
|
29738
|
+
scope,
|
|
29739
|
+
storageAdapter,
|
|
29740
|
+
async prepare() {
|
|
29741
|
+
const encrypted = await encryptWithPassword(plaintext, password);
|
|
29742
|
+
return {
|
|
29743
|
+
encrypted,
|
|
29744
|
+
wanted: {
|
|
29745
|
+
...candidate(envelope, encrypted, keccak256(plaintext)),
|
|
29746
|
+
lineage
|
|
29747
|
+
},
|
|
29748
|
+
async verifyStored(bytes) {
|
|
29749
|
+
const clear = await decryptWithPassword(bytes, password);
|
|
29750
|
+
const env = DataFileEnvelopeSchema.parse(JSON.parse(new TextDecoder().decode(clear)));
|
|
29751
|
+
if (env.scope !== scope || !Number.isFinite(Date.parse(env.collectedAt)))
|
|
29752
|
+
throw new Error("Publication envelope scope/timestamp mismatch");
|
|
29753
|
+
return candidate(env, bytes, keccak256(clear));
|
|
29754
|
+
}
|
|
29755
|
+
};
|
|
29756
|
+
}
|
|
29757
|
+
});
|
|
29758
|
+
}
|
|
29759
|
+
async function publishPreparedVersion(options) {
|
|
29760
|
+
const { scope, storageAdapter, fencedPublication, signer } = options;
|
|
29761
|
+
const isDeleted = (row) => Boolean(row.deletedAt) || isTombstoneRecord(row);
|
|
29762
|
+
let fence = await fencedPublication?.read({
|
|
29763
|
+
ownerAddress: options.ownerAddress,
|
|
29764
|
+
scope
|
|
29765
|
+
});
|
|
29766
|
+
let head = fence ? fence.head : options.head;
|
|
29767
|
+
await options.checkHead?.(head ?? null);
|
|
29768
|
+
function requireFence(reason) {
|
|
29769
|
+
if (!fence)
|
|
29770
|
+
throw new NeedsFencedPublicationError(scope, reason);
|
|
29771
|
+
return fence;
|
|
29772
|
+
}
|
|
29773
|
+
function checkDeletion() {
|
|
29774
|
+
if (!head || !isDeleted(head))
|
|
29775
|
+
return;
|
|
29776
|
+
requireFence("publication crosses a deletion");
|
|
29777
|
+
if (options.acknowledgedDeletionVersion !== BigInt(head.expectedVersion))
|
|
29778
|
+
throw new NeedsFencedPublicationError(scope, "tombstone was not acknowledged by this publication");
|
|
29779
|
+
}
|
|
29780
|
+
checkDeletion();
|
|
29781
|
+
const { encrypted, wanted, verifyStored } = await options.prepare();
|
|
29782
|
+
const wantedHash = wanted.dataHash;
|
|
29783
|
+
const keyUrl = (version5) => storageAdapter.urlForKey(`${scope}/${version5}`);
|
|
29784
|
+
async function readCandidate(version5) {
|
|
29785
|
+
const bytes = await storageAdapter.download(keyUrl(version5));
|
|
29786
|
+
return verifyStored(bytes);
|
|
29787
|
+
}
|
|
29788
|
+
async function commit(version5, value, mode) {
|
|
29789
|
+
const request = {
|
|
29790
|
+
ownerAddress: options.ownerAddress,
|
|
29791
|
+
scope,
|
|
29792
|
+
dataHash: value.dataHash,
|
|
29793
|
+
metadataHash: value.metadataHash,
|
|
29794
|
+
expectedVersion: String(version5),
|
|
29795
|
+
signature: await signer.signAddData({
|
|
29796
|
+
ownerAddress: options.ownerAddress,
|
|
29797
|
+
scope,
|
|
29798
|
+
dataHash: value.dataHash,
|
|
29799
|
+
metadataHash: value.metadataHash,
|
|
29800
|
+
expectedVersion: version5
|
|
29801
|
+
})
|
|
29802
|
+
};
|
|
29803
|
+
const lineage = value.lineage;
|
|
29804
|
+
let lineageFields;
|
|
29805
|
+
if (lineage) {
|
|
29806
|
+
if (!signer.signLineageAttestation || !fencedPublication && !options.lineageGateway)
|
|
29807
|
+
throw new Error(`Cannot register derivative ${scope}: lineage registration needs a gateway URL (lineageGateway is not configured)`);
|
|
29808
|
+
lineageFields = {
|
|
29809
|
+
lineage: lineage.sources,
|
|
29810
|
+
lineageSignature: await signer.signLineageAttestation({
|
|
29811
|
+
ownerAddress: options.ownerAddress,
|
|
29812
|
+
scope,
|
|
29813
|
+
expectedVersion: version5,
|
|
29814
|
+
dataHash: value.dataHash,
|
|
29815
|
+
sources: lineage.sources
|
|
29816
|
+
})
|
|
29817
|
+
};
|
|
29818
|
+
}
|
|
29819
|
+
let id;
|
|
29820
|
+
if (fencedPublication) {
|
|
29821
|
+
const previous = requireFence("registration/adoption");
|
|
29822
|
+
const result = await fencedPublication.commit({
|
|
29823
|
+
...request,
|
|
29824
|
+
...lineageFields,
|
|
29825
|
+
mode,
|
|
29826
|
+
fence: previous
|
|
29827
|
+
});
|
|
29828
|
+
const registered = result.fence.head;
|
|
29829
|
+
if (result.fence.generation !== previous.generation || !registered || isDeleted(registered) || registered.expectedVersion !== String(version5) || !sameHash(registered.dataHash, value.dataHash) || !sameHash(registered.metadataHash, value.metadataHash) || registered.id !== result.dataPointId)
|
|
29830
|
+
throw new Error("Gateway returned inconsistent publication evidence");
|
|
29831
|
+
fence = result.fence;
|
|
29832
|
+
head = registered;
|
|
29833
|
+
id = result.dataPointId;
|
|
29834
|
+
} else if (mode === "adopt") {
|
|
29835
|
+
id = head?.id;
|
|
29836
|
+
} else {
|
|
29837
|
+
const result = lineageFields ? await options.lineageGateway.registerDataPoint({
|
|
29838
|
+
...request,
|
|
29839
|
+
...lineageFields
|
|
29840
|
+
}) : await options.gateway.registerDataPoint(request);
|
|
29841
|
+
id = result.dataPointId;
|
|
29842
|
+
}
|
|
29843
|
+
if (!id)
|
|
29844
|
+
throw new Error(`Gateway registerDataPoint did not return a dataPointId for ${scope} version ${version5}`);
|
|
29845
|
+
return {
|
|
29846
|
+
version: version5,
|
|
29847
|
+
url: keyUrl(version5),
|
|
29848
|
+
dataPointId: id,
|
|
29849
|
+
sizeBytes: value.sizeBytes,
|
|
29850
|
+
dataHash: value.dataHash,
|
|
29851
|
+
metadataHash: value.metadataHash
|
|
29852
|
+
};
|
|
29853
|
+
}
|
|
29854
|
+
let version4 = head === void 0 ? options.preferredVersion : BigInt(head?.expectedVersion ?? "0") + 1n;
|
|
29855
|
+
let rebased = false;
|
|
29856
|
+
for (let step = 0; step < 4; step++) {
|
|
29857
|
+
checkDeletion();
|
|
29858
|
+
if (head && !isDeleted(head) && sameHash(head.dataHash, wantedHash)) {
|
|
29859
|
+
version4 = BigInt(head.expectedVersion);
|
|
29860
|
+
const url2 = keyUrl(version4);
|
|
29861
|
+
if (!await storageAdapter.exists(url2)) {
|
|
29862
|
+
requireFence("healing a committed version's missing bytes");
|
|
29863
|
+
if (!sameHash(wanted.metadataHash, head.metadataHash))
|
|
29864
|
+
throw new Error("Missing committed blob cannot be healed: metadata commitment mismatch");
|
|
29865
|
+
try {
|
|
29866
|
+
await storageAdapter.upload(`${scope}/${version4}`, encrypted);
|
|
29867
|
+
} catch (error51) {
|
|
29868
|
+
if (!(error51 instanceof StoredBlobConflictError))
|
|
29869
|
+
throw error51;
|
|
29870
|
+
}
|
|
29871
|
+
}
|
|
29872
|
+
const value2 = await readCandidate(version4);
|
|
29873
|
+
if (!sameHash(value2.dataHash, head.dataHash) || !sameHash(value2.metadataHash, head.metadataHash))
|
|
29874
|
+
throw new Error("Adopted publication commitment mismatch");
|
|
29875
|
+
return commit(version4, value2, "adopt");
|
|
29876
|
+
}
|
|
29877
|
+
if (fence)
|
|
29878
|
+
version4 = BigInt(head?.expectedVersion ?? "0") + 1n;
|
|
29879
|
+
if (head && BigInt(head.expectedVersion) >= version4)
|
|
29880
|
+
version4 = BigInt(head.expectedVersion) + 1n;
|
|
29881
|
+
let value = wanted;
|
|
29882
|
+
try {
|
|
29883
|
+
await storageAdapter.upload(`${scope}/${version4}`, encrypted);
|
|
29884
|
+
} catch (error51) {
|
|
29885
|
+
if (!(error51 instanceof StoredBlobConflictError))
|
|
29886
|
+
throw error51;
|
|
29887
|
+
value = await readCandidate(version4);
|
|
29888
|
+
if (!sameHash(value.dataHash, wantedHash))
|
|
29889
|
+
requireFence("resuming an occupied unregistered version");
|
|
29890
|
+
}
|
|
29891
|
+
try {
|
|
29892
|
+
const result = await commit(version4, value, "register");
|
|
29893
|
+
if (sameHash(value.dataHash, wantedHash))
|
|
29894
|
+
return result;
|
|
29895
|
+
version4++;
|
|
29896
|
+
} catch (error51) {
|
|
29897
|
+
if (fencedPublication || !(error51 instanceof Error) || !/Gateway error: 409\b/.test(error51.message))
|
|
29898
|
+
throw error51;
|
|
29899
|
+
if (rebased)
|
|
29900
|
+
throw error51;
|
|
29901
|
+
rebased = true;
|
|
29902
|
+
head = await options.readHead();
|
|
29903
|
+
await options.checkHead?.(head);
|
|
29904
|
+
checkDeletion();
|
|
29905
|
+
const next = parseGatewayNextVersion(error51.message);
|
|
29906
|
+
if (!head && next === null)
|
|
29907
|
+
throw error51;
|
|
29908
|
+
const observedNext = BigInt(head?.expectedVersion ?? "0") + 1n;
|
|
29909
|
+
if (next !== null && BigInt(next) > observedNext)
|
|
29910
|
+
requireFence("gateway version hint advances beyond the observed registry head");
|
|
29911
|
+
version4 = observedNext;
|
|
29912
|
+
}
|
|
29913
|
+
}
|
|
29914
|
+
throw new Error(`Publication contention for ${scope}; retry next cycle`);
|
|
29915
|
+
}
|
|
29916
|
+
function parseGatewayNextVersion(message) {
|
|
29917
|
+
const nextValid = message.match(/next valid version is (\d+)/i);
|
|
29918
|
+
if (nextValid)
|
|
29919
|
+
return Number(nextValid[1]);
|
|
29920
|
+
const effectiveMax = message.match(/effective max \((\d+)/i);
|
|
29921
|
+
if (effectiveMax)
|
|
29922
|
+
return Number(effectiveMax[1]) + 1;
|
|
29923
|
+
const storedValue = message.match(/strictly greater than the stored value (\d+)/i);
|
|
29924
|
+
return storedValue ? Number(storedValue[1]) + 1 : null;
|
|
29925
|
+
}
|
|
29926
|
+
|
|
29645
29927
|
// ../core/dist/additions/version-inventory.js
|
|
29646
29928
|
var uint256 = external_exports.string().regex(/^(0|[1-9][0-9]{0,77})$/).refine((value) => BigInt(value) < 2n ** 256n);
|
|
29647
29929
|
var hash2 = external_exports.string().regex(/^0x[0-9a-fA-F]{64}$/).transform((value) => value.toLowerCase());
|
|
@@ -29763,7 +30045,7 @@ function createVersionInventoryClient(options) {
|
|
|
29763
30045
|
async function list(scope, readOptions = {}) {
|
|
29764
30046
|
const maxPages = external_exports.number().int().positive().parse(readOptions.maxPages ?? 1e3);
|
|
29765
30047
|
let after = "0";
|
|
29766
|
-
let
|
|
30048
|
+
let head2 = null;
|
|
29767
30049
|
const versions = [];
|
|
29768
30050
|
for (let count = 0; count < maxPages; count++) {
|
|
29769
30051
|
const result = await page(scope, {
|
|
@@ -29771,12 +30053,12 @@ function createVersionInventoryClient(options) {
|
|
|
29771
30053
|
signal: readOptions.signal,
|
|
29772
30054
|
budget: readOptions.budget
|
|
29773
30055
|
});
|
|
29774
|
-
if (count > 0 && JSON.stringify(
|
|
30056
|
+
if (count > 0 && JSON.stringify(head2) !== JSON.stringify(result.data.head))
|
|
29775
30057
|
throw new Error("Gateway inventory head changed during traversal");
|
|
29776
|
-
|
|
30058
|
+
head2 = result.data.head;
|
|
29777
30059
|
versions.push(...result.data.versions);
|
|
29778
30060
|
if (!result.pagination.hasMore)
|
|
29779
|
-
return { head, versions };
|
|
30061
|
+
return { head: head2, versions };
|
|
29780
30062
|
const next = result.pagination.nextAfter;
|
|
29781
30063
|
if (next === null)
|
|
29782
30064
|
throw new Error("Gateway inventory missing next cursor");
|
|
@@ -29818,12 +30100,25 @@ function createVersionInventoryClient(options) {
|
|
|
29818
30100
|
}
|
|
29819
30101
|
throw new Error("Gateway scope page budget exceeded");
|
|
29820
30102
|
}
|
|
29821
|
-
|
|
30103
|
+
async function head(scope, signal) {
|
|
30104
|
+
const current = (await page(scope, { limit: 1, signal })).data.head;
|
|
30105
|
+
return current ? {
|
|
30106
|
+
expectedVersion: current.expectedVersion,
|
|
30107
|
+
deletedAt: current.deletedAt
|
|
30108
|
+
} : null;
|
|
30109
|
+
}
|
|
30110
|
+
return { page, list, listScopes, head };
|
|
30111
|
+
}
|
|
30112
|
+
|
|
30113
|
+
// ../core/dist/replication/namespace.js
|
|
30114
|
+
var REPLICA_SCOPE_PREFIX = "pdpp_replica_v1";
|
|
30115
|
+
function isReplicaScope(scope) {
|
|
30116
|
+
return scope === REPLICA_SCOPE_PREFIX || scope.startsWith(`${REPLICA_SCOPE_PREFIX}.`);
|
|
29822
30117
|
}
|
|
29823
30118
|
|
|
29824
30119
|
// ../core/dist/policy/reserved-scopes.js
|
|
29825
30120
|
function isSystemScope(scope) {
|
|
29826
|
-
return scope.startsWith("vana.system.");
|
|
30121
|
+
return scope.startsWith("vana.system.") || isReplicaScope(scope);
|
|
29827
30122
|
}
|
|
29828
30123
|
|
|
29829
30124
|
// ../core/dist/additions/durable.js
|
|
@@ -29851,14 +30146,27 @@ function additionsLedgerScope(scope) {
|
|
|
29851
30146
|
const literal2 = `${ADDITIONS_SUMMARY_SCOPE}.${scope}`;
|
|
29852
30147
|
return new TextEncoder().encode(literal2).byteLength <= 256 ? literal2 : `vana.system.additions-hash.${keccak256(stringToHex(scope)).slice(2)}`;
|
|
29853
30148
|
}
|
|
30149
|
+
var AdditionsRecoveryError = class extends Error {
|
|
30150
|
+
code;
|
|
30151
|
+
constructor(code, message = code) {
|
|
30152
|
+
super(message);
|
|
30153
|
+
this.code = code;
|
|
30154
|
+
this.name = "AdditionsRecoveryError";
|
|
30155
|
+
}
|
|
30156
|
+
};
|
|
29854
30157
|
var InaccessibleLedger = class extends Error {
|
|
29855
30158
|
};
|
|
30159
|
+
var CheckpointSearchExceeded = class extends AdditionsBudgetExceeded {
|
|
30160
|
+
};
|
|
30161
|
+
var CHECKPOINT_READ_LIMIT = 256;
|
|
29856
30162
|
var BoundedWorkUnavailable = class extends Error {
|
|
29857
30163
|
};
|
|
29858
30164
|
var ReadBudget = class _ReadBudget extends AdditionsBudget {
|
|
29859
30165
|
limited;
|
|
30166
|
+
checkpoints;
|
|
29860
30167
|
constructor(options, parent) {
|
|
29861
30168
|
super(options.byteBudget, options.timeBudgetMs, options.signal, parent);
|
|
30169
|
+
this.checkpoints = parent?.checkpoints ?? { reads: 0, rejected: /* @__PURE__ */ new Map() };
|
|
29862
30170
|
this.limited = options.byteBudget !== void 0 || options.timeBudgetMs !== void 0;
|
|
29863
30171
|
}
|
|
29864
30172
|
/** A failed source unit cannot spend the bytes held for its durable prefix. */
|
|
@@ -29891,6 +30199,27 @@ function sameInventory(a2, b2) {
|
|
|
29891
30199
|
function settled(slot) {
|
|
29892
30200
|
return slot.status === "confirmed" || slot.status === "finalized";
|
|
29893
30201
|
}
|
|
30202
|
+
function eligible(slot) {
|
|
30203
|
+
return !slot.isTombstone && ["confirmed", "finalized", "pending", "submitting"].includes(slot.status);
|
|
30204
|
+
}
|
|
30205
|
+
function sourceWindow(snapshot) {
|
|
30206
|
+
const end = BigInt(snapshot.head?.expectedVersion ?? "0");
|
|
30207
|
+
const rows = snapshot.versions.filter((slot) => BigInt(slot.expectedVersion) <= end);
|
|
30208
|
+
const after = BigInt(rows.filter((slot) => slot.isTombstone && settled(slot)).at(-1)?.expectedVersion ?? "0");
|
|
30209
|
+
return {
|
|
30210
|
+
end,
|
|
30211
|
+
after,
|
|
30212
|
+
relevant: rows.filter((slot) => BigInt(slot.expectedVersion) > after)
|
|
30213
|
+
};
|
|
30214
|
+
}
|
|
30215
|
+
function findCheckpointRegistration(snapshot, version4, commitment) {
|
|
30216
|
+
if (!snapshot.head || snapshot.head.deletedAt !== null)
|
|
30217
|
+
return void 0;
|
|
30218
|
+
const { end, after } = sourceWindow(snapshot);
|
|
30219
|
+
if (BigInt(version4) > end || BigInt(version4) <= after)
|
|
30220
|
+
return void 0;
|
|
30221
|
+
return snapshot.versions.find((row) => row.expectedVersion === version4 && eligible(row) && row.dataHash.toLowerCase() === commitment.dataHash.toLowerCase() && row.metadataHash.toLowerCase() === commitment.metadataHash.toLowerCase());
|
|
30222
|
+
}
|
|
29894
30223
|
function sourceData(data) {
|
|
29895
30224
|
if (data === null || typeof data !== "object" || Array.isArray(data))
|
|
29896
30225
|
return null;
|
|
@@ -29908,19 +30237,31 @@ function createDurableAdditions(options) {
|
|
|
29908
30237
|
if (!budget.limited)
|
|
29909
30238
|
budget.check(encrypted.byteLength);
|
|
29910
30239
|
const password = hex3(deriveScopeKey(options.masterKey, scope));
|
|
29911
|
-
|
|
30240
|
+
let plaintext;
|
|
30241
|
+
try {
|
|
30242
|
+
plaintext = budget.limited && options.boundedWork ? await options.boundedWork.decrypt(encrypted, password, budget) : await decryptWithPassword(encrypted, password);
|
|
30243
|
+
} catch (error51) {
|
|
30244
|
+
if (error51 instanceof AdditionsRecoveryError || error51 instanceof AdditionsBudgetExceeded || budget.signal?.aborted)
|
|
30245
|
+
throw error51;
|
|
30246
|
+
throw new AdditionsRecoveryError("decrypt_failed");
|
|
30247
|
+
}
|
|
29912
30248
|
budget.check(plaintext.byteLength);
|
|
29913
30249
|
if (keccak256(plaintext).toLowerCase() !== slot.dataHash.toLowerCase())
|
|
29914
|
-
throw new
|
|
30250
|
+
throw new AdditionsRecoveryError("data_hash_mismatch", "Additions content commitment mismatch");
|
|
29915
30251
|
budget.check(plaintext.byteLength * 3);
|
|
29916
|
-
|
|
30252
|
+
let envelope;
|
|
30253
|
+
try {
|
|
30254
|
+
envelope = DataFileEnvelopeSchema.parse(JSON.parse(new TextDecoder().decode(plaintext)));
|
|
30255
|
+
} catch {
|
|
30256
|
+
throw new AdditionsRecoveryError("invalid_envelope");
|
|
30257
|
+
}
|
|
29917
30258
|
const metadataHash = keccak256(stringToHex(JSON.stringify({
|
|
29918
30259
|
scope,
|
|
29919
30260
|
collectedAt: envelope.collectedAt,
|
|
29920
30261
|
sizeBytes: encrypted.byteLength
|
|
29921
30262
|
})));
|
|
29922
30263
|
if (envelope.scope !== scope || !Number.isFinite(Date.parse(envelope.collectedAt)) || metadataHash.toLowerCase() !== slot.metadataHash.toLowerCase())
|
|
29923
|
-
throw new
|
|
30264
|
+
throw new AdditionsRecoveryError("metadata_hash_mismatch", "Additions metadata commitment mismatch");
|
|
29924
30265
|
budget.check();
|
|
29925
30266
|
return envelope;
|
|
29926
30267
|
}
|
|
@@ -29931,21 +30272,50 @@ function createDurableAdditions(options) {
|
|
|
29931
30272
|
const head = snapshot.head;
|
|
29932
30273
|
if (!head || head.deletedAt !== null)
|
|
29933
30274
|
return null;
|
|
29934
|
-
const slot = snapshot
|
|
30275
|
+
const slot = findCheckpointRegistration(snapshot, head.expectedVersion, head);
|
|
29935
30276
|
if (!slot)
|
|
29936
30277
|
throw new Error("Additions head missing from inventory");
|
|
29937
30278
|
return { snapshot, envelope: await readEnvelope(scope, slot, budget) };
|
|
29938
30279
|
}
|
|
29939
|
-
async function readDocument(scope, budget) {
|
|
30280
|
+
async function readDocument(scope, budget, source, search) {
|
|
30281
|
+
const { relevant, after } = sourceWindow(source);
|
|
29940
30282
|
const systemScope = additionsLedgerScope(scope);
|
|
29941
30283
|
const snapshot = await inventory.list(systemScope, budget.readOptions);
|
|
29942
30284
|
if (!snapshot.head || snapshot.head.deletedAt !== null)
|
|
29943
30285
|
return null;
|
|
29944
|
-
const boundary = snapshot.versions.filter((row) => row.isTombstone).at(-1)?.expectedVersion ?? "0";
|
|
30286
|
+
const boundary = snapshot.versions.filter((row) => row.isTombstone && settled(row) && BigInt(row.expectedVersion) <= BigInt(snapshot.head.expectedVersion)).at(-1)?.expectedVersion ?? "0";
|
|
29945
30287
|
let inaccessible = false;
|
|
29946
|
-
|
|
29947
|
-
|
|
30288
|
+
const sourceFingerprint = fingerprintVersionInventory(source);
|
|
30289
|
+
for (let index = snapshot.versions.length - 1; index >= 0; index--) {
|
|
30290
|
+
budget.check();
|
|
30291
|
+
const slot = snapshot.versions[index];
|
|
30292
|
+
if (BigInt(slot.expectedVersion) <= BigInt(boundary) || BigInt(slot.expectedVersion) > BigInt(snapshot.head.expectedVersion) || search && BigInt(slot.expectedVersion) >= BigInt(search.before) || !eligible(slot))
|
|
29948
30293
|
continue;
|
|
30294
|
+
const identity = JSON.stringify([
|
|
30295
|
+
systemScope,
|
|
30296
|
+
slot.expectedVersion,
|
|
30297
|
+
slot.dataHash.toLowerCase(),
|
|
30298
|
+
slot.metadataHash.toLowerCase(),
|
|
30299
|
+
sourceFingerprint
|
|
30300
|
+
]);
|
|
30301
|
+
const rejected = budget.checkpoints.rejected.get(identity);
|
|
30302
|
+
if (rejected !== void 0) {
|
|
30303
|
+
inaccessible ||= rejected === "inaccessible";
|
|
30304
|
+
continue;
|
|
30305
|
+
}
|
|
30306
|
+
if (budget.checkpoints.reads >= CHECKPOINT_READ_LIMIT) {
|
|
30307
|
+
try {
|
|
30308
|
+
options.onRecoveryDiagnostic?.({
|
|
30309
|
+
scope,
|
|
30310
|
+
version: slot.expectedVersion,
|
|
30311
|
+
code: "checkpoint_search_exhausted"
|
|
30312
|
+
});
|
|
30313
|
+
} catch {
|
|
30314
|
+
}
|
|
30315
|
+
throw new CheckpointSearchExceeded("Retained checkpoint search exhausted");
|
|
30316
|
+
}
|
|
30317
|
+
budget.check(identity.length * 2 + 64);
|
|
30318
|
+
budget.checkpoints.reads++;
|
|
29949
30319
|
let envelope;
|
|
29950
30320
|
try {
|
|
29951
30321
|
envelope = await readEnvelope(systemScope, slot, budget);
|
|
@@ -29953,18 +30323,30 @@ function createDurableAdditions(options) {
|
|
|
29953
30323
|
if (error51 instanceof AdditionsBudgetExceeded || budget.signal?.aborted)
|
|
29954
30324
|
throw error51;
|
|
29955
30325
|
inaccessible = true;
|
|
30326
|
+
budget.checkpoints.rejected.set(identity, "inaccessible");
|
|
29956
30327
|
continue;
|
|
29957
30328
|
}
|
|
29958
30329
|
const parsed = documentSchema.safeParse(envelope.data);
|
|
29959
|
-
if (!parsed.success || parsed.data.owner !== owner || parsed.data.network !== options.network || parsed.data.scope !== scope)
|
|
30330
|
+
if (!parsed.success || parsed.data.owner !== owner || parsed.data.network !== options.network || parsed.data.scope !== scope) {
|
|
30331
|
+
budget.checkpoints.rejected.set(identity, "invalid");
|
|
29960
30332
|
continue;
|
|
30333
|
+
}
|
|
29961
30334
|
const ledger = parsed.data.ledger === null ? null : readScopeFirstSeenLedger(parsed.data.ledger);
|
|
29962
|
-
if (parsed.data.ledger !== null && (!ledger || ledger.scope !== scope))
|
|
30335
|
+
if (parsed.data.ledger !== null && (!ledger || ledger.scope !== scope)) {
|
|
30336
|
+
budget.checkpoints.rejected.set(identity, "invalid");
|
|
30337
|
+
continue;
|
|
30338
|
+
}
|
|
30339
|
+
const candidate = { ...parsed.data, ledger };
|
|
30340
|
+
if (candidate.slots.length > relevant.length || !candidate.slots.every((row, i2) => eligible(relevant[i2]) && sameCommitment(row, relevant[i2])) || candidate.through !== (candidate.slots.at(-1)?.expectedVersion ?? String(after))) {
|
|
30341
|
+
budget.checkpoints.rejected.set(identity, "invalid");
|
|
30342
|
+
continue;
|
|
30343
|
+
}
|
|
30344
|
+
if (search && candidate.slots.length <= search.longerThan)
|
|
29963
30345
|
continue;
|
|
29964
30346
|
return {
|
|
29965
|
-
|
|
29966
|
-
|
|
29967
|
-
|
|
30347
|
+
document: candidate,
|
|
30348
|
+
publicationVersion: slot.expectedVersion,
|
|
30349
|
+
repairHead: slot.expectedVersion !== snapshot.head.expectedVersion
|
|
29968
30350
|
};
|
|
29969
30351
|
}
|
|
29970
30352
|
if (inaccessible)
|
|
@@ -29976,48 +30358,44 @@ function createDurableAdditions(options) {
|
|
|
29976
30358
|
if (budget.limited) {
|
|
29977
30359
|
if (!options.boundedWork)
|
|
29978
30360
|
throw new BoundedWorkUnavailable("Bounded checkpoint publication unavailable");
|
|
29979
|
-
const
|
|
30361
|
+
const proof2 = await options.boundedWork.publish(scope, data, budget);
|
|
29980
30362
|
budget.check();
|
|
29981
30363
|
const check3 = await inventory.list(scope, budget.readOptions);
|
|
29982
|
-
const slot = check3
|
|
30364
|
+
const slot = findCheckpointRegistration(check3, proof2.expectedVersion, proof2);
|
|
29983
30365
|
if (!slot)
|
|
29984
30366
|
throw new Error("Bounded checkpoint registration was replaced");
|
|
29985
|
-
const
|
|
29986
|
-
if (JSON.stringify(
|
|
30367
|
+
const envelope = await readEnvelope(scope, slot, budget);
|
|
30368
|
+
if (JSON.stringify(envelope.data) !== JSON.stringify(data))
|
|
29987
30369
|
throw new Error("Bounded checkpoint content was replaced");
|
|
29988
30370
|
budget.check();
|
|
29989
30371
|
await options.boundedWork.confirmed?.(scope, budget);
|
|
29990
30372
|
return;
|
|
29991
30373
|
}
|
|
29992
30374
|
const snapshot = await inventory.list(scope, budget.readOptions);
|
|
29993
|
-
const
|
|
29994
|
-
|
|
29995
|
-
|
|
29996
|
-
|
|
29997
|
-
const
|
|
29998
|
-
const metadataHash = keccak256(stringToHex(JSON.stringify({
|
|
29999
|
-
scope,
|
|
30000
|
-
collectedAt: envelope.collectedAt,
|
|
30001
|
-
sizeBytes: encrypted.byteLength
|
|
30002
|
-
})));
|
|
30003
|
-
await storageAdapter.upload(`${scope}/${version4}`, encrypted);
|
|
30004
|
-
const signature = await options.signer.signAddData({
|
|
30005
|
-
ownerAddress: getAddress(owner),
|
|
30006
|
-
scope,
|
|
30007
|
-
dataHash,
|
|
30008
|
-
metadataHash,
|
|
30009
|
-
expectedVersion: version4
|
|
30010
|
-
});
|
|
30011
|
-
await options.gateway.registerDataPoint({
|
|
30375
|
+
const toHead = (state) => state.head ? {
|
|
30376
|
+
...state.head,
|
|
30377
|
+
id: computeDataPointId(owner, scope)
|
|
30378
|
+
} : null;
|
|
30379
|
+
const proof = await publishVersion({
|
|
30012
30380
|
ownerAddress: owner,
|
|
30013
|
-
scope,
|
|
30014
|
-
|
|
30015
|
-
|
|
30016
|
-
|
|
30017
|
-
|
|
30381
|
+
envelope: createDataFileEnvelope(scope, (/* @__PURE__ */ new Date()).toISOString(), data),
|
|
30382
|
+
preferredVersion: BigInt(snapshot.versions.at(-1)?.expectedVersion ?? "0") + 1n,
|
|
30383
|
+
masterKey: options.masterKey,
|
|
30384
|
+
storageAdapter,
|
|
30385
|
+
signer: options.signer,
|
|
30386
|
+
gateway: options.gateway,
|
|
30387
|
+
fencedPublication: options.fencedPublication,
|
|
30388
|
+
head: toHead(snapshot),
|
|
30389
|
+
readHead: async () => toHead(await inventory.list(scope, budget.readOptions)),
|
|
30390
|
+
// Rebuilding an explicitly deleted system document is a deliberate re-add.
|
|
30391
|
+
acknowledgedDeletionVersion: snapshot.head?.deletedAt ? BigInt(snapshot.head.expectedVersion) : void 0
|
|
30392
|
+
}).catch((error51) => {
|
|
30393
|
+
if (error51 instanceof NeedsFencedPublicationError)
|
|
30394
|
+
options.onPublicationBlocked?.(error51);
|
|
30395
|
+
throw error51;
|
|
30018
30396
|
});
|
|
30019
30397
|
const check2 = await inventory.list(scope, budget.readOptions);
|
|
30020
|
-
const registered = check2
|
|
30398
|
+
const registered = findCheckpointRegistration(check2, String(proof.version), proof);
|
|
30021
30399
|
if (!registered)
|
|
30022
30400
|
throw new Error("Concurrent additions publication replaced the registration");
|
|
30023
30401
|
await readEnvelope(scope, registered, budget);
|
|
@@ -30038,21 +30416,18 @@ function createDurableAdditions(options) {
|
|
|
30038
30416
|
coverage: !sameInventory(snapshot, check2) ? "behind" : head ? settled(head) && tombstone ? "complete" : "partial" : snapshot.versions.length ? "partial" : "complete"
|
|
30039
30417
|
};
|
|
30040
30418
|
}
|
|
30041
|
-
const end =
|
|
30042
|
-
|
|
30043
|
-
const boundary = rows.filter((slot) => slot.isTombstone && settled(slot)).at(-1);
|
|
30044
|
-
const after = BigInt(boundary?.expectedVersion ?? "0");
|
|
30045
|
-
const relevant = rows.filter((slot) => BigInt(slot.expectedVersion) > after);
|
|
30046
|
-
let existing = null;
|
|
30419
|
+
const { end, after, relevant } = sourceWindow(snapshot);
|
|
30420
|
+
let checkpoint = null;
|
|
30047
30421
|
let inaccessibleExisting = false;
|
|
30048
30422
|
try {
|
|
30049
|
-
|
|
30423
|
+
checkpoint = await readDocument(scope, budget, snapshot);
|
|
30050
30424
|
} catch (error51) {
|
|
30051
30425
|
if (error51 instanceof AdditionsBudgetExceeded || budget.signal?.aborted)
|
|
30052
30426
|
throw error51;
|
|
30053
30427
|
inaccessibleExisting = true;
|
|
30054
30428
|
}
|
|
30055
|
-
|
|
30429
|
+
let existing = checkpoint?.document ?? null;
|
|
30430
|
+
const prefixValid = existing !== null;
|
|
30056
30431
|
let ledger = prefixValid ? existing.ledger : null;
|
|
30057
30432
|
const folded = prefixValid ? relevant.slice(0, existing.slots.length) : [];
|
|
30058
30433
|
let currentTotal = prefixValid ? existing.currentTotal : 0;
|
|
@@ -30065,6 +30440,7 @@ function createDurableAdditions(options) {
|
|
|
30065
30440
|
coverage = "partial";
|
|
30066
30441
|
expected = BigInt(slot.expectedVersion) + 1n;
|
|
30067
30442
|
}
|
|
30443
|
+
const sourceCoverage = coverage;
|
|
30068
30444
|
const checkpointBytes = (candidate, count) => 128 * 1024 + 128 * new TextEncoder().encode(JSON.stringify({
|
|
30069
30445
|
ledger: candidate,
|
|
30070
30446
|
slots: relevant.slice(0, count),
|
|
@@ -30074,17 +30450,15 @@ function createDurableAdditions(options) {
|
|
|
30074
30450
|
through,
|
|
30075
30451
|
currentTotal
|
|
30076
30452
|
})).byteLength;
|
|
30077
|
-
|
|
30453
|
+
while (folded.length < relevant.length) {
|
|
30454
|
+
const slot = relevant[folded.length];
|
|
30455
|
+
let unitBudget = budget;
|
|
30078
30456
|
try {
|
|
30079
|
-
|
|
30457
|
+
unitBudget = budget.limited ? budget.excluding(checkpointBytes(ledger, folded.length)) : budget;
|
|
30080
30458
|
unitBudget.check();
|
|
30081
30459
|
if (BigInt(slot.expectedVersion) !== BigInt(through) + 1n)
|
|
30082
30460
|
coverage = "partial";
|
|
30083
|
-
if (
|
|
30084
|
-
coverage = "partial";
|
|
30085
|
-
break;
|
|
30086
|
-
}
|
|
30087
|
-
if (slot.isTombstone) {
|
|
30461
|
+
if (!eligible(slot)) {
|
|
30088
30462
|
coverage = "partial";
|
|
30089
30463
|
break;
|
|
30090
30464
|
}
|
|
@@ -30092,21 +30466,21 @@ function createDurableAdditions(options) {
|
|
|
30092
30466
|
const proof = uploaded?.proof;
|
|
30093
30467
|
const inMemory = proof ? DataFileEnvelopeSchema.safeParse(proof.envelope) : null;
|
|
30094
30468
|
const bytes = proof ? new TextEncoder().encode(JSON.stringify(proof.envelope)) : null;
|
|
30095
|
-
const
|
|
30469
|
+
const metadata2 = inMemory?.success && proof ? keccak256(stringToHex(JSON.stringify({
|
|
30096
30470
|
scope,
|
|
30097
30471
|
collectedAt: inMemory.data.collectedAt,
|
|
30098
30472
|
sizeBytes: proof.encryptedSize
|
|
30099
30473
|
}))) : null;
|
|
30100
|
-
if (inMemory?.success && bytes && inMemory.data.scope === scope && keccak256(bytes) === slot.dataHash &&
|
|
30474
|
+
if (inMemory?.success && bytes && inMemory.data.scope === scope && keccak256(bytes) === slot.dataHash && metadata2 === slot.metadataHash) {
|
|
30101
30475
|
const data = sourceData(inMemory.data.data);
|
|
30102
30476
|
if (!data)
|
|
30103
|
-
throw new
|
|
30477
|
+
throw new AdditionsRecoveryError("unsupported_source_data");
|
|
30104
30478
|
version4 = { scope, collectedAt: inMemory.data.collectedAt, data };
|
|
30105
30479
|
} else {
|
|
30106
30480
|
const envelope = await readEnvelope(scope, slot, unitBudget);
|
|
30107
30481
|
const data = sourceData(envelope.data);
|
|
30108
30482
|
if (!data)
|
|
30109
|
-
throw new
|
|
30483
|
+
throw new AdditionsRecoveryError("unsupported_source_data");
|
|
30110
30484
|
version4 = { scope, collectedAt: envelope.collectedAt, data };
|
|
30111
30485
|
}
|
|
30112
30486
|
const hadBaseline = ledger !== null && ledger.baseline !== null;
|
|
@@ -30124,7 +30498,39 @@ function createDurableAdditions(options) {
|
|
|
30124
30498
|
folded.push(slot);
|
|
30125
30499
|
through = slot.expectedVersion;
|
|
30126
30500
|
} catch (error51) {
|
|
30127
|
-
|
|
30501
|
+
if (checkpoint && !budget.signal?.aborted) {
|
|
30502
|
+
const searchBudget = budget.limited ? budget.excluding(checkpointBytes(ledger, folded.length)) : budget;
|
|
30503
|
+
try {
|
|
30504
|
+
const fallback = await readDocument(scope, searchBudget, snapshot, {
|
|
30505
|
+
before: checkpoint.publicationVersion,
|
|
30506
|
+
longerThan: folded.length
|
|
30507
|
+
});
|
|
30508
|
+
if (fallback) {
|
|
30509
|
+
checkpoint = fallback;
|
|
30510
|
+
existing = fallback.document;
|
|
30511
|
+
ledger = existing.ledger;
|
|
30512
|
+
currentTotal = existing.currentTotal;
|
|
30513
|
+
through = existing.through;
|
|
30514
|
+
folded.splice(0, folded.length, ...relevant.slice(0, existing.slots.length));
|
|
30515
|
+
coverage = sourceCoverage;
|
|
30516
|
+
continue;
|
|
30517
|
+
}
|
|
30518
|
+
} catch (failure) {
|
|
30519
|
+
if (failure instanceof AdditionsBudgetExceeded)
|
|
30520
|
+
error51 = failure;
|
|
30521
|
+
else if (searchBudget.signal?.aborted)
|
|
30522
|
+
error51 = new AdditionsBudgetExceeded("Checkpoint fallback allowance exhausted");
|
|
30523
|
+
}
|
|
30524
|
+
}
|
|
30525
|
+
try {
|
|
30526
|
+
options.onRecoveryDiagnostic?.({
|
|
30527
|
+
scope,
|
|
30528
|
+
version: slot.expectedVersion,
|
|
30529
|
+
code: error51 instanceof AdditionsBudgetExceeded || unitBudget.signal?.aborted && unitBudget.signal.reason instanceof DOMException && unitBudget.signal.reason.name === "TimeoutError" ? "budget_exceeded" : budget.signal?.aborted ? "cancelled" : error51 instanceof AdditionsRecoveryError ? error51.code : "replay_failed"
|
|
30530
|
+
});
|
|
30531
|
+
} catch {
|
|
30532
|
+
}
|
|
30533
|
+
coverage = error51 instanceof AdditionsBudgetExceeded || budget.signal?.aborted || unitBudget.signal?.aborted ? "behind" : "partial";
|
|
30128
30534
|
break;
|
|
30129
30535
|
}
|
|
30130
30536
|
}
|
|
@@ -30153,7 +30559,7 @@ function createDurableAdditions(options) {
|
|
|
30153
30559
|
slots: folded,
|
|
30154
30560
|
ledger
|
|
30155
30561
|
};
|
|
30156
|
-
if ((!existing && !inaccessibleExisting || prefixValid || coverage === "complete") && JSON.stringify(document2) !== JSON.stringify(existing)) {
|
|
30562
|
+
if ((!existing && !inaccessibleExisting || prefixValid || coverage === "complete") && (checkpoint?.repairHead || JSON.stringify(document2) !== JSON.stringify(existing))) {
|
|
30157
30563
|
try {
|
|
30158
30564
|
await publish(additionsLedgerScope(scope), { ...document2 }, budget);
|
|
30159
30565
|
} catch {
|
|
@@ -30261,9 +30667,9 @@ function createDurableAdditions(options) {
|
|
|
30261
30667
|
return;
|
|
30262
30668
|
if (proof && keccak256(new TextEncoder().encode(JSON.stringify(proof.envelope))) !== head.dataHash)
|
|
30263
30669
|
return;
|
|
30264
|
-
const previous = await readDocument(version4.scope, budget);
|
|
30265
|
-
const
|
|
30266
|
-
const startsFresh = BigInt(head.expectedVersion) ===
|
|
30670
|
+
const previous = (await readDocument(version4.scope, budget, snapshot))?.document;
|
|
30671
|
+
const { after } = sourceWindow(snapshot);
|
|
30672
|
+
const startsFresh = BigInt(head.expectedVersion) === after + 1n;
|
|
30267
30673
|
if (!startsFresh && (!previous || BigInt(previous.through) + 1n !== BigInt(head.expectedVersion)))
|
|
30268
30674
|
return;
|
|
30269
30675
|
const uploaded = !budget.limited && "collectedAt" in version4 && "data" in version4 ? { version: version4, proof } : void 0;
|
|
@@ -30271,9 +30677,13 @@ function createDurableAdditions(options) {
|
|
|
30271
30677
|
} catch {
|
|
30272
30678
|
}
|
|
30273
30679
|
},
|
|
30274
|
-
async deleteScope(scope) {
|
|
30680
|
+
async deleteScope(scope, deletion) {
|
|
30681
|
+
deletion?.signal?.throwIfAborted();
|
|
30682
|
+
options.signal?.throwIfAborted();
|
|
30275
30683
|
if (isSystemScope(scope))
|
|
30276
30684
|
return;
|
|
30685
|
+
if (deletion?.durableOnly)
|
|
30686
|
+
throw new Error("Bounded additions deletion is unavailable");
|
|
30277
30687
|
if (!options.deleteSystemScope)
|
|
30278
30688
|
throw new Error("Durable additions deletion is unavailable");
|
|
30279
30689
|
await options.deleteSystemScope(additionsLedgerScope(scope));
|
|
@@ -30300,12 +30710,24 @@ async function decryptBoundedAdditions(encrypted, password, budget) {
|
|
|
30300
30710
|
ignoreMalformedPackets: false
|
|
30301
30711
|
};
|
|
30302
30712
|
const message = await no({ binaryMessage: encrypted, config: config2 });
|
|
30303
|
-
|
|
30304
|
-
|
|
30305
|
-
|
|
30306
|
-
|
|
30307
|
-
|
|
30308
|
-
|
|
30713
|
+
let result;
|
|
30714
|
+
try {
|
|
30715
|
+
result = await po({
|
|
30716
|
+
message,
|
|
30717
|
+
passwords: [password],
|
|
30718
|
+
format: "binary",
|
|
30719
|
+
config: config2
|
|
30720
|
+
});
|
|
30721
|
+
} catch (error51) {
|
|
30722
|
+
if (error51 instanceof Error && error51.message.includes(
|
|
30723
|
+
"Compressed OpenPGP packets are unsupported in bounded recovery"
|
|
30724
|
+
))
|
|
30725
|
+
throw new AdditionsRecoveryError(
|
|
30726
|
+
"compressed_packet",
|
|
30727
|
+
"Compressed OpenPGP packets are unsupported in bounded recovery"
|
|
30728
|
+
);
|
|
30729
|
+
throw error51;
|
|
30730
|
+
}
|
|
30309
30731
|
budget.charge();
|
|
30310
30732
|
if (!(result.data instanceof Uint8Array))
|
|
30311
30733
|
throw new Error("Unexpected OpenPGP stream");
|
|
@@ -30388,11 +30810,12 @@ function createService(init) {
|
|
|
30388
30810
|
const reconciledScopes = /* @__PURE__ */ new Set();
|
|
30389
30811
|
async function reconcilePending(scope, budget) {
|
|
30390
30812
|
if (reconciledScopes.has(scope)) return null;
|
|
30391
|
-
const
|
|
30392
|
-
if (!
|
|
30813
|
+
const pending2 = await transport("readPending", [scope], budget);
|
|
30814
|
+
if (!pending2) {
|
|
30393
30815
|
reconciledScopes.add(scope);
|
|
30394
30816
|
return null;
|
|
30395
30817
|
}
|
|
30818
|
+
let prior = pending2;
|
|
30396
30819
|
let snapshot = await inventory.list(scope, {
|
|
30397
30820
|
budget,
|
|
30398
30821
|
signal: budget.signal
|
|
@@ -30404,7 +30827,8 @@ function createService(init) {
|
|
|
30404
30827
|
if (slot && replaced && !["confirmed", "finalized"].includes(slot.status))
|
|
30405
30828
|
throw new Error("Pending checkpoint replacement is not settled");
|
|
30406
30829
|
if (!slot) {
|
|
30407
|
-
await transport("publish", [prior], budget);
|
|
30830
|
+
const published = await transport("publish", [prior], budget);
|
|
30831
|
+
prior = { ...prior, expectedVersion: published.expectedVersion };
|
|
30408
30832
|
snapshot = await inventory.list(scope, {
|
|
30409
30833
|
budget,
|
|
30410
30834
|
signal: budget.signal
|
|
@@ -30413,7 +30837,7 @@ function createService(init) {
|
|
|
30413
30837
|
(row) => row.expectedVersion === prior.expectedVersion
|
|
30414
30838
|
);
|
|
30415
30839
|
}
|
|
30416
|
-
if (!slot || !replaced && (
|
|
30840
|
+
if (!slot || !replaced && !findCheckpointRegistration(snapshot, prior.expectedVersion, prior))
|
|
30417
30841
|
throw new Error("Interrupted checkpoint registration remains ambiguous");
|
|
30418
30842
|
const proof = replaced ? slot : prior;
|
|
30419
30843
|
let data;
|
|
@@ -30445,18 +30869,17 @@ function createService(init) {
|
|
|
30445
30869
|
throw new Error("Interrupted checkpoint commitment mismatch");
|
|
30446
30870
|
data = envelope.data;
|
|
30447
30871
|
}
|
|
30448
|
-
|
|
30449
|
-
|
|
30450
|
-
|
|
30451
|
-
|
|
30452
|
-
|
|
30453
|
-
|
|
30454
|
-
|
|
30455
|
-
|
|
30456
|
-
|
|
30457
|
-
|
|
30458
|
-
|
|
30459
|
-
}
|
|
30872
|
+
const latest = await inventory.list(scope, {
|
|
30873
|
+
budget,
|
|
30874
|
+
signal: budget.signal
|
|
30875
|
+
});
|
|
30876
|
+
const visible = slot.isTombstone ? latest.head && BigInt(proof.expectedVersion) <= BigInt(latest.head.expectedVersion) && latest.versions.find(
|
|
30877
|
+
(row) => row.expectedVersion === proof.expectedVersion && row.dataHash === proof.dataHash && row.metadataHash === proof.metadataHash && row.isTombstone
|
|
30878
|
+
) : findCheckpointRegistration(latest, proof.expectedVersion, proof);
|
|
30879
|
+
if (!visible || replaced && !["confirmed", "finalized"].includes(visible.status))
|
|
30880
|
+
throw new Error(
|
|
30881
|
+
"Interrupted checkpoint registration changed during verification"
|
|
30882
|
+
);
|
|
30460
30883
|
await transport("clearPending", [scope], budget);
|
|
30461
30884
|
reconciledScopes.add(scope);
|
|
30462
30885
|
return replaced ? null : { proof: prior, data };
|
|
@@ -30475,10 +30898,21 @@ function createService(init) {
|
|
|
30475
30898
|
listScopes: async (options) => {
|
|
30476
30899
|
activeBudget = options?.budget;
|
|
30477
30900
|
return inventory.listScopes(options);
|
|
30901
|
+
},
|
|
30902
|
+
head: (scope, signal) => {
|
|
30903
|
+
activeBudget = void 0;
|
|
30904
|
+
return inventory.head(scope, signal);
|
|
30478
30905
|
}
|
|
30479
30906
|
};
|
|
30907
|
+
const reported = /* @__PURE__ */ new Set();
|
|
30480
30908
|
return createDurableAdditions({
|
|
30481
30909
|
...init,
|
|
30910
|
+
onRecoveryDiagnostic: init.diagnostics ? (event) => {
|
|
30911
|
+
const key = JSON.stringify(event);
|
|
30912
|
+
if (reported.size >= 32 || reported.has(key)) return;
|
|
30913
|
+
reported.add(key);
|
|
30914
|
+
worker.postMessage({ kind: "diagnostic", event });
|
|
30915
|
+
} : void 0,
|
|
30482
30916
|
inventory: boundedInventory,
|
|
30483
30917
|
storageAdapter: {
|
|
30484
30918
|
urlForKey: (key) => key,
|
|
@@ -30550,8 +30984,7 @@ function createService(init) {
|
|
|
30550
30984
|
)
|
|
30551
30985
|
)
|
|
30552
30986
|
};
|
|
30553
|
-
|
|
30554
|
-
return prepared;
|
|
30987
|
+
return transport("publish", [prepared], budget);
|
|
30555
30988
|
}
|
|
30556
30989
|
}
|
|
30557
30990
|
});
|
|
@@ -30566,7 +30999,11 @@ worker.onmessage = (event) => {
|
|
|
30566
30999
|
request?.budget?.charge();
|
|
30567
31000
|
if (message.error)
|
|
30568
31001
|
request?.reject(
|
|
30569
|
-
message.budgetExceeded ? new AdditionsBudgetExceeded(message.error) : new
|
|
31002
|
+
message.budgetExceeded ? new AdditionsBudgetExceeded(message.error) : message.publicationBlocked ? new NeedsFencedPublicationError(
|
|
31003
|
+
message.publicationBlocked.scope,
|
|
31004
|
+
message.publicationBlocked.reason,
|
|
31005
|
+
false
|
|
31006
|
+
) : new Error(message.error)
|
|
30570
31007
|
);
|
|
30571
31008
|
else request?.resolve(message.result);
|
|
30572
31009
|
} catch (error51) {
|