@opendatalabs/personal-server-ts-server 1.6.0 → 1.8.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/app.d.ts +6 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +2 -0
- package/dist/app.js.map +1 -1
- package/dist/bootstrap.d.ts +7 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +50 -3
- package/dist/bootstrap.js.map +1 -1
- package/dist/logging/access-log.d.ts +1 -1
- package/dist/logging/access-log.d.ts.map +1 -1
- package/dist/pending-blob-deletions.d.ts +10 -0
- package/dist/pending-blob-deletions.d.ts.map +1 -0
- package/dist/pending-blob-deletions.js +38 -0
- package/dist/pending-blob-deletions.js.map +1 -0
- package/dist/routes/data.d.ts +10 -1
- package/dist/routes/data.d.ts.map +1 -1
- package/dist/routes/data.js +2 -0
- package/dist/routes/data.js.map +1 -1
- package/dist/storage/index-manager.d.ts.map +1 -1
- package/dist/storage/index-manager.js +4 -2
- package/dist/storage/index-manager.js.map +1 -1
- package/dist/storage/index-schema.d.ts +1 -1
- package/dist/storage/index-schema.d.ts.map +1 -1
- package/dist/storage/index-schema.js +9 -2
- package/dist/storage/index-schema.js.map +1 -1
- package/dist/storage/node-data-storage.d.ts.map +1 -1
- package/dist/storage/node-data-storage.js +10 -0
- package/dist/storage/node-data-storage.js.map +1 -1
- package/dist/ui/ps-lite-debug.js +2058 -229
- package/package.json +3 -3
package/dist/ui/ps-lite-debug.js
CHANGED
|
@@ -105536,6 +105536,17 @@ var GENERIC_PAYMENT_TYPES = {
|
|
|
105536
105536
|
]
|
|
105537
105537
|
};
|
|
105538
105538
|
|
|
105539
|
+
// ../core/dist/lineage/attestation.js
|
|
105540
|
+
var LINEAGE_ATTESTATION_TYPES = {
|
|
105541
|
+
LineageAttestation: [
|
|
105542
|
+
{ name: "ownerAddress", type: "address" },
|
|
105543
|
+
{ name: "scope", type: "string" },
|
|
105544
|
+
{ name: "expectedVersion", type: "uint256" },
|
|
105545
|
+
{ name: "dataHash", type: "bytes32" },
|
|
105546
|
+
{ name: "sources", type: "bytes32[]" }
|
|
105547
|
+
]
|
|
105548
|
+
};
|
|
105549
|
+
|
|
105539
105550
|
// ../core/dist/signing/signer.js
|
|
105540
105551
|
function createServerSigner(account, gatewayConfig) {
|
|
105541
105552
|
return {
|
|
@@ -105568,6 +105579,14 @@ function createServerSigner(account, gatewayConfig) {
|
|
|
105568
105579
|
message: msg
|
|
105569
105580
|
});
|
|
105570
105581
|
},
|
|
105582
|
+
async signLineageAttestation(msg) {
|
|
105583
|
+
return account.signTypedData({
|
|
105584
|
+
domain: dataRegistryDomain(gatewayConfig),
|
|
105585
|
+
types: LINEAGE_ATTESTATION_TYPES,
|
|
105586
|
+
primaryType: "LineageAttestation",
|
|
105587
|
+
message: { ...msg, sources: [...msg.sources] }
|
|
105588
|
+
});
|
|
105589
|
+
},
|
|
105571
105590
|
async signRecordDataAccess(msg) {
|
|
105572
105591
|
return account.signTypedData({
|
|
105573
105592
|
domain: dataRegistryDomain(gatewayConfig),
|
|
@@ -105579,6 +105598,498 @@ function createServerSigner(account, gatewayConfig) {
|
|
|
105579
105598
|
};
|
|
105580
105599
|
}
|
|
105581
105600
|
|
|
105601
|
+
// ../core/dist/signing/request-signer.js
|
|
105602
|
+
function createRequestSigner(account) {
|
|
105603
|
+
return {
|
|
105604
|
+
async signRequest(params) {
|
|
105605
|
+
return buildWeb3SignedHeader({
|
|
105606
|
+
signMessage: (message) => account.signMessage(message),
|
|
105607
|
+
aud: params.aud,
|
|
105608
|
+
method: params.method,
|
|
105609
|
+
uri: params.uri,
|
|
105610
|
+
body: params.body,
|
|
105611
|
+
grantId: params.grantId
|
|
105612
|
+
});
|
|
105613
|
+
}
|
|
105614
|
+
};
|
|
105615
|
+
}
|
|
105616
|
+
|
|
105617
|
+
// ../core/dist/errors/catalog.js
|
|
105618
|
+
var ProtocolError = class extends Error {
|
|
105619
|
+
code;
|
|
105620
|
+
errorCode;
|
|
105621
|
+
details;
|
|
105622
|
+
constructor(code, errorCode, message, details) {
|
|
105623
|
+
super(message);
|
|
105624
|
+
this.code = code;
|
|
105625
|
+
this.errorCode = errorCode;
|
|
105626
|
+
this.details = details;
|
|
105627
|
+
this.name = this.constructor.name;
|
|
105628
|
+
}
|
|
105629
|
+
toJSON() {
|
|
105630
|
+
return {
|
|
105631
|
+
error: {
|
|
105632
|
+
code: this.code,
|
|
105633
|
+
errorCode: this.errorCode,
|
|
105634
|
+
message: this.message,
|
|
105635
|
+
...this.details !== void 0 && { details: this.details }
|
|
105636
|
+
}
|
|
105637
|
+
};
|
|
105638
|
+
}
|
|
105639
|
+
};
|
|
105640
|
+
var MissingAuthError2 = class extends ProtocolError {
|
|
105641
|
+
constructor(details) {
|
|
105642
|
+
super(401, "MISSING_AUTH", "Missing authentication", details);
|
|
105643
|
+
}
|
|
105644
|
+
};
|
|
105645
|
+
var InvalidSignatureError3 = class extends ProtocolError {
|
|
105646
|
+
constructor(details) {
|
|
105647
|
+
super(401, "INVALID_SIGNATURE", "Invalid signature", details);
|
|
105648
|
+
}
|
|
105649
|
+
};
|
|
105650
|
+
var UnregisteredBuilderError = class extends ProtocolError {
|
|
105651
|
+
constructor(details) {
|
|
105652
|
+
super(401, "UNREGISTERED_BUILDER", "Unregistered builder", details);
|
|
105653
|
+
}
|
|
105654
|
+
};
|
|
105655
|
+
var NotOwnerError = class extends ProtocolError {
|
|
105656
|
+
constructor(details) {
|
|
105657
|
+
super(401, "NOT_OWNER", "Not the owner", details);
|
|
105658
|
+
}
|
|
105659
|
+
};
|
|
105660
|
+
var ExpiredTokenError2 = class extends ProtocolError {
|
|
105661
|
+
constructor(details) {
|
|
105662
|
+
super(401, "EXPIRED_TOKEN", "Token has expired", details);
|
|
105663
|
+
}
|
|
105664
|
+
};
|
|
105665
|
+
var GrantRequiredError = class extends ProtocolError {
|
|
105666
|
+
constructor(details) {
|
|
105667
|
+
super(403, "GRANT_REQUIRED", "Grant required", details);
|
|
105668
|
+
}
|
|
105669
|
+
};
|
|
105670
|
+
var GrantExpiredError = class extends ProtocolError {
|
|
105671
|
+
constructor(details) {
|
|
105672
|
+
super(403, "GRANT_EXPIRED", "Grant has expired", details);
|
|
105673
|
+
}
|
|
105674
|
+
};
|
|
105675
|
+
var GrantRevokedError = class extends ProtocolError {
|
|
105676
|
+
constructor(details) {
|
|
105677
|
+
super(403, "GRANT_REVOKED", "Grant has been revoked", details);
|
|
105678
|
+
}
|
|
105679
|
+
};
|
|
105680
|
+
var ScopeMismatchError = class extends ProtocolError {
|
|
105681
|
+
constructor(details) {
|
|
105682
|
+
super(403, "SCOPE_MISMATCH", "Scope not granted", details);
|
|
105683
|
+
}
|
|
105684
|
+
};
|
|
105685
|
+
var GrantOwnerMismatchError = class extends ProtocolError {
|
|
105686
|
+
constructor(details) {
|
|
105687
|
+
super(403, "GRANT_OWNER_MISMATCH", "Grant was not issued by this server's owner", details);
|
|
105688
|
+
}
|
|
105689
|
+
};
|
|
105690
|
+
var PsUnavailableError = class extends ProtocolError {
|
|
105691
|
+
constructor(details) {
|
|
105692
|
+
super(503, "PS_UNAVAILABLE", "Personal Server runtime unavailable", details);
|
|
105693
|
+
}
|
|
105694
|
+
};
|
|
105695
|
+
var ServerNotConfiguredError = class extends ProtocolError {
|
|
105696
|
+
constructor(details) {
|
|
105697
|
+
super(500, "SERVER_NOT_CONFIGURED", "Server is not configured", details);
|
|
105698
|
+
}
|
|
105699
|
+
};
|
|
105700
|
+
var LineageInvalidError = class extends ProtocolError {
|
|
105701
|
+
constructor(message, details) {
|
|
105702
|
+
super(400, "LINEAGE_INVALID", message, details);
|
|
105703
|
+
}
|
|
105704
|
+
};
|
|
105705
|
+
var LineageScopeUnderSourcePrefixError = class extends ProtocolError {
|
|
105706
|
+
constructor(details) {
|
|
105707
|
+
super(400, "LINEAGE_SCOPE_UNDER_SOURCE_PREFIX", `Derived scope "${details.scope}" shares its first segment with source scope "${details.sourceScope}"; a wildcard grant on that namespace would read both. Name derivatives under their own namespace.`, details);
|
|
105708
|
+
}
|
|
105709
|
+
};
|
|
105710
|
+
var LineageSourceUnknownError = class extends ProtocolError {
|
|
105711
|
+
constructor(details) {
|
|
105712
|
+
super(422, "LINEAGE_SOURCE_UNKNOWN", "One or more lineage sources are not data points of this owner", details);
|
|
105713
|
+
}
|
|
105714
|
+
};
|
|
105715
|
+
var LineageSourceLookupFailedError = class extends ProtocolError {
|
|
105716
|
+
constructor(details) {
|
|
105717
|
+
super(502, "LINEAGE_SOURCE_LOOKUP_FAILED", "Could not resolve a lineage source at the gateway", details);
|
|
105718
|
+
}
|
|
105719
|
+
};
|
|
105720
|
+
var LineageUnavailableError = class extends ProtocolError {
|
|
105721
|
+
constructor(details) {
|
|
105722
|
+
super(503, "LINEAGE_UNAVAILABLE", "This server is not configured to reach the gateway lineage graph (gateway URL or server signing key missing)", details);
|
|
105723
|
+
}
|
|
105724
|
+
};
|
|
105725
|
+
var LineageGatewayError = class extends ProtocolError {
|
|
105726
|
+
constructor(details) {
|
|
105727
|
+
super(502, "LINEAGE_GATEWAY_ERROR", `Gateway lineage request failed with status ${details.status}`, details);
|
|
105728
|
+
}
|
|
105729
|
+
};
|
|
105730
|
+
var LineageCascadeUnavailableError = class extends ProtocolError {
|
|
105731
|
+
constructor(details) {
|
|
105732
|
+
super(501, "LINEAGE_CASCADE_UNAVAILABLE", "DELETE ?cascade=lineage is specified but not implemented yet: the lineage walk that finds every derivative is missing. Delete scopes one at a time; each single-scope delete is durable.", details);
|
|
105733
|
+
}
|
|
105734
|
+
};
|
|
105735
|
+
var InvalidCascadeError = class extends ProtocolError {
|
|
105736
|
+
constructor(details) {
|
|
105737
|
+
super(400, "INVALID_CASCADE", 'Unsupported cascade mode; the only supported value is "lineage"', details);
|
|
105738
|
+
}
|
|
105739
|
+
};
|
|
105740
|
+
var DeleteTombstoneFailedError = class extends ProtocolError {
|
|
105741
|
+
constructor(details) {
|
|
105742
|
+
super(502, "DELETE_TOMBSTONE_FAILED", "Gateway did not acknowledge the deletion tombstone; nothing was deleted", details);
|
|
105743
|
+
}
|
|
105744
|
+
};
|
|
105745
|
+
var DataDeletedError = class extends ProtocolError {
|
|
105746
|
+
constructor(details) {
|
|
105747
|
+
super(410, "DATA_DELETED", "Data point has been deleted", details);
|
|
105748
|
+
}
|
|
105749
|
+
};
|
|
105750
|
+
|
|
105751
|
+
// ../core/dist/sync/data-point-id.js
|
|
105752
|
+
function computeDataPointId(ownerAddress, scope) {
|
|
105753
|
+
return keccak256(encodeAbiParameters([
|
|
105754
|
+
{ name: "ownerAddress", type: "address" },
|
|
105755
|
+
{ name: "scope", type: "string" }
|
|
105756
|
+
], [ownerAddress.toLowerCase(), scope]));
|
|
105757
|
+
}
|
|
105758
|
+
|
|
105759
|
+
// ../core/dist/lineage/lineage.js
|
|
105760
|
+
var LINEAGE_KEY = "$lineage";
|
|
105761
|
+
var LINEAGE_FIELD = "lineage";
|
|
105762
|
+
var MAX_LINEAGE_SOURCES = 256;
|
|
105763
|
+
var LOCAL_SCOPE_SCAN_PAGE = 1e3;
|
|
105764
|
+
var BYTES32_HEX = /^0x[0-9a-fA-F]{64}$/;
|
|
105765
|
+
function isRecord(value) {
|
|
105766
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
105767
|
+
}
|
|
105768
|
+
function hasReservedLineageKey(data) {
|
|
105769
|
+
return Object.prototype.hasOwnProperty.call(data, LINEAGE_KEY);
|
|
105770
|
+
}
|
|
105771
|
+
function stampLineage(data, lineage) {
|
|
105772
|
+
return { ...data, [LINEAGE_KEY]: lineage };
|
|
105773
|
+
}
|
|
105774
|
+
var StoredLineageMalformedError = class extends Error {
|
|
105775
|
+
constructor(detail) {
|
|
105776
|
+
super(`Stored $lineage is malformed: ${detail}`);
|
|
105777
|
+
this.name = "StoredLineageMalformedError";
|
|
105778
|
+
}
|
|
105779
|
+
};
|
|
105780
|
+
function readStoredLineage(data) {
|
|
105781
|
+
if (!isRecord(data) || !(LINEAGE_KEY in data))
|
|
105782
|
+
return null;
|
|
105783
|
+
const value = data[LINEAGE_KEY];
|
|
105784
|
+
if (!isRecord(value)) {
|
|
105785
|
+
throw new StoredLineageMalformedError("not an object");
|
|
105786
|
+
}
|
|
105787
|
+
const sources = value.sources;
|
|
105788
|
+
if (!Array.isArray(sources) || !sources.every((id2) => typeof id2 === "string" && BYTES32_HEX.test(id2))) {
|
|
105789
|
+
throw new StoredLineageMalformedError("sources is not a list of bytes32 ids");
|
|
105790
|
+
}
|
|
105791
|
+
if (typeof value.writtenAt !== "string") {
|
|
105792
|
+
throw new StoredLineageMalformedError("writtenAt is not a string");
|
|
105793
|
+
}
|
|
105794
|
+
return {
|
|
105795
|
+
sources: sources.map((id2) => id2.toLowerCase()),
|
|
105796
|
+
writtenAt: value.writtenAt
|
|
105797
|
+
};
|
|
105798
|
+
}
|
|
105799
|
+
function extractLineageField(container) {
|
|
105800
|
+
if (!isRecord(container))
|
|
105801
|
+
return void 0;
|
|
105802
|
+
return container[LINEAGE_FIELD];
|
|
105803
|
+
}
|
|
105804
|
+
function parseLineageSources(value) {
|
|
105805
|
+
if (!Array.isArray(value)) {
|
|
105806
|
+
throw new LineageInvalidError(`${LINEAGE_FIELD} must be an array of data point ids (0x-prefixed 32-byte hex)`);
|
|
105807
|
+
}
|
|
105808
|
+
if (value.length > MAX_LINEAGE_SOURCES) {
|
|
105809
|
+
throw new LineageInvalidError(`${LINEAGE_FIELD} lists ${value.length} sources; the maximum is ${MAX_LINEAGE_SOURCES}`, { max: MAX_LINEAGE_SOURCES, count: value.length });
|
|
105810
|
+
}
|
|
105811
|
+
const seen = /* @__PURE__ */ new Set();
|
|
105812
|
+
const sources = [];
|
|
105813
|
+
for (const entry of value) {
|
|
105814
|
+
if (typeof entry !== "string" || !BYTES32_HEX.test(entry)) {
|
|
105815
|
+
throw new LineageInvalidError(`${LINEAGE_FIELD} entries must be 0x-prefixed 32-byte hex data point ids`, { entry: typeof entry === "string" ? entry : typeof entry });
|
|
105816
|
+
}
|
|
105817
|
+
const id2 = entry.toLowerCase();
|
|
105818
|
+
if (seen.has(id2)) {
|
|
105819
|
+
throw new LineageInvalidError(`${LINEAGE_FIELD} lists the same source twice`, { duplicate: id2 });
|
|
105820
|
+
}
|
|
105821
|
+
seen.add(id2);
|
|
105822
|
+
sources.push(id2);
|
|
105823
|
+
}
|
|
105824
|
+
return sources;
|
|
105825
|
+
}
|
|
105826
|
+
function scopeNamespace(scope) {
|
|
105827
|
+
const dot = scope.indexOf(".");
|
|
105828
|
+
return dot === -1 ? scope : scope.slice(0, dot);
|
|
105829
|
+
}
|
|
105830
|
+
function derivedScopeViolatesNaming(derivedScope, sourceScope) {
|
|
105831
|
+
return scopeNamespace(derivedScope) === scopeNamespace(sourceScope);
|
|
105832
|
+
}
|
|
105833
|
+
function assertDerivedScopeNaming(derivedScope, sourceScopes) {
|
|
105834
|
+
for (const sourceScope of sourceScopes) {
|
|
105835
|
+
if (derivedScopeViolatesNaming(derivedScope, sourceScope)) {
|
|
105836
|
+
throw new LineageScopeUnderSourcePrefixError({
|
|
105837
|
+
scope: derivedScope,
|
|
105838
|
+
sourceScope
|
|
105839
|
+
});
|
|
105840
|
+
}
|
|
105841
|
+
}
|
|
105842
|
+
}
|
|
105843
|
+
async function resolveLineageSources(input) {
|
|
105844
|
+
const ownId = computeDataPointId(input.serverOwner, input.scope);
|
|
105845
|
+
const self2 = input.sources.find((id2) => id2 === ownId);
|
|
105846
|
+
if (self2) {
|
|
105847
|
+
throw new LineageInvalidError("A record cannot list its own data point as a lineage source", { dataPointId: self2 });
|
|
105848
|
+
}
|
|
105849
|
+
const local = localScopesById(input.storage, input.serverOwner, new Set(input.sources));
|
|
105850
|
+
const resolved = [];
|
|
105851
|
+
const unknown2 = [];
|
|
105852
|
+
for (const dataPointId of input.sources) {
|
|
105853
|
+
const localScope = local.get(dataPointId);
|
|
105854
|
+
if (localScope !== void 0) {
|
|
105855
|
+
resolved.push({
|
|
105856
|
+
dataPointId,
|
|
105857
|
+
scope: localScope,
|
|
105858
|
+
version: null,
|
|
105859
|
+
deletedAt: null
|
|
105860
|
+
});
|
|
105861
|
+
continue;
|
|
105862
|
+
}
|
|
105863
|
+
if (!input.gateway) {
|
|
105864
|
+
unknown2.push(dataPointId);
|
|
105865
|
+
continue;
|
|
105866
|
+
}
|
|
105867
|
+
let record2;
|
|
105868
|
+
try {
|
|
105869
|
+
record2 = await input.gateway.getDataPoint(dataPointId);
|
|
105870
|
+
} catch (err2) {
|
|
105871
|
+
throw new LineageSourceLookupFailedError({
|
|
105872
|
+
dataPointId,
|
|
105873
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
105874
|
+
});
|
|
105875
|
+
}
|
|
105876
|
+
if (!record2 || record2.ownerAddress.toLowerCase() !== input.serverOwner.toLowerCase()) {
|
|
105877
|
+
unknown2.push(dataPointId);
|
|
105878
|
+
continue;
|
|
105879
|
+
}
|
|
105880
|
+
resolved.push({
|
|
105881
|
+
dataPointId,
|
|
105882
|
+
scope: record2.scope,
|
|
105883
|
+
version: record2.version,
|
|
105884
|
+
deletedAt: record2.deletedAt
|
|
105885
|
+
});
|
|
105886
|
+
}
|
|
105887
|
+
if (unknown2.length > 0) {
|
|
105888
|
+
throw new LineageSourceUnknownError({ unknown: unknown2 });
|
|
105889
|
+
}
|
|
105890
|
+
return resolved;
|
|
105891
|
+
}
|
|
105892
|
+
function localScopesById(storage, serverOwner, wanted) {
|
|
105893
|
+
const byId = /* @__PURE__ */ new Map();
|
|
105894
|
+
for (let offset = 0; ; offset += LOCAL_SCOPE_SCAN_PAGE) {
|
|
105895
|
+
const { scopes, total } = storage.listScopes({
|
|
105896
|
+
limit: LOCAL_SCOPE_SCAN_PAGE,
|
|
105897
|
+
offset
|
|
105898
|
+
});
|
|
105899
|
+
for (const summary of scopes) {
|
|
105900
|
+
const id2 = computeDataPointId(serverOwner, summary.scope);
|
|
105901
|
+
if (wanted.has(id2))
|
|
105902
|
+
byId.set(id2, summary.scope);
|
|
105903
|
+
}
|
|
105904
|
+
if (byId.size === wanted.size || scopes.length === 0 || offset + scopes.length >= total) {
|
|
105905
|
+
break;
|
|
105906
|
+
}
|
|
105907
|
+
}
|
|
105908
|
+
return byId;
|
|
105909
|
+
}
|
|
105910
|
+
async function prepareLineage(input) {
|
|
105911
|
+
const sources = parseLineageSources(input.field);
|
|
105912
|
+
if (!input.serverOwner) {
|
|
105913
|
+
throw new ServerNotConfiguredError({
|
|
105914
|
+
reason: "serverOwner is required to validate lineage sources"
|
|
105915
|
+
});
|
|
105916
|
+
}
|
|
105917
|
+
const resolved = await resolveLineageSources({
|
|
105918
|
+
scope: input.scope,
|
|
105919
|
+
sources,
|
|
105920
|
+
serverOwner: input.serverOwner,
|
|
105921
|
+
storage: input.storage,
|
|
105922
|
+
gateway: input.gateway
|
|
105923
|
+
});
|
|
105924
|
+
assertDerivedScopeNaming(input.scope, resolved.map((source) => source.scope));
|
|
105925
|
+
return { sources, writtenAt: input.now().toISOString() };
|
|
105926
|
+
}
|
|
105927
|
+
|
|
105928
|
+
// ../core/dist/lineage/gateway.js
|
|
105929
|
+
function isRecord2(value) {
|
|
105930
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
105931
|
+
}
|
|
105932
|
+
function isLineageNode(value) {
|
|
105933
|
+
if (!isRecord2(value))
|
|
105934
|
+
return false;
|
|
105935
|
+
if (value.redacted === true) {
|
|
105936
|
+
return Object.keys(value).length === 1;
|
|
105937
|
+
}
|
|
105938
|
+
if (typeof value.dataPointId !== "string")
|
|
105939
|
+
return false;
|
|
105940
|
+
return typeof value.scope === "string" && typeof value.version === "string" && (value.deletedAt === null || typeof value.deletedAt === "string");
|
|
105941
|
+
}
|
|
105942
|
+
function isGatewayProof(value) {
|
|
105943
|
+
return isRecord2(value) && typeof value.userSignature === "string" && typeof value.gatewaySignature === "string" && typeof value.timestamp === "number" && typeof value.status === "string" && (value.estimatedConfirmation === null || typeof value.estimatedConfirmation === "string") && (value.chainBlockHeight === null || typeof value.chainBlockHeight === "number");
|
|
105944
|
+
}
|
|
105945
|
+
function derivesDataPointId(id2, ownerAddress, scope) {
|
|
105946
|
+
try {
|
|
105947
|
+
return computeDataPointId(ownerAddress, scope).toLowerCase() === id2.toLowerCase();
|
|
105948
|
+
} catch {
|
|
105949
|
+
return false;
|
|
105950
|
+
}
|
|
105951
|
+
}
|
|
105952
|
+
function parseLineageView(value) {
|
|
105953
|
+
if (!isRecord2(value) || typeof value.dataPointId !== "string" || typeof value.ownerAddress !== "string" || typeof value.scope !== "string" || typeof value.version !== "string" || !(value.deletedAt === null || typeof value.deletedAt === "string") || !Array.isArray(value.sources) || !value.sources.every(isLineageNode) || !Array.isArray(value.derivatives) || !value.derivatives.every(isLineageNode) || !(value.grantId === void 0 || typeof value.grantId === "string") || !(value.derivativesTruncated === void 0 || value.derivativesTruncated === true)) {
|
|
105954
|
+
return null;
|
|
105955
|
+
}
|
|
105956
|
+
return value;
|
|
105957
|
+
}
|
|
105958
|
+
function createGatewayLineageClient(options) {
|
|
105959
|
+
const base = options.gatewayUrl.replace(/\/+$/, "");
|
|
105960
|
+
const origin = new URL(base).origin;
|
|
105961
|
+
const doFetch = options.fetch ?? fetch;
|
|
105962
|
+
async function readJson(res) {
|
|
105963
|
+
try {
|
|
105964
|
+
return await res.json();
|
|
105965
|
+
} catch {
|
|
105966
|
+
return null;
|
|
105967
|
+
}
|
|
105968
|
+
}
|
|
105969
|
+
return {
|
|
105970
|
+
async getDataPoint(dataPointId) {
|
|
105971
|
+
const res = await doFetch(`${base}/v1/data/${encodeURIComponent(dataPointId)}?includeDeleted=true`);
|
|
105972
|
+
if (res.status === 404)
|
|
105973
|
+
return null;
|
|
105974
|
+
if (!res.ok) {
|
|
105975
|
+
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
105976
|
+
}
|
|
105977
|
+
const body = await readJson(res);
|
|
105978
|
+
const data = isRecord2(body) ? body.data : void 0;
|
|
105979
|
+
if (!isRecord2(data) || typeof data.id !== "string" || typeof data.ownerAddress !== "string" || typeof data.scope !== "string" || typeof data.expectedVersion !== "string") {
|
|
105980
|
+
throw new Error("Gateway error: malformed data point response");
|
|
105981
|
+
}
|
|
105982
|
+
if (data.id.toLowerCase() !== dataPointId.toLowerCase()) {
|
|
105983
|
+
throw new Error(`Gateway error: data point response is for ${data.id}, requested ${dataPointId}`);
|
|
105984
|
+
}
|
|
105985
|
+
if (!derivesDataPointId(data.id, data.ownerAddress, data.scope)) {
|
|
105986
|
+
throw new Error(`Gateway error: data point ${data.id} does not derive from its owner and scope`);
|
|
105987
|
+
}
|
|
105988
|
+
return {
|
|
105989
|
+
dataPointId: data.id,
|
|
105990
|
+
ownerAddress: data.ownerAddress,
|
|
105991
|
+
scope: data.scope,
|
|
105992
|
+
version: data.expectedVersion,
|
|
105993
|
+
deletedAt: typeof data.deletedAt === "string" ? data.deletedAt : null
|
|
105994
|
+
};
|
|
105995
|
+
},
|
|
105996
|
+
async getLineage(input) {
|
|
105997
|
+
if (!options.requestSigner) {
|
|
105998
|
+
throw new LineageUnavailableError({ reason: "no request signer" });
|
|
105999
|
+
}
|
|
106000
|
+
const uri = `/v1/data/${input.dataPointId.toLowerCase()}/lineage` + (input.version !== void 0 ? `/${input.version}` : "");
|
|
106001
|
+
const authorization = await options.requestSigner.signRequest({
|
|
106002
|
+
aud: origin,
|
|
106003
|
+
method: "GET",
|
|
106004
|
+
uri,
|
|
106005
|
+
grantId: input.grantId?.toLowerCase()
|
|
106006
|
+
});
|
|
106007
|
+
const res = await doFetch(`${base}${uri}`, {
|
|
106008
|
+
headers: { Authorization: authorization }
|
|
106009
|
+
});
|
|
106010
|
+
const body = await readJson(res);
|
|
106011
|
+
if (!res.ok)
|
|
106012
|
+
return { ok: false, status: res.status, body };
|
|
106013
|
+
const data = parseLineageView(isRecord2(body) ? body.data : void 0);
|
|
106014
|
+
const proof = isRecord2(body) ? body.proof : void 0;
|
|
106015
|
+
if (!data || !isGatewayProof(proof)) {
|
|
106016
|
+
return {
|
|
106017
|
+
ok: false,
|
|
106018
|
+
status: res.status,
|
|
106019
|
+
body: { error: "malformed lineage response", received: body }
|
|
106020
|
+
};
|
|
106021
|
+
}
|
|
106022
|
+
const requestedId = input.dataPointId.toLowerCase();
|
|
106023
|
+
const requestedGrant = input.grantId?.toLowerCase();
|
|
106024
|
+
const servedGrant = data.grantId?.toLowerCase();
|
|
106025
|
+
const viewMismatch = data.dataPointId.toLowerCase() !== requestedId || input.version !== void 0 && data.version !== input.version || requestedGrant !== servedGrant;
|
|
106026
|
+
if (viewMismatch) {
|
|
106027
|
+
return {
|
|
106028
|
+
ok: false,
|
|
106029
|
+
status: res.status,
|
|
106030
|
+
body: {
|
|
106031
|
+
error: "lineage response does not match the requested view",
|
|
106032
|
+
requested: {
|
|
106033
|
+
dataPointId: requestedId,
|
|
106034
|
+
version: input.version,
|
|
106035
|
+
grantId: requestedGrant
|
|
106036
|
+
},
|
|
106037
|
+
received: {
|
|
106038
|
+
dataPointId: data.dataPointId,
|
|
106039
|
+
version: data.version,
|
|
106040
|
+
grantId: servedGrant
|
|
106041
|
+
}
|
|
106042
|
+
}
|
|
106043
|
+
};
|
|
106044
|
+
}
|
|
106045
|
+
if (!derivesDataPointId(data.dataPointId, data.ownerAddress, data.scope)) {
|
|
106046
|
+
return {
|
|
106047
|
+
ok: false,
|
|
106048
|
+
status: res.status,
|
|
106049
|
+
body: {
|
|
106050
|
+
error: "lineage view does not derive from its owner and scope",
|
|
106051
|
+
received: {
|
|
106052
|
+
dataPointId: data.dataPointId,
|
|
106053
|
+
ownerAddress: data.ownerAddress,
|
|
106054
|
+
scope: data.scope
|
|
106055
|
+
}
|
|
106056
|
+
}
|
|
106057
|
+
};
|
|
106058
|
+
}
|
|
106059
|
+
return { ok: true, data, proof };
|
|
106060
|
+
},
|
|
106061
|
+
async registerDataPoint(params) {
|
|
106062
|
+
const res = await doFetch(`${base}/v1/data`, {
|
|
106063
|
+
method: "POST",
|
|
106064
|
+
headers: {
|
|
106065
|
+
"Content-Type": "application/json",
|
|
106066
|
+
Authorization: `Web3Signed ${params.signature}`
|
|
106067
|
+
},
|
|
106068
|
+
body: JSON.stringify({
|
|
106069
|
+
ownerAddress: params.ownerAddress,
|
|
106070
|
+
scope: params.scope,
|
|
106071
|
+
dataHash: params.dataHash,
|
|
106072
|
+
metadataHash: params.metadataHash,
|
|
106073
|
+
expectedVersion: params.expectedVersion,
|
|
106074
|
+
lineage: [...params.lineage],
|
|
106075
|
+
lineageSignature: params.lineageSignature
|
|
106076
|
+
})
|
|
106077
|
+
});
|
|
106078
|
+
if (!res.ok) {
|
|
106079
|
+
const body2 = await readJson(res);
|
|
106080
|
+
const detail = isRecord2(body2) && typeof body2.error === "string" && body2.error || res.statusText;
|
|
106081
|
+
throw new Error(`Gateway error: ${res.status} ${detail}`);
|
|
106082
|
+
}
|
|
106083
|
+
const body = await readJson(res);
|
|
106084
|
+
const record2 = isRecord2(body) ? body : {};
|
|
106085
|
+
return {
|
|
106086
|
+
dataPointId: typeof record2.dataPointId === "string" ? record2.dataPointId : typeof record2.id === "string" ? record2.id : void 0,
|
|
106087
|
+
expectedVersion: typeof record2.expectedVersion === "string" ? record2.expectedVersion : void 0
|
|
106088
|
+
};
|
|
106089
|
+
}
|
|
106090
|
+
};
|
|
106091
|
+
}
|
|
106092
|
+
|
|
105582
106093
|
// ../lite/node_modules/@opendatalabs/vana-sdk/dist/index.browser.js
|
|
105583
106094
|
init_hmac();
|
|
105584
106095
|
init_sha2();
|
|
@@ -108843,6 +109354,7 @@ async function createPersistentPsLiteStorage(adapter, persistence = createIndexe
|
|
|
108843
109354
|
schemaId: entry.schemaId ?? null,
|
|
108844
109355
|
version: version4,
|
|
108845
109356
|
dataPointId: entry.dataPointId ?? null,
|
|
109357
|
+
afterTombstoneVersion: entry.afterTombstoneVersion ?? null,
|
|
108846
109358
|
id: state.nextId,
|
|
108847
109359
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
108848
109360
|
};
|
|
@@ -108936,25 +109448,34 @@ async function createPersistentPsLiteStorage(adapter, persistence = createIndexe
|
|
|
108936
109448
|
await persist();
|
|
108937
109449
|
return deleted;
|
|
108938
109450
|
},
|
|
109451
|
+
async deleteVersion(scope, collectedAt2) {
|
|
109452
|
+
const entry = state.entries.find((e10) => e10.scope === scope && e10.collectedAt === collectedAt2);
|
|
109453
|
+
if (!entry)
|
|
109454
|
+
return false;
|
|
109455
|
+
return removeEntry(entry);
|
|
109456
|
+
},
|
|
108939
109457
|
async deleteByFileId(fileId) {
|
|
108940
109458
|
const entry = state.entries.find((e10) => e10.fileId === fileId);
|
|
108941
109459
|
if (!entry)
|
|
108942
109460
|
return false;
|
|
108943
|
-
|
|
108944
|
-
await Promise.all([
|
|
108945
|
-
fileStore.deleteEnvelope(blobPath),
|
|
108946
|
-
fallbackStore.deleteEnvelope(blobPath),
|
|
108947
|
-
fileStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve(),
|
|
108948
|
-
fallbackStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve()
|
|
108949
|
-
]);
|
|
108950
|
-
state = {
|
|
108951
|
-
...state,
|
|
108952
|
-
entries: state.entries.filter((e10) => e10 !== entry)
|
|
108953
|
-
};
|
|
108954
|
-
await persist();
|
|
108955
|
-
return true;
|
|
109461
|
+
return removeEntry(entry);
|
|
108956
109462
|
}
|
|
108957
109463
|
};
|
|
109464
|
+
async function removeEntry(entry) {
|
|
109465
|
+
const blobPath = envelopePath(entry.scope, entry.collectedAt);
|
|
109466
|
+
await Promise.all([
|
|
109467
|
+
fileStore.deleteEnvelope(blobPath),
|
|
109468
|
+
fallbackStore.deleteEnvelope(blobPath),
|
|
109469
|
+
fileStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve(),
|
|
109470
|
+
fallbackStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve()
|
|
109471
|
+
]);
|
|
109472
|
+
state = {
|
|
109473
|
+
...state,
|
|
109474
|
+
entries: state.entries.filter((e10) => e10 !== entry)
|
|
109475
|
+
};
|
|
109476
|
+
await persist();
|
|
109477
|
+
return true;
|
|
109478
|
+
}
|
|
108958
109479
|
if (fileStore.readEnvelopePreview) {
|
|
108959
109480
|
storagePort.readEnvelopePreview = async (scope, collectedAt2, { maxBytes }) => {
|
|
108960
109481
|
const path = envelopePath(scope, collectedAt2);
|
|
@@ -109588,90 +110109,6 @@ async function loadOrCreatePsLiteServerIdentity(params) {
|
|
|
109588
110109
|
return { persisted, account };
|
|
109589
110110
|
}
|
|
109590
110111
|
|
|
109591
|
-
// ../core/dist/errors/catalog.js
|
|
109592
|
-
var ProtocolError = class extends Error {
|
|
109593
|
-
code;
|
|
109594
|
-
errorCode;
|
|
109595
|
-
details;
|
|
109596
|
-
constructor(code, errorCode, message, details) {
|
|
109597
|
-
super(message);
|
|
109598
|
-
this.code = code;
|
|
109599
|
-
this.errorCode = errorCode;
|
|
109600
|
-
this.details = details;
|
|
109601
|
-
this.name = this.constructor.name;
|
|
109602
|
-
}
|
|
109603
|
-
toJSON() {
|
|
109604
|
-
return {
|
|
109605
|
-
error: {
|
|
109606
|
-
code: this.code,
|
|
109607
|
-
errorCode: this.errorCode,
|
|
109608
|
-
message: this.message,
|
|
109609
|
-
...this.details !== void 0 && { details: this.details }
|
|
109610
|
-
}
|
|
109611
|
-
};
|
|
109612
|
-
}
|
|
109613
|
-
};
|
|
109614
|
-
var MissingAuthError2 = class extends ProtocolError {
|
|
109615
|
-
constructor(details) {
|
|
109616
|
-
super(401, "MISSING_AUTH", "Missing authentication", details);
|
|
109617
|
-
}
|
|
109618
|
-
};
|
|
109619
|
-
var InvalidSignatureError3 = class extends ProtocolError {
|
|
109620
|
-
constructor(details) {
|
|
109621
|
-
super(401, "INVALID_SIGNATURE", "Invalid signature", details);
|
|
109622
|
-
}
|
|
109623
|
-
};
|
|
109624
|
-
var UnregisteredBuilderError = class extends ProtocolError {
|
|
109625
|
-
constructor(details) {
|
|
109626
|
-
super(401, "UNREGISTERED_BUILDER", "Unregistered builder", details);
|
|
109627
|
-
}
|
|
109628
|
-
};
|
|
109629
|
-
var NotOwnerError = class extends ProtocolError {
|
|
109630
|
-
constructor(details) {
|
|
109631
|
-
super(401, "NOT_OWNER", "Not the owner", details);
|
|
109632
|
-
}
|
|
109633
|
-
};
|
|
109634
|
-
var ExpiredTokenError2 = class extends ProtocolError {
|
|
109635
|
-
constructor(details) {
|
|
109636
|
-
super(401, "EXPIRED_TOKEN", "Token has expired", details);
|
|
109637
|
-
}
|
|
109638
|
-
};
|
|
109639
|
-
var GrantRequiredError = class extends ProtocolError {
|
|
109640
|
-
constructor(details) {
|
|
109641
|
-
super(403, "GRANT_REQUIRED", "Grant required", details);
|
|
109642
|
-
}
|
|
109643
|
-
};
|
|
109644
|
-
var GrantExpiredError = class extends ProtocolError {
|
|
109645
|
-
constructor(details) {
|
|
109646
|
-
super(403, "GRANT_EXPIRED", "Grant has expired", details);
|
|
109647
|
-
}
|
|
109648
|
-
};
|
|
109649
|
-
var GrantRevokedError = class extends ProtocolError {
|
|
109650
|
-
constructor(details) {
|
|
109651
|
-
super(403, "GRANT_REVOKED", "Grant has been revoked", details);
|
|
109652
|
-
}
|
|
109653
|
-
};
|
|
109654
|
-
var ScopeMismatchError = class extends ProtocolError {
|
|
109655
|
-
constructor(details) {
|
|
109656
|
-
super(403, "SCOPE_MISMATCH", "Scope not granted", details);
|
|
109657
|
-
}
|
|
109658
|
-
};
|
|
109659
|
-
var GrantOwnerMismatchError = class extends ProtocolError {
|
|
109660
|
-
constructor(details) {
|
|
109661
|
-
super(403, "GRANT_OWNER_MISMATCH", "Grant was not issued by this server's owner", details);
|
|
109662
|
-
}
|
|
109663
|
-
};
|
|
109664
|
-
var PsUnavailableError = class extends ProtocolError {
|
|
109665
|
-
constructor(details) {
|
|
109666
|
-
super(503, "PS_UNAVAILABLE", "Personal Server runtime unavailable", details);
|
|
109667
|
-
}
|
|
109668
|
-
};
|
|
109669
|
-
var ServerNotConfiguredError = class extends ProtocolError {
|
|
109670
|
-
constructor(details) {
|
|
109671
|
-
super(500, "SERVER_NOT_CONFIGURED", "Server is not configured", details);
|
|
109672
|
-
}
|
|
109673
|
-
};
|
|
109674
|
-
|
|
109675
110112
|
// ../core/dist/auth/request.js
|
|
109676
110113
|
function resolveOrigin(origin) {
|
|
109677
110114
|
return typeof origin === "function" ? origin() : origin;
|
|
@@ -110323,18 +110760,47 @@ function normalizeLimit(value) {
|
|
|
110323
110760
|
function normalizeOffset(value) {
|
|
110324
110761
|
return value ?? 0;
|
|
110325
110762
|
}
|
|
110326
|
-
function
|
|
110763
|
+
function isRecord3(value) {
|
|
110327
110764
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
110328
110765
|
}
|
|
110766
|
+
var VISIBILITY_PAGE_SIZE = 200;
|
|
110329
110767
|
async function listDataScopesContract(input) {
|
|
110330
110768
|
const limit = normalizeLimit(input.limit);
|
|
110331
110769
|
const offset = normalizeOffset(input.offset);
|
|
110332
|
-
|
|
110333
|
-
|
|
110334
|
-
|
|
110335
|
-
|
|
110336
|
-
|
|
110337
|
-
|
|
110770
|
+
let page;
|
|
110771
|
+
let total;
|
|
110772
|
+
if (input.isVisible) {
|
|
110773
|
+
const visible = [];
|
|
110774
|
+
for (let scan = 0; ; scan += VISIBILITY_PAGE_SIZE) {
|
|
110775
|
+
const batch = input.storage.listScopes({
|
|
110776
|
+
scopePrefix: input.scopePrefix,
|
|
110777
|
+
limit: VISIBILITY_PAGE_SIZE,
|
|
110778
|
+
offset: scan
|
|
110779
|
+
});
|
|
110780
|
+
for (const summary of batch.scopes) {
|
|
110781
|
+
const latest = input.storage.findEntry({
|
|
110782
|
+
scope: summary.scope,
|
|
110783
|
+
at: summary.latestCollectedAt
|
|
110784
|
+
});
|
|
110785
|
+
if (!latest || await input.isVisible(summary.scope, latest)) {
|
|
110786
|
+
visible.push(summary);
|
|
110787
|
+
}
|
|
110788
|
+
}
|
|
110789
|
+
if (batch.scopes.length < VISIBILITY_PAGE_SIZE)
|
|
110790
|
+
break;
|
|
110791
|
+
}
|
|
110792
|
+
total = visible.length;
|
|
110793
|
+
page = visible.slice(offset, offset + limit);
|
|
110794
|
+
} else {
|
|
110795
|
+
const result = input.storage.listScopes({
|
|
110796
|
+
scopePrefix: input.scopePrefix,
|
|
110797
|
+
limit,
|
|
110798
|
+
offset
|
|
110799
|
+
});
|
|
110800
|
+
page = result.scopes;
|
|
110801
|
+
total = result.total;
|
|
110802
|
+
}
|
|
110803
|
+
const scopes = await Promise.all(page.map(async (summary) => {
|
|
110338
110804
|
const entry = input.storage.findEntry({
|
|
110339
110805
|
scope: summary.scope,
|
|
110340
110806
|
at: summary.latestCollectedAt
|
|
@@ -110342,7 +110808,7 @@ async function listDataScopesContract(input) {
|
|
|
110342
110808
|
if (!entry) {
|
|
110343
110809
|
return summary;
|
|
110344
110810
|
}
|
|
110345
|
-
const hasBlocks = typeof input.storage.
|
|
110811
|
+
const hasBlocks = typeof input.storage.hasScopeBlocks === "function" ? await input.storage.hasScopeBlocks(summary.scope, summary.latestCollectedAt) : false;
|
|
110346
110812
|
return {
|
|
110347
110813
|
...summary,
|
|
110348
110814
|
dataStatus: hasBlocks ? "ready" : "indexing",
|
|
@@ -110353,33 +110819,52 @@ async function listDataScopesContract(input) {
|
|
|
110353
110819
|
ok: true,
|
|
110354
110820
|
response: {
|
|
110355
110821
|
scopes,
|
|
110356
|
-
total
|
|
110822
|
+
total,
|
|
110357
110823
|
limit,
|
|
110358
110824
|
offset
|
|
110359
110825
|
}
|
|
110360
110826
|
};
|
|
110361
110827
|
}
|
|
110362
|
-
function listDataVersionsContract(input) {
|
|
110828
|
+
async function listDataVersionsContract(input) {
|
|
110363
110829
|
const scopeResult = parseDataScopeContract(input.scopeParam);
|
|
110364
110830
|
if (!scopeResult.ok)
|
|
110365
110831
|
return scopeResult;
|
|
110366
110832
|
const limit = normalizeLimit(input.limit);
|
|
110367
110833
|
const offset = normalizeOffset(input.offset);
|
|
110368
|
-
|
|
110369
|
-
|
|
110370
|
-
|
|
110371
|
-
|
|
110834
|
+
let page;
|
|
110835
|
+
let total;
|
|
110836
|
+
if (input.isVisible) {
|
|
110837
|
+
const visible = [];
|
|
110838
|
+
for (let scan = 0; ; scan += VISIBILITY_PAGE_SIZE) {
|
|
110839
|
+
const batch = input.storage.listVersions(scopeResult.scope, {
|
|
110840
|
+
limit: VISIBILITY_PAGE_SIZE,
|
|
110841
|
+
offset: scan
|
|
110842
|
+
});
|
|
110843
|
+
for (const entry of batch) {
|
|
110844
|
+
if (await input.isVisible(scopeResult.scope, entry)) {
|
|
110845
|
+
visible.push(entry);
|
|
110846
|
+
}
|
|
110847
|
+
}
|
|
110848
|
+
if (batch.length < VISIBILITY_PAGE_SIZE)
|
|
110849
|
+
break;
|
|
110850
|
+
}
|
|
110851
|
+
total = visible.length;
|
|
110852
|
+
page = visible.slice(offset, offset + limit);
|
|
110853
|
+
} else {
|
|
110854
|
+
page = input.storage.listVersions(scopeResult.scope, { limit, offset });
|
|
110855
|
+
total = input.storage.countVersions(scopeResult.scope);
|
|
110856
|
+
}
|
|
110372
110857
|
return {
|
|
110373
110858
|
ok: true,
|
|
110374
110859
|
scope: scopeResult.scope,
|
|
110375
110860
|
response: {
|
|
110376
110861
|
scope: scopeResult.scope,
|
|
110377
|
-
versions:
|
|
110862
|
+
versions: page.map((entry) => ({
|
|
110378
110863
|
fileId: entry.fileId,
|
|
110379
110864
|
schemaId: entry.schemaId,
|
|
110380
110865
|
collectedAt: entry.collectedAt
|
|
110381
110866
|
})),
|
|
110382
|
-
total
|
|
110867
|
+
total,
|
|
110383
110868
|
limit,
|
|
110384
110869
|
offset
|
|
110385
110870
|
}
|
|
@@ -110414,7 +110899,7 @@ async function ingestDataContract(input) {
|
|
|
110414
110899
|
const scopeResult = parseDataScopeContract(input.scopeParam);
|
|
110415
110900
|
if (!scopeResult.ok)
|
|
110416
110901
|
return scopeResult;
|
|
110417
|
-
if (!
|
|
110902
|
+
if (!isRecord3(input.body)) {
|
|
110418
110903
|
return {
|
|
110419
110904
|
ok: false,
|
|
110420
110905
|
status: 400,
|
|
@@ -110434,7 +110919,17 @@ async function ingestDataContract(input) {
|
|
|
110434
110919
|
}
|
|
110435
110920
|
};
|
|
110436
110921
|
}
|
|
110437
|
-
|
|
110922
|
+
if (hasReservedLineageKey(input.body)) {
|
|
110923
|
+
return {
|
|
110924
|
+
ok: false,
|
|
110925
|
+
status: 400,
|
|
110926
|
+
body: {
|
|
110927
|
+
error: "INVALID_BODY",
|
|
110928
|
+
message: "Request body must not contain the reserved $lineage key"
|
|
110929
|
+
}
|
|
110930
|
+
};
|
|
110931
|
+
}
|
|
110932
|
+
const envelope = createDataFileEnvelope(scopeResult.scope, input.collectedAt, stampServerKeys(input.body, input));
|
|
110438
110933
|
const writeResult = await input.storage.writeEnvelope(envelope);
|
|
110439
110934
|
try {
|
|
110440
110935
|
await writeBlockSidecars(input.storage, envelope);
|
|
@@ -110446,20 +110941,34 @@ async function ingestDataContract(input) {
|
|
|
110446
110941
|
path: writeResult.relativePath,
|
|
110447
110942
|
scope: scopeResult.scope,
|
|
110448
110943
|
collectedAt: input.collectedAt,
|
|
110449
|
-
sizeBytes: writeResult.sizeBytes
|
|
110944
|
+
sizeBytes: writeResult.sizeBytes,
|
|
110945
|
+
afterTombstoneVersion: input.afterTombstoneVersion ?? null
|
|
110450
110946
|
});
|
|
110451
110947
|
return {
|
|
110452
110948
|
ok: true,
|
|
110453
110949
|
scope: scopeResult.scope,
|
|
110454
110950
|
collectedAt: input.collectedAt,
|
|
110455
|
-
response:
|
|
110456
|
-
scope: scopeResult.scope,
|
|
110457
|
-
collectedAt: input.collectedAt,
|
|
110458
|
-
status: input.status
|
|
110459
|
-
},
|
|
110951
|
+
response: ingestResponse(scopeResult.scope, input),
|
|
110460
110952
|
writeResult
|
|
110461
110953
|
};
|
|
110462
110954
|
}
|
|
110955
|
+
function stampServerKeys(data, input) {
|
|
110956
|
+
let stamped = data;
|
|
110957
|
+
if (input.lineage)
|
|
110958
|
+
stamped = stampLineage(stamped, input.lineage);
|
|
110959
|
+
if (input.attribution) {
|
|
110960
|
+
stamped = stampWriterAttribution(stamped, input.attribution);
|
|
110961
|
+
}
|
|
110962
|
+
return stamped;
|
|
110963
|
+
}
|
|
110964
|
+
function ingestResponse(scope, input) {
|
|
110965
|
+
return {
|
|
110966
|
+
scope,
|
|
110967
|
+
collectedAt: input.collectedAt,
|
|
110968
|
+
status: input.status,
|
|
110969
|
+
...input.lineage ? { lineage: { sources: input.lineage.sources } } : {}
|
|
110970
|
+
};
|
|
110971
|
+
}
|
|
110463
110972
|
async function ingestBinaryDataContract(input) {
|
|
110464
110973
|
const scopeResult = parseDataScopeContract(input.scopeParam);
|
|
110465
110974
|
if (!scopeResult.ok)
|
|
@@ -110474,6 +110983,16 @@ async function ingestBinaryDataContract(input) {
|
|
|
110474
110983
|
}
|
|
110475
110984
|
};
|
|
110476
110985
|
}
|
|
110986
|
+
if (isRecord3(input.metadata) && (hasReservedWriterKey(input.metadata) || hasReservedLineageKey(input.metadata))) {
|
|
110987
|
+
return {
|
|
110988
|
+
ok: false,
|
|
110989
|
+
status: 400,
|
|
110990
|
+
body: {
|
|
110991
|
+
error: "INVALID_BODY",
|
|
110992
|
+
message: "X-Vana-Metadata must not contain the reserved $lineage or $writtenBy keys"
|
|
110993
|
+
}
|
|
110994
|
+
};
|
|
110995
|
+
}
|
|
110477
110996
|
const contentHash = await sha256Hex(input.bytes);
|
|
110478
110997
|
const data = buildBinaryEnvelopeData({
|
|
110479
110998
|
bytes: input.bytes,
|
|
@@ -110482,7 +111001,7 @@ async function ingestBinaryDataContract(input) {
|
|
|
110482
111001
|
contentHash,
|
|
110483
111002
|
metadata: input.metadata
|
|
110484
111003
|
});
|
|
110485
|
-
const envelope = createDataFileEnvelope(scopeResult.scope, input.collectedAt,
|
|
111004
|
+
const envelope = createDataFileEnvelope(scopeResult.scope, input.collectedAt, stampServerKeys(data, input));
|
|
110486
111005
|
const writeResult = await input.storage.writeEnvelope(envelope);
|
|
110487
111006
|
try {
|
|
110488
111007
|
await writeBlockSidecars(input.storage, envelope);
|
|
@@ -110494,29 +111013,17 @@ async function ingestBinaryDataContract(input) {
|
|
|
110494
111013
|
path: writeResult.relativePath,
|
|
110495
111014
|
scope: scopeResult.scope,
|
|
110496
111015
|
collectedAt: input.collectedAt,
|
|
110497
|
-
sizeBytes: input.bytes.length
|
|
111016
|
+
sizeBytes: input.bytes.length,
|
|
111017
|
+
afterTombstoneVersion: input.afterTombstoneVersion ?? null
|
|
110498
111018
|
});
|
|
110499
111019
|
return {
|
|
110500
111020
|
ok: true,
|
|
110501
111021
|
scope: scopeResult.scope,
|
|
110502
111022
|
collectedAt: input.collectedAt,
|
|
110503
|
-
response:
|
|
110504
|
-
scope: scopeResult.scope,
|
|
110505
|
-
collectedAt: input.collectedAt,
|
|
110506
|
-
status: input.status
|
|
110507
|
-
},
|
|
111023
|
+
response: ingestResponse(scopeResult.scope, input),
|
|
110508
111024
|
writeResult
|
|
110509
111025
|
};
|
|
110510
111026
|
}
|
|
110511
|
-
async function deleteDataScopeContract(input) {
|
|
110512
|
-
const scopeResult = parseDataScopeContract(input.scopeParam);
|
|
110513
|
-
if (!scopeResult.ok)
|
|
110514
|
-
return scopeResult;
|
|
110515
|
-
return {
|
|
110516
|
-
ok: true,
|
|
110517
|
-
deletedCount: await input.storage.deleteScope(scopeResult.scope)
|
|
110518
|
-
};
|
|
110519
|
-
}
|
|
110520
111027
|
async function writeBlockSidecars(storage, envelope) {
|
|
110521
111028
|
if (!storage.writeBlockManifest)
|
|
110522
111029
|
return;
|
|
@@ -111102,6 +111609,548 @@ async function syncFileContract(input) {
|
|
|
111102
111609
|
return contractOk({ fileId: input.fileId, status: "started" }, 202);
|
|
111103
111610
|
}
|
|
111104
111611
|
|
|
111612
|
+
// ../core/dist/sync/tombstone.js
|
|
111613
|
+
var TOMBSTONE_DATA_HASH_LABEL = "vana.data-point.tombstone.v1";
|
|
111614
|
+
var TOMBSTONE_METADATA_HASH_LABEL = "vana.data-point.tombstone.metadata.v1";
|
|
111615
|
+
var TOMBSTONE_DATA_HASH = keccak256(stringToHex(TOMBSTONE_DATA_HASH_LABEL));
|
|
111616
|
+
var TOMBSTONE_METADATA_HASH = keccak256(stringToHex(TOMBSTONE_METADATA_HASH_LABEL));
|
|
111617
|
+
function isTombstoneRecord(record2) {
|
|
111618
|
+
return record2.dataHash.toLowerCase() === TOMBSTONE_DATA_HASH && record2.metadataHash.toLowerCase() === TOMBSTONE_METADATA_HASH;
|
|
111619
|
+
}
|
|
111620
|
+
|
|
111621
|
+
// ../core/dist/sync/scope-deletions.js
|
|
111622
|
+
var DEFAULT_SCOPE_DELETION_MAX_STALENESS_MS = 12e4;
|
|
111623
|
+
var DEFAULT_SCOPE_DELETION_GATEWAY_RETRY_MS = 15e3;
|
|
111624
|
+
var DEFAULT_MAX_LIVE_ENTRIES = 1e4;
|
|
111625
|
+
function createScopeDeletionTracker(options = {}) {
|
|
111626
|
+
const maxStalenessMs = options.maxStalenessMs ?? DEFAULT_SCOPE_DELETION_MAX_STALENESS_MS;
|
|
111627
|
+
const gatewayRetryMs = options.gatewayRetryMs ?? DEFAULT_SCOPE_DELETION_GATEWAY_RETRY_MS;
|
|
111628
|
+
const maxLiveEntries = options.maxLiveEntries ?? DEFAULT_MAX_LIVE_ENTRIES;
|
|
111629
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
111630
|
+
const nowMs = () => now().getTime();
|
|
111631
|
+
const deleted = /* @__PURE__ */ new Map();
|
|
111632
|
+
const live = /* @__PURE__ */ new Map();
|
|
111633
|
+
let lastFeedSyncMs = null;
|
|
111634
|
+
let lastGatewayFailureMs = null;
|
|
111635
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
111636
|
+
function rememberLive(scope, at3) {
|
|
111637
|
+
deleted.delete(scope);
|
|
111638
|
+
live.delete(scope);
|
|
111639
|
+
live.set(scope, at3);
|
|
111640
|
+
while (live.size > maxLiveEntries) {
|
|
111641
|
+
const oldest = live.keys().next().value;
|
|
111642
|
+
if (oldest === void 0)
|
|
111643
|
+
break;
|
|
111644
|
+
live.delete(oldest);
|
|
111645
|
+
}
|
|
111646
|
+
}
|
|
111647
|
+
function rememberDeleted(scope, tombstone, source) {
|
|
111648
|
+
deleted.set(scope, {
|
|
111649
|
+
deletedAt: tombstone.deletedAt,
|
|
111650
|
+
version: normalizeVersion(tombstone.version),
|
|
111651
|
+
source,
|
|
111652
|
+
verifiedAtMs: nowMs()
|
|
111653
|
+
});
|
|
111654
|
+
live.delete(scope);
|
|
111655
|
+
}
|
|
111656
|
+
function isFresh(at3) {
|
|
111657
|
+
return at3 !== null && nowMs() - at3 <= maxStalenessMs;
|
|
111658
|
+
}
|
|
111659
|
+
function verdictFromRecord(scope, record2) {
|
|
111660
|
+
const deletedAt = deletionTimestamp(record2);
|
|
111661
|
+
if (deletedAt !== null) {
|
|
111662
|
+
const version4 = tombstoneVersion(record2);
|
|
111663
|
+
rememberDeleted(scope, { deletedAt, version: version4 }, "gateway");
|
|
111664
|
+
return {
|
|
111665
|
+
deleted: true,
|
|
111666
|
+
deletedAt,
|
|
111667
|
+
version: version4,
|
|
111668
|
+
source: "gateway",
|
|
111669
|
+
verified: true
|
|
111670
|
+
};
|
|
111671
|
+
}
|
|
111672
|
+
rememberLive(scope, nowMs());
|
|
111673
|
+
return { deleted: false, source: "gateway", verified: true };
|
|
111674
|
+
}
|
|
111675
|
+
async function lookup2(scope) {
|
|
111676
|
+
const feed = options.feed;
|
|
111677
|
+
const owner = options.serverOwner;
|
|
111678
|
+
if (!feed || !owner)
|
|
111679
|
+
return null;
|
|
111680
|
+
if (lastGatewayFailureMs !== null && nowMs() - lastGatewayFailureMs < gatewayRetryMs) {
|
|
111681
|
+
return null;
|
|
111682
|
+
}
|
|
111683
|
+
const pending = inflight.get(scope);
|
|
111684
|
+
if (pending)
|
|
111685
|
+
return pending;
|
|
111686
|
+
const request2 = (async () => {
|
|
111687
|
+
try {
|
|
111688
|
+
const record2 = await feed.getDataPoint({
|
|
111689
|
+
ownerAddress: owner,
|
|
111690
|
+
scope
|
|
111691
|
+
});
|
|
111692
|
+
lastGatewayFailureMs = null;
|
|
111693
|
+
return verdictFromRecord(scope, record2);
|
|
111694
|
+
} catch (err2) {
|
|
111695
|
+
lastGatewayFailureMs = nowMs();
|
|
111696
|
+
options.logger?.warn?.({
|
|
111697
|
+
scope,
|
|
111698
|
+
error: err2 instanceof Error ? err2.message : String(err2),
|
|
111699
|
+
retryAfterMs: gatewayRetryMs
|
|
111700
|
+
}, "Could not check gateway deletion state; serving last known state");
|
|
111701
|
+
return null;
|
|
111702
|
+
} finally {
|
|
111703
|
+
inflight.delete(scope);
|
|
111704
|
+
}
|
|
111705
|
+
})();
|
|
111706
|
+
inflight.set(scope, request2);
|
|
111707
|
+
return request2;
|
|
111708
|
+
}
|
|
111709
|
+
return {
|
|
111710
|
+
maxStalenessMs,
|
|
111711
|
+
markDeleted(scope, tombstone, source = "feed") {
|
|
111712
|
+
rememberDeleted(scope, tombstone, source);
|
|
111713
|
+
},
|
|
111714
|
+
markLive(scope) {
|
|
111715
|
+
rememberLive(scope, nowMs());
|
|
111716
|
+
},
|
|
111717
|
+
noteFeedSynced(at3, options2) {
|
|
111718
|
+
lastFeedSyncMs = (at3 ?? now()).getTime();
|
|
111719
|
+
if (!options2?.full)
|
|
111720
|
+
return;
|
|
111721
|
+
for (const tombstone of deleted.values()) {
|
|
111722
|
+
tombstone.verifiedAtMs = Math.max(tombstone.verifiedAtMs, lastFeedSyncMs);
|
|
111723
|
+
}
|
|
111724
|
+
},
|
|
111725
|
+
knownDeletion(scope) {
|
|
111726
|
+
const known = deleted.get(scope);
|
|
111727
|
+
return known === void 0 ? null : { deletedAt: known.deletedAt, version: known.version };
|
|
111728
|
+
},
|
|
111729
|
+
feedAgeMs() {
|
|
111730
|
+
return lastFeedSyncMs === null ? null : nowMs() - lastFeedSyncMs;
|
|
111731
|
+
},
|
|
111732
|
+
async resolve(scope, resolveOptions) {
|
|
111733
|
+
const known = deleted.get(scope);
|
|
111734
|
+
if (known !== void 0) {
|
|
111735
|
+
if (isFresh(known.verifiedAtMs)) {
|
|
111736
|
+
return {
|
|
111737
|
+
deleted: true,
|
|
111738
|
+
deletedAt: known.deletedAt,
|
|
111739
|
+
version: known.version,
|
|
111740
|
+
source: known.source,
|
|
111741
|
+
verified: true
|
|
111742
|
+
};
|
|
111743
|
+
}
|
|
111744
|
+
const rechecked = await lookup2(scope);
|
|
111745
|
+
if (rechecked !== null)
|
|
111746
|
+
return rechecked;
|
|
111747
|
+
return {
|
|
111748
|
+
deleted: true,
|
|
111749
|
+
deletedAt: known.deletedAt,
|
|
111750
|
+
version: known.version,
|
|
111751
|
+
source: known.source,
|
|
111752
|
+
verified: false
|
|
111753
|
+
};
|
|
111754
|
+
}
|
|
111755
|
+
if (isFresh(live.get(scope) ?? null)) {
|
|
111756
|
+
return { deleted: false, source: "gateway", verified: true };
|
|
111757
|
+
}
|
|
111758
|
+
const consult = resolveOptions?.consultGateway ?? "if-stale";
|
|
111759
|
+
if (consult === "if-stale" && isFresh(lastFeedSyncMs)) {
|
|
111760
|
+
return { deleted: false, source: "feed", verified: true };
|
|
111761
|
+
}
|
|
111762
|
+
return await lookup2(scope) ?? {
|
|
111763
|
+
deleted: false,
|
|
111764
|
+
source: "assumed-live",
|
|
111765
|
+
verified: false
|
|
111766
|
+
};
|
|
111767
|
+
}
|
|
111768
|
+
};
|
|
111769
|
+
}
|
|
111770
|
+
function deletionTimestamp(record2) {
|
|
111771
|
+
if (!record2)
|
|
111772
|
+
return null;
|
|
111773
|
+
if (record2.deletedAt)
|
|
111774
|
+
return record2.deletedAt;
|
|
111775
|
+
return isTombstoneRecord(record2) ? record2.addedAt : null;
|
|
111776
|
+
}
|
|
111777
|
+
function tombstoneVersion(record2) {
|
|
111778
|
+
return normalizeVersion(record2?.expectedVersion ?? null);
|
|
111779
|
+
}
|
|
111780
|
+
function normalizeVersion(value) {
|
|
111781
|
+
if (typeof value !== "string" || !/^\d+$/.test(value))
|
|
111782
|
+
return null;
|
|
111783
|
+
return BigInt(value) > 0n ? BigInt(value).toString() : null;
|
|
111784
|
+
}
|
|
111785
|
+
function isEntryCoveredByTombstone(entry, tombstone) {
|
|
111786
|
+
const version4 = normalizeVersion(tombstone.version);
|
|
111787
|
+
if (version4 === null)
|
|
111788
|
+
return true;
|
|
111789
|
+
const tombstoned = BigInt(version4);
|
|
111790
|
+
if (entry.dataPointId !== null)
|
|
111791
|
+
return BigInt(entry.version) <= tombstoned;
|
|
111792
|
+
const marker = entry.afterTombstoneVersion;
|
|
111793
|
+
if (marker === null || marker === void 0 || !Number.isSafeInteger(marker)) {
|
|
111794
|
+
return true;
|
|
111795
|
+
}
|
|
111796
|
+
return BigInt(marker) < tombstoned;
|
|
111797
|
+
}
|
|
111798
|
+
|
|
111799
|
+
// ../core/dist/sync/workers/delete.js
|
|
111800
|
+
var BLOB_DELETE_BATCH_SIZE = 15;
|
|
111801
|
+
function planBlobDeletions(storage, scope, tombstoneVersionValue) {
|
|
111802
|
+
const tombstone = { version: tombstoneVersionValue };
|
|
111803
|
+
const last2 = tombstoneVersionValue === null ? null : BigInt(tombstoneVersionValue);
|
|
111804
|
+
const keys = /* @__PURE__ */ new Set();
|
|
111805
|
+
const PAGE_SIZE = 500;
|
|
111806
|
+
for (let offset = 0; ; offset += PAGE_SIZE) {
|
|
111807
|
+
const entries = storage.listVersions(scope, { limit: PAGE_SIZE, offset });
|
|
111808
|
+
for (const entry of entries) {
|
|
111809
|
+
if (!isEntryCoveredByTombstone(entry, tombstone))
|
|
111810
|
+
continue;
|
|
111811
|
+
const version4 = BigInt(entry.version);
|
|
111812
|
+
if (last2 !== null && version4 >= 1n && version4 <= last2)
|
|
111813
|
+
continue;
|
|
111814
|
+
keys.add(version4.toString());
|
|
111815
|
+
}
|
|
111816
|
+
if (entries.length < PAGE_SIZE)
|
|
111817
|
+
break;
|
|
111818
|
+
}
|
|
111819
|
+
return {
|
|
111820
|
+
keys: [...keys].sort((a10, b10) => BigInt(a10) < BigInt(b10) ? -1 : 1),
|
|
111821
|
+
range: last2 === null || last2 < 1n ? null : { from: "1", to: last2.toString() }
|
|
111822
|
+
};
|
|
111823
|
+
}
|
|
111824
|
+
function takeFromRange(range, count) {
|
|
111825
|
+
const from = BigInt(range.from);
|
|
111826
|
+
const to3 = BigInt(range.to);
|
|
111827
|
+
const versions = [];
|
|
111828
|
+
let cursor = from;
|
|
111829
|
+
while (cursor <= to3 && versions.length < count) {
|
|
111830
|
+
versions.push(cursor.toString());
|
|
111831
|
+
cursor += 1n;
|
|
111832
|
+
}
|
|
111833
|
+
return {
|
|
111834
|
+
versions,
|
|
111835
|
+
rest: cursor <= to3 ? { from: cursor.toString(), to: range.to } : null
|
|
111836
|
+
};
|
|
111837
|
+
}
|
|
111838
|
+
function rangeSize(range) {
|
|
111839
|
+
return BigInt(range.to) - BigInt(range.from) + 1n;
|
|
111840
|
+
}
|
|
111841
|
+
function countPendingKeys(markers) {
|
|
111842
|
+
let total = 0n;
|
|
111843
|
+
for (const marker of markers) {
|
|
111844
|
+
if (marker.version !== null)
|
|
111845
|
+
total += 1n;
|
|
111846
|
+
else if (marker.range)
|
|
111847
|
+
total += rangeSize(marker.range);
|
|
111848
|
+
else
|
|
111849
|
+
total += 1n;
|
|
111850
|
+
}
|
|
111851
|
+
return total > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(total);
|
|
111852
|
+
}
|
|
111853
|
+
async function deleteScope(deps, scope) {
|
|
111854
|
+
const { storage, deleteData, pendingBlobDeletions, scopeDeletions, logger } = deps;
|
|
111855
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
111856
|
+
const dataPointId = deps.serverOwner ? computeDataPointId(deps.serverOwner, scope) : null;
|
|
111857
|
+
const result = {
|
|
111858
|
+
scope,
|
|
111859
|
+
dataPointId,
|
|
111860
|
+
durable: false,
|
|
111861
|
+
steps: {
|
|
111862
|
+
gateway: { status: "skipped", reason: "sync-disabled" },
|
|
111863
|
+
storage: { status: "skipped", reason: "sync-disabled" },
|
|
111864
|
+
local: { status: "skipped" }
|
|
111865
|
+
},
|
|
111866
|
+
pendingBlobDeletion: false
|
|
111867
|
+
};
|
|
111868
|
+
if (deleteData) {
|
|
111869
|
+
let tombstoneVersionValue = null;
|
|
111870
|
+
let tombstoneKnown = false;
|
|
111871
|
+
try {
|
|
111872
|
+
let outcome = await deleteData.tombstone(scope);
|
|
111873
|
+
if (outcome.status === "not-registered") {
|
|
111874
|
+
let registry2 = await registryState(deps, scope);
|
|
111875
|
+
if (registry2.status === "live") {
|
|
111876
|
+
outcome = await deleteData.tombstone(scope);
|
|
111877
|
+
registry2 = await registryState(deps, scope);
|
|
111878
|
+
}
|
|
111879
|
+
if (outcome.status === "not-registered" && registry2.status !== "deleted-or-absent") {
|
|
111880
|
+
throw registry2.status === "unknown" ? registry2.error : new Error("Scope was registered concurrently while it was being deleted; retry the delete");
|
|
111881
|
+
}
|
|
111882
|
+
}
|
|
111883
|
+
if (outcome.status === "not-registered") {
|
|
111884
|
+
result.steps.gateway = { status: "skipped", reason: "not-registered" };
|
|
111885
|
+
} else {
|
|
111886
|
+
tombstoneKnown = true;
|
|
111887
|
+
tombstoneVersionValue = outcome.version === null ? null : tombstoneVersion({ expectedVersion: outcome.version });
|
|
111888
|
+
result.steps.gateway = {
|
|
111889
|
+
status: "ok",
|
|
111890
|
+
...outcome.status === "already-deleted" && {
|
|
111891
|
+
reason: "already-deleted"
|
|
111892
|
+
},
|
|
111893
|
+
version: outcome.version,
|
|
111894
|
+
deletedAt: outcome.deletedAt
|
|
111895
|
+
};
|
|
111896
|
+
scopeDeletions?.markDeleted(scope, {
|
|
111897
|
+
deletedAt: outcome.deletedAt ?? now().toISOString(),
|
|
111898
|
+
version: outcome.version
|
|
111899
|
+
}, "local-delete");
|
|
111900
|
+
}
|
|
111901
|
+
result.durable = true;
|
|
111902
|
+
} catch (err2) {
|
|
111903
|
+
const message = errorMessage2(err2);
|
|
111904
|
+
result.steps.gateway = { status: "failed", error: message };
|
|
111905
|
+
result.steps.storage = { status: "skipped", reason: "gateway-failed" };
|
|
111906
|
+
result.steps.local = { status: "skipped", reason: "gateway-failed" };
|
|
111907
|
+
logger.error({ scope, dataPointId, error: message }, "Gateway tombstone failed; scope NOT deleted (local copy kept so sync cannot resurrect a half-deleted scope)");
|
|
111908
|
+
return result;
|
|
111909
|
+
}
|
|
111910
|
+
const plan = planBlobDeletions(storage, scope, tombstoneVersionValue);
|
|
111911
|
+
const batch = plan.keys.slice(0, BLOB_DELETE_BATCH_SIZE);
|
|
111912
|
+
const leftovers = plan.keys.slice(BLOB_DELETE_BATCH_SIZE).map((version4) => ({ scope, version: version4 }));
|
|
111913
|
+
if (plan.range) {
|
|
111914
|
+
const taken = takeFromRange(plan.range, BLOB_DELETE_BATCH_SIZE - batch.length);
|
|
111915
|
+
batch.push(...taken.versions);
|
|
111916
|
+
if (taken.rest)
|
|
111917
|
+
leftovers.push({ scope, version: null, range: taken.rest });
|
|
111918
|
+
}
|
|
111919
|
+
if (tombstoneKnown && tombstoneVersionValue === null) {
|
|
111920
|
+
leftovers.push({ scope, version: null });
|
|
111921
|
+
}
|
|
111922
|
+
const storageStep = await deleteBlobKeys({ deleteData, pendingBlobDeletions, logger }, scope, batch, leftovers);
|
|
111923
|
+
result.steps.storage = storageStep.step;
|
|
111924
|
+
result.pendingBlobDeletion = storageStep.pending > 0;
|
|
111925
|
+
}
|
|
111926
|
+
try {
|
|
111927
|
+
const deletedCount = await storage.deleteScope(scope);
|
|
111928
|
+
result.steps.local = { status: "ok", deletedCount };
|
|
111929
|
+
} catch (err2) {
|
|
111930
|
+
const message = errorMessage2(err2);
|
|
111931
|
+
result.steps.local = { status: "failed", error: message };
|
|
111932
|
+
logger.error({ scope, error: message }, "Local scope deletion failed");
|
|
111933
|
+
}
|
|
111934
|
+
logger.info({
|
|
111935
|
+
scope,
|
|
111936
|
+
dataPointId,
|
|
111937
|
+
durable: result.durable,
|
|
111938
|
+
gateway: result.steps.gateway.status,
|
|
111939
|
+
storage: result.steps.storage.status,
|
|
111940
|
+
local: result.steps.local.status
|
|
111941
|
+
}, "Scope deletion finished");
|
|
111942
|
+
return result;
|
|
111943
|
+
}
|
|
111944
|
+
async function deleteBlobKeys(deps, scope, batch, leftovers) {
|
|
111945
|
+
const { deleteData, pendingBlobDeletions, logger } = deps;
|
|
111946
|
+
let outcome;
|
|
111947
|
+
try {
|
|
111948
|
+
outcome = batch.length > 0 && deleteData ? await deleteData.deleteBlobVersions(scope, batch) : { deleted: [], missing: [], failed: [] };
|
|
111949
|
+
} catch (err2) {
|
|
111950
|
+
outcome = {
|
|
111951
|
+
deleted: [],
|
|
111952
|
+
missing: [],
|
|
111953
|
+
failed: batch.map((version4) => ({ version: version4, error: errorMessage2(err2) }))
|
|
111954
|
+
};
|
|
111955
|
+
}
|
|
111956
|
+
const completed = [...outcome.deleted, ...outcome.missing].map((version4) => ({ scope, version: version4 }));
|
|
111957
|
+
const remaining = [
|
|
111958
|
+
...outcome.failed.map(({ version: version4 }) => ({ scope, version: version4 })),
|
|
111959
|
+
...leftovers
|
|
111960
|
+
];
|
|
111961
|
+
const remainingKeys = countPendingKeys(remaining);
|
|
111962
|
+
let recorded = remainingKeys;
|
|
111963
|
+
if (pendingBlobDeletions) {
|
|
111964
|
+
try {
|
|
111965
|
+
if (completed.length > 0)
|
|
111966
|
+
await pendingBlobDeletions.remove(completed);
|
|
111967
|
+
if (remaining.length > 0)
|
|
111968
|
+
await pendingBlobDeletions.add(remaining);
|
|
111969
|
+
} catch (markerErr) {
|
|
111970
|
+
recorded = 0;
|
|
111971
|
+
logger.error({ scope, error: errorMessage2(markerErr), keys: remainingKeys }, "Could not record pending blob deletion markers");
|
|
111972
|
+
}
|
|
111973
|
+
} else if (remaining.length > 0) {
|
|
111974
|
+
recorded = 0;
|
|
111975
|
+
logger.error({ scope, keys: remainingKeys }, "Blob deletions left unfinished with no marker store to retry them");
|
|
111976
|
+
}
|
|
111977
|
+
const counts = {
|
|
111978
|
+
blobsDeleted: outcome.deleted.length,
|
|
111979
|
+
blobsMissing: outcome.missing.length,
|
|
111980
|
+
blobsPending: remainingKeys
|
|
111981
|
+
};
|
|
111982
|
+
if (outcome.failed.length > 0) {
|
|
111983
|
+
const first = outcome.failed[0];
|
|
111984
|
+
logger.warn({
|
|
111985
|
+
scope,
|
|
111986
|
+
failed: outcome.failed.length,
|
|
111987
|
+
pending: recorded,
|
|
111988
|
+
error: first.error
|
|
111989
|
+
}, "Storage blob deletion failed for some keys after gateway tombstone; will retry");
|
|
111990
|
+
return {
|
|
111991
|
+
step: {
|
|
111992
|
+
status: "failed",
|
|
111993
|
+
error: `${outcome.failed.length} blob delete(s) failed: ${first.error}`,
|
|
111994
|
+
...counts
|
|
111995
|
+
},
|
|
111996
|
+
pending: recorded
|
|
111997
|
+
};
|
|
111998
|
+
}
|
|
111999
|
+
if (remaining.length > 0) {
|
|
112000
|
+
logger.info({ scope, ...counts }, "Storage blob deletion continues on later sync cycles (rate-limited batch)");
|
|
112001
|
+
return { step: { status: "deferred", ...counts }, pending: recorded };
|
|
112002
|
+
}
|
|
112003
|
+
return { step: { status: "ok", ...counts }, pending: 0 };
|
|
112004
|
+
}
|
|
112005
|
+
async function retryPendingBlobDeletions(deps) {
|
|
112006
|
+
const { deleteData, pendingBlobDeletions, logger } = deps;
|
|
112007
|
+
const result = {
|
|
112008
|
+
completed: [],
|
|
112009
|
+
superseded: [],
|
|
112010
|
+
failed: [],
|
|
112011
|
+
remaining: 0
|
|
112012
|
+
};
|
|
112013
|
+
if (!deleteData || !pendingBlobDeletions)
|
|
112014
|
+
return result;
|
|
112015
|
+
let markers = await pendingBlobDeletions.list();
|
|
112016
|
+
if (markers.length === 0)
|
|
112017
|
+
return result;
|
|
112018
|
+
for (const marker of markers.filter((key) => key.version === null && !key.range)) {
|
|
112019
|
+
const registry2 = await registryState(deps, marker.scope);
|
|
112020
|
+
if (registry2.status === "unknown") {
|
|
112021
|
+
result.failed.push({
|
|
112022
|
+
scope: marker.scope,
|
|
112023
|
+
version: null,
|
|
112024
|
+
error: registry2.error.message
|
|
112025
|
+
});
|
|
112026
|
+
continue;
|
|
112027
|
+
}
|
|
112028
|
+
if (registry2.status === "live") {
|
|
112029
|
+
await pendingBlobDeletions.remove([marker]);
|
|
112030
|
+
result.superseded.push(marker.scope);
|
|
112031
|
+
logger.warn({
|
|
112032
|
+
scope: marker.scope,
|
|
112033
|
+
dataPointId: registry2.record.id,
|
|
112034
|
+
version: registry2.record.expectedVersion
|
|
112035
|
+
}, "Scope was re-added after its tombstone; dropping the unexpanded blob deletion marker so the live version's ciphertext survives");
|
|
112036
|
+
continue;
|
|
112037
|
+
}
|
|
112038
|
+
const plan = planBlobDeletions(deps.storage ?? { listVersions: () => [] }, marker.scope, registry2.status === "deleted" ? registry2.version : null);
|
|
112039
|
+
const expanded = plan.keys.map((version4) => ({
|
|
112040
|
+
scope: marker.scope,
|
|
112041
|
+
version: version4
|
|
112042
|
+
}));
|
|
112043
|
+
if (plan.range) {
|
|
112044
|
+
expanded.push({ scope: marker.scope, version: null, range: plan.range });
|
|
112045
|
+
}
|
|
112046
|
+
await pendingBlobDeletions.remove([marker]);
|
|
112047
|
+
await pendingBlobDeletions.add(expanded);
|
|
112048
|
+
}
|
|
112049
|
+
markers = await pendingBlobDeletions.list();
|
|
112050
|
+
let budget = BLOB_DELETE_BATCH_SIZE;
|
|
112051
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
112052
|
+
const exactOrigin = /* @__PURE__ */ new Set();
|
|
112053
|
+
const advancedRanges = [];
|
|
112054
|
+
const enqueue = (scope, version4) => {
|
|
112055
|
+
const versions = byScope.get(scope) ?? [];
|
|
112056
|
+
versions.push(version4);
|
|
112057
|
+
byScope.set(scope, versions);
|
|
112058
|
+
};
|
|
112059
|
+
for (const marker of markers) {
|
|
112060
|
+
if (budget === 0)
|
|
112061
|
+
break;
|
|
112062
|
+
if (marker.version !== null) {
|
|
112063
|
+
enqueue(marker.scope, marker.version);
|
|
112064
|
+
exactOrigin.add(`${marker.scope}\0${marker.version}`);
|
|
112065
|
+
budget -= 1;
|
|
112066
|
+
}
|
|
112067
|
+
}
|
|
112068
|
+
for (const marker of markers) {
|
|
112069
|
+
if (budget === 0)
|
|
112070
|
+
break;
|
|
112071
|
+
if (marker.version === null && marker.range) {
|
|
112072
|
+
const taken = takeFromRange(marker.range, budget);
|
|
112073
|
+
for (const version4 of taken.versions)
|
|
112074
|
+
enqueue(marker.scope, version4);
|
|
112075
|
+
budget -= taken.versions.length;
|
|
112076
|
+
advancedRanges.push({
|
|
112077
|
+
old: marker,
|
|
112078
|
+
next: taken.rest ? { scope: marker.scope, version: null, range: taken.rest } : null
|
|
112079
|
+
});
|
|
112080
|
+
}
|
|
112081
|
+
}
|
|
112082
|
+
for (const [scope, versions] of byScope) {
|
|
112083
|
+
let outcome;
|
|
112084
|
+
try {
|
|
112085
|
+
outcome = await deleteData.deleteBlobVersions(scope, versions);
|
|
112086
|
+
} catch (err2) {
|
|
112087
|
+
const message = errorMessage2(err2);
|
|
112088
|
+
outcome = {
|
|
112089
|
+
deleted: [],
|
|
112090
|
+
missing: [],
|
|
112091
|
+
failed: versions.map((version4) => ({ version: version4, error: message }))
|
|
112092
|
+
};
|
|
112093
|
+
}
|
|
112094
|
+
const completed = [...outcome.deleted, ...outcome.missing].filter((version4) => exactOrigin.has(`${scope}\0${version4}`)).map((version4) => ({ scope, version: version4 }));
|
|
112095
|
+
if (completed.length > 0)
|
|
112096
|
+
await pendingBlobDeletions.remove(completed);
|
|
112097
|
+
result.completed.push(...[...outcome.deleted, ...outcome.missing].map((version4) => ({ scope, version: version4 })));
|
|
112098
|
+
const failedFromRange = outcome.failed.filter(({ version: version4 }) => !exactOrigin.has(`${scope}\0${version4}`)).map(({ version: version4 }) => ({ scope, version: version4 }));
|
|
112099
|
+
if (failedFromRange.length > 0) {
|
|
112100
|
+
await pendingBlobDeletions.add(failedFromRange);
|
|
112101
|
+
}
|
|
112102
|
+
for (const failure of outcome.failed) {
|
|
112103
|
+
result.failed.push({ scope, ...failure });
|
|
112104
|
+
}
|
|
112105
|
+
if (outcome.deleted.length + outcome.missing.length > 0) {
|
|
112106
|
+
logger.info({
|
|
112107
|
+
scope,
|
|
112108
|
+
deleted: outcome.deleted.length,
|
|
112109
|
+
missing: outcome.missing.length
|
|
112110
|
+
}, "Completed pending blob deletions");
|
|
112111
|
+
}
|
|
112112
|
+
if (outcome.failed.length > 0) {
|
|
112113
|
+
logger.warn({
|
|
112114
|
+
scope,
|
|
112115
|
+
failed: outcome.failed.length,
|
|
112116
|
+
error: outcome.failed[0].error
|
|
112117
|
+
}, "Pending blob deletion failed again");
|
|
112118
|
+
}
|
|
112119
|
+
}
|
|
112120
|
+
for (const { old, next } of advancedRanges) {
|
|
112121
|
+
await pendingBlobDeletions.remove([old]);
|
|
112122
|
+
if (next)
|
|
112123
|
+
await pendingBlobDeletions.add([next]);
|
|
112124
|
+
}
|
|
112125
|
+
result.remaining = (await pendingBlobDeletions.list()).length;
|
|
112126
|
+
return result;
|
|
112127
|
+
}
|
|
112128
|
+
async function registryState(deps, scope) {
|
|
112129
|
+
if (!deps.dataPointFeed || !deps.serverOwner) {
|
|
112130
|
+
return { status: "deleted-or-absent" };
|
|
112131
|
+
}
|
|
112132
|
+
let record2;
|
|
112133
|
+
try {
|
|
112134
|
+
record2 = await deps.dataPointFeed.getDataPoint({
|
|
112135
|
+
ownerAddress: deps.serverOwner,
|
|
112136
|
+
scope
|
|
112137
|
+
});
|
|
112138
|
+
} catch (err2) {
|
|
112139
|
+
return {
|
|
112140
|
+
status: "unknown",
|
|
112141
|
+
error: err2 instanceof Error ? err2 : new Error(String(err2))
|
|
112142
|
+
};
|
|
112143
|
+
}
|
|
112144
|
+
if (record2 === null)
|
|
112145
|
+
return { status: "deleted-or-absent" };
|
|
112146
|
+
if (deletionTimestamp(record2) === null)
|
|
112147
|
+
return { status: "live", record: record2 };
|
|
112148
|
+
return { status: "deleted", version: tombstoneVersion(record2) };
|
|
112149
|
+
}
|
|
112150
|
+
function errorMessage2(err2) {
|
|
112151
|
+
return err2 instanceof Error ? err2.message : String(err2);
|
|
112152
|
+
}
|
|
112153
|
+
|
|
111105
112154
|
// ../core/dist/payment/x402.js
|
|
111106
112155
|
function generateRecordId() {
|
|
111107
112156
|
const bytes2 = new Uint8Array(32);
|
|
@@ -111582,6 +112631,51 @@ async function handleX402Cycle(input) {
|
|
|
111582
112631
|
function collectedAt(now) {
|
|
111583
112632
|
return now().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
111584
112633
|
}
|
|
112634
|
+
async function resolveReadDeletion(deps, scope, entry) {
|
|
112635
|
+
if (!deps.scopeDeletions)
|
|
112636
|
+
return null;
|
|
112637
|
+
const verdict = await deps.scopeDeletions.resolve(scope, {
|
|
112638
|
+
consultGateway: entry ? "if-stale" : "always"
|
|
112639
|
+
});
|
|
112640
|
+
if (!verdict.deleted)
|
|
112641
|
+
return null;
|
|
112642
|
+
if (entry && !isEntryCoveredByTombstone(entry, verdict)) {
|
|
112643
|
+
return null;
|
|
112644
|
+
}
|
|
112645
|
+
return {
|
|
112646
|
+
scope,
|
|
112647
|
+
dataPointId: deps.serverOwner ? computeDataPointId(deps.serverOwner, scope) : null,
|
|
112648
|
+
deletedAt: verdict.deletedAt
|
|
112649
|
+
};
|
|
112650
|
+
}
|
|
112651
|
+
async function assertScopeNotDeleted(deps, scope, entry) {
|
|
112652
|
+
const deletion = await resolveReadDeletion(deps, scope, entry);
|
|
112653
|
+
if (deletion)
|
|
112654
|
+
throw new DataDeletedError(deletion);
|
|
112655
|
+
}
|
|
112656
|
+
function discoveryVisibility(deps) {
|
|
112657
|
+
if (!deps.scopeDeletions)
|
|
112658
|
+
return void 0;
|
|
112659
|
+
return async (scope, entry) => await resolveReadDeletion(deps, scope, entry) === null;
|
|
112660
|
+
}
|
|
112661
|
+
async function ingestTombstoneMarker(deps, scope) {
|
|
112662
|
+
if (!deps.scopeDeletions)
|
|
112663
|
+
return null;
|
|
112664
|
+
const verdict = await deps.scopeDeletions.resolve(scope);
|
|
112665
|
+
if (!verdict.deleted || verdict.version === null)
|
|
112666
|
+
return null;
|
|
112667
|
+
const version4 = Number(verdict.version);
|
|
112668
|
+
return Number.isSafeInteger(version4) ? version4 : null;
|
|
112669
|
+
}
|
|
112670
|
+
function apiLoggerAsLogger(logger) {
|
|
112671
|
+
const noop = () => void 0;
|
|
112672
|
+
return {
|
|
112673
|
+
debug: (payload, message) => (logger?.debug ?? noop)(payload, message ?? ""),
|
|
112674
|
+
info: (payload, message) => (logger?.info ?? noop)(payload, message ?? ""),
|
|
112675
|
+
warn: (payload, message) => (logger?.warn ?? noop)(payload, message ?? ""),
|
|
112676
|
+
error: (payload, message) => (logger?.error ?? noop)(payload, message ?? "")
|
|
112677
|
+
};
|
|
112678
|
+
}
|
|
111585
112679
|
function notifyNewData(syncManager) {
|
|
111586
112680
|
if (!syncManager)
|
|
111587
112681
|
return;
|
|
@@ -111613,6 +112707,30 @@ function reportPersonalServerReadFulfillment(deps, event) {
|
|
|
111613
112707
|
warnReadFulfillmentReporterFailed(deps, event, err2);
|
|
111614
112708
|
}
|
|
111615
112709
|
}
|
|
112710
|
+
async function prepareWriteLineage(deps, scope, field) {
|
|
112711
|
+
if (field === void 0 || field === null)
|
|
112712
|
+
return void 0;
|
|
112713
|
+
return prepareLineage({
|
|
112714
|
+
scope,
|
|
112715
|
+
field,
|
|
112716
|
+
serverOwner: deps.serverOwner,
|
|
112717
|
+
storage: deps.storage,
|
|
112718
|
+
gateway: deps.lineageGateway,
|
|
112719
|
+
now: deps.now ?? (() => /* @__PURE__ */ new Date())
|
|
112720
|
+
});
|
|
112721
|
+
}
|
|
112722
|
+
function resolveLineageGrantView(authResult) {
|
|
112723
|
+
if (authResult === void 0 || authResult.grantId === "owner" || authResult.grantId === "policy-bypass") {
|
|
112724
|
+
return { grantId: void 0 };
|
|
112725
|
+
}
|
|
112726
|
+
const grantId = authResult.grantId;
|
|
112727
|
+
if (typeof grantId !== "string" || grantId === "" || grantId === "unknown") {
|
|
112728
|
+
throw new GrantRequiredError({
|
|
112729
|
+
reason: "a lineage read by a builder needs a resolved grant"
|
|
112730
|
+
});
|
|
112731
|
+
}
|
|
112732
|
+
return { grantId };
|
|
112733
|
+
}
|
|
111616
112734
|
async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
111617
112735
|
return withApiErrors(async () => {
|
|
111618
112736
|
const url2 = new URL(request2.url);
|
|
@@ -111625,7 +112743,8 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111625
112743
|
storage: deps.storage,
|
|
111626
112744
|
scopePrefix: url2.searchParams.get("scopePrefix") ?? void 0,
|
|
111627
112745
|
limit: normalizeLimit2(url2.searchParams.get("limit"), 20),
|
|
111628
|
-
offset: normalizeLimit2(url2.searchParams.get("offset"), 0)
|
|
112746
|
+
offset: normalizeLimit2(url2.searchParams.get("offset"), 0),
|
|
112747
|
+
isVisible: discoveryVisibility(deps)
|
|
111629
112748
|
});
|
|
111630
112749
|
return jsonResponse(result.response);
|
|
111631
112750
|
}
|
|
@@ -111634,16 +112753,78 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111634
112753
|
if (request2.method !== "GET")
|
|
111635
112754
|
return methodNotAllowed();
|
|
111636
112755
|
await deps.auth.authorizeBuilderList(request2);
|
|
111637
|
-
const result = listDataVersionsContract({
|
|
112756
|
+
const result = await listDataVersionsContract({
|
|
111638
112757
|
storage: deps.storage,
|
|
111639
112758
|
scopeParam: decodePathPart(parts[0]),
|
|
111640
112759
|
limit: normalizeLimit2(url2.searchParams.get("limit"), 20),
|
|
111641
|
-
offset: normalizeLimit2(url2.searchParams.get("offset"), 0)
|
|
112760
|
+
offset: normalizeLimit2(url2.searchParams.get("offset"), 0),
|
|
112761
|
+
isVisible: discoveryVisibility(deps)
|
|
111642
112762
|
});
|
|
111643
112763
|
if (!result.ok)
|
|
111644
112764
|
return contractErrorResponse(result);
|
|
112765
|
+
if (result.response.total === 0) {
|
|
112766
|
+
await assertScopeNotDeleted(deps, result.scope, void 0);
|
|
112767
|
+
}
|
|
111645
112768
|
return jsonResponse(result.response);
|
|
111646
112769
|
}
|
|
112770
|
+
if ((parts.length === 2 || parts.length === 3) && parts[1] === "lineage") {
|
|
112771
|
+
if (request2.method !== "GET")
|
|
112772
|
+
return methodNotAllowed();
|
|
112773
|
+
const scopeResult = parseDataScopeContract(decodePathPart(parts[0]));
|
|
112774
|
+
if (!scopeResult.ok)
|
|
112775
|
+
return contractErrorResponse(scopeResult);
|
|
112776
|
+
if (url2.searchParams.has("version")) {
|
|
112777
|
+
return errorResponse(400, "INVALID_VERSION", "version is a path segment (/v1/data/:scope/lineage/:version), not a query parameter");
|
|
112778
|
+
}
|
|
112779
|
+
if (url2.search.length > 0) {
|
|
112780
|
+
return errorResponse(400, "INVALID_QUERY", "lineage reads take no query parameters; the version is a path segment and the grant view is the signed grantId claim");
|
|
112781
|
+
}
|
|
112782
|
+
const version4 = parts.length === 3 ? decodePathPart(parts[2]) : void 0;
|
|
112783
|
+
if (version4 !== void 0 && !/^[1-9]\d*$/.test(version4)) {
|
|
112784
|
+
return errorResponse(400, "INVALID_VERSION", "version must be a positive decimal integer");
|
|
112785
|
+
}
|
|
112786
|
+
const authResult = await deps.auth.authorizeBuilderRead({
|
|
112787
|
+
request: request2,
|
|
112788
|
+
scope: scopeResult.scope,
|
|
112789
|
+
grantId: selectedGrantId(request2, url2)
|
|
112790
|
+
});
|
|
112791
|
+
if (!deps.serverOwner) {
|
|
112792
|
+
throw new ServerNotConfiguredError({
|
|
112793
|
+
reason: "serverOwner is required to resolve the data point id"
|
|
112794
|
+
});
|
|
112795
|
+
}
|
|
112796
|
+
if (!deps.lineageGateway)
|
|
112797
|
+
throw new LineageUnavailableError();
|
|
112798
|
+
const { grantId } = resolveLineageGrantView(authResult);
|
|
112799
|
+
let result;
|
|
112800
|
+
try {
|
|
112801
|
+
result = await deps.lineageGateway.getLineage({
|
|
112802
|
+
dataPointId: computeDataPointId(deps.serverOwner, scopeResult.scope),
|
|
112803
|
+
version: version4,
|
|
112804
|
+
grantId
|
|
112805
|
+
});
|
|
112806
|
+
} catch (err2) {
|
|
112807
|
+
if (err2 instanceof ProtocolError)
|
|
112808
|
+
throw err2;
|
|
112809
|
+
throw new LineageGatewayError({
|
|
112810
|
+
status: 0,
|
|
112811
|
+
body: { error: err2 instanceof Error ? err2.message : String(err2) }
|
|
112812
|
+
});
|
|
112813
|
+
}
|
|
112814
|
+
if (!result.ok) {
|
|
112815
|
+
if (result.status === 404) {
|
|
112816
|
+
return errorResponse(404, "NOT_FOUND", version4 ? `Scope "${scopeResult.scope}" has no registered version ${version4}` : `Scope "${scopeResult.scope}" is not registered at the gateway`);
|
|
112817
|
+
}
|
|
112818
|
+
if (result.status === 403) {
|
|
112819
|
+
throw new ProtocolError(403, "LINEAGE_FORBIDDEN", "The gateway refused the lineage view for this grant", { gateway: result.body });
|
|
112820
|
+
}
|
|
112821
|
+
throw new LineageGatewayError({
|
|
112822
|
+
status: result.status,
|
|
112823
|
+
body: result.body
|
|
112824
|
+
});
|
|
112825
|
+
}
|
|
112826
|
+
return jsonResponse({ data: result.data, proof: result.proof });
|
|
112827
|
+
}
|
|
111647
112828
|
if (parts.length !== 1)
|
|
111648
112829
|
return notFound();
|
|
111649
112830
|
const scopeParam = decodePathPart(parts[0]);
|
|
@@ -111665,6 +112846,7 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111665
112846
|
fileId: url2.searchParams.get("fileId") ?? selectedEntry?.fileId ?? void 0,
|
|
111666
112847
|
at: url2.searchParams.get("at") ?? void 0
|
|
111667
112848
|
});
|
|
112849
|
+
await assertScopeNotDeleted(deps, scopeResult.scope, selectedEntry);
|
|
111668
112850
|
const isOwnerSignal = authResult?.grantId === "owner" || authResult?.grantId === "policy-bypass";
|
|
111669
112851
|
const builder = authResult?.builder;
|
|
111670
112852
|
const resolvedGrantId = !isOwnerSignal && authResult?.grantId ? authResult.grantId : void 0;
|
|
@@ -111719,8 +112901,12 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111719
112901
|
fileId: url2.searchParams.get("fileId") ?? void 0,
|
|
111720
112902
|
at: url2.searchParams.get("at") ?? void 0
|
|
111721
112903
|
});
|
|
111722
|
-
if (!result.ok)
|
|
112904
|
+
if (!result.ok) {
|
|
112905
|
+
if (result.status === 404) {
|
|
112906
|
+
await assertScopeNotDeleted(deps, scopeResult.scope, void 0);
|
|
112907
|
+
}
|
|
111723
112908
|
return contractErrorResponse(result);
|
|
112909
|
+
}
|
|
111724
112910
|
const logId = deps.createLogId?.() ?? crypto.randomUUID();
|
|
111725
112911
|
const timestamp = (deps.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
|
|
111726
112912
|
const ipAddress = request2.headers.get("x-forwarded-for") ?? request2.headers.get("x-real-ip") ?? "unknown";
|
|
@@ -111800,6 +112986,7 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111800
112986
|
return failWrite(contractErrorResponse(scopeResult));
|
|
111801
112987
|
const collectedAtValue = collectedAt(deps.now ?? (() => /* @__PURE__ */ new Date()));
|
|
111802
112988
|
const status2 = deps.syncManager ? "syncing" : "stored";
|
|
112989
|
+
const afterTombstoneVersion = await ingestTombstoneMarker(deps, scopeResult.scope);
|
|
111803
112990
|
const logBuilderWrite = async () => {
|
|
111804
112991
|
if (!writeAuth)
|
|
111805
112992
|
return;
|
|
@@ -111825,16 +113012,20 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111825
113012
|
};
|
|
111826
113013
|
if (!isJsonContentType(request2)) {
|
|
111827
113014
|
const bytes2 = new Uint8Array(await request2.arrayBuffer());
|
|
113015
|
+
const metadata = parseMetadataHeader(request2.headers.get("x-vana-metadata"));
|
|
113016
|
+
const lineage2 = await prepareWriteLineage(deps, scopeResult.scope, extractLineageField(metadata));
|
|
111828
113017
|
const result2 = await ingestBinaryDataContract({
|
|
111829
113018
|
storage: deps.storage,
|
|
111830
113019
|
scopeParam: scopeResult.scope,
|
|
111831
113020
|
bytes: bytes2,
|
|
111832
113021
|
mimeType: binaryMimeType(request2),
|
|
111833
113022
|
filename: binaryFilename(request2),
|
|
111834
|
-
metadata
|
|
113023
|
+
metadata,
|
|
111835
113024
|
collectedAt: collectedAtValue,
|
|
111836
113025
|
status: status2,
|
|
111837
|
-
attribution: writeAuth?.attribution
|
|
113026
|
+
attribution: writeAuth?.attribution,
|
|
113027
|
+
lineage: lineage2,
|
|
113028
|
+
afterTombstoneVersion
|
|
111838
113029
|
});
|
|
111839
113030
|
if (!result2.ok)
|
|
111840
113031
|
return failWrite(contractErrorResponse(result2));
|
|
@@ -111854,13 +113045,16 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111854
113045
|
const parsed = await parseJsonObjectBody(request2, "Request body must be valid JSON");
|
|
111855
113046
|
if (!parsed.ok)
|
|
111856
113047
|
return failWrite(contractResponse(parsed.result));
|
|
113048
|
+
const lineage = await prepareWriteLineage(deps, scopeResult.scope, extractLineageField(parsed.body));
|
|
111857
113049
|
const result = await ingestDataContract({
|
|
111858
113050
|
storage: deps.storage,
|
|
111859
113051
|
scopeParam: scopeResult.scope,
|
|
111860
113052
|
body: parsed.body,
|
|
111861
113053
|
collectedAt: collectedAtValue,
|
|
111862
113054
|
status: status2,
|
|
111863
|
-
attribution: writeAuth?.attribution
|
|
113055
|
+
attribution: writeAuth?.attribution,
|
|
113056
|
+
lineage,
|
|
113057
|
+
afterTombstoneVersion
|
|
111864
113058
|
});
|
|
111865
113059
|
if (!result.ok)
|
|
111866
113060
|
return failWrite(contractErrorResponse(result));
|
|
@@ -111889,22 +113083,54 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
111889
113083
|
}
|
|
111890
113084
|
if (request2.method === "DELETE") {
|
|
111891
113085
|
await deps.auth.authorizeOwner(request2);
|
|
113086
|
+
const cascade = url2.searchParams.get("cascade");
|
|
113087
|
+
if (cascade !== null && cascade !== "lineage") {
|
|
113088
|
+
throw new InvalidCascadeError({ cascade });
|
|
113089
|
+
}
|
|
111892
113090
|
const parsed = parseDataScopeContract(scopeParam);
|
|
111893
|
-
if (parsed.ok
|
|
111894
|
-
|
|
111895
|
-
|
|
111896
|
-
|
|
111897
|
-
deps.logger?.info?.({ scope: scopeParam, error: err2.message }, "Remote scope deletion failed; proceeding with local delete");
|
|
111898
|
-
}
|
|
113091
|
+
if (!parsed.ok)
|
|
113092
|
+
return contractErrorResponse(parsed);
|
|
113093
|
+
if (cascade === "lineage") {
|
|
113094
|
+
throw new LineageCascadeUnavailableError({ scope: parsed.scope });
|
|
111899
113095
|
}
|
|
111900
|
-
const result = await
|
|
113096
|
+
const result = deps.syncManager?.deleteScope ? await deps.syncManager.deleteScope(parsed.scope) : await deleteScope({
|
|
111901
113097
|
storage: deps.storage,
|
|
111902
|
-
|
|
111903
|
-
|
|
111904
|
-
|
|
111905
|
-
|
|
111906
|
-
|
|
111907
|
-
|
|
113098
|
+
serverOwner: deps.serverOwner,
|
|
113099
|
+
deleteData: null,
|
|
113100
|
+
logger: apiLoggerAsLogger(deps.logger)
|
|
113101
|
+
}, parsed.scope);
|
|
113102
|
+
if (result.steps.gateway.status === "failed") {
|
|
113103
|
+
throw new DeleteTombstoneFailedError({
|
|
113104
|
+
scope: parsed.scope,
|
|
113105
|
+
result
|
|
113106
|
+
});
|
|
113107
|
+
}
|
|
113108
|
+
try {
|
|
113109
|
+
await deps.accessLogWriter.write({
|
|
113110
|
+
logId: deps.createLogId?.() ?? crypto.randomUUID(),
|
|
113111
|
+
grantId: "owner",
|
|
113112
|
+
builder: deps.serverOwner ?? "owner",
|
|
113113
|
+
action: "delete",
|
|
113114
|
+
scope: parsed.scope,
|
|
113115
|
+
timestamp: (deps.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
|
|
113116
|
+
ipAddress: request2.headers.get("x-forwarded-for") ?? request2.headers.get("x-real-ip") ?? "unknown",
|
|
113117
|
+
userAgent: request2.headers.get("user-agent") ?? "unknown"
|
|
113118
|
+
});
|
|
113119
|
+
} catch (err2) {
|
|
113120
|
+
deps.logger?.warn?.({
|
|
113121
|
+
scope: parsed.scope,
|
|
113122
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
113123
|
+
}, "Delete access-log entry failed; scope already deleted");
|
|
113124
|
+
}
|
|
113125
|
+
deps.logger?.info?.({
|
|
113126
|
+
scope: parsed.scope,
|
|
113127
|
+
durable: result.durable,
|
|
113128
|
+
gateway: result.steps.gateway.status,
|
|
113129
|
+
storage: result.steps.storage.status,
|
|
113130
|
+
local: result.steps.local.status,
|
|
113131
|
+
deletedCount: result.steps.local.deletedCount
|
|
113132
|
+
}, "Scope deleted");
|
|
113133
|
+
return jsonResponse(result, { status: 200 });
|
|
111908
113134
|
}
|
|
111909
113135
|
return methodNotAllowed();
|
|
111910
113136
|
});
|
|
@@ -112214,6 +113440,16 @@ var McpDataReadError = class extends Error {
|
|
|
112214
113440
|
};
|
|
112215
113441
|
function createMcpDataReadClient(options) {
|
|
112216
113442
|
const basePath = options.basePath ?? "/v1/data";
|
|
113443
|
+
async function assertScopeReadable(scope, entry) {
|
|
113444
|
+
try {
|
|
113445
|
+
await assertScopeNotDeleted(options.dataApiDeps, scope, entry);
|
|
113446
|
+
} catch (err2) {
|
|
113447
|
+
if (err2 instanceof ProtocolError) {
|
|
113448
|
+
throw new McpDataReadError(err2.code, err2.toJSON());
|
|
113449
|
+
}
|
|
113450
|
+
throw err2;
|
|
113451
|
+
}
|
|
113452
|
+
}
|
|
112217
113453
|
async function authorizeScopeRead(params) {
|
|
112218
113454
|
const safeScope = encodeURIComponent(params.scope);
|
|
112219
113455
|
const signingUri = `${basePath}/${safeScope}`;
|
|
@@ -112301,6 +113537,9 @@ function createMcpDataReadClient(options) {
|
|
|
112301
113537
|
const entry = storage.findEntry({ scope });
|
|
112302
113538
|
if (!entry)
|
|
112303
113539
|
return null;
|
|
113540
|
+
if (await resolveReadDeletion(options.dataApiDeps, scope, entry)) {
|
|
113541
|
+
return null;
|
|
113542
|
+
}
|
|
112304
113543
|
const hasBlocks = typeof storage.hasScopeBlocks === "function" ? await storage.hasScopeBlocks(scope, entry.collectedAt) : false;
|
|
112305
113544
|
return {
|
|
112306
113545
|
scope,
|
|
@@ -112329,6 +113568,7 @@ function createMcpDataReadClient(options) {
|
|
|
112329
113568
|
message: `No data found for scope "${scope}"`
|
|
112330
113569
|
});
|
|
112331
113570
|
}
|
|
113571
|
+
await assertScopeReadable(scope, selectedEntry);
|
|
112332
113572
|
const { request: request2, authResult } = await authorizeScopeRead({
|
|
112333
113573
|
scope,
|
|
112334
113574
|
grantId,
|
|
@@ -112386,6 +113626,7 @@ function createMcpDataReadClient(options) {
|
|
|
112386
113626
|
message: `No data found for scope "${scope}"`
|
|
112387
113627
|
});
|
|
112388
113628
|
}
|
|
113629
|
+
await assertScopeReadable(scope, selectedEntry);
|
|
112389
113630
|
const { request: request2, authResult } = await authorizeScopeRead({
|
|
112390
113631
|
scope,
|
|
112391
113632
|
grantId,
|
|
@@ -116049,15 +117290,15 @@ var makeIssue = (params) => {
|
|
|
116049
117290
|
message: issueData.message
|
|
116050
117291
|
};
|
|
116051
117292
|
}
|
|
116052
|
-
let
|
|
117293
|
+
let errorMessage3 = "";
|
|
116053
117294
|
const maps = errorMaps.filter((m10) => !!m10).slice().reverse();
|
|
116054
117295
|
for (const map2 of maps) {
|
|
116055
|
-
|
|
117296
|
+
errorMessage3 = map2(fullIssue, { data, defaultError: errorMessage3 }).message;
|
|
116056
117297
|
}
|
|
116057
117298
|
return {
|
|
116058
117299
|
...issueData,
|
|
116059
117300
|
path: fullPath,
|
|
116060
|
-
message:
|
|
117301
|
+
message: errorMessage3
|
|
116061
117302
|
};
|
|
116062
117303
|
};
|
|
116063
117304
|
function addIssueToContext(ctx, issueData) {
|
|
@@ -121337,19 +122578,19 @@ var getRefs = (options) => {
|
|
|
121337
122578
|
};
|
|
121338
122579
|
|
|
121339
122580
|
// ../../node_modules/zod-to-json-schema/dist/esm/errorMessages.js
|
|
121340
|
-
function addErrorMessage(res, key,
|
|
122581
|
+
function addErrorMessage(res, key, errorMessage3, refs) {
|
|
121341
122582
|
if (!refs?.errorMessages)
|
|
121342
122583
|
return;
|
|
121343
|
-
if (
|
|
122584
|
+
if (errorMessage3) {
|
|
121344
122585
|
res.errorMessage = {
|
|
121345
122586
|
...res.errorMessage,
|
|
121346
|
-
[key]:
|
|
122587
|
+
[key]: errorMessage3
|
|
121347
122588
|
};
|
|
121348
122589
|
}
|
|
121349
122590
|
}
|
|
121350
|
-
function setResponseValueAndErrors(res, key, value,
|
|
122591
|
+
function setResponseValueAndErrors(res, key, value, errorMessage3, refs) {
|
|
121351
122592
|
res[key] = value;
|
|
121352
|
-
addErrorMessage(res, key,
|
|
122593
|
+
addErrorMessage(res, key, errorMessage3, refs);
|
|
121353
122594
|
}
|
|
121354
122595
|
|
|
121355
122596
|
// ../../node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
|
|
@@ -122660,8 +123901,8 @@ var Protocol = class {
|
|
|
122660
123901
|
if (queuedMessage.type === "response") {
|
|
122661
123902
|
resolver(message);
|
|
122662
123903
|
} else {
|
|
122663
|
-
const
|
|
122664
|
-
const error51 = new McpError(
|
|
123904
|
+
const errorMessage3 = message;
|
|
123905
|
+
const error51 = new McpError(errorMessage3.error.code, errorMessage3.error.message, errorMessage3.error.data);
|
|
122665
123906
|
resolver(error51);
|
|
122666
123907
|
}
|
|
122667
123908
|
} else {
|
|
@@ -123961,23 +125202,23 @@ var Server = class extends Protocol {
|
|
|
123961
125202
|
const wrappedHandler = async (request2, extra) => {
|
|
123962
125203
|
const validatedRequest = safeParse3(CallToolRequestSchema, request2);
|
|
123963
125204
|
if (!validatedRequest.success) {
|
|
123964
|
-
const
|
|
123965
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${
|
|
125205
|
+
const errorMessage3 = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
125206
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage3}`);
|
|
123966
125207
|
}
|
|
123967
125208
|
const { params } = validatedRequest.data;
|
|
123968
125209
|
const result = await Promise.resolve(handler(request2, extra));
|
|
123969
125210
|
if (params.task) {
|
|
123970
125211
|
const taskValidationResult = safeParse3(CreateTaskResultSchema, result);
|
|
123971
125212
|
if (!taskValidationResult.success) {
|
|
123972
|
-
const
|
|
123973
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${
|
|
125213
|
+
const errorMessage3 = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
|
|
125214
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage3}`);
|
|
123974
125215
|
}
|
|
123975
125216
|
return taskValidationResult.data;
|
|
123976
125217
|
}
|
|
123977
125218
|
const validationResult = safeParse3(CallToolResultSchema, result);
|
|
123978
125219
|
if (!validationResult.success) {
|
|
123979
|
-
const
|
|
123980
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${
|
|
125220
|
+
const errorMessage3 = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
|
125221
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage3}`);
|
|
123981
125222
|
}
|
|
123982
125223
|
return validationResult.data;
|
|
123983
125224
|
};
|
|
@@ -124693,12 +125934,12 @@ var McpServer = class {
|
|
|
124693
125934
|
* @param errorMessage - The error message.
|
|
124694
125935
|
* @returns The tool error result.
|
|
124695
125936
|
*/
|
|
124696
|
-
createToolError(
|
|
125937
|
+
createToolError(errorMessage3) {
|
|
124697
125938
|
return {
|
|
124698
125939
|
content: [
|
|
124699
125940
|
{
|
|
124700
125941
|
type: "text",
|
|
124701
|
-
text:
|
|
125942
|
+
text: errorMessage3
|
|
124702
125943
|
}
|
|
124703
125944
|
],
|
|
124704
125945
|
isError: true
|
|
@@ -124716,8 +125957,8 @@ var McpServer = class {
|
|
|
124716
125957
|
const parseResult = await safeParseAsync3(schemaToParse, args);
|
|
124717
125958
|
if (!parseResult.success) {
|
|
124718
125959
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
124719
|
-
const
|
|
124720
|
-
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${
|
|
125960
|
+
const errorMessage3 = getParseErrorMessage(error51);
|
|
125961
|
+
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${errorMessage3}`);
|
|
124721
125962
|
}
|
|
124722
125963
|
return parseResult.data;
|
|
124723
125964
|
}
|
|
@@ -124741,8 +125982,8 @@ var McpServer = class {
|
|
|
124741
125982
|
const parseResult = await safeParseAsync3(outputObj, result.structuredContent);
|
|
124742
125983
|
if (!parseResult.success) {
|
|
124743
125984
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
124744
|
-
const
|
|
124745
|
-
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${
|
|
125985
|
+
const errorMessage3 = getParseErrorMessage(error51);
|
|
125986
|
+
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${errorMessage3}`);
|
|
124746
125987
|
}
|
|
124747
125988
|
}
|
|
124748
125989
|
/**
|
|
@@ -124954,8 +126195,8 @@ var McpServer = class {
|
|
|
124954
126195
|
const parseResult = await safeParseAsync3(argsObj, request2.params.arguments);
|
|
124955
126196
|
if (!parseResult.success) {
|
|
124956
126197
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
124957
|
-
const
|
|
124958
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request2.params.name}: ${
|
|
126198
|
+
const errorMessage3 = getParseErrorMessage(error51);
|
|
126199
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request2.params.name}: ${errorMessage3}`);
|
|
124959
126200
|
}
|
|
124960
126201
|
const args = parseResult.data;
|
|
124961
126202
|
const cb2 = prompt.callback;
|
|
@@ -127051,6 +128292,7 @@ function createPsLiteRuntime(options) {
|
|
|
127051
128292
|
accessLogWriter,
|
|
127052
128293
|
readFulfillmentReporter: options.readFulfillmentReporter,
|
|
127053
128294
|
syncManager: options.syncManager ?? null,
|
|
128295
|
+
scopeDeletions: options.scopeDeletions,
|
|
127054
128296
|
now,
|
|
127055
128297
|
createLogId,
|
|
127056
128298
|
// x402 payment enforcement for builder reads. Only engages with a
|
|
@@ -127070,7 +128312,8 @@ function createPsLiteRuntime(options) {
|
|
|
127070
128312
|
// recordDataAccess attributes the read to the correct owner; if
|
|
127071
128313
|
// serverOwner is absent the accessRecord is safely omitted.
|
|
127072
128314
|
serverOwner: options.serverOwner,
|
|
127073
|
-
serverSigner: x402ServerSigner
|
|
128315
|
+
serverSigner: x402ServerSigner,
|
|
128316
|
+
lineageGateway: options.lineageGateway
|
|
127074
128317
|
}, { basePath: dataPrefix });
|
|
127075
128318
|
}
|
|
127076
128319
|
if (url2.pathname.startsWith("/auth/device")) {
|
|
@@ -127526,6 +128769,45 @@ var OrphanedEntryError = class extends Error {
|
|
|
127526
128769
|
this.name = "OrphanedEntryError";
|
|
127527
128770
|
}
|
|
127528
128771
|
};
|
|
128772
|
+
var DeletedScopeEntryError = class extends Error {
|
|
128773
|
+
constructor(path, deletedAt) {
|
|
128774
|
+
super(`Dropped local entry for a scope deleted at ${deletedAt}: ${path}`);
|
|
128775
|
+
this.name = "DeletedScopeEntryError";
|
|
128776
|
+
}
|
|
128777
|
+
};
|
|
128778
|
+
async function dropIfCoveredByDeletion(deps, entry, tombstone, deletedAt, uploaded) {
|
|
128779
|
+
const version4 = tombstoneVersion(tombstone);
|
|
128780
|
+
if (!isEntryCoveredByTombstone(entry, { version: version4 }))
|
|
128781
|
+
return;
|
|
128782
|
+
if (uploaded) {
|
|
128783
|
+
try {
|
|
128784
|
+
await deps.storageAdapter.delete(uploaded.url);
|
|
128785
|
+
} catch (err2) {
|
|
128786
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
128787
|
+
if (deps.pendingBlobDeletions) {
|
|
128788
|
+
await deps.pendingBlobDeletions.add([
|
|
128789
|
+
{ scope: entry.scope, version: String(entry.version) }
|
|
128790
|
+
]);
|
|
128791
|
+
}
|
|
128792
|
+
deps.logger.warn({
|
|
128793
|
+
scope: entry.scope,
|
|
128794
|
+
url: uploaded.url,
|
|
128795
|
+
error: message,
|
|
128796
|
+
queuedForCleanup: Boolean(deps.pendingBlobDeletions)
|
|
128797
|
+
}, "Could not delete the ciphertext uploaded for an entry the tombstone covers");
|
|
128798
|
+
}
|
|
128799
|
+
}
|
|
128800
|
+
await deps.storage.deleteVersion(entry.scope, entry.collectedAt);
|
|
128801
|
+
deps.logger.warn({
|
|
128802
|
+
path: entry.path,
|
|
128803
|
+
scope: entry.scope,
|
|
128804
|
+
deletedAt,
|
|
128805
|
+
tombstoneVersion: version4,
|
|
128806
|
+
entryVersion: entry.version,
|
|
128807
|
+
afterTombstoneVersion: entry.afterTombstoneVersion ?? null
|
|
128808
|
+
}, "Dropped unsynced local entry: the gateway reports its scope as deleted");
|
|
128809
|
+
throw new DeletedScopeEntryError(entry.path, deletedAt);
|
|
128810
|
+
}
|
|
127529
128811
|
function isMissingPayloadError(err2) {
|
|
127530
128812
|
return err2 instanceof Error && err2.code === "ENOENT";
|
|
127531
128813
|
}
|
|
@@ -127544,6 +128826,20 @@ async function uploadOne(deps, entry) {
|
|
|
127544
128826
|
}
|
|
127545
128827
|
throw err2;
|
|
127546
128828
|
}
|
|
128829
|
+
let registerVersion = BigInt(entry.version);
|
|
128830
|
+
if (!entry.dataPointId && deps.dataPointFeed) {
|
|
128831
|
+
const remote = await deps.dataPointFeed.getDataPoint({
|
|
128832
|
+
ownerAddress: serverOwner,
|
|
128833
|
+
scope: entry.scope
|
|
128834
|
+
});
|
|
128835
|
+
const deletedAt = deletionTimestamp(remote);
|
|
128836
|
+
if (remote && deletedAt !== null) {
|
|
128837
|
+
await dropIfCoveredByDeletion(deps, entry, remote, deletedAt);
|
|
128838
|
+
const afterTombstone = BigInt(remote.expectedVersion) + 1n;
|
|
128839
|
+
if (afterTombstone > registerVersion)
|
|
128840
|
+
registerVersion = afterTombstone;
|
|
128841
|
+
}
|
|
128842
|
+
}
|
|
127547
128843
|
const scopeKey = deriveScopeKey(masterKey, entry.scope);
|
|
127548
128844
|
const scopeKeyHex = uint8ToHex(scopeKey);
|
|
127549
128845
|
const plaintext = new TextEncoder().encode(JSON.stringify(envelope));
|
|
@@ -127554,7 +128850,7 @@ async function uploadOne(deps, entry) {
|
|
|
127554
128850
|
collectedAt: entry.collectedAt,
|
|
127555
128851
|
sizeBytes: encrypted.byteLength
|
|
127556
128852
|
})));
|
|
127557
|
-
const storageKey = `${entry.scope}/${
|
|
128853
|
+
const storageKey = `${entry.scope}/${registerVersion}`;
|
|
127558
128854
|
let url2 = await storageAdapter.upload(storageKey, encrypted);
|
|
127559
128855
|
let dataPointId;
|
|
127560
128856
|
if (entry.dataPointId) {
|
|
@@ -127568,14 +128864,35 @@ async function uploadOne(deps, entry) {
|
|
|
127568
128864
|
metadataHash,
|
|
127569
128865
|
expectedVersion: version4
|
|
127570
128866
|
});
|
|
127571
|
-
const
|
|
128867
|
+
const registration = {
|
|
127572
128868
|
ownerAddress: serverOwner,
|
|
127573
128869
|
scope: entry.scope,
|
|
127574
128870
|
dataHash,
|
|
127575
128871
|
metadataHash,
|
|
127576
128872
|
expectedVersion: String(version4),
|
|
127577
128873
|
signature: addDataSignature
|
|
127578
|
-
}
|
|
128874
|
+
};
|
|
128875
|
+
const lineage = readStoredLineage(envelope.data);
|
|
128876
|
+
let dataPointResult;
|
|
128877
|
+
if (lineage) {
|
|
128878
|
+
if (!deps.lineageGateway) {
|
|
128879
|
+
throw new Error(`Cannot register derivative ${entry.path} (scope=${entry.scope}): lineage registration needs a gateway URL (lineageGateway is not configured)`);
|
|
128880
|
+
}
|
|
128881
|
+
const lineageSignature = await signer.signLineageAttestation({
|
|
128882
|
+
ownerAddress: serverOwner,
|
|
128883
|
+
scope: entry.scope,
|
|
128884
|
+
expectedVersion: version4,
|
|
128885
|
+
dataHash,
|
|
128886
|
+
sources: lineage.sources
|
|
128887
|
+
});
|
|
128888
|
+
dataPointResult = await deps.lineageGateway.registerDataPoint({
|
|
128889
|
+
...registration,
|
|
128890
|
+
lineage: lineage.sources,
|
|
128891
|
+
lineageSignature
|
|
128892
|
+
});
|
|
128893
|
+
} else {
|
|
128894
|
+
dataPointResult = await gateway.registerDataPoint(registration);
|
|
128895
|
+
}
|
|
127579
128896
|
const id2 = dataPointResult.dataPointId ?? null;
|
|
127580
128897
|
if (!id2) {
|
|
127581
128898
|
throw new Error(`Gateway registerDataPoint did not return a dataPointId for ${entry.path} (scope=${entry.scope}, version=${version4})`);
|
|
@@ -127583,11 +128900,23 @@ async function uploadOne(deps, entry) {
|
|
|
127583
128900
|
return id2;
|
|
127584
128901
|
};
|
|
127585
128902
|
try {
|
|
127586
|
-
dataPointId = await registerAt(
|
|
128903
|
+
dataPointId = await registerAt(registerVersion);
|
|
128904
|
+
if (registerVersion !== BigInt(entry.version)) {
|
|
128905
|
+
await storage.updateEntryVersion(entry.path, Number(registerVersion));
|
|
128906
|
+
}
|
|
127587
128907
|
} catch (err2) {
|
|
127588
128908
|
if (!isStaleVersionConflict(err2))
|
|
127589
128909
|
throw err2;
|
|
127590
|
-
const record2 = await
|
|
128910
|
+
const record2 = deps.dataPointFeed ? await deps.dataPointFeed.getDataPoint({
|
|
128911
|
+
ownerAddress: serverOwner,
|
|
128912
|
+
scope: entry.scope
|
|
128913
|
+
}) : await gateway.getDataPoint(computeDataPointId(serverOwner, entry.scope));
|
|
128914
|
+
const conflictDeletedAt = record2 ? deletionTimestamp(record2) : null;
|
|
128915
|
+
if (record2 && conflictDeletedAt !== null) {
|
|
128916
|
+
await dropIfCoveredByDeletion(deps, entry, record2, conflictDeletedAt, {
|
|
128917
|
+
url: url2
|
|
128918
|
+
});
|
|
128919
|
+
}
|
|
127591
128920
|
if (record2 && record2.dataHash.toLowerCase() === dataHash.toLowerCase()) {
|
|
127592
128921
|
dataPointId = record2.id;
|
|
127593
128922
|
const adoptedVersion = Number(record2.expectedVersion);
|
|
@@ -127613,6 +128942,7 @@ async function uploadOne(deps, entry) {
|
|
|
127613
128942
|
}
|
|
127614
128943
|
}
|
|
127615
128944
|
await storage.updateDataPointId(entry.path, dataPointId);
|
|
128945
|
+
deps.scopeDeletions?.markLive(entry.scope);
|
|
127616
128946
|
}
|
|
127617
128947
|
logger.info({
|
|
127618
128948
|
path: entry.path,
|
|
@@ -127632,7 +128962,7 @@ async function uploadAll(deps, options) {
|
|
|
127632
128962
|
const result = await uploadOne(deps, entry);
|
|
127633
128963
|
results.push(result);
|
|
127634
128964
|
} catch (err2) {
|
|
127635
|
-
if (err2 instanceof OrphanedEntryError) {
|
|
128965
|
+
if (err2 instanceof OrphanedEntryError || err2 instanceof DeletedScopeEntryError) {
|
|
127636
128966
|
continue;
|
|
127637
128967
|
}
|
|
127638
128968
|
const error51 = err2;
|
|
@@ -127660,11 +128990,100 @@ function parseGatewayNextVersion(message) {
|
|
|
127660
128990
|
return Number(storedValue[1]) + 1;
|
|
127661
128991
|
return null;
|
|
127662
128992
|
}
|
|
127663
|
-
|
|
127664
|
-
|
|
127665
|
-
|
|
127666
|
-
|
|
127667
|
-
|
|
128993
|
+
|
|
128994
|
+
// ../core/dist/sync/data-point-feed.js
|
|
128995
|
+
function createGatewayDataPointFeed(options) {
|
|
128996
|
+
const base = options.gatewayUrl.replace(/\/+$/, "");
|
|
128997
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
128998
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
128999
|
+
return {
|
|
129000
|
+
async listDataPointsByOwner(owner, cursor, listOptions) {
|
|
129001
|
+
const params = new URLSearchParams({ user: owner });
|
|
129002
|
+
if (cursor !== null)
|
|
129003
|
+
params.set("cursor", cursor);
|
|
129004
|
+
if (listOptions?.since)
|
|
129005
|
+
params.set("since", listOptions.since);
|
|
129006
|
+
if (listOptions?.limit !== void 0) {
|
|
129007
|
+
params.set("limit", String(listOptions.limit));
|
|
129008
|
+
}
|
|
129009
|
+
if (listOptions?.includeDeleted)
|
|
129010
|
+
params.set("includeDeleted", "true");
|
|
129011
|
+
const res = await fetchImpl(`${base}/v1/data?${params.toString()}`);
|
|
129012
|
+
if (!res.ok) {
|
|
129013
|
+
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
129014
|
+
}
|
|
129015
|
+
const envelope = await res.json();
|
|
129016
|
+
const nextCursor = envelope.pagination?.hasMore === false ? null : envelope.pagination?.nextCursor ?? null;
|
|
129017
|
+
const rows = envelope.data?.dataPoints ?? [];
|
|
129018
|
+
return {
|
|
129019
|
+
dataPoints: rows.map((row) => normalizeRecord(row)),
|
|
129020
|
+
cursor: nextCursor
|
|
129021
|
+
};
|
|
129022
|
+
},
|
|
129023
|
+
async getDataPoint(input) {
|
|
129024
|
+
const dataPointId = computeDataPointId(input.ownerAddress, input.scope);
|
|
129025
|
+
const res = await fetchImpl(`${base}/v1/data/${dataPointId}?includeDeleted=true`);
|
|
129026
|
+
if (res.status === 404)
|
|
129027
|
+
return null;
|
|
129028
|
+
if (res.status === 410) {
|
|
129029
|
+
const body2 = await res.json().catch(() => null);
|
|
129030
|
+
const echoed = unwrap(body2);
|
|
129031
|
+
const deletedAt = stringField(echoed, "deletedAt") ?? now().toISOString();
|
|
129032
|
+
return {
|
|
129033
|
+
id: dataPointId,
|
|
129034
|
+
ownerAddress: input.ownerAddress,
|
|
129035
|
+
scope: input.scope,
|
|
129036
|
+
dataHash: stringField(echoed, "dataHash") ?? TOMBSTONE_DATA_HASH,
|
|
129037
|
+
metadataHash: stringField(echoed, "metadataHash") ?? TOMBSTONE_METADATA_HASH,
|
|
129038
|
+
expectedVersion: stringField(echoed, "expectedVersion") ?? "0",
|
|
129039
|
+
addedAt: stringField(echoed, "addedAt") ?? deletedAt,
|
|
129040
|
+
deletedAt
|
|
129041
|
+
};
|
|
129042
|
+
}
|
|
129043
|
+
if (!res.ok) {
|
|
129044
|
+
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
129045
|
+
}
|
|
129046
|
+
const body = await res.json();
|
|
129047
|
+
return normalizeRecord(unwrap(body));
|
|
129048
|
+
}
|
|
129049
|
+
};
|
|
129050
|
+
}
|
|
129051
|
+
function unwrap(body) {
|
|
129052
|
+
if (typeof body !== "object" || body === null)
|
|
129053
|
+
return null;
|
|
129054
|
+
const record2 = body;
|
|
129055
|
+
if (typeof record2.data === "object" && record2.data !== null) {
|
|
129056
|
+
return record2.data;
|
|
129057
|
+
}
|
|
129058
|
+
return record2;
|
|
129059
|
+
}
|
|
129060
|
+
function stringField(record2, key) {
|
|
129061
|
+
const value = record2?.[key];
|
|
129062
|
+
return typeof value === "string" ? value : void 0;
|
|
129063
|
+
}
|
|
129064
|
+
function normalizeRecord(row) {
|
|
129065
|
+
const record2 = row ?? {};
|
|
129066
|
+
const deletedAt = record2.deletedAt;
|
|
129067
|
+
return {
|
|
129068
|
+
...record2,
|
|
129069
|
+
deletedAt: typeof deletedAt === "string" ? deletedAt : null
|
|
129070
|
+
};
|
|
129071
|
+
}
|
|
129072
|
+
function feedFromGatewayClient(gateway) {
|
|
129073
|
+
return {
|
|
129074
|
+
async listDataPointsByOwner(owner, cursor, listOptions) {
|
|
129075
|
+
const { includeDeleted: _includeDeleted, ...sdkOptions } = listOptions ?? {};
|
|
129076
|
+
const result = Object.keys(sdkOptions).length > 0 ? await gateway.listDataPointsByOwner(owner, cursor, sdkOptions) : await gateway.listDataPointsByOwner(owner, cursor);
|
|
129077
|
+
return {
|
|
129078
|
+
dataPoints: result.dataPoints.map((row) => normalizeRecord(row)),
|
|
129079
|
+
cursor: result.cursor
|
|
129080
|
+
};
|
|
129081
|
+
},
|
|
129082
|
+
async getDataPoint(input) {
|
|
129083
|
+
const row = await gateway.getDataPoint(computeDataPointId(input.ownerAddress, input.scope));
|
|
129084
|
+
return row === null ? null : normalizeRecord(row);
|
|
129085
|
+
}
|
|
129086
|
+
};
|
|
127668
129087
|
}
|
|
127669
129088
|
|
|
127670
129089
|
// ../core/dist/sync/issues.js
|
|
@@ -128004,10 +129423,43 @@ async function downloadAll(deps, options = {}) {
|
|
|
128004
129423
|
if (options.fullReconcile || repairSummary.missingEnvelopeEntries > 0) {
|
|
128005
129424
|
options.retryMemory?.onListingReset();
|
|
128006
129425
|
}
|
|
128007
|
-
const
|
|
129426
|
+
const feed = deps.dataPointFeed ?? feedFromGatewayClient(gateway);
|
|
129427
|
+
const { dataPoints, cursor: nextCursor } = await feed.listDataPointsByOwner(serverOwner, lastCursor, { includeDeleted: true });
|
|
129428
|
+
if (deps.scopeDeletions) {
|
|
129429
|
+
for (const dataPoint of dataPoints) {
|
|
129430
|
+
const deletedAt = deletionTimestamp(dataPoint);
|
|
129431
|
+
if (deletedAt !== null) {
|
|
129432
|
+
deps.scopeDeletions.markDeleted(dataPoint.scope, {
|
|
129433
|
+
deletedAt,
|
|
129434
|
+
version: tombstoneVersion(dataPoint)
|
|
129435
|
+
});
|
|
129436
|
+
} else {
|
|
129437
|
+
deps.scopeDeletions.markLive(dataPoint.scope);
|
|
129438
|
+
}
|
|
129439
|
+
}
|
|
129440
|
+
if (nextCursor === null) {
|
|
129441
|
+
deps.scopeDeletions.noteFeedSynced(void 0, {
|
|
129442
|
+
full: lastCursor === null
|
|
129443
|
+
});
|
|
129444
|
+
}
|
|
129445
|
+
}
|
|
128008
129446
|
const results = [];
|
|
128009
129447
|
let failed = false;
|
|
128010
129448
|
for (const dataPoint of dataPoints) {
|
|
129449
|
+
const deletedAt = deletionTimestamp(dataPoint);
|
|
129450
|
+
if (deletedAt !== null) {
|
|
129451
|
+
try {
|
|
129452
|
+
await reconcileDeletedDataPoint(deps, dataPoint, deletedAt);
|
|
129453
|
+
} catch (err2) {
|
|
129454
|
+
logger.error({
|
|
129455
|
+
dataPointId: dataPoint.id,
|
|
129456
|
+
scope: dataPoint.scope,
|
|
129457
|
+
error: err2.message
|
|
129458
|
+
}, "Failed to reconcile deleted data point locally");
|
|
129459
|
+
failed = true;
|
|
129460
|
+
}
|
|
129461
|
+
continue;
|
|
129462
|
+
}
|
|
128011
129463
|
const retryKey = downloadRetryKey(dataPoint);
|
|
128012
129464
|
const decision = options.retryMemory?.decide(retryKey) ?? "attempt";
|
|
128013
129465
|
if (decision === "give-up") {
|
|
@@ -128063,6 +129515,49 @@ async function downloadAll(deps, options = {}) {
|
|
|
128063
129515
|
}
|
|
128064
129516
|
return results;
|
|
128065
129517
|
}
|
|
129518
|
+
async function reconcileDeletedDataPoint(deps, record2, deletedAt) {
|
|
129519
|
+
const tombstone = { version: tombstoneVersion(record2) };
|
|
129520
|
+
const tombstoned = tombstone.version === null ? null : BigInt(tombstone.version);
|
|
129521
|
+
const orphanKeys = [];
|
|
129522
|
+
const { storage, logger } = deps;
|
|
129523
|
+
const PAGE_SIZE = 500;
|
|
129524
|
+
const stale = [];
|
|
129525
|
+
let kept = 0;
|
|
129526
|
+
for (let offset = 0; ; offset += PAGE_SIZE) {
|
|
129527
|
+
const entries = storage.listVersions(record2.scope, {
|
|
129528
|
+
limit: PAGE_SIZE,
|
|
129529
|
+
offset
|
|
129530
|
+
});
|
|
129531
|
+
for (const entry of entries) {
|
|
129532
|
+
if (isEntryCoveredByTombstone(entry, tombstone)) {
|
|
129533
|
+
stale.push({ scope: entry.scope, collectedAt: entry.collectedAt });
|
|
129534
|
+
if (entry.dataPointId === null && (tombstoned === null || BigInt(entry.version) > tombstoned)) {
|
|
129535
|
+
orphanKeys.push({
|
|
129536
|
+
scope: entry.scope,
|
|
129537
|
+
version: String(entry.version)
|
|
129538
|
+
});
|
|
129539
|
+
}
|
|
129540
|
+
} else {
|
|
129541
|
+
kept += 1;
|
|
129542
|
+
}
|
|
129543
|
+
}
|
|
129544
|
+
if (entries.length < PAGE_SIZE)
|
|
129545
|
+
break;
|
|
129546
|
+
}
|
|
129547
|
+
let removed = 0;
|
|
129548
|
+
for (const version4 of stale) {
|
|
129549
|
+
if (await storage.deleteVersion(version4.scope, version4.collectedAt)) {
|
|
129550
|
+
removed += 1;
|
|
129551
|
+
}
|
|
129552
|
+
}
|
|
129553
|
+
if (orphanKeys.length > 0 && deps.pendingBlobDeletions) {
|
|
129554
|
+
await deps.pendingBlobDeletions.add(orphanKeys);
|
|
129555
|
+
}
|
|
129556
|
+
if (removed > 0 || kept > 0) {
|
|
129557
|
+
logger.info({ dataPointId: record2.id, scope: record2.scope, deletedAt, removed, kept }, "Reconciled gateway deletion against local index");
|
|
129558
|
+
}
|
|
129559
|
+
return { scope: record2.scope, deletedAt, removed, kept };
|
|
129560
|
+
}
|
|
128066
129561
|
async function repairLocalMissingBlockSidecars(deps) {
|
|
128067
129562
|
const { storage, logger, diagnostics } = deps;
|
|
128068
129563
|
if (!storage.writeBlockManifest || !storage.hasScopeBlocks) {
|
|
@@ -128221,28 +129716,6 @@ async function repairMissingBlockSidecars(storage, logger, ctx, entry, diagnosti
|
|
|
128221
129716
|
}
|
|
128222
129717
|
}
|
|
128223
129718
|
|
|
128224
|
-
// ../core/dist/sync/workers/delete.js
|
|
128225
|
-
async function deleteScopeRemote(deps, scope) {
|
|
128226
|
-
const { storage, logger } = deps;
|
|
128227
|
-
let syncedVersions = 0;
|
|
128228
|
-
const PAGE_SIZE = 1e3;
|
|
128229
|
-
for (let offset = 0; ; offset += PAGE_SIZE) {
|
|
128230
|
-
const entries = storage.listVersions(scope, { limit: PAGE_SIZE, offset });
|
|
128231
|
-
syncedVersions += entries.filter((e10) => e10.dataPointId !== null).length;
|
|
128232
|
-
if (entries.length < PAGE_SIZE)
|
|
128233
|
-
break;
|
|
128234
|
-
}
|
|
128235
|
-
if (syncedVersions > 0) {
|
|
128236
|
-
logger.warn({ scope, syncedVersions }, "Remote scope deletion is not supported on the DPv2 gateway (no de-registration endpoint); local data was removed but the remote data point(s) and ciphertext blob(s) remain");
|
|
128237
|
-
}
|
|
128238
|
-
return {
|
|
128239
|
-
scope,
|
|
128240
|
-
filesDeregistered: 0,
|
|
128241
|
-
blobsDeleted: 0,
|
|
128242
|
-
errors: []
|
|
128243
|
-
};
|
|
128244
|
-
}
|
|
128245
|
-
|
|
128246
129719
|
// ../core/dist/sync/engine/sync-manager.js
|
|
128247
129720
|
var MAX_ERRORS = 10;
|
|
128248
129721
|
function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
@@ -128260,12 +129733,28 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128260
129733
|
let rerunRequested = false;
|
|
128261
129734
|
let needsFullReconcile = true;
|
|
128262
129735
|
const downloadRetryMemory = createDownloadRetryMemory();
|
|
129736
|
+
const dataPointFeed = downloadDeps.dataPointFeed ?? uploadDeps.dataPointFeed;
|
|
129737
|
+
const scopeDeletions = uploadDeps.scopeDeletions ?? downloadDeps.scopeDeletions;
|
|
129738
|
+
const workerUploadDeps = {
|
|
129739
|
+
...uploadDeps,
|
|
129740
|
+
pendingBlobDeletions: uploadDeps.pendingBlobDeletions ?? options?.pendingBlobDeletions
|
|
129741
|
+
};
|
|
129742
|
+
const workerDownloadDeps = {
|
|
129743
|
+
...downloadDeps,
|
|
129744
|
+
pendingBlobDeletions: downloadDeps.pendingBlobDeletions ?? options?.pendingBlobDeletions
|
|
129745
|
+
};
|
|
129746
|
+
let mutationQueue = Promise.resolve();
|
|
129747
|
+
function exclusive(operation) {
|
|
129748
|
+
const run = mutationQueue.then(operation, operation);
|
|
129749
|
+
mutationQueue = run.catch(() => void 0);
|
|
129750
|
+
return run;
|
|
129751
|
+
}
|
|
128263
129752
|
async function runCycle() {
|
|
128264
129753
|
if (cycleInFlight) {
|
|
128265
129754
|
rerunRequested = true;
|
|
128266
129755
|
return cycleInFlight;
|
|
128267
129756
|
}
|
|
128268
|
-
cycleInFlight = (async () => {
|
|
129757
|
+
cycleInFlight = exclusive(async () => {
|
|
128269
129758
|
do {
|
|
128270
129759
|
rerunRequested = false;
|
|
128271
129760
|
const canRun = await (options?.canSync?.() ?? { ok: true });
|
|
@@ -128276,7 +129765,19 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128276
129765
|
}
|
|
128277
129766
|
blocked = null;
|
|
128278
129767
|
try {
|
|
128279
|
-
|
|
129768
|
+
await retryPendingBlobDeletions({
|
|
129769
|
+
deleteData: options?.deleteData,
|
|
129770
|
+
pendingBlobDeletions: options?.pendingBlobDeletions,
|
|
129771
|
+
dataPointFeed,
|
|
129772
|
+
serverOwner: uploadDeps.serverOwner,
|
|
129773
|
+
storage: uploadDeps.storage,
|
|
129774
|
+
logger: uploadDeps.logger
|
|
129775
|
+
});
|
|
129776
|
+
} catch (err2) {
|
|
129777
|
+
uploadDeps.logger.warn({ error: err2.message }, "Pending blob deletion retry failed");
|
|
129778
|
+
}
|
|
129779
|
+
try {
|
|
129780
|
+
const uploadResults = await uploadAll(workerUploadDeps, {
|
|
128280
129781
|
batchSize: uploadBatchSize,
|
|
128281
129782
|
onError(entry, error51) {
|
|
128282
129783
|
pushError({
|
|
@@ -128300,7 +129801,7 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128300
129801
|
}
|
|
128301
129802
|
try {
|
|
128302
129803
|
const fullReconcile = needsFullReconcile;
|
|
128303
|
-
const downloadResults = await downloadAll(
|
|
129804
|
+
const downloadResults = await downloadAll(workerDownloadDeps, {
|
|
128304
129805
|
fullReconcile,
|
|
128305
129806
|
retryMemory: downloadRetryMemory
|
|
128306
129807
|
});
|
|
@@ -128322,7 +129823,7 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128322
129823
|
}
|
|
128323
129824
|
lastSync = (/* @__PURE__ */ new Date()).toISOString();
|
|
128324
129825
|
} while (rerunRequested && isRunning);
|
|
128325
|
-
})
|
|
129826
|
+
});
|
|
128326
129827
|
try {
|
|
128327
129828
|
await cycleInFlight;
|
|
128328
129829
|
} finally {
|
|
@@ -128411,13 +129912,291 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128411
129912
|
uploadDeps.logger.debug("New data notification received");
|
|
128412
129913
|
scheduleNotifiedCycle();
|
|
128413
129914
|
},
|
|
128414
|
-
|
|
128415
|
-
|
|
129915
|
+
deleteScope(scope) {
|
|
129916
|
+
return exclusive(() => deleteScope({
|
|
129917
|
+
storage: uploadDeps.storage,
|
|
129918
|
+
serverOwner: uploadDeps.serverOwner,
|
|
129919
|
+
deleteData: options?.deleteData,
|
|
129920
|
+
pendingBlobDeletions: options?.pendingBlobDeletions,
|
|
129921
|
+
scopeDeletions,
|
|
129922
|
+
dataPointFeed,
|
|
129923
|
+
logger: uploadDeps.logger
|
|
129924
|
+
}, scope));
|
|
128416
129925
|
}
|
|
128417
129926
|
};
|
|
128418
129927
|
return manager;
|
|
128419
129928
|
}
|
|
128420
129929
|
|
|
129930
|
+
// ../core/dist/sync/delete-data-port.js
|
|
129931
|
+
function createGatewayDeleteDataPort(options) {
|
|
129932
|
+
const gatewayBase = options.gatewayUrl.replace(/\/+$/, "");
|
|
129933
|
+
const storageBase = options.storage.endpoint.replace(/\/+$/, "");
|
|
129934
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
129935
|
+
const owner = options.serverOwner.toLowerCase();
|
|
129936
|
+
async function sendTombstone(scope, dataPointId, version4) {
|
|
129937
|
+
const signature = await options.signer.signAddData({
|
|
129938
|
+
ownerAddress: options.serverOwner,
|
|
129939
|
+
scope,
|
|
129940
|
+
dataHash: TOMBSTONE_DATA_HASH,
|
|
129941
|
+
metadataHash: TOMBSTONE_METADATA_HASH,
|
|
129942
|
+
expectedVersion: version4
|
|
129943
|
+
});
|
|
129944
|
+
return fetchImpl(`${gatewayBase}/v1/data/${dataPointId}`, {
|
|
129945
|
+
method: "DELETE",
|
|
129946
|
+
headers: {
|
|
129947
|
+
"Content-Type": "application/json",
|
|
129948
|
+
Authorization: `Web3Signed ${signature}`
|
|
129949
|
+
},
|
|
129950
|
+
body: JSON.stringify({
|
|
129951
|
+
ownerAddress: options.serverOwner,
|
|
129952
|
+
scope,
|
|
129953
|
+
expectedVersion: String(version4),
|
|
129954
|
+
signature
|
|
129955
|
+
})
|
|
129956
|
+
});
|
|
129957
|
+
}
|
|
129958
|
+
return {
|
|
129959
|
+
async tombstone(scope) {
|
|
129960
|
+
const dataPointId = computeDataPointId(options.serverOwner, scope);
|
|
129961
|
+
const current = await options.dataPointFeed.getDataPoint({
|
|
129962
|
+
ownerAddress: options.serverOwner,
|
|
129963
|
+
scope
|
|
129964
|
+
});
|
|
129965
|
+
if (current === null) {
|
|
129966
|
+
return { status: "not-registered", dataPointId };
|
|
129967
|
+
}
|
|
129968
|
+
if (current.deletedAt !== null) {
|
|
129969
|
+
return {
|
|
129970
|
+
status: "already-deleted",
|
|
129971
|
+
dataPointId,
|
|
129972
|
+
version: current.expectedVersion,
|
|
129973
|
+
deletedAt: current.deletedAt
|
|
129974
|
+
};
|
|
129975
|
+
}
|
|
129976
|
+
let version4 = BigInt(current.expectedVersion) + 1n;
|
|
129977
|
+
let res = await sendTombstone(scope, dataPointId, version4);
|
|
129978
|
+
if (res.status === 409) {
|
|
129979
|
+
const body2 = await res.json().catch(() => null);
|
|
129980
|
+
const conflict = unwrap2(body2);
|
|
129981
|
+
const nextExplicit = integerField(conflict, "nextExpectedVersion") ?? integerField(body2, "nextExpectedVersion");
|
|
129982
|
+
const currentExpected = integerField(conflict, "currentExpectedVersion") ?? integerField(body2, "currentExpectedVersion");
|
|
129983
|
+
const legacyNext = parseGatewayNextVersion(detailFromBody(body2, res.statusText));
|
|
129984
|
+
const next = nextExplicit !== null ? nextExplicit : currentExpected !== null ? currentExpected + 1n : legacyNext !== null ? BigInt(legacyNext) : null;
|
|
129985
|
+
if (next === null) {
|
|
129986
|
+
throw new Error(`Gateway error: 409 ${detailFromBody(body2, res.statusText)}`);
|
|
129987
|
+
}
|
|
129988
|
+
version4 = next;
|
|
129989
|
+
res = await sendTombstone(scope, dataPointId, version4);
|
|
129990
|
+
}
|
|
129991
|
+
if (res.status === 404) {
|
|
129992
|
+
return { status: "not-registered", dataPointId };
|
|
129993
|
+
}
|
|
129994
|
+
if (res.status === 410) {
|
|
129995
|
+
const body2 = await res.json().catch(() => null);
|
|
129996
|
+
const echoed = unwrap2(body2);
|
|
129997
|
+
let winning = normalizeVersionString(stringField2(echoed, "expectedVersion"));
|
|
129998
|
+
let deletedAt = stringField2(echoed, "deletedAt");
|
|
129999
|
+
if (winning === null) {
|
|
130000
|
+
const reread = await options.dataPointFeed.getDataPoint({ ownerAddress: options.serverOwner, scope }).catch(() => null);
|
|
130001
|
+
if (reread && reread.deletedAt !== null) {
|
|
130002
|
+
winning = normalizeVersionString(reread.expectedVersion);
|
|
130003
|
+
deletedAt = deletedAt ?? reread.deletedAt;
|
|
130004
|
+
}
|
|
130005
|
+
}
|
|
130006
|
+
return {
|
|
130007
|
+
status: "already-deleted",
|
|
130008
|
+
dataPointId,
|
|
130009
|
+
version: winning,
|
|
130010
|
+
deletedAt
|
|
130011
|
+
};
|
|
130012
|
+
}
|
|
130013
|
+
if (!res.ok) {
|
|
130014
|
+
throw new Error(`Gateway error: ${res.status} ${await errorDetail(res)}`);
|
|
130015
|
+
}
|
|
130016
|
+
const body = await res.json().catch(() => null);
|
|
130017
|
+
const row = unwrap2(body);
|
|
130018
|
+
return {
|
|
130019
|
+
status: "tombstoned",
|
|
130020
|
+
dataPointId: stringField2(row, "dataPointId") ?? dataPointId,
|
|
130021
|
+
version: stringField2(row, "expectedVersion") ?? String(version4),
|
|
130022
|
+
deletedAt: stringField2(row, "deletedAt")
|
|
130023
|
+
};
|
|
130024
|
+
},
|
|
130025
|
+
async deleteBlobVersions(scope, versions) {
|
|
130026
|
+
const outcome = {
|
|
130027
|
+
deleted: [],
|
|
130028
|
+
missing: [],
|
|
130029
|
+
failed: []
|
|
130030
|
+
};
|
|
130031
|
+
for (const version4 of versions) {
|
|
130032
|
+
const path = `/v1/chains/${options.storage.chainId}/blobs/${owner}/${encodeURIComponent(scope)}/${encodeURIComponent(version4)}`;
|
|
130033
|
+
try {
|
|
130034
|
+
const authorization = await buildWeb3SignedHeader({
|
|
130035
|
+
signMessage: (message) => options.storage.signMessage(message),
|
|
130036
|
+
aud: storageBase,
|
|
130037
|
+
method: "DELETE",
|
|
130038
|
+
uri: path
|
|
130039
|
+
});
|
|
130040
|
+
const res = await fetchImpl(`${storageBase}${path}`, {
|
|
130041
|
+
method: "DELETE",
|
|
130042
|
+
headers: { authorization }
|
|
130043
|
+
});
|
|
130044
|
+
if (res.status === 404) {
|
|
130045
|
+
outcome.missing.push(version4);
|
|
130046
|
+
} else if (res.ok) {
|
|
130047
|
+
outcome.deleted.push(version4);
|
|
130048
|
+
} else {
|
|
130049
|
+
outcome.failed.push({
|
|
130050
|
+
version: version4,
|
|
130051
|
+
error: `vana-storage delete failed: ${res.status} ${res.statusText}`
|
|
130052
|
+
});
|
|
130053
|
+
}
|
|
130054
|
+
} catch (err2) {
|
|
130055
|
+
outcome.failed.push({
|
|
130056
|
+
version: version4,
|
|
130057
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
130058
|
+
});
|
|
130059
|
+
}
|
|
130060
|
+
}
|
|
130061
|
+
return outcome;
|
|
130062
|
+
}
|
|
130063
|
+
};
|
|
130064
|
+
}
|
|
130065
|
+
async function errorDetail(res) {
|
|
130066
|
+
const body = await res.json().catch(() => null);
|
|
130067
|
+
return detailFromBody(body, res.statusText);
|
|
130068
|
+
}
|
|
130069
|
+
function detailFromBody(body, fallback) {
|
|
130070
|
+
if (typeof body === "object" && body !== null) {
|
|
130071
|
+
const record2 = body;
|
|
130072
|
+
if (typeof record2.error === "string")
|
|
130073
|
+
return record2.error;
|
|
130074
|
+
if (typeof record2.message === "string")
|
|
130075
|
+
return record2.message;
|
|
130076
|
+
if (typeof record2.error === "object" && record2.error !== null) {
|
|
130077
|
+
const nested = record2.error;
|
|
130078
|
+
if (typeof nested.message === "string")
|
|
130079
|
+
return nested.message;
|
|
130080
|
+
}
|
|
130081
|
+
}
|
|
130082
|
+
return fallback;
|
|
130083
|
+
}
|
|
130084
|
+
function normalizeVersionString(value) {
|
|
130085
|
+
if (value === null || !/^\d+$/.test(value))
|
|
130086
|
+
return null;
|
|
130087
|
+
const parsed = BigInt(value);
|
|
130088
|
+
return parsed > 0n ? parsed.toString() : null;
|
|
130089
|
+
}
|
|
130090
|
+
function integerField(record2, key) {
|
|
130091
|
+
if (typeof record2 !== "object" || record2 === null)
|
|
130092
|
+
return null;
|
|
130093
|
+
const value = record2[key];
|
|
130094
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
130095
|
+
return BigInt(value);
|
|
130096
|
+
}
|
|
130097
|
+
if (typeof value === "string" && /^\d+$/.test(value))
|
|
130098
|
+
return BigInt(value);
|
|
130099
|
+
return null;
|
|
130100
|
+
}
|
|
130101
|
+
function unwrap2(body) {
|
|
130102
|
+
if (typeof body !== "object" || body === null)
|
|
130103
|
+
return null;
|
|
130104
|
+
const record2 = body;
|
|
130105
|
+
if (typeof record2.data === "object" && record2.data !== null) {
|
|
130106
|
+
return record2.data;
|
|
130107
|
+
}
|
|
130108
|
+
return record2;
|
|
130109
|
+
}
|
|
130110
|
+
function stringField2(record2, key) {
|
|
130111
|
+
const value = record2?.[key];
|
|
130112
|
+
return typeof value === "string" ? value : null;
|
|
130113
|
+
}
|
|
130114
|
+
|
|
130115
|
+
// ../core/dist/sync/pending-blob-deletions.js
|
|
130116
|
+
function markerId(key) {
|
|
130117
|
+
const range = key.range ? `${key.range.from}-${key.range.to}` : "";
|
|
130118
|
+
return `${key.scope}\0${key.version ?? ""}\0${range}`;
|
|
130119
|
+
}
|
|
130120
|
+
function normalizeRange(value) {
|
|
130121
|
+
if (typeof value !== "object" || value === null)
|
|
130122
|
+
return void 0;
|
|
130123
|
+
const { from, to: to3 } = value;
|
|
130124
|
+
if (typeof from !== "string" || typeof to3 !== "string" || !/^\d+$/.test(from) || !/^\d+$/.test(to3) || BigInt(from) > BigInt(to3)) {
|
|
130125
|
+
return void 0;
|
|
130126
|
+
}
|
|
130127
|
+
return { from, to: to3 };
|
|
130128
|
+
}
|
|
130129
|
+
function normalizePendingBlobDeletions(stored) {
|
|
130130
|
+
if (!Array.isArray(stored))
|
|
130131
|
+
return [];
|
|
130132
|
+
const keys = [];
|
|
130133
|
+
for (const item of stored) {
|
|
130134
|
+
if (typeof item === "string") {
|
|
130135
|
+
keys.push({ scope: item, version: null });
|
|
130136
|
+
} else if (typeof item === "object" && item !== null && typeof item.scope === "string") {
|
|
130137
|
+
const version4 = item.version;
|
|
130138
|
+
const range = typeof version4 === "string" ? void 0 : normalizeRange(item.range);
|
|
130139
|
+
keys.push({
|
|
130140
|
+
scope: item.scope,
|
|
130141
|
+
version: typeof version4 === "string" ? version4 : null,
|
|
130142
|
+
...range ? { range } : {}
|
|
130143
|
+
});
|
|
130144
|
+
}
|
|
130145
|
+
}
|
|
130146
|
+
return keys;
|
|
130147
|
+
}
|
|
130148
|
+
function createPendingBlobDeletionStore(kv) {
|
|
130149
|
+
let queue = Promise.resolve();
|
|
130150
|
+
function serialized(operation) {
|
|
130151
|
+
const run = queue.then(operation, operation);
|
|
130152
|
+
queue = run.catch(() => void 0);
|
|
130153
|
+
return run;
|
|
130154
|
+
}
|
|
130155
|
+
async function current() {
|
|
130156
|
+
return normalizePendingBlobDeletions(await kv.read());
|
|
130157
|
+
}
|
|
130158
|
+
return {
|
|
130159
|
+
list() {
|
|
130160
|
+
return serialized(current);
|
|
130161
|
+
},
|
|
130162
|
+
add(keys) {
|
|
130163
|
+
return serialized(async () => {
|
|
130164
|
+
if (keys.length === 0)
|
|
130165
|
+
return;
|
|
130166
|
+
const existing = await current();
|
|
130167
|
+
const known = new Set(existing.map(markerId));
|
|
130168
|
+
const next = [...existing];
|
|
130169
|
+
for (const key of keys) {
|
|
130170
|
+
const id2 = markerId(key);
|
|
130171
|
+
if (known.has(id2))
|
|
130172
|
+
continue;
|
|
130173
|
+
known.add(id2);
|
|
130174
|
+
next.push({
|
|
130175
|
+
scope: key.scope,
|
|
130176
|
+
version: key.version,
|
|
130177
|
+
...key.range ? { range: { ...key.range } } : {}
|
|
130178
|
+
});
|
|
130179
|
+
}
|
|
130180
|
+
if (next.length === existing.length)
|
|
130181
|
+
return;
|
|
130182
|
+
await kv.write(next);
|
|
130183
|
+
});
|
|
130184
|
+
},
|
|
130185
|
+
remove(keys) {
|
|
130186
|
+
return serialized(async () => {
|
|
130187
|
+
if (keys.length === 0)
|
|
130188
|
+
return;
|
|
130189
|
+
const existing = await current();
|
|
130190
|
+
const gone = new Set(keys.map(markerId));
|
|
130191
|
+
const next = existing.filter((key) => !gone.has(markerId(key)));
|
|
130192
|
+
if (next.length === existing.length)
|
|
130193
|
+
return;
|
|
130194
|
+
await kv.write(next);
|
|
130195
|
+
});
|
|
130196
|
+
}
|
|
130197
|
+
};
|
|
130198
|
+
}
|
|
130199
|
+
|
|
128421
130200
|
// ../core/dist/storage/adapters/sdk.js
|
|
128422
130201
|
function createSdkStorageAdapter(providerOrFactory, options) {
|
|
128423
130202
|
let cachedProvider;
|
|
@@ -128478,8 +130257,11 @@ function copyBytes(data) {
|
|
|
128478
130257
|
|
|
128479
130258
|
// ../core/dist/storage/adapters/vana.js
|
|
128480
130259
|
var DEFAULT_VANA_STORAGE_ENDPOINT = "https://storage.vana.org";
|
|
130260
|
+
function resolveVanaStorageEndpoint(config2) {
|
|
130261
|
+
return (config2.storage.config.vana?.apiUrl ?? DEFAULT_VANA_STORAGE_ENDPOINT).replace(/\/+$/, "");
|
|
130262
|
+
}
|
|
128481
130263
|
function createVanaSyncStorageAdapter(params) {
|
|
128482
|
-
const endpoint = (params.config
|
|
130264
|
+
const endpoint = resolveVanaStorageEndpoint(params.config);
|
|
128483
130265
|
const owner = params.serverOwner.toLowerCase();
|
|
128484
130266
|
const chainId = params.config.gateway.chainId;
|
|
128485
130267
|
return createSdkStorageAdapter(createVanaStorageProvider({
|
|
@@ -128534,6 +130316,7 @@ async function resolvePsLiteOwner(input) {
|
|
|
128534
130316
|
|
|
128535
130317
|
// ../lite/dist/sync.js
|
|
128536
130318
|
var SYNC_CURSOR_KEY = "sync-cursor-v1";
|
|
130319
|
+
var PENDING_BLOB_DELETIONS_KEY = "pending-blob-deletions-v1";
|
|
128537
130320
|
function createBrowserLogger(logger) {
|
|
128538
130321
|
const fallback = {
|
|
128539
130322
|
info: console.info.bind(console),
|
|
@@ -128564,6 +130347,19 @@ function createPsLiteSyncCursor(stateStore) {
|
|
|
128564
130347
|
}
|
|
128565
130348
|
};
|
|
128566
130349
|
}
|
|
130350
|
+
function createPsLitePendingBlobDeletionStore(stateStore) {
|
|
130351
|
+
return createPendingBlobDeletionStore({
|
|
130352
|
+
async read() {
|
|
130353
|
+
const state = await stateStore.get(PENDING_BLOB_DELETIONS_KEY);
|
|
130354
|
+
if (!state)
|
|
130355
|
+
return null;
|
|
130356
|
+
return normalizePendingBlobDeletions(state.keys ?? state.scopes);
|
|
130357
|
+
},
|
|
130358
|
+
async write(keys) {
|
|
130359
|
+
await stateStore.set(PENDING_BLOB_DELETIONS_KEY, { keys });
|
|
130360
|
+
}
|
|
130361
|
+
});
|
|
130362
|
+
}
|
|
128567
130363
|
function buildDownloadDiagnosticsHook(recorder) {
|
|
128568
130364
|
return {
|
|
128569
130365
|
onDownloadStart(fileId) {
|
|
@@ -128649,6 +130445,20 @@ async function createPsLiteSyncManager(options) {
|
|
|
128649
130445
|
});
|
|
128650
130446
|
const cursor = createPsLiteSyncCursor(options.stateStore);
|
|
128651
130447
|
const logger = createBrowserLogger(options.logger);
|
|
130448
|
+
const dataPointFeed = options.dataPointFeed ?? createGatewayDataPointFeed({ gatewayUrl: options.config.gateway.url });
|
|
130449
|
+
const scopeDeletions = options.scopeDeletions ?? createScopeDeletionTracker({ feed: dataPointFeed, serverOwner, logger });
|
|
130450
|
+
const deleteData = createGatewayDeleteDataPort({
|
|
130451
|
+
gatewayUrl: options.config.gateway.url,
|
|
130452
|
+
dataPointFeed,
|
|
130453
|
+
serverOwner,
|
|
130454
|
+
signer,
|
|
130455
|
+
storage: {
|
|
130456
|
+
endpoint: resolveVanaStorageEndpoint(options.config),
|
|
130457
|
+
chainId: options.config.gateway.chainId,
|
|
130458
|
+
signMessage: (message) => options.serverAccount.signMessage(message)
|
|
130459
|
+
}
|
|
130460
|
+
});
|
|
130461
|
+
const pendingBlobDeletions = createPsLitePendingBlobDeletionStore(options.stateStore);
|
|
128652
130462
|
const downloadDiagnostics = options.diagnostics ? buildDownloadDiagnosticsHook(options.diagnostics) : void 0;
|
|
128653
130463
|
const syncManager = createSyncManager({
|
|
128654
130464
|
storage: options.storage,
|
|
@@ -128657,7 +130467,10 @@ async function createPsLiteSyncManager(options) {
|
|
|
128657
130467
|
signer,
|
|
128658
130468
|
masterKey,
|
|
128659
130469
|
serverOwner,
|
|
128660
|
-
logger
|
|
130470
|
+
logger,
|
|
130471
|
+
lineageGateway: options.lineageGateway,
|
|
130472
|
+
dataPointFeed,
|
|
130473
|
+
scopeDeletions
|
|
128661
130474
|
}, {
|
|
128662
130475
|
storage: options.storage,
|
|
128663
130476
|
storageAdapter,
|
|
@@ -128666,8 +130479,12 @@ async function createPsLiteSyncManager(options) {
|
|
|
128666
130479
|
masterKey,
|
|
128667
130480
|
serverOwner,
|
|
128668
130481
|
logger,
|
|
128669
|
-
diagnostics: downloadDiagnostics
|
|
130482
|
+
diagnostics: downloadDiagnostics,
|
|
130483
|
+
dataPointFeed,
|
|
130484
|
+
scopeDeletions
|
|
128670
130485
|
}, {
|
|
130486
|
+
deleteData,
|
|
130487
|
+
pendingBlobDeletions,
|
|
128671
130488
|
async canSync() {
|
|
128672
130489
|
try {
|
|
128673
130490
|
const serverInfo = await gateway.getServer(options.serverAccount.address);
|
|
@@ -128689,7 +130506,7 @@ async function createPsLiteSyncManager(options) {
|
|
|
128689
130506
|
}
|
|
128690
130507
|
});
|
|
128691
130508
|
syncManager.start();
|
|
128692
|
-
return { syncManager, serverOwner };
|
|
130509
|
+
return { syncManager, serverOwner, dataPointFeed, scopeDeletions };
|
|
128693
130510
|
}
|
|
128694
130511
|
|
|
128695
130512
|
// ../lite/dist/persistence.js
|
|
@@ -128750,9 +130567,14 @@ async function createIndexedDbPsLiteRuntime(options) {
|
|
|
128750
130567
|
contracts: config2.gateway.contracts
|
|
128751
130568
|
});
|
|
128752
130569
|
const diagnostics = options.diagnostics ?? new DiagnosticsRecorder();
|
|
130570
|
+
const lineageGateway = createGatewayLineageClient({
|
|
130571
|
+
gatewayUrl: config2.gateway.url,
|
|
130572
|
+
requestSigner: createRequestSigner(identity.account)
|
|
130573
|
+
});
|
|
128753
130574
|
let syncManager = options.syncManager ?? null;
|
|
130575
|
+
let scopeDeletions = options.scopeDeletions;
|
|
128754
130576
|
if (!syncManager && config2.sync.enabled) {
|
|
128755
|
-
|
|
130577
|
+
const sync = await createPsLiteSyncManager({
|
|
128756
130578
|
config: config2,
|
|
128757
130579
|
stateStore,
|
|
128758
130580
|
storage,
|
|
@@ -128760,9 +130582,14 @@ async function createIndexedDbPsLiteRuntime(options) {
|
|
|
128760
130582
|
ownerAddress: options.ownerAddress,
|
|
128761
130583
|
serverAccount: identity.account,
|
|
128762
130584
|
gateway,
|
|
130585
|
+
dataPointFeed: options.dataPointFeed,
|
|
130586
|
+
scopeDeletions,
|
|
128763
130587
|
diagnostics,
|
|
128764
|
-
logger: options.logger
|
|
128765
|
-
|
|
130588
|
+
logger: options.logger,
|
|
130589
|
+
lineageGateway
|
|
130590
|
+
});
|
|
130591
|
+
syncManager = sync.syncManager;
|
|
130592
|
+
scopeDeletions = sync.scopeDeletions;
|
|
128766
130593
|
}
|
|
128767
130594
|
let runtimeRef = null;
|
|
128768
130595
|
const auth = options.auth ?? createWeb3SignedPsLiteAuth({
|
|
@@ -128791,7 +130618,9 @@ async function createIndexedDbPsLiteRuntime(options) {
|
|
|
128791
130618
|
serverOwner,
|
|
128792
130619
|
serverSigner,
|
|
128793
130620
|
syncManager,
|
|
130621
|
+
scopeDeletions,
|
|
128794
130622
|
diagnostics,
|
|
130623
|
+
lineageGateway,
|
|
128795
130624
|
saveConfig: async (nextConfig) => {
|
|
128796
130625
|
const saved = await savePsLiteConfig(stateStore, nextConfig);
|
|
128797
130626
|
Object.assign(config2, saved);
|