@tinycloud/node-sdk 3.8.0-beta.0 → 3.8.0-beta.10
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/{TinyCloudNode-BtKzLDJX.d.ts → TinyCloudNode-DnD-SH6t.d.ts} +27 -4
- package/dist/{TinyCloudNode-ggmlnSfI.d.cts → TinyCloudNode-Dy65bxqs.d.cts} +27 -4
- package/dist/{authority-sJ6buHMj.d.ts → authority-BQnTX3fI.d.ts} +21 -5
- package/dist/{authority-_SYAE-uV.d.cts → authority-Rbye1U4o.d.cts} +21 -5
- package/dist/core.cjs +196 -29
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +5 -4
- package/dist/core.d.ts +5 -4
- package/dist/core.js +190 -25
- package/dist/core.js.map +1 -1
- package/dist/credentials-core.d.cts +1 -1
- package/dist/credentials-core.d.ts +1 -1
- package/dist/credentials.d.cts +1 -1
- package/dist/credentials.d.ts +1 -1
- package/dist/{delegation-0LKZkmP2.d.cts → delegation-Ckc3UETl.d.cts} +1 -1
- package/dist/{delegation-0LKZkmP2.d.ts → delegation-Ckc3UETl.d.ts} +1 -1
- package/dist/encryption-keys.d.cts +2 -2
- package/dist/encryption-keys.d.ts +2 -2
- package/dist/index.cjs +249 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +236 -28
- package/dist/index.js.map +1 -1
- package/dist/replication/authority.cjs +43 -1
- package/dist/replication/authority.cjs.map +1 -1
- package/dist/replication/authority.d.cts +4 -3
- package/dist/replication/authority.d.ts +4 -3
- package/dist/replication/authority.js +42 -1
- package/dist/replication/authority.js.map +1 -1
- package/dist/replication/runtime.cjs +1 -0
- package/dist/replication/runtime.cjs.map +1 -1
- package/dist/replication/runtime.d.cts +1 -1
- package/dist/replication/runtime.d.ts +1 -1
- package/dist/replication/runtime.js +1 -0
- package/dist/replication/runtime.js.map +1 -1
- package/dist/{runtime-v62FzQHz.d.ts → runtime-CO4VXnPq.d.ts} +2 -1
- package/dist/{runtime-D1o9Eybt.d.cts → runtime-mRhSu-vJ.d.cts} +2 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -17053,7 +17053,7 @@ function augmentSignInEntriesWithReplication(input) {
|
|
|
17053
17053
|
}
|
|
17054
17054
|
eligiblePaths.push(path);
|
|
17055
17055
|
}
|
|
17056
|
-
if (eligiblePaths.length === replication.prefixes.length && eligiblePaths.length > 0 && hasUnrestrictedGetCoverage(input.entries, input.primarySpaceId, "")) {
|
|
17056
|
+
if (replication.syncScope !== "prefixes" && eligiblePaths.length === replication.prefixes.length && eligiblePaths.length > 0 && hasUnrestrictedGetCoverage(input.entries, input.primarySpaceId, "")) {
|
|
17057
17057
|
return [{
|
|
17058
17058
|
service: KV_SERVICE,
|
|
17059
17059
|
space: input.primarySpaceId,
|
|
@@ -17086,6 +17086,12 @@ var init_authority_sign_in = __esm({
|
|
|
17086
17086
|
|
|
17087
17087
|
// src/replication/config.ts
|
|
17088
17088
|
function assertValidReplicationConfig(replication) {
|
|
17089
|
+
if (replication?.syncScope !== void 0 && replication.syncScope !== "prefixes") {
|
|
17090
|
+
throw new TypeError('replication.syncScope must be "prefixes"');
|
|
17091
|
+
}
|
|
17092
|
+
if (replication?.contentFetch !== void 0 && replication.contentFetch !== "eager" && replication.contentFetch !== "lazy") {
|
|
17093
|
+
throw new TypeError('replication.contentFetch must be "eager" or "lazy"');
|
|
17094
|
+
}
|
|
17089
17095
|
if (replication === void 0 || !replication.enabled) return;
|
|
17090
17096
|
if (replication.storage === void 0 || replication.storage === null) {
|
|
17091
17097
|
throw new TypeError("replication.enabled requires replication.storage");
|
|
@@ -17140,6 +17146,7 @@ function resolvedOptions(options) {
|
|
|
17140
17146
|
maxStalenessMs: options.maxStalenessMs ?? 12e4,
|
|
17141
17147
|
staleSyncTimeoutMs: options.staleSyncTimeoutMs ?? 5e3,
|
|
17142
17148
|
allowSecrets: options.allowSecrets === true,
|
|
17149
|
+
contentFetch: options.contentFetch ?? "eager",
|
|
17143
17150
|
verify: options.verify === true
|
|
17144
17151
|
};
|
|
17145
17152
|
}
|
|
@@ -17411,6 +17418,7 @@ __export(authority_exports, {
|
|
|
17411
17418
|
assertValidReplicationConfig: () => assertValidReplicationConfig,
|
|
17412
17419
|
augmentSignInEntriesWithReplication: () => augmentSignInEntriesWithReplication,
|
|
17413
17420
|
createReplicationAuthority: () => createReplicationAuthority,
|
|
17421
|
+
eraseReplicaLocalCopy: () => eraseReplicaLocalCopy,
|
|
17414
17422
|
establishReplicaSessionStamp: () => establishReplicaSessionStamp,
|
|
17415
17423
|
hasUnrestrictedGetCoverage: () => hasUnrestrictedGetCoverage,
|
|
17416
17424
|
mintNodeReplicationGrant: () => mintNodeReplicationGrant,
|
|
@@ -17441,6 +17449,38 @@ function reportReplicaDenial(result, reason, onEvent, context) {
|
|
|
17441
17449
|
} catch {
|
|
17442
17450
|
}
|
|
17443
17451
|
}
|
|
17452
|
+
async function eraseReplicaLocalCopy(lifecycle, trigger, denyStatus, handlers) {
|
|
17453
|
+
if (lifecycle?.kind !== "indexeddb" || lifecycle.eraseLocalCopy === void 0) return void 0;
|
|
17454
|
+
let outcome = { status: "failed", code: "STORAGE_ERROR", marker: false };
|
|
17455
|
+
for (let attempt = 0; attempt <= ERASE_RETRY_DELAYS_MS.length; attempt++) {
|
|
17456
|
+
if (attempt > 0) await new Promise((resolve2) => setTimeout(resolve2, ERASE_RETRY_DELAYS_MS[attempt - 1]));
|
|
17457
|
+
try {
|
|
17458
|
+
outcome = await lifecycle.eraseLocalCopy({ signal: AbortSignal.timeout(ERASE_ATTEMPT_MS) });
|
|
17459
|
+
} catch {
|
|
17460
|
+
outcome = { status: "failed", code: "STORAGE_ERROR", marker: false };
|
|
17461
|
+
}
|
|
17462
|
+
if (outcome.status !== "failed") break;
|
|
17463
|
+
}
|
|
17464
|
+
const keysKept = denyStatus === "marker" || denyStatus === "unguarded";
|
|
17465
|
+
const purge = outcome.status === "erased" ? { ok: true } : { ok: false, retryNow: outcome.status === "failed" };
|
|
17466
|
+
if (outcome.status === "erased" || outcome.status === "refused" && !keysKept) return { outcome, purge };
|
|
17467
|
+
const logoutPending = outcome.status === "failed" && outcome.marker;
|
|
17468
|
+
const event = {
|
|
17469
|
+
type: "replica.purge.failed",
|
|
17470
|
+
trigger,
|
|
17471
|
+
reason: logoutPending ? "logout_pending" : "gate_unavailable",
|
|
17472
|
+
code: outcome.code,
|
|
17473
|
+
retryNow: outcome.status === "failed"
|
|
17474
|
+
};
|
|
17475
|
+
for (const handler of handlers) {
|
|
17476
|
+
try {
|
|
17477
|
+
handler(event);
|
|
17478
|
+
} catch (error) {
|
|
17479
|
+
console.error('Error in "replica.purge.failed" handler:', error);
|
|
17480
|
+
}
|
|
17481
|
+
}
|
|
17482
|
+
return logoutPending ? { outcome, purge, logoutPending } : { outcome, purge };
|
|
17483
|
+
}
|
|
17444
17484
|
function verifiedOwnerConsentAnchor(session, wasmBindings, exactVerifiedRecap2) {
|
|
17445
17485
|
if (typeof session.siwe !== "string" || typeof session.signature !== "string" || typeof session.address !== "string" || typeof session.chainId !== "number") return null;
|
|
17446
17486
|
try {
|
|
@@ -17699,7 +17739,7 @@ function createReplicationAuthority(host) {
|
|
|
17699
17739
|
};
|
|
17700
17740
|
return authority;
|
|
17701
17741
|
}
|
|
17702
|
-
var import_siwe3, import_sdk_core12, import_replica, parseUcanGrant, KV_GET2, KV_SYNC2, KV_SERVICE2, AUTHORITY_EXPIRY_MARGIN_MS;
|
|
17742
|
+
var import_siwe3, import_sdk_core12, import_replica, parseUcanGrant, ERASE_RETRY_DELAYS_MS, ERASE_ATTEMPT_MS, KV_GET2, KV_SYNC2, KV_SERVICE2, AUTHORITY_EXPIRY_MARGIN_MS;
|
|
17703
17743
|
var init_authority = __esm({
|
|
17704
17744
|
"src/replication/authority.ts"() {
|
|
17705
17745
|
"use strict";
|
|
@@ -17709,6 +17749,8 @@ var init_authority = __esm({
|
|
|
17709
17749
|
init_config();
|
|
17710
17750
|
init_authority_sign_in();
|
|
17711
17751
|
parseUcanGrant = import_replica.parseUcanGrant;
|
|
17752
|
+
ERASE_RETRY_DELAYS_MS = [150, 450];
|
|
17753
|
+
ERASE_ATTEMPT_MS = 3e3;
|
|
17712
17754
|
KV_GET2 = import_sdk_core12.KV.GET;
|
|
17713
17755
|
KV_SYNC2 = import_sdk_core12.KV.SYNC;
|
|
17714
17756
|
KV_SERVICE2 = "tinycloud.kv";
|
|
@@ -18786,13 +18828,42 @@ function getNodeReplicationLoaders() {
|
|
|
18786
18828
|
|
|
18787
18829
|
// src/TinyCloudNode.ts
|
|
18788
18830
|
var import_sdk_core10 = require("@tinycloud/sdk-core");
|
|
18789
|
-
var
|
|
18831
|
+
var import_sdk_services4 = require("@tinycloud/sdk-services");
|
|
18790
18832
|
var import_requestLog2 = require("@tinycloud/sdk-services/telemetry/requestLog");
|
|
18833
|
+
var import_resource2 = require("@tinycloud/sdk-services/encryption/resource");
|
|
18791
18834
|
|
|
18792
18835
|
// src/authorization/NodeUserAuthorization.ts
|
|
18793
18836
|
var import_node_crypto = require("crypto");
|
|
18794
18837
|
var import_siwe = require("siwe");
|
|
18795
18838
|
var import_sdk_core5 = require("@tinycloud/sdk-core");
|
|
18839
|
+
var import_resource = require("@tinycloud/sdk-services/encryption/resource");
|
|
18840
|
+
var import_sdk_services3 = require("@tinycloud/sdk-services");
|
|
18841
|
+
|
|
18842
|
+
// src/authorization/appKeyHostBinding.ts
|
|
18843
|
+
var DOMAIN_LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
18844
|
+
var IPV4 = /^\d+\.\d+\.\d+\.\d+$/;
|
|
18845
|
+
var APP_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
18846
|
+
function appKeyHostBinding(domain, appId) {
|
|
18847
|
+
if (!APP_ID.test(appId)) return false;
|
|
18848
|
+
if (domain.endsWith(":")) return false;
|
|
18849
|
+
let url;
|
|
18850
|
+
try {
|
|
18851
|
+
url = new URL(`https://${domain}`);
|
|
18852
|
+
} catch {
|
|
18853
|
+
return false;
|
|
18854
|
+
}
|
|
18855
|
+
if (url.protocol !== "https:" || url.port !== "" || url.username !== "" || url.password !== "") return false;
|
|
18856
|
+
if (url.pathname !== "/" || url.search !== "" || url.hash !== "") return false;
|
|
18857
|
+
const host = url.hostname;
|
|
18858
|
+
if (host.startsWith("[") || host.endsWith(".") || IPV4.test(host)) return false;
|
|
18859
|
+
const labels = host.split(".");
|
|
18860
|
+
if (labels.length < 2 || labels[labels.length - 1] === "localhost") return false;
|
|
18861
|
+
if (!labels.every((label) => DOMAIN_LABEL.test(label))) return false;
|
|
18862
|
+
const reversed = labels.reverse().join(".");
|
|
18863
|
+
return appId === reversed || appId.startsWith(`${reversed}.`);
|
|
18864
|
+
}
|
|
18865
|
+
|
|
18866
|
+
// src/authorization/NodeUserAuthorization.ts
|
|
18796
18867
|
init_authority_sign_in();
|
|
18797
18868
|
|
|
18798
18869
|
// src/authorization/caveatRefusal.ts
|
|
@@ -19304,6 +19375,23 @@ var NodeUserAuthorization = class {
|
|
|
19304
19375
|
);
|
|
19305
19376
|
return this._capabilityRequest;
|
|
19306
19377
|
}
|
|
19378
|
+
async refreshNamedKeyFeatureForSignIn(address, chainId) {
|
|
19379
|
+
const request = this.getCapabilityRequest();
|
|
19380
|
+
const siweDomain = this.siweConfig?.domain ?? this.domain;
|
|
19381
|
+
const hasNamedKeys = request?.manifests.some((manifest) => manifest.keys?.length && appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id));
|
|
19382
|
+
if (hasNamedKeys) {
|
|
19383
|
+
await this.resolveTinyCloudHostsForSignIn(address, chainId);
|
|
19384
|
+
await this.refreshNodeInfo();
|
|
19385
|
+
}
|
|
19386
|
+
}
|
|
19387
|
+
/** Manifest key paths that this sign-in cannot grant. */
|
|
19388
|
+
get unavailableKeyPaths() {
|
|
19389
|
+
const request = this.getCapabilityRequest();
|
|
19390
|
+
const siweDomain = this.siweConfig?.domain ?? this.domain;
|
|
19391
|
+
return (request?.manifests ?? []).flatMap(
|
|
19392
|
+
(manifest) => this._nodeFeatures.includes("encryption-named-keys-v1") && appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id) ? [] : (manifest.keys ?? []).map((entry) => "path" in entry ? entry.path : entry.prefix)
|
|
19393
|
+
);
|
|
19394
|
+
}
|
|
19307
19395
|
resolveSpaceName(space, address, chainId) {
|
|
19308
19396
|
if (space.startsWith("tinycloud:")) {
|
|
19309
19397
|
return space;
|
|
@@ -19495,15 +19583,31 @@ var NodeUserAuthorization = class {
|
|
|
19495
19583
|
}
|
|
19496
19584
|
const rawAbilities = {};
|
|
19497
19585
|
const currentDid = (0, import_sdk_core5.pkhDid)(address, chainId);
|
|
19586
|
+
if (this._nodeFeatures.includes("encryption-named-keys-v1")) {
|
|
19587
|
+
const siweDomain = this.siweConfig?.domain ?? this.domain;
|
|
19588
|
+
for (const manifest of request.manifests) {
|
|
19589
|
+
if (!appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id)) continue;
|
|
19590
|
+
for (const declaration of manifest.keys ?? []) {
|
|
19591
|
+
const path = "path" in declaration ? declaration.path : declaration.prefix;
|
|
19592
|
+
const resource = `urn:tinycloud:encryption:${currentDid}:default/${path}`;
|
|
19593
|
+
for (const ability of declaration.abilities) {
|
|
19594
|
+
addRawAbility(rawAbilities, resource, `tinycloud.encryption/${ability}`);
|
|
19595
|
+
}
|
|
19596
|
+
}
|
|
19597
|
+
}
|
|
19598
|
+
}
|
|
19498
19599
|
const spaceResources = request.resources.filter((entry) => {
|
|
19499
19600
|
if (entry.service !== import_sdk_core5.ENCRYPTION_PERMISSION_SERVICE) {
|
|
19500
19601
|
return true;
|
|
19501
19602
|
}
|
|
19603
|
+
const parsed = entry.path.includes("/") ? (0, import_resource.parseEncryptionResource)(entry.path) : { ...(0, import_sdk_services3.parseNetworkId)(entry.path), kind: "network" };
|
|
19604
|
+
if (parsed.kind !== "network") {
|
|
19605
|
+
throw new import_sdk_core5.ManifestValidationError("named keys go in manifest.keys");
|
|
19606
|
+
}
|
|
19502
19607
|
for (const action of entry.actions) {
|
|
19503
19608
|
addRawAbility(rawAbilities, entry.path, action);
|
|
19504
19609
|
}
|
|
19505
|
-
if (entry.actions.includes(DECRYPT_ACTION)) {
|
|
19506
|
-
const parsed = (0, import_sdk_core5.parseNetworkId)(entry.path);
|
|
19610
|
+
if (entry.actions.includes(DECRYPT_ACTION) && parsed.kind === "network") {
|
|
19507
19611
|
if (didPrincipalMatches(parsed.ownerDid, currentDid)) {
|
|
19508
19612
|
addRawAbility(rawAbilities, entry.path, NETWORK_CREATE_ACTION);
|
|
19509
19613
|
}
|
|
@@ -19899,6 +20003,8 @@ var NodeUserAuthorization = class {
|
|
|
19899
20003
|
this._chainId = chainId;
|
|
19900
20004
|
await this.resolveTinyCloudHostsForSignIn(address, chainId);
|
|
19901
20005
|
this.assertSignInCurrent(generation);
|
|
20006
|
+
await this.refreshNamedKeyFeatureForSignIn(address, chainId);
|
|
20007
|
+
this.assertSignInCurrent(generation);
|
|
19902
20008
|
const keyId = `session-${Date.now()}`;
|
|
19903
20009
|
this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
|
|
19904
20010
|
this.activeSessionKeyId = keyId;
|
|
@@ -20045,6 +20151,7 @@ var NodeUserAuthorization = class {
|
|
|
20045
20151
|
refuseCaveated(this.getCapabilityRequest()?.manifests);
|
|
20046
20152
|
const address = (0, import_sdk_core5.canonicalizeAddress)(await this.signer.getAddress());
|
|
20047
20153
|
const chainId = await this.signer.getChainId();
|
|
20154
|
+
await this.refreshNamedKeyFeatureForSignIn(address, chainId);
|
|
20048
20155
|
const keyId = `session-${Date.now()}`;
|
|
20049
20156
|
this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
|
|
20050
20157
|
this.activeSessionKeyId = keyId;
|
|
@@ -21098,6 +21205,7 @@ var ROOT_DELEGATION_ACTIONS = [
|
|
|
21098
21205
|
import_sdk_core10.DUCKDB.ALL
|
|
21099
21206
|
];
|
|
21100
21207
|
var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core10.EXPIRY.SESSION_MS;
|
|
21208
|
+
var OWNER_REVOCATION_WINDOW_MS = 10 * 6e4;
|
|
21101
21209
|
function unifiedRootAttenuation(capabilities) {
|
|
21102
21210
|
const attenuation = {};
|
|
21103
21211
|
for (const capability of capabilities) {
|
|
@@ -21562,6 +21670,7 @@ function replicaRestoreRefusal(error) {
|
|
|
21562
21670
|
case "purge_pending":
|
|
21563
21671
|
case "logout_pending":
|
|
21564
21672
|
case "gate_unavailable":
|
|
21673
|
+
case "wallet_provider_required":
|
|
21565
21674
|
return error.gate;
|
|
21566
21675
|
}
|
|
21567
21676
|
}
|
|
@@ -21596,6 +21705,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21596
21705
|
this.auth = null;
|
|
21597
21706
|
this.tc = null;
|
|
21598
21707
|
this._chainId = 1;
|
|
21708
|
+
this.replicaPurgeFailedHandlers = /* @__PURE__ */ new Set();
|
|
21599
21709
|
/** Mints the replica session stamp on each fresh sign-in (TC-858 §4.1). Undefined when replication is off. */
|
|
21600
21710
|
this.establishReplicaStamp = async (session) => {
|
|
21601
21711
|
const replication = this.config.replication;
|
|
@@ -21627,6 +21737,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21627
21737
|
return void 0;
|
|
21628
21738
|
}
|
|
21629
21739
|
};
|
|
21740
|
+
this._keysUnavailable = [];
|
|
21630
21741
|
this._baseVaults = /* @__PURE__ */ new Map();
|
|
21631
21742
|
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
21632
21743
|
this._secrets = /* @__PURE__ */ new Map();
|
|
@@ -21802,6 +21913,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21802
21913
|
return instance ? instance.control.purge(input) : runtime.then((ready) => ready.control.purge(input));
|
|
21803
21914
|
},
|
|
21804
21915
|
clearPending: async () => (await runtime).control.clearPending(),
|
|
21916
|
+
purgeLocalCopy: async () => (await this.eraseReplicaLocalCopy("purge_local_copy"))?.purge ?? { ok: false, retryNow: false },
|
|
21805
21917
|
close: async () => (await runtime).control.close()
|
|
21806
21918
|
};
|
|
21807
21919
|
}
|
|
@@ -21856,18 +21968,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21856
21968
|
get freshEncryptionNetworkCreated() {
|
|
21857
21969
|
return this._freshEncryptionNetworkCreated;
|
|
21858
21970
|
}
|
|
21859
|
-
/**
|
|
21860
|
-
* Subscribe to `storage.full`. It fires on the first write any service had
|
|
21861
|
-
* rejected because the owner's TinyCloud storage is full
|
|
21862
|
-
* (`STORAGE_QUOTA_EXCEEDED` or `STORAGE_LIMIT_REACHED`), so an app can show
|
|
21863
|
-
* one read-only banner. Reads keep working. For the signed-in account's own
|
|
21864
|
-
* storage it fires once per episode: the episode ends only when a write to
|
|
21865
|
-
* that storage succeeds, or on sign-out. A `storage.status()` read does not
|
|
21866
|
-
* end it. A rejection on another owner's delegated space fires once per
|
|
21867
|
-
* owner, until that owner's `storage.status()` reports space again. Returns
|
|
21868
|
-
* the unsubscribe function.
|
|
21869
|
-
*/
|
|
21870
21971
|
on(event, handler) {
|
|
21972
|
+
if (event === "replica.purge.failed") {
|
|
21973
|
+
const listener = handler;
|
|
21974
|
+
this.replicaPurgeFailedHandlers.add(listener);
|
|
21975
|
+
return () => {
|
|
21976
|
+
this.replicaPurgeFailedHandlers.delete(listener);
|
|
21977
|
+
};
|
|
21978
|
+
}
|
|
21871
21979
|
if (event !== "storage.full") {
|
|
21872
21980
|
throw new Error(`Unknown TinyCloud event: ${String(event)}`);
|
|
21873
21981
|
}
|
|
@@ -22087,7 +22195,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22087
22195
|
replication: config.replication?.enabled === true ? {
|
|
22088
22196
|
enabled: true,
|
|
22089
22197
|
prefixes: config.replication.prefixes,
|
|
22090
|
-
allowSecrets: config.replication.allowSecrets === true
|
|
22198
|
+
allowSecrets: config.replication.allowSecrets === true,
|
|
22199
|
+
syncScope: config.replication.syncScope
|
|
22091
22200
|
} : void 0
|
|
22092
22201
|
});
|
|
22093
22202
|
this.tc = new import_sdk_core10.TinyCloud(this.auth, {
|
|
@@ -22347,6 +22456,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22347
22456
|
const leavingAuth = this.auth;
|
|
22348
22457
|
const leavingContext = this._serviceContext;
|
|
22349
22458
|
let denied;
|
|
22459
|
+
let erased;
|
|
22350
22460
|
try {
|
|
22351
22461
|
this.teardownSession();
|
|
22352
22462
|
} finally {
|
|
@@ -22357,6 +22467,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22357
22467
|
try {
|
|
22358
22468
|
await this.accountRegistryTail;
|
|
22359
22469
|
await this.quiesceReplicaRuntime();
|
|
22470
|
+
if (denied) erased = await this.eraseReplicaLocalCopy("sign_out", denied.status);
|
|
22360
22471
|
} finally {
|
|
22361
22472
|
if (leavingAddress) {
|
|
22362
22473
|
await (leavingAuth ? leavingAuth.clearPersistedSession(leavingAddress) : this.config.sessionStorage?.clear(leavingAddress));
|
|
@@ -22364,8 +22475,37 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22364
22475
|
}
|
|
22365
22476
|
}
|
|
22366
22477
|
}
|
|
22367
|
-
if (denied?.status === "unguarded") {
|
|
22368
|
-
throw
|
|
22478
|
+
if (denied?.status === "unguarded" && erased?.outcome.status !== "erased") {
|
|
22479
|
+
throw Object.assign(
|
|
22480
|
+
new Error(`Replica gate was not denied (${denied.code ?? "unknown"}); the replica may still be restorable.`),
|
|
22481
|
+
{
|
|
22482
|
+
code: "REPLICA_PURGE_FAILED",
|
|
22483
|
+
reason: "gate_unavailable",
|
|
22484
|
+
retryNow: erased?.outcome.status === "failed"
|
|
22485
|
+
}
|
|
22486
|
+
);
|
|
22487
|
+
}
|
|
22488
|
+
}
|
|
22489
|
+
/**
|
|
22490
|
+
* Erases the browser local copy after a deny (retry, event and next-load marker live in the lazy
|
|
22491
|
+
* replication authority). Never rejects; `undefined` when replication is off or the storage keeps
|
|
22492
|
+
* no browser database.
|
|
22493
|
+
*/
|
|
22494
|
+
async eraseReplicaLocalCopy(trigger, denyStatus) {
|
|
22495
|
+
const replication = this.config.replication;
|
|
22496
|
+
if (!replication?.enabled) return void 0;
|
|
22497
|
+
try {
|
|
22498
|
+
const { eraseReplicaLocalCopy: eraseReplicaLocalCopy2 } = await getNodeReplicationLoaders().authority();
|
|
22499
|
+
const erased = await eraseReplicaLocalCopy2(
|
|
22500
|
+
replication.storage.lifecycle,
|
|
22501
|
+
trigger,
|
|
22502
|
+
denyStatus,
|
|
22503
|
+
this.replicaPurgeFailedHandlers
|
|
22504
|
+
);
|
|
22505
|
+
if (erased?.logoutPending) this.replicaRestoreGate = "logout_pending";
|
|
22506
|
+
return erased;
|
|
22507
|
+
} catch {
|
|
22508
|
+
return void 0;
|
|
22369
22509
|
}
|
|
22370
22510
|
}
|
|
22371
22511
|
/**
|
|
@@ -22425,6 +22565,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22425
22565
|
this._hooks = void 0;
|
|
22426
22566
|
this._vault = void 0;
|
|
22427
22567
|
this._encryption = void 0;
|
|
22568
|
+
this._namedKeyClient = void 0;
|
|
22569
|
+
this._keysUnavailable = [];
|
|
22428
22570
|
this._baseVaults.clear();
|
|
22429
22571
|
this._baseSecrets.clear();
|
|
22430
22572
|
this._secrets.clear();
|
|
@@ -22529,6 +22671,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22529
22671
|
const priorPrincipal = this.replicaSessionPrincipal ?? (this.address ? (0, import_sdk_core10.pkhDid)(this.address, this._chainId) : void 0);
|
|
22530
22672
|
if (this.config.replication?.enabled && priorPrincipal && priorPrincipal !== nextPrincipal) {
|
|
22531
22673
|
const denial = await this.denyReplicaGate({ reason: "account_switch", principal: priorPrincipal, next: nextPrincipal });
|
|
22674
|
+
if (denial) {
|
|
22675
|
+
await this.quiesceReplicaRuntime();
|
|
22676
|
+
await this.eraseReplicaLocalCopy("account_switch", denial.status);
|
|
22677
|
+
}
|
|
22532
22678
|
this.replicaRestoreGate = denial?.status === "unguarded" ? "gate_unavailable" : "stamp_stale";
|
|
22533
22679
|
}
|
|
22534
22680
|
if (address !== this._address || chainId !== this._chainId) {
|
|
@@ -22543,6 +22689,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22543
22689
|
this._hooks = void 0;
|
|
22544
22690
|
this._vault = void 0;
|
|
22545
22691
|
this._encryption = void 0;
|
|
22692
|
+
this._namedKeyClient = void 0;
|
|
22693
|
+
this._keysUnavailable = [];
|
|
22546
22694
|
this._baseVaults.clear();
|
|
22547
22695
|
this._baseSecrets.clear();
|
|
22548
22696
|
this._secrets.clear();
|
|
@@ -22595,6 +22743,26 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22595
22743
|
this.assertSessionEpoch(epoch, "Sign-in");
|
|
22596
22744
|
await this.ensureRequestedEncryptionNetworks();
|
|
22597
22745
|
this.assertSessionEpoch(epoch, "Sign-in");
|
|
22746
|
+
this._keysUnavailable = this.auth?.unavailableKeyPaths ?? [];
|
|
22747
|
+
if (this._keysUnavailable.length > 0) {
|
|
22748
|
+
this.notificationHandler.warning(`Named keys unavailable: ${this._keysUnavailable.join(", ")}`);
|
|
22749
|
+
}
|
|
22750
|
+
if (this.nodeFeatures.includes("encryption-named-keys-v1")) {
|
|
22751
|
+
for (const manifest of this.auth?.capabilityRequest?.manifests ?? []) {
|
|
22752
|
+
for (const declaration of manifest.keys ?? []) {
|
|
22753
|
+
if ("path" in declaration && declaration.abilities.includes("key.create") && !this._keysUnavailable.includes(declaration.path)) {
|
|
22754
|
+
try {
|
|
22755
|
+
await this.keys.ensureKey(declaration.path);
|
|
22756
|
+
} catch (error) {
|
|
22757
|
+
this._keysUnavailable.push(declaration.path);
|
|
22758
|
+
const code = error && typeof error === "object" && "code" in error && typeof error.code === "string" && /^[A-Z_]+$/.test(error.code) ? error.code : "UNKNOWN";
|
|
22759
|
+
this.notificationHandler.warning(`Named key unavailable: ${declaration.path} (${code})`);
|
|
22760
|
+
}
|
|
22761
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
22762
|
+
}
|
|
22763
|
+
}
|
|
22764
|
+
}
|
|
22765
|
+
}
|
|
22598
22766
|
if (!bootstrapped && this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
|
|
22599
22767
|
await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core10.SECRETS_SPACE));
|
|
22600
22768
|
}
|
|
@@ -23171,7 +23339,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
23171
23339
|
if (!this.currentSessionCoversAccountRegistry()) {
|
|
23172
23340
|
if (!_TinyCloudNode.accountRegistrySkipLogged) {
|
|
23173
23341
|
_TinyCloudNode.accountRegistrySkipLogged = true;
|
|
23174
|
-
|
|
23342
|
+
import_sdk_services4.tinyCloudDebugLogger.log("registry.skip");
|
|
23175
23343
|
}
|
|
23176
23344
|
return;
|
|
23177
23345
|
}
|
|
@@ -23382,7 +23550,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
23382
23550
|
const networkIds = /* @__PURE__ */ new Set();
|
|
23383
23551
|
for (const resource of request.resources) {
|
|
23384
23552
|
if (resource.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
|
|
23385
|
-
|
|
23553
|
+
const parsed = resource.path.includes("/") ? (0, import_resource2.parseEncryptionResource)(resource.path) : { ...(0, import_sdk_core10.parseNetworkId)(resource.path), kind: "network" };
|
|
23554
|
+
if (parsed.kind === "network") networkIds.add(resource.path);
|
|
23386
23555
|
}
|
|
23387
23556
|
}
|
|
23388
23557
|
return [...networkIds];
|
|
@@ -23932,6 +24101,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
23932
24101
|
this._hooks = stagedGraph.hooks;
|
|
23933
24102
|
this._vault = stagedGraph.vault;
|
|
23934
24103
|
this._encryption = stagedGraph.encryption;
|
|
24104
|
+
this._namedKeyClient = void 0;
|
|
24105
|
+
this._keysUnavailable = [];
|
|
23935
24106
|
this._capabilityRegistry = stagedGraph.capabilityRegistry;
|
|
23936
24107
|
this._keyProvider = stagedGraph.keyProvider;
|
|
23937
24108
|
this._sharingService = stagedGraph.sharingService;
|
|
@@ -24509,7 +24680,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24509
24680
|
replication: this.config.replication?.enabled === true ? {
|
|
24510
24681
|
enabled: true,
|
|
24511
24682
|
prefixes: this.config.replication.prefixes,
|
|
24512
|
-
allowSecrets: this.config.replication.allowSecrets === true
|
|
24683
|
+
allowSecrets: this.config.replication.allowSecrets === true,
|
|
24684
|
+
syncScope: this.config.replication.syncScope
|
|
24513
24685
|
} : void 0
|
|
24514
24686
|
});
|
|
24515
24687
|
this.tc = new import_sdk_core10.TinyCloud(this.auth, {
|
|
@@ -24571,7 +24743,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24571
24743
|
replication: this.config.replication?.enabled === true ? {
|
|
24572
24744
|
enabled: true,
|
|
24573
24745
|
prefixes: this.config.replication.prefixes,
|
|
24574
|
-
allowSecrets: this.config.replication.allowSecrets === true
|
|
24746
|
+
allowSecrets: this.config.replication.allowSecrets === true,
|
|
24747
|
+
syncScope: this.config.replication.syncScope
|
|
24575
24748
|
} : void 0
|
|
24576
24749
|
});
|
|
24577
24750
|
this.tc = new import_sdk_core10.TinyCloud(this.auth, {
|
|
@@ -24839,7 +25012,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
24839
25012
|
);
|
|
24840
25013
|
graph.assertActive();
|
|
24841
25014
|
if (!response.ok) {
|
|
24842
|
-
const permissionHint = response.status === 401 || response.status === 403 ? (0,
|
|
25015
|
+
const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services4.parsePermissionHint)({
|
|
24843
25016
|
service: "tinycloud.encryption",
|
|
24844
25017
|
path: networkId,
|
|
24845
25018
|
actions: ["tinycloud.encryption/decrypt"]
|
|
@@ -25283,7 +25456,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
25283
25456
|
* Sign a wallet (CACAO) revocation of the delegation `cid` for the node's
|
|
25284
25457
|
* `POST /revoke`, and return its Authorization header value. The node
|
|
25285
25458
|
* accepts it when the owner delegated `cid` or owns a space its abilities
|
|
25286
|
-
* target, whichever key issued it. Valid for
|
|
25459
|
+
* target, whichever key issued it. Valid for 10 minutes. Requires the
|
|
25287
25460
|
* owner wallet signer.
|
|
25288
25461
|
*/
|
|
25289
25462
|
async signOwnerRevocation(cid) {
|
|
@@ -25299,7 +25472,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
25299
25472
|
chainId: session.chainId,
|
|
25300
25473
|
nonce: (0, import_siwe2.generateNonce)(),
|
|
25301
25474
|
issuedAt: issuedAt.toISOString(),
|
|
25302
|
-
expirationTime: new Date(issuedAt.getTime() +
|
|
25475
|
+
expirationTime: new Date(issuedAt.getTime() + OWNER_REVOCATION_WINDOW_MS).toISOString()
|
|
25303
25476
|
}).prepareMessage();
|
|
25304
25477
|
const signature2 = await this.signer.signMessage(siwe);
|
|
25305
25478
|
return this.wasmBindings.siweToDelegationHeaders({ siwe, signature: signature2 }).Authorization;
|
|
@@ -25526,6 +25699,40 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
25526
25699
|
get encryption() {
|
|
25527
25700
|
return this.getEncryptionService();
|
|
25528
25701
|
}
|
|
25702
|
+
/** Named keys bound to the current session. */
|
|
25703
|
+
get keys() {
|
|
25704
|
+
return new Proxy({}, {
|
|
25705
|
+
get: (_target, property) => {
|
|
25706
|
+
if (property === "refreshNodeInfo") {
|
|
25707
|
+
return () => {
|
|
25708
|
+
void this._namedKeyClient?.then((client) => client.refreshNodeInfo());
|
|
25709
|
+
};
|
|
25710
|
+
}
|
|
25711
|
+
if (typeof property !== "string" || ![
|
|
25712
|
+
"getPublicKey",
|
|
25713
|
+
"describeKey",
|
|
25714
|
+
"createKey",
|
|
25715
|
+
"blockKey",
|
|
25716
|
+
"unblockKey",
|
|
25717
|
+
"ensureKey",
|
|
25718
|
+
"encrypt",
|
|
25719
|
+
"decrypt",
|
|
25720
|
+
"decryptMany"
|
|
25721
|
+
].includes(property)) return void 0;
|
|
25722
|
+
return (...args) => {
|
|
25723
|
+
this._namedKeyClient ?? (this._namedKeyClient = import("./encryption-keys.cjs").then(({ createNamedKeyClient }) => createNamedKeyClient(this)));
|
|
25724
|
+
return this._namedKeyClient.then((client) => {
|
|
25725
|
+
const method = client[property];
|
|
25726
|
+
return method.apply(client, args);
|
|
25727
|
+
});
|
|
25728
|
+
};
|
|
25729
|
+
}
|
|
25730
|
+
});
|
|
25731
|
+
}
|
|
25732
|
+
/** Manifest key paths unavailable during the latest `signIn()` attempt. */
|
|
25733
|
+
get keysUnavailable() {
|
|
25734
|
+
return this._keysUnavailable;
|
|
25735
|
+
}
|
|
25529
25736
|
async getEncryptionNetwork(nameOrNetworkId = this.getDefaultEncryptionNetworkId()) {
|
|
25530
25737
|
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
25531
25738
|
return this.fetchEncryptionNetworkAt(
|
|
@@ -25653,7 +25860,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
25653
25860
|
);
|
|
25654
25861
|
if (result.status !== "ok") {
|
|
25655
25862
|
if (result.status === "permission_required") {
|
|
25656
|
-
const hint = (0,
|
|
25863
|
+
const hint = (0, import_sdk_services4.parsePermissionHint)(result.hint);
|
|
25657
25864
|
if (hint === void 0) return { status: "read_failed" };
|
|
25658
25865
|
return {
|
|
25659
25866
|
status: "permission_required",
|
|
@@ -27998,7 +28205,7 @@ var import_node_fs = require("fs");
|
|
|
27998
28205
|
var import_promises = require("fs/promises");
|
|
27999
28206
|
var import_node_path = require("path");
|
|
28000
28207
|
var import_sdk_core14 = require("@tinycloud/sdk-core");
|
|
28001
|
-
var
|
|
28208
|
+
var import_sdk_services5 = require("@tinycloud/sdk-services");
|
|
28002
28209
|
var import_contractConstants = require("@tinycloud/sdk-services/kv/replication/contractConstants");
|
|
28003
28210
|
init_authority();
|
|
28004
28211
|
var REPLICA_LOGOUT_PENDING_FILE = "replica-logout-pending.json";
|
|
@@ -28560,7 +28767,7 @@ function sha256Base32(material) {
|
|
|
28560
28767
|
return out.slice(0, 26);
|
|
28561
28768
|
}
|
|
28562
28769
|
function partitionDirOf(root, identity) {
|
|
28563
|
-
return (0, import_node_path.join)(root, sha256Base32((0,
|
|
28770
|
+
return (0, import_node_path.join)(root, sha256Base32((0, import_sdk_services5.replicationIdentityKey)(identity)));
|
|
28564
28771
|
}
|
|
28565
28772
|
function replicaHashOf(prefix, deviceDid) {
|
|
28566
28773
|
return sha256Base32(`${prefix}
|
|
@@ -28634,8 +28841,8 @@ function deviceRecordOf(value) {
|
|
|
28634
28841
|
}
|
|
28635
28842
|
function sameIdentity(a, b) {
|
|
28636
28843
|
try {
|
|
28637
|
-
const left = (0,
|
|
28638
|
-
const right = (0,
|
|
28844
|
+
const left = (0, import_sdk_services5.canonicalReplicationIdentity)(a);
|
|
28845
|
+
const right = (0, import_sdk_services5.canonicalReplicationIdentity)(b);
|
|
28639
28846
|
return left.host === right.host && left.space === right.space && left.principal === right.principal;
|
|
28640
28847
|
} catch {
|
|
28641
28848
|
return false;
|
|
@@ -28651,7 +28858,7 @@ async function ensurePartitionIdentity(dir, identity, dirSync) {
|
|
|
28651
28858
|
const file = (0, import_node_path.join)(dir, "identity.json");
|
|
28652
28859
|
const existing = await readJsonFile(file);
|
|
28653
28860
|
if (existing === void 0) {
|
|
28654
|
-
await writeJsonAtomic(file, { v: 1, ...(0,
|
|
28861
|
+
await writeJsonAtomic(file, { v: 1, ...(0, import_sdk_services5.canonicalReplicationIdentity)(identity) }, dirSync);
|
|
28655
28862
|
return;
|
|
28656
28863
|
}
|
|
28657
28864
|
const record = identityRecordOf(existing);
|
|
@@ -28750,7 +28957,7 @@ withGate_fn = async function(section) {
|
|
|
28750
28957
|
if (snapshot === void 0) throw gated("gate_unavailable");
|
|
28751
28958
|
const [principalHash, identityKeyHash] = await Promise.all([
|
|
28752
28959
|
gate.principalHashOf(snapshot.salt, this.identity.principal),
|
|
28753
|
-
gate.identityHashOf(snapshot.salt, (0,
|
|
28960
|
+
gate.identityHashOf(snapshot.salt, (0, import_sdk_services5.replicationIdentityKey)(this.identity))
|
|
28754
28961
|
]);
|
|
28755
28962
|
const access = {
|
|
28756
28963
|
stamp: __privateGet(this, _stamp),
|
|
@@ -29021,7 +29228,8 @@ var SqliteReplicaHandle = class {
|
|
|
29021
29228
|
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
29022
29229
|
const engine = new (__privateGet(this, _replica)).Replica({
|
|
29023
29230
|
store: __privateGet(this, _store),
|
|
29024
|
-
transportFor
|
|
29231
|
+
transportFor,
|
|
29232
|
+
...this.spec.contentFetch === void 0 ? {} : { contentFetch: this.spec.contentFetch }
|
|
29025
29233
|
});
|
|
29026
29234
|
const running = engine.sync({ signal: abort.signal });
|
|
29027
29235
|
const registration = { promise: running, abort: () => abort.abort() };
|
|
@@ -29250,7 +29458,7 @@ function createSqliteReplicaStorage(options) {
|
|
|
29250
29458
|
if (snapshot === void 0) throw gated("gate_unavailable");
|
|
29251
29459
|
const [principalHash, identityKeyHash] = await Promise.all([
|
|
29252
29460
|
gate.principalHashOf(snapshot.salt, principal),
|
|
29253
|
-
identity === void 0 ? Promise.resolve(void 0) : gate.identityHashOf(snapshot.salt, (0,
|
|
29461
|
+
identity === void 0 ? Promise.resolve(void 0) : gate.identityHashOf(snapshot.salt, (0, import_sdk_services5.replicationIdentityKey)(identity))
|
|
29254
29462
|
]);
|
|
29255
29463
|
return profileSection(async () => {
|
|
29256
29464
|
assertLogoutClear(options.logoutPendingFile);
|
|
@@ -29273,7 +29481,7 @@ function createSqliteReplicaStorage(options) {
|
|
|
29273
29481
|
if (snapshot === void 0) throw gated("gate_unavailable");
|
|
29274
29482
|
const [principalHash, identityKeyHash] = await Promise.all([
|
|
29275
29483
|
gate.principalHashOf(snapshot.salt, spec.identity.principal),
|
|
29276
|
-
gate.identityHashOf(snapshot.salt, (0,
|
|
29484
|
+
gate.identityHashOf(snapshot.salt, (0, import_sdk_services5.replicationIdentityKey)(spec.identity))
|
|
29277
29485
|
]);
|
|
29278
29486
|
const access = {
|
|
29279
29487
|
stamp: spec.stamp,
|
|
@@ -29357,7 +29565,7 @@ function createSqliteReplicaStorage(options) {
|
|
|
29357
29565
|
const identity = identityRecordOf(await readJsonFile((0, import_node_path.join)(idDir, "identity.json")));
|
|
29358
29566
|
if (identity === void 0) throw new ReplicaStorageError("STORAGE_ERROR", `Missing identity at ${idDir}.`);
|
|
29359
29567
|
if (await gate.principalHashOf(salt, identity.principal) !== principalHash) continue;
|
|
29360
|
-
const identityKeyHash = await gate.identityHashOf(salt, (0,
|
|
29568
|
+
const identityKeyHash = await gate.identityHashOf(salt, (0, import_sdk_services5.replicationIdentityKey)(identity));
|
|
29361
29569
|
const recordedAt = Date.now();
|
|
29362
29570
|
if (await pathExists((0, import_node_path.join)(idDir, "pending.json")) || await pathExists((0, import_node_path.join)(idDir, "device.jwk"))) {
|
|
29363
29571
|
intents.push({ id: `pending:${identityKeyHash}`, kind: "pending", identityKeyHash, principalHash, recordedAt });
|
|
@@ -30035,7 +30243,7 @@ function createSqliteReplicaStorage(options) {
|
|
|
30035
30243
|
for (const dir of await identityDirs()) {
|
|
30036
30244
|
const identity = identityRecordOf(await readJsonFile((0, import_node_path.join)(dir, "identity.json")));
|
|
30037
30245
|
if (identity === void 0) throw new ReplicaStorageError("STORAGE_ERROR", `Missing identity at ${dir}.`);
|
|
30038
|
-
const hash3 = await gate.identityHashOf(state.salt, (0,
|
|
30246
|
+
const hash3 = await gate.identityHashOf(state.salt, (0, import_sdk_services5.replicationIdentityKey)(identity));
|
|
30039
30247
|
if (intent.kind === "pending" ? hash3 === intent.identityKeyHash : intent.partitionId.startsWith(`${hash3}:`)) {
|
|
30040
30248
|
idDir = dir;
|
|
30041
30249
|
break;
|
|
@@ -30181,7 +30389,7 @@ function createSqliteReplicaStorage(options) {
|
|
|
30181
30389
|
const gate = await fileGate();
|
|
30182
30390
|
const snapshot = await gate.readGateSnapshot(profileDir);
|
|
30183
30391
|
if (snapshot === void 0) throw gated("gate_unavailable");
|
|
30184
|
-
const identityKeyHash = await gate.identityHashOf(snapshot.salt, (0,
|
|
30392
|
+
const identityKeyHash = await gate.identityHashOf(snapshot.salt, (0, import_sdk_services5.replicationIdentityKey)(spec.identity));
|
|
30185
30393
|
const resolvePolicy = async (at, recordFirst) => {
|
|
30186
30394
|
const policy = spec.grantPolicy;
|
|
30187
30395
|
if (!Number.isSafeInteger(policy.grantTtlMs) || policy.grantTtlMs <= 0 || policy.grantTtlMs > import_contractConstants.MAX_GRANT_TTL_MS) {
|
|
@@ -30203,7 +30411,7 @@ function createSqliteReplicaStorage(options) {
|
|
|
30203
30411
|
let partitionId;
|
|
30204
30412
|
const storeGuard = (section) => guarded(spec.identity.principal, spec.stamp, spec.identity, partitionId, section);
|
|
30205
30413
|
return guarded(spec.identity.principal, spec.stamp, spec.identity, void 0, async () => {
|
|
30206
|
-
if ((0,
|
|
30414
|
+
if ((0, import_sdk_services5.requiresSecretsOptIn)(spec.space, spec.prefix) && spec.allowSecrets !== true) {
|
|
30207
30415
|
throw new replica.ReplicaError(
|
|
30208
30416
|
replica.ReplicaErrorCode.SECRETS_OPT_IN_REQUIRED,
|
|
30209
30417
|
`Replicating ${spec.space}/kv/${spec.prefix} copies secret material to disk; pass allowSecrets to opt in.`
|
|
@@ -30449,7 +30657,7 @@ function createSqliteReplicaStorage(options) {
|
|
|
30449
30657
|
const gate = await fileGate();
|
|
30450
30658
|
const currentGate = await gate.readGateSnapshot(profileDir);
|
|
30451
30659
|
if (currentGate !== void 0 && currentGate.principalHash !== null && currentGate.principalHash === await gate.principalHashOf(currentGate.salt, target.identity.principal)) {
|
|
30452
|
-
const identityKeyHash = await gate.identityHashOf(currentGate.salt, (0,
|
|
30660
|
+
const identityKeyHash = await gate.identityHashOf(currentGate.salt, (0, import_sdk_services5.replicationIdentityKey)(target.identity));
|
|
30453
30661
|
await retainGrantInstalls(gate, currentGate, identityKeyHash, store);
|
|
30454
30662
|
}
|
|
30455
30663
|
if (state.revoked === null) {
|