@tinycloud/node-sdk 3.8.0-beta.1 → 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-Ckqu_fqH.d.ts → TinyCloudNode-DnD-SH6t.d.ts} +26 -3
- package/dist/{TinyCloudNode-DDfx8Fx5.d.cts → TinyCloudNode-Dy65bxqs.d.cts} +26 -3
- package/dist/{authority-DcyJpajL.d.ts → authority-BQnTX3fI.d.ts} +20 -4
- package/dist/{authority-BwM_s3Ya.d.cts → authority-Rbye1U4o.d.cts} +20 -4
- package/dist/core.cjs +189 -25
- 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 +183 -21
- 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 +239 -37
- 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 +226 -24
- package/dist/index.js.map +1 -1
- package/dist/replication/authority.cjs +39 -0
- 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 +38 -0
- 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/core.cjs
CHANGED
|
@@ -58,6 +58,7 @@ __export(core_exports, {
|
|
|
58
58
|
PermissionNotInManifestError: () => import_sdk_core14.PermissionNotInManifestError,
|
|
59
59
|
PrefixedKVService: () => import_sdk_core15.PrefixedKVService,
|
|
60
60
|
ProtocolMismatchError: () => import_sdk_core22.ProtocolMismatchError,
|
|
61
|
+
RuntimeDelegationRejectedError: () => RuntimeDelegationRejectedError,
|
|
61
62
|
SECRET_NAME_RE: () => import_sdk_core18.SECRET_NAME_RE,
|
|
62
63
|
SQLAction: () => import_sdk_core16.SQLAction,
|
|
63
64
|
SQLService: () => import_sdk_core16.SQLService,
|
|
@@ -80,6 +81,7 @@ __export(core_exports, {
|
|
|
80
81
|
VersionCheckError: () => import_sdk_core22.VersionCheckError,
|
|
81
82
|
WasmKeyProvider: () => WasmKeyProvider,
|
|
82
83
|
activateCompactRuntimeDelegation: () => activateCompactRuntimeDelegation,
|
|
84
|
+
activateValidatedRuntimeDelegation: () => activateValidatedRuntimeDelegation,
|
|
83
85
|
addressStorageKey: () => import_sdk_core13.addressStorageKey,
|
|
84
86
|
buildSpaceUri: () => import_sdk_core21.buildSpaceUri,
|
|
85
87
|
canonicalizeAddress: () => import_sdk_core13.canonicalizeAddress,
|
|
@@ -345,6 +347,32 @@ var FileSessionStorage = class {
|
|
|
345
347
|
var import_node_crypto = require("crypto");
|
|
346
348
|
var import_siwe = require("siwe");
|
|
347
349
|
var import_sdk_core5 = require("@tinycloud/sdk-core");
|
|
350
|
+
var import_resource = require("@tinycloud/sdk-services/encryption/resource");
|
|
351
|
+
var import_sdk_services2 = require("@tinycloud/sdk-services");
|
|
352
|
+
|
|
353
|
+
// src/authorization/appKeyHostBinding.ts
|
|
354
|
+
var DOMAIN_LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
355
|
+
var IPV4 = /^\d+\.\d+\.\d+\.\d+$/;
|
|
356
|
+
var APP_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
357
|
+
function appKeyHostBinding(domain, appId) {
|
|
358
|
+
if (!APP_ID.test(appId)) return false;
|
|
359
|
+
if (domain.endsWith(":")) return false;
|
|
360
|
+
let url;
|
|
361
|
+
try {
|
|
362
|
+
url = new URL(`https://${domain}`);
|
|
363
|
+
} catch {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
if (url.protocol !== "https:" || url.port !== "" || url.username !== "" || url.password !== "") return false;
|
|
367
|
+
if (url.pathname !== "/" || url.search !== "" || url.hash !== "") return false;
|
|
368
|
+
const host = url.hostname;
|
|
369
|
+
if (host.startsWith("[") || host.endsWith(".") || IPV4.test(host)) return false;
|
|
370
|
+
const labels = host.split(".");
|
|
371
|
+
if (labels.length < 2 || labels[labels.length - 1] === "localhost") return false;
|
|
372
|
+
if (!labels.every((label) => DOMAIN_LABEL.test(label))) return false;
|
|
373
|
+
const reversed = labels.reverse().join(".");
|
|
374
|
+
return appId === reversed || appId.startsWith(`${reversed}.`);
|
|
375
|
+
}
|
|
348
376
|
|
|
349
377
|
// src/replication/authority-sign-in.ts
|
|
350
378
|
var import_sdk_core2 = require("@tinycloud/sdk-core");
|
|
@@ -832,6 +860,23 @@ var NodeUserAuthorization = class {
|
|
|
832
860
|
);
|
|
833
861
|
return this._capabilityRequest;
|
|
834
862
|
}
|
|
863
|
+
async refreshNamedKeyFeatureForSignIn(address, chainId) {
|
|
864
|
+
const request = this.getCapabilityRequest();
|
|
865
|
+
const siweDomain = this.siweConfig?.domain ?? this.domain;
|
|
866
|
+
const hasNamedKeys = request?.manifests.some((manifest) => manifest.keys?.length && appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id));
|
|
867
|
+
if (hasNamedKeys) {
|
|
868
|
+
await this.resolveTinyCloudHostsForSignIn(address, chainId);
|
|
869
|
+
await this.refreshNodeInfo();
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
/** Manifest key paths that this sign-in cannot grant. */
|
|
873
|
+
get unavailableKeyPaths() {
|
|
874
|
+
const request = this.getCapabilityRequest();
|
|
875
|
+
const siweDomain = this.siweConfig?.domain ?? this.domain;
|
|
876
|
+
return (request?.manifests ?? []).flatMap(
|
|
877
|
+
(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)
|
|
878
|
+
);
|
|
879
|
+
}
|
|
835
880
|
resolveSpaceName(space, address, chainId) {
|
|
836
881
|
if (space.startsWith("tinycloud:")) {
|
|
837
882
|
return space;
|
|
@@ -1023,15 +1068,31 @@ var NodeUserAuthorization = class {
|
|
|
1023
1068
|
}
|
|
1024
1069
|
const rawAbilities = {};
|
|
1025
1070
|
const currentDid = (0, import_sdk_core5.pkhDid)(address, chainId);
|
|
1071
|
+
if (this._nodeFeatures.includes("encryption-named-keys-v1")) {
|
|
1072
|
+
const siweDomain = this.siweConfig?.domain ?? this.domain;
|
|
1073
|
+
for (const manifest of request.manifests) {
|
|
1074
|
+
if (!appKeyHostBinding(siweDomain, manifest.keys_app_id ?? manifest.app_id)) continue;
|
|
1075
|
+
for (const declaration of manifest.keys ?? []) {
|
|
1076
|
+
const path = "path" in declaration ? declaration.path : declaration.prefix;
|
|
1077
|
+
const resource = `urn:tinycloud:encryption:${currentDid}:default/${path}`;
|
|
1078
|
+
for (const ability of declaration.abilities) {
|
|
1079
|
+
addRawAbility(rawAbilities, resource, `tinycloud.encryption/${ability}`);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1026
1084
|
const spaceResources = request.resources.filter((entry) => {
|
|
1027
1085
|
if (entry.service !== import_sdk_core5.ENCRYPTION_PERMISSION_SERVICE) {
|
|
1028
1086
|
return true;
|
|
1029
1087
|
}
|
|
1088
|
+
const parsed = entry.path.includes("/") ? (0, import_resource.parseEncryptionResource)(entry.path) : { ...(0, import_sdk_services2.parseNetworkId)(entry.path), kind: "network" };
|
|
1089
|
+
if (parsed.kind !== "network") {
|
|
1090
|
+
throw new import_sdk_core5.ManifestValidationError("named keys go in manifest.keys");
|
|
1091
|
+
}
|
|
1030
1092
|
for (const action of entry.actions) {
|
|
1031
1093
|
addRawAbility(rawAbilities, entry.path, action);
|
|
1032
1094
|
}
|
|
1033
|
-
if (entry.actions.includes(DECRYPT_ACTION)) {
|
|
1034
|
-
const parsed = (0, import_sdk_core5.parseNetworkId)(entry.path);
|
|
1095
|
+
if (entry.actions.includes(DECRYPT_ACTION) && parsed.kind === "network") {
|
|
1035
1096
|
if (didPrincipalMatches(parsed.ownerDid, currentDid)) {
|
|
1036
1097
|
addRawAbility(rawAbilities, entry.path, NETWORK_CREATE_ACTION);
|
|
1037
1098
|
}
|
|
@@ -1427,6 +1488,8 @@ var NodeUserAuthorization = class {
|
|
|
1427
1488
|
this._chainId = chainId;
|
|
1428
1489
|
await this.resolveTinyCloudHostsForSignIn(address, chainId);
|
|
1429
1490
|
this.assertSignInCurrent(generation);
|
|
1491
|
+
await this.refreshNamedKeyFeatureForSignIn(address, chainId);
|
|
1492
|
+
this.assertSignInCurrent(generation);
|
|
1430
1493
|
const keyId = `session-${Date.now()}`;
|
|
1431
1494
|
this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
|
|
1432
1495
|
this.activeSessionKeyId = keyId;
|
|
@@ -1573,6 +1636,7 @@ var NodeUserAuthorization = class {
|
|
|
1573
1636
|
refuseCaveated(this.getCapabilityRequest()?.manifests);
|
|
1574
1637
|
const address = (0, import_sdk_core5.canonicalizeAddress)(await this.signer.getAddress());
|
|
1575
1638
|
const chainId = await this.signer.getChainId();
|
|
1639
|
+
await this.refreshNamedKeyFeatureForSignIn(address, chainId);
|
|
1576
1640
|
const keyId = `session-${Date.now()}`;
|
|
1577
1641
|
this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
|
|
1578
1642
|
this.activeSessionKeyId = keyId;
|
|
@@ -2152,7 +2216,7 @@ var NodeUserAuthorization = class {
|
|
|
2152
2216
|
};
|
|
2153
2217
|
|
|
2154
2218
|
// src/recordingServiceContext.ts
|
|
2155
|
-
var
|
|
2219
|
+
var import_sdk_services3 = require("@tinycloud/sdk-services");
|
|
2156
2220
|
var import_requestLog = require("@tinycloud/sdk-services/telemetry/requestLog");
|
|
2157
2221
|
|
|
2158
2222
|
// src/recordingRegistry.ts
|
|
@@ -2197,9 +2261,9 @@ function replicationEvent(sample, op) {
|
|
|
2197
2261
|
}
|
|
2198
2262
|
function createServiceContext(config) {
|
|
2199
2263
|
const { requestSink, ...base } = config;
|
|
2200
|
-
return requestSink === void 0 ? new
|
|
2264
|
+
return requestSink === void 0 ? new import_sdk_services3.ServiceContext(base) : new RecordingServiceContext(base, requestSink);
|
|
2201
2265
|
}
|
|
2202
|
-
var RecordingServiceContext = class extends
|
|
2266
|
+
var RecordingServiceContext = class extends import_sdk_services3.ServiceContext {
|
|
2203
2267
|
constructor(config, sink) {
|
|
2204
2268
|
const pending = {};
|
|
2205
2269
|
super({
|
|
@@ -2793,8 +2857,9 @@ function deserializeDelegation(data) {
|
|
|
2793
2857
|
// src/TinyCloudNode.ts
|
|
2794
2858
|
var import_siwe2 = require("siwe");
|
|
2795
2859
|
var import_sdk_core11 = require("@tinycloud/sdk-core");
|
|
2796
|
-
var
|
|
2860
|
+
var import_sdk_services4 = require("@tinycloud/sdk-services");
|
|
2797
2861
|
var import_requestLog2 = require("@tinycloud/sdk-services/telemetry/requestLog");
|
|
2862
|
+
var import_resource2 = require("@tinycloud/sdk-services/encryption/resource");
|
|
2798
2863
|
|
|
2799
2864
|
// src/account/AccountService.ts
|
|
2800
2865
|
var import_sdk_core7 = require("@tinycloud/sdk-core");
|
|
@@ -3271,6 +3336,7 @@ var ROOT_DELEGATION_ACTIONS = [
|
|
|
3271
3336
|
import_sdk_core11.DUCKDB.ALL
|
|
3272
3337
|
];
|
|
3273
3338
|
var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core11.EXPIRY.SESSION_MS;
|
|
3339
|
+
var OWNER_REVOCATION_WINDOW_MS = 10 * 6e4;
|
|
3274
3340
|
function unifiedRootAttenuation(capabilities) {
|
|
3275
3341
|
const attenuation = {};
|
|
3276
3342
|
for (const capability of capabilities) {
|
|
@@ -3735,6 +3801,7 @@ function replicaRestoreRefusal(error) {
|
|
|
3735
3801
|
case "purge_pending":
|
|
3736
3802
|
case "logout_pending":
|
|
3737
3803
|
case "gate_unavailable":
|
|
3804
|
+
case "wallet_provider_required":
|
|
3738
3805
|
return error.gate;
|
|
3739
3806
|
}
|
|
3740
3807
|
}
|
|
@@ -3769,6 +3836,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3769
3836
|
this.auth = null;
|
|
3770
3837
|
this.tc = null;
|
|
3771
3838
|
this._chainId = 1;
|
|
3839
|
+
this.replicaPurgeFailedHandlers = /* @__PURE__ */ new Set();
|
|
3772
3840
|
/** Mints the replica session stamp on each fresh sign-in (TC-858 §4.1). Undefined when replication is off. */
|
|
3773
3841
|
this.establishReplicaStamp = async (session) => {
|
|
3774
3842
|
const replication = this.config.replication;
|
|
@@ -3800,6 +3868,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3800
3868
|
return void 0;
|
|
3801
3869
|
}
|
|
3802
3870
|
};
|
|
3871
|
+
this._keysUnavailable = [];
|
|
3803
3872
|
this._baseVaults = /* @__PURE__ */ new Map();
|
|
3804
3873
|
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
3805
3874
|
this._secrets = /* @__PURE__ */ new Map();
|
|
@@ -3975,6 +4044,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3975
4044
|
return instance ? instance.control.purge(input) : runtime.then((ready) => ready.control.purge(input));
|
|
3976
4045
|
},
|
|
3977
4046
|
clearPending: async () => (await runtime).control.clearPending(),
|
|
4047
|
+
purgeLocalCopy: async () => (await this.eraseReplicaLocalCopy("purge_local_copy"))?.purge ?? { ok: false, retryNow: false },
|
|
3978
4048
|
close: async () => (await runtime).control.close()
|
|
3979
4049
|
};
|
|
3980
4050
|
}
|
|
@@ -4029,18 +4099,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4029
4099
|
get freshEncryptionNetworkCreated() {
|
|
4030
4100
|
return this._freshEncryptionNetworkCreated;
|
|
4031
4101
|
}
|
|
4032
|
-
/**
|
|
4033
|
-
* Subscribe to `storage.full`. It fires on the first write any service had
|
|
4034
|
-
* rejected because the owner's TinyCloud storage is full
|
|
4035
|
-
* (`STORAGE_QUOTA_EXCEEDED` or `STORAGE_LIMIT_REACHED`), so an app can show
|
|
4036
|
-
* one read-only banner. Reads keep working. For the signed-in account's own
|
|
4037
|
-
* storage it fires once per episode: the episode ends only when a write to
|
|
4038
|
-
* that storage succeeds, or on sign-out. A `storage.status()` read does not
|
|
4039
|
-
* end it. A rejection on another owner's delegated space fires once per
|
|
4040
|
-
* owner, until that owner's `storage.status()` reports space again. Returns
|
|
4041
|
-
* the unsubscribe function.
|
|
4042
|
-
*/
|
|
4043
4102
|
on(event, handler) {
|
|
4103
|
+
if (event === "replica.purge.failed") {
|
|
4104
|
+
const listener = handler;
|
|
4105
|
+
this.replicaPurgeFailedHandlers.add(listener);
|
|
4106
|
+
return () => {
|
|
4107
|
+
this.replicaPurgeFailedHandlers.delete(listener);
|
|
4108
|
+
};
|
|
4109
|
+
}
|
|
4044
4110
|
if (event !== "storage.full") {
|
|
4045
4111
|
throw new Error(`Unknown TinyCloud event: ${String(event)}`);
|
|
4046
4112
|
}
|
|
@@ -4521,6 +4587,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4521
4587
|
const leavingAuth = this.auth;
|
|
4522
4588
|
const leavingContext = this._serviceContext;
|
|
4523
4589
|
let denied;
|
|
4590
|
+
let erased;
|
|
4524
4591
|
try {
|
|
4525
4592
|
this.teardownSession();
|
|
4526
4593
|
} finally {
|
|
@@ -4531,6 +4598,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4531
4598
|
try {
|
|
4532
4599
|
await this.accountRegistryTail;
|
|
4533
4600
|
await this.quiesceReplicaRuntime();
|
|
4601
|
+
if (denied) erased = await this.eraseReplicaLocalCopy("sign_out", denied.status);
|
|
4534
4602
|
} finally {
|
|
4535
4603
|
if (leavingAddress) {
|
|
4536
4604
|
await (leavingAuth ? leavingAuth.clearPersistedSession(leavingAddress) : this.config.sessionStorage?.clear(leavingAddress));
|
|
@@ -4538,8 +4606,37 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4538
4606
|
}
|
|
4539
4607
|
}
|
|
4540
4608
|
}
|
|
4541
|
-
if (denied?.status === "unguarded") {
|
|
4542
|
-
throw
|
|
4609
|
+
if (denied?.status === "unguarded" && erased?.outcome.status !== "erased") {
|
|
4610
|
+
throw Object.assign(
|
|
4611
|
+
new Error(`Replica gate was not denied (${denied.code ?? "unknown"}); the replica may still be restorable.`),
|
|
4612
|
+
{
|
|
4613
|
+
code: "REPLICA_PURGE_FAILED",
|
|
4614
|
+
reason: "gate_unavailable",
|
|
4615
|
+
retryNow: erased?.outcome.status === "failed"
|
|
4616
|
+
}
|
|
4617
|
+
);
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
/**
|
|
4621
|
+
* Erases the browser local copy after a deny (retry, event and next-load marker live in the lazy
|
|
4622
|
+
* replication authority). Never rejects; `undefined` when replication is off or the storage keeps
|
|
4623
|
+
* no browser database.
|
|
4624
|
+
*/
|
|
4625
|
+
async eraseReplicaLocalCopy(trigger, denyStatus) {
|
|
4626
|
+
const replication = this.config.replication;
|
|
4627
|
+
if (!replication?.enabled) return void 0;
|
|
4628
|
+
try {
|
|
4629
|
+
const { eraseReplicaLocalCopy } = await getNodeReplicationLoaders().authority();
|
|
4630
|
+
const erased = await eraseReplicaLocalCopy(
|
|
4631
|
+
replication.storage.lifecycle,
|
|
4632
|
+
trigger,
|
|
4633
|
+
denyStatus,
|
|
4634
|
+
this.replicaPurgeFailedHandlers
|
|
4635
|
+
);
|
|
4636
|
+
if (erased?.logoutPending) this.replicaRestoreGate = "logout_pending";
|
|
4637
|
+
return erased;
|
|
4638
|
+
} catch {
|
|
4639
|
+
return void 0;
|
|
4543
4640
|
}
|
|
4544
4641
|
}
|
|
4545
4642
|
/**
|
|
@@ -4599,6 +4696,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4599
4696
|
this._hooks = void 0;
|
|
4600
4697
|
this._vault = void 0;
|
|
4601
4698
|
this._encryption = void 0;
|
|
4699
|
+
this._namedKeyClient = void 0;
|
|
4700
|
+
this._keysUnavailable = [];
|
|
4602
4701
|
this._baseVaults.clear();
|
|
4603
4702
|
this._baseSecrets.clear();
|
|
4604
4703
|
this._secrets.clear();
|
|
@@ -4703,6 +4802,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4703
4802
|
const priorPrincipal = this.replicaSessionPrincipal ?? (this.address ? (0, import_sdk_core11.pkhDid)(this.address, this._chainId) : void 0);
|
|
4704
4803
|
if (this.config.replication?.enabled && priorPrincipal && priorPrincipal !== nextPrincipal) {
|
|
4705
4804
|
const denial = await this.denyReplicaGate({ reason: "account_switch", principal: priorPrincipal, next: nextPrincipal });
|
|
4805
|
+
if (denial) {
|
|
4806
|
+
await this.quiesceReplicaRuntime();
|
|
4807
|
+
await this.eraseReplicaLocalCopy("account_switch", denial.status);
|
|
4808
|
+
}
|
|
4706
4809
|
this.replicaRestoreGate = denial?.status === "unguarded" ? "gate_unavailable" : "stamp_stale";
|
|
4707
4810
|
}
|
|
4708
4811
|
if (address !== this._address || chainId !== this._chainId) {
|
|
@@ -4717,6 +4820,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4717
4820
|
this._hooks = void 0;
|
|
4718
4821
|
this._vault = void 0;
|
|
4719
4822
|
this._encryption = void 0;
|
|
4823
|
+
this._namedKeyClient = void 0;
|
|
4824
|
+
this._keysUnavailable = [];
|
|
4720
4825
|
this._baseVaults.clear();
|
|
4721
4826
|
this._baseSecrets.clear();
|
|
4722
4827
|
this._secrets.clear();
|
|
@@ -4769,6 +4874,26 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4769
4874
|
this.assertSessionEpoch(epoch, "Sign-in");
|
|
4770
4875
|
await this.ensureRequestedEncryptionNetworks();
|
|
4771
4876
|
this.assertSessionEpoch(epoch, "Sign-in");
|
|
4877
|
+
this._keysUnavailable = this.auth?.unavailableKeyPaths ?? [];
|
|
4878
|
+
if (this._keysUnavailable.length > 0) {
|
|
4879
|
+
this.notificationHandler.warning(`Named keys unavailable: ${this._keysUnavailable.join(", ")}`);
|
|
4880
|
+
}
|
|
4881
|
+
if (this.nodeFeatures.includes("encryption-named-keys-v1")) {
|
|
4882
|
+
for (const manifest of this.auth?.capabilityRequest?.manifests ?? []) {
|
|
4883
|
+
for (const declaration of manifest.keys ?? []) {
|
|
4884
|
+
if ("path" in declaration && declaration.abilities.includes("key.create") && !this._keysUnavailable.includes(declaration.path)) {
|
|
4885
|
+
try {
|
|
4886
|
+
await this.keys.ensureKey(declaration.path);
|
|
4887
|
+
} catch (error) {
|
|
4888
|
+
this._keysUnavailable.push(declaration.path);
|
|
4889
|
+
const code = error && typeof error === "object" && "code" in error && typeof error.code === "string" && /^[A-Z_]+$/.test(error.code) ? error.code : "UNKNOWN";
|
|
4890
|
+
this.notificationHandler.warning(`Named key unavailable: ${declaration.path} (${code})`);
|
|
4891
|
+
}
|
|
4892
|
+
this.assertSessionEpoch(epoch, "Sign-in");
|
|
4893
|
+
}
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4772
4897
|
if (!bootstrapped && this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
|
|
4773
4898
|
await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core11.SECRETS_SPACE));
|
|
4774
4899
|
}
|
|
@@ -5345,7 +5470,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5345
5470
|
if (!this.currentSessionCoversAccountRegistry()) {
|
|
5346
5471
|
if (!_TinyCloudNode.accountRegistrySkipLogged) {
|
|
5347
5472
|
_TinyCloudNode.accountRegistrySkipLogged = true;
|
|
5348
|
-
|
|
5473
|
+
import_sdk_services4.tinyCloudDebugLogger.log("registry.skip");
|
|
5349
5474
|
}
|
|
5350
5475
|
return;
|
|
5351
5476
|
}
|
|
@@ -5556,7 +5681,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5556
5681
|
const networkIds = /* @__PURE__ */ new Set();
|
|
5557
5682
|
for (const resource of request.resources) {
|
|
5558
5683
|
if (resource.service === import_sdk_core11.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
|
|
5559
|
-
|
|
5684
|
+
const parsed = resource.path.includes("/") ? (0, import_resource2.parseEncryptionResource)(resource.path) : { ...(0, import_sdk_core11.parseNetworkId)(resource.path), kind: "network" };
|
|
5685
|
+
if (parsed.kind === "network") networkIds.add(resource.path);
|
|
5560
5686
|
}
|
|
5561
5687
|
}
|
|
5562
5688
|
return [...networkIds];
|
|
@@ -6106,6 +6232,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6106
6232
|
this._hooks = stagedGraph.hooks;
|
|
6107
6233
|
this._vault = stagedGraph.vault;
|
|
6108
6234
|
this._encryption = stagedGraph.encryption;
|
|
6235
|
+
this._namedKeyClient = void 0;
|
|
6236
|
+
this._keysUnavailable = [];
|
|
6109
6237
|
this._capabilityRegistry = stagedGraph.capabilityRegistry;
|
|
6110
6238
|
this._keyProvider = stagedGraph.keyProvider;
|
|
6111
6239
|
this._sharingService = stagedGraph.sharingService;
|
|
@@ -7015,7 +7143,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7015
7143
|
);
|
|
7016
7144
|
graph.assertActive();
|
|
7017
7145
|
if (!response.ok) {
|
|
7018
|
-
const permissionHint = response.status === 401 || response.status === 403 ? (0,
|
|
7146
|
+
const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services4.parsePermissionHint)({
|
|
7019
7147
|
service: "tinycloud.encryption",
|
|
7020
7148
|
path: networkId,
|
|
7021
7149
|
actions: ["tinycloud.encryption/decrypt"]
|
|
@@ -7459,7 +7587,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7459
7587
|
* Sign a wallet (CACAO) revocation of the delegation `cid` for the node's
|
|
7460
7588
|
* `POST /revoke`, and return its Authorization header value. The node
|
|
7461
7589
|
* accepts it when the owner delegated `cid` or owns a space its abilities
|
|
7462
|
-
* target, whichever key issued it. Valid for
|
|
7590
|
+
* target, whichever key issued it. Valid for 10 minutes. Requires the
|
|
7463
7591
|
* owner wallet signer.
|
|
7464
7592
|
*/
|
|
7465
7593
|
async signOwnerRevocation(cid) {
|
|
@@ -7475,7 +7603,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7475
7603
|
chainId: session.chainId,
|
|
7476
7604
|
nonce: (0, import_siwe2.generateNonce)(),
|
|
7477
7605
|
issuedAt: issuedAt.toISOString(),
|
|
7478
|
-
expirationTime: new Date(issuedAt.getTime() +
|
|
7606
|
+
expirationTime: new Date(issuedAt.getTime() + OWNER_REVOCATION_WINDOW_MS).toISOString()
|
|
7479
7607
|
}).prepareMessage();
|
|
7480
7608
|
const signature = await this.signer.signMessage(siwe);
|
|
7481
7609
|
return this.wasmBindings.siweToDelegationHeaders({ siwe, signature }).Authorization;
|
|
@@ -7702,6 +7830,40 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7702
7830
|
get encryption() {
|
|
7703
7831
|
return this.getEncryptionService();
|
|
7704
7832
|
}
|
|
7833
|
+
/** Named keys bound to the current session. */
|
|
7834
|
+
get keys() {
|
|
7835
|
+
return new Proxy({}, {
|
|
7836
|
+
get: (_target, property) => {
|
|
7837
|
+
if (property === "refreshNodeInfo") {
|
|
7838
|
+
return () => {
|
|
7839
|
+
void this._namedKeyClient?.then((client) => client.refreshNodeInfo());
|
|
7840
|
+
};
|
|
7841
|
+
}
|
|
7842
|
+
if (typeof property !== "string" || ![
|
|
7843
|
+
"getPublicKey",
|
|
7844
|
+
"describeKey",
|
|
7845
|
+
"createKey",
|
|
7846
|
+
"blockKey",
|
|
7847
|
+
"unblockKey",
|
|
7848
|
+
"ensureKey",
|
|
7849
|
+
"encrypt",
|
|
7850
|
+
"decrypt",
|
|
7851
|
+
"decryptMany"
|
|
7852
|
+
].includes(property)) return void 0;
|
|
7853
|
+
return (...args) => {
|
|
7854
|
+
this._namedKeyClient ?? (this._namedKeyClient = import("./encryption-keys.cjs").then(({ createNamedKeyClient }) => createNamedKeyClient(this)));
|
|
7855
|
+
return this._namedKeyClient.then((client) => {
|
|
7856
|
+
const method = client[property];
|
|
7857
|
+
return method.apply(client, args);
|
|
7858
|
+
});
|
|
7859
|
+
};
|
|
7860
|
+
}
|
|
7861
|
+
});
|
|
7862
|
+
}
|
|
7863
|
+
/** Manifest key paths unavailable during the latest `signIn()` attempt. */
|
|
7864
|
+
get keysUnavailable() {
|
|
7865
|
+
return this._keysUnavailable;
|
|
7866
|
+
}
|
|
7705
7867
|
async getEncryptionNetwork(nameOrNetworkId = this.getDefaultEncryptionNetworkId()) {
|
|
7706
7868
|
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
7707
7869
|
return this.fetchEncryptionNetworkAt(
|
|
@@ -7829,7 +7991,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7829
7991
|
);
|
|
7830
7992
|
if (result.status !== "ok") {
|
|
7831
7993
|
if (result.status === "permission_required") {
|
|
7832
|
-
const hint = (0,
|
|
7994
|
+
const hint = (0, import_sdk_services4.parsePermissionHint)(result.hint);
|
|
7833
7995
|
if (hint === void 0) return { status: "read_failed" };
|
|
7834
7996
|
return {
|
|
7835
7997
|
status: "permission_required",
|
|
@@ -10007,6 +10169,7 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
|
|
|
10007
10169
|
PermissionNotInManifestError,
|
|
10008
10170
|
PrefixedKVService,
|
|
10009
10171
|
ProtocolMismatchError,
|
|
10172
|
+
RuntimeDelegationRejectedError,
|
|
10010
10173
|
SECRET_NAME_RE,
|
|
10011
10174
|
SQLAction,
|
|
10012
10175
|
SQLService,
|
|
@@ -10029,6 +10192,7 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
|
|
|
10029
10192
|
VersionCheckError,
|
|
10030
10193
|
WasmKeyProvider,
|
|
10031
10194
|
activateCompactRuntimeDelegation,
|
|
10195
|
+
activateValidatedRuntimeDelegation,
|
|
10032
10196
|
addressStorageKey,
|
|
10033
10197
|
buildSpaceUri,
|
|
10034
10198
|
canonicalizeAddress,
|