@tinycloud/node-sdk 3.12.0-beta.1 → 3.12.0-beta.3
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/README.md +39 -0
- package/dist/{NodeUserAuthorization-BtoDI9in.d.cts → NodeUserAuthorization-B_TFUlua.d.cts} +19 -53
- package/dist/{NodeUserAuthorization-BtoDI9in.d.ts → NodeUserAuthorization-B_TFUlua.d.ts} +19 -53
- package/dist/{TinyCloudNode-DLrINr98.d.ts → TinyCloudNode-Brcu8QoX.d.cts} +33 -59
- package/dist/{TinyCloudNode-C24728N_.d.cts → TinyCloudNode-DBJUnsMN.d.ts} +33 -59
- package/dist/{authority-BQN2Z3st.d.ts → authority-BFc5lesl.d.ts} +1 -1
- package/dist/{authority-DDdheOL6.d.cts → authority-DQ6R1HEG.d.cts} +1 -1
- package/dist/core.cjs +555 -320
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +5 -5
- package/dist/core.d.ts +5 -5
- package/dist/core.js +581 -324
- 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-BQbAuKad.d.cts → delegation-CeOWDnBB.d.cts} +7 -0
- package/dist/{delegation-BQbAuKad.d.ts → delegation-CeOWDnBB.d.ts} +7 -0
- package/dist/encryption-keys.d.cts +3 -3
- package/dist/encryption-keys.d.ts +3 -3
- package/dist/index.cjs +572 -337
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +582 -325
- package/dist/index.js.map +1 -1
- package/dist/replication/authority.d.cts +4 -4
- package/dist/replication/authority.d.ts +4 -4
- package/dist/space-hosting.cjs +48 -6
- package/dist/space-hosting.cjs.map +1 -1
- package/dist/space-hosting.d.cts +23 -8
- package/dist/space-hosting.d.ts +23 -8
- package/dist/space-hosting.js +48 -6
- package/dist/space-hosting.js.map +1 -1
- package/package.json +4 -4
package/dist/core.cjs
CHANGED
|
@@ -54,7 +54,10 @@ __export(core_exports, {
|
|
|
54
54
|
KVService: () => import_sdk_core15.KVService,
|
|
55
55
|
ManifestValidationError: () => import_sdk_core14.ManifestValidationError,
|
|
56
56
|
MemorySessionStorage: () => MemorySessionStorage,
|
|
57
|
+
NodeIdentityMismatchError: () => import_sdk_services7.NodeIdentityMismatchError,
|
|
58
|
+
NodeNotRespondingError: () => import_sdk_services7.NodeNotRespondingError,
|
|
57
59
|
NodeUserAuthorization: () => NodeUserAuthorization,
|
|
60
|
+
PartialNodeWriteError: () => import_sdk_services7.PartialNodeWriteError,
|
|
58
61
|
PermissionNotInManifestError: () => import_sdk_core14.PermissionNotInManifestError,
|
|
59
62
|
PrefixedKVService: () => import_sdk_core15.PrefixedKVService,
|
|
60
63
|
ProtocolMismatchError: () => import_sdk_core22.ProtocolMismatchError,
|
|
@@ -138,6 +141,7 @@ __export(core_exports, {
|
|
|
138
141
|
});
|
|
139
142
|
module.exports = __toCommonJS(core_exports);
|
|
140
143
|
var import_sdk_core12 = require("@tinycloud/sdk-core");
|
|
144
|
+
var import_sdk_services7 = require("@tinycloud/sdk-services");
|
|
141
145
|
|
|
142
146
|
// src/replication/module-registry.ts
|
|
143
147
|
var nodeLoaders;
|
|
@@ -609,11 +613,12 @@ var NodeUserAuthorization = class {
|
|
|
609
613
|
this.tinycloudHosts = config.tinycloudHosts;
|
|
610
614
|
this.tinycloudRegistryUrl = config.tinycloudRegistryUrl;
|
|
611
615
|
this.tinycloudFallbackHosts = config.tinycloudFallbackHosts;
|
|
612
|
-
this.registryPolicy = config.registryPolicy;
|
|
613
616
|
this.newUserHost = config.newUserHost;
|
|
614
617
|
this.registryChainId = config.registryChainId;
|
|
615
618
|
this.registrySequenceStore = config.registrySequenceStore ?? (0, import_sdk_core5.createInMemoryRegistrySequenceStore)();
|
|
619
|
+
this.registryCacheStore = config.registryCacheStore ?? (0, import_sdk_core5.createInMemoryRegistryCacheStore)();
|
|
616
620
|
this.onNodeNotFound = config.onNodeNotFound;
|
|
621
|
+
this.onRegistryFallback = config.onRegistryFallback;
|
|
617
622
|
this.autoDiscoverLocalNode = config.autoDiscoverLocalNode;
|
|
618
623
|
this.localNodeUrl = config.localNodeUrl;
|
|
619
624
|
this.localLinkName = config.localLinkName;
|
|
@@ -681,13 +686,8 @@ var NodeUserAuthorization = class {
|
|
|
681
686
|
* undefined for missing SIWEs and the SDK then treats the session as
|
|
682
687
|
* expired-at-epoch-zero.
|
|
683
688
|
*
|
|
684
|
-
* @param hosts -
|
|
685
|
-
*
|
|
686
|
-
* present (and non-empty) they are adopted directly so the restored
|
|
687
|
-
* session resolves to the same node as the original sign-in without
|
|
688
|
-
* re-running registry/fallback resolution. When absent (old session)
|
|
689
|
-
* hosts are resolved lazily on the first host-needing call via
|
|
690
|
-
* {@link ensureTinyCloudHosts}.
|
|
689
|
+
* @param hosts - Persisted host hints for genuine no-entry onboarding.
|
|
690
|
+
* Current signed registry membership always takes precedence.
|
|
691
691
|
*/
|
|
692
692
|
setRestoredTinyCloudSession(session, hosts) {
|
|
693
693
|
const address = (0, import_sdk_core5.canonicalizeAddress)(session.address);
|
|
@@ -749,89 +749,84 @@ var NodeUserAuthorization = class {
|
|
|
749
749
|
signature: session.signature
|
|
750
750
|
};
|
|
751
751
|
}
|
|
752
|
-
/**
|
|
753
|
-
* Ensure `tinycloudHosts` are resolved before a host-needing call.
|
|
754
|
-
*
|
|
755
|
-
* Fresh sign-in resolves hosts up front; a restored session may not have
|
|
756
|
-
* (old persisted sessions predate {@link PersistedSessionData.tinycloudHosts}).
|
|
757
|
-
* This guard makes a restored session resolve the node exactly like a fresh
|
|
758
|
-
* sign-in — persisted hosts are preferred (already set by
|
|
759
|
-
* {@link setRestoredTinyCloudSession}), otherwise the registry/fallback
|
|
760
|
-
* resolution runs lazily here. Idempotent: {@link resolveTinyCloudHostsForSignIn}
|
|
761
|
-
* early-returns when hosts are already set.
|
|
762
|
-
*
|
|
763
|
-
* Throws if hosts are unset and the restored session has no address/chainId
|
|
764
|
-
* to resolve from — a real failure that must surface, not be masked.
|
|
765
|
-
*/
|
|
752
|
+
/** Refresh the primary space's registry destinations, including after restore. */
|
|
766
753
|
async ensureTinyCloudHosts() {
|
|
767
|
-
if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
|
|
768
|
-
return;
|
|
769
|
-
}
|
|
770
754
|
if (this._address === void 0 || this._chainId === void 0) {
|
|
771
|
-
throw new Error(
|
|
772
|
-
|
|
773
|
-
|
|
755
|
+
throw new Error("Cannot resolve TinyCloud hosts: sign in or restore a session first.");
|
|
756
|
+
}
|
|
757
|
+
await this.resolveTinyCloudHostsForSignIn(this._address, this._chainId, this._tinyCloudSession?.spaceId);
|
|
758
|
+
}
|
|
759
|
+
async resolveTinyCloudHostsForSignIn(address, chainId, restoredSpaceId) {
|
|
760
|
+
const spaceId = restoredSpaceId ?? this.resolveSignInCapabilities(address, chainId).spaceId;
|
|
761
|
+
const destinations = await this.resolveResourceDestinations(spaceId, "read");
|
|
762
|
+
for (const destination of destinations) await (0, import_sdk_services2.verifyResourceDestination)(destination, globalThis.fetch.bind(globalThis));
|
|
763
|
+
this.tinycloudHosts = destinations.map(({ url }) => url);
|
|
764
|
+
}
|
|
765
|
+
/** Current full-resource registry routing; saved hosts are only no-entry hints. */
|
|
766
|
+
async resolveResourceDestinations(resource, access, noEntryHosts = this.tinycloudHosts ?? []) {
|
|
767
|
+
const owner = resource.startsWith("urn:tinycloud:encryption:") ? (0, import_sdk_services2.parseNetworkId)(resource.split("/")[0]).ownerDid : (0, import_sdk_core5.parseSpaceUri)(resource)?.owner ?? (() => {
|
|
768
|
+
const key = /^tinycloud:key:(z[^:]+):[^/]+$/.exec(resource);
|
|
769
|
+
return key ? `did:key:${key[1]}` : void 0;
|
|
770
|
+
})();
|
|
771
|
+
if (!owner) throw new Error(`Cannot determine registry owner for ${resource}`);
|
|
772
|
+
const subject = owner.startsWith("did:pkh:") ? (0, import_sdk_core5.registryOwnerSubjectV1)(owner.slice(owner.lastIndexOf(":") + 1), this.registryChainId) : owner;
|
|
773
|
+
for (let attempt = 1; ; attempt++) {
|
|
774
|
+
try {
|
|
775
|
+
const resolved = await (0, import_sdk_core5.resolveRegistryResource)(subject, resource, access, {
|
|
776
|
+
registryUrl: this.tinycloudRegistryUrl,
|
|
777
|
+
registryChainId: this.registryChainId,
|
|
778
|
+
sequenceStore: this.registrySequenceStore,
|
|
779
|
+
cacheStore: this.registryCacheStore,
|
|
780
|
+
onRegistryFallback: this.onRegistryFallback
|
|
781
|
+
});
|
|
782
|
+
this.registryVerdict = resolved.verdict;
|
|
783
|
+
if (resolved.verdict.status === "unregistered") {
|
|
784
|
+
if (noEntryHosts.length === 0 && (this.autoDiscoverLocalNode ?? true)) {
|
|
785
|
+
const local = await (0, import_sdk_core5.discoverLocalTinyCloudNode)({
|
|
786
|
+
localNodeUrl: this.localNodeUrl,
|
|
787
|
+
localLinkName: this.localLinkName,
|
|
788
|
+
expectedNodeDid: this.expectedNodeDid,
|
|
789
|
+
identityStore: this.localNodeIdentityStore
|
|
790
|
+
});
|
|
791
|
+
if (local) {
|
|
792
|
+
(0, import_sdk_core5.warnRegistryDefaultNode)(resolved.verdict, this.registryCacheStore, this.onRegistryFallback);
|
|
793
|
+
return [{ url: local.url }];
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
const host = noEntryHosts[0] ?? this.newUserHost ?? (this.tinycloudFallbackHosts === void 0 ? "https://node.tinycloud.xyz" : this.tinycloudFallbackHosts?.[0]);
|
|
797
|
+
if (!host || this.newUserHost === null && noEntryHosts.length === 0) throw new import_sdk_core5.NodeNotFoundError(subject, resolved.verdict);
|
|
798
|
+
const url = (0, import_sdk_core5.exactHttpOrigin)(host, "new-user host");
|
|
799
|
+
(0, import_sdk_core5.warnRegistryDefaultNode)(resolved.verdict, this.registryCacheStore, this.onRegistryFallback);
|
|
800
|
+
return [{ url }];
|
|
801
|
+
}
|
|
802
|
+
const destinations = resolved.hosts.flatMap((host) => host.urls.map((url) => ({ url, nodeDid: host.nodeDid })));
|
|
803
|
+
return destinations;
|
|
804
|
+
} catch (error) {
|
|
805
|
+
if (!(error instanceof import_sdk_core5.NodeNotFoundError) && !(error instanceof import_sdk_core5.RegistryUnavailableError)) throw error;
|
|
806
|
+
if (!this.onNodeNotFound) throw error;
|
|
807
|
+
const decision = await this.onNodeNotFound({ error, attempt });
|
|
808
|
+
if (decision.action === "retry") continue;
|
|
809
|
+
if (decision.action === "use-host" && error.verdict?.status === "unregistered") {
|
|
810
|
+
const url = (0, import_sdk_core5.exactHttpOrigin)(decision.host, "new-user host");
|
|
811
|
+
(0, import_sdk_core5.warnRegistryDefaultNode)(error.verdict, this.registryCacheStore, this.onRegistryFallback);
|
|
812
|
+
return [{ url }];
|
|
813
|
+
}
|
|
814
|
+
throw error;
|
|
815
|
+
}
|
|
774
816
|
}
|
|
775
|
-
await this.resolveTinyCloudHostsForSignIn(this._address, this._chainId);
|
|
776
817
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
return;
|
|
780
|
-
}
|
|
781
|
-
if (this.registryPolicy === "fail-closed") {
|
|
782
|
-
const resolved2 = await (0, import_sdk_core5.resolveFailClosedTinyCloudHosts)(address, {
|
|
783
|
-
registryUrl: this.tinycloudRegistryUrl,
|
|
784
|
-
registryChainId: this.registryChainId,
|
|
785
|
-
newUserHost: this.newUserHost,
|
|
786
|
-
sequenceStore: this.registrySequenceStore,
|
|
787
|
-
onNodeNotFound: this.onNodeNotFound,
|
|
788
|
-
autoDiscoverLocalNode: this.autoDiscoverLocalNode,
|
|
789
|
-
localNodeUrl: this.localNodeUrl,
|
|
790
|
-
localLinkName: this.localLinkName,
|
|
791
|
-
expectedNodeDid: this.expectedNodeDid,
|
|
792
|
-
localNodeIdentityStore: this.localNodeIdentityStore
|
|
793
|
-
});
|
|
794
|
-
this.tinycloudHosts = resolved2.hosts;
|
|
795
|
-
this.registryVerdict = resolved2.verdict;
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
const subject = (0, import_sdk_core5.pkhDid)(address, chainId);
|
|
799
|
-
const resolved = await (0, import_sdk_core5.resolveTinyCloudHosts)(subject, {
|
|
800
|
-
registryUrl: this.tinycloudRegistryUrl,
|
|
801
|
-
fallbackHosts: this.tinycloudFallbackHosts,
|
|
802
|
-
autoDiscoverLocalNode: this.autoDiscoverLocalNode,
|
|
803
|
-
localNodeUrl: this.localNodeUrl,
|
|
804
|
-
localLinkName: this.localLinkName,
|
|
805
|
-
expectedNodeDid: this.expectedNodeDid,
|
|
806
|
-
localNodeIdentityStore: this.localNodeIdentityStore
|
|
807
|
-
});
|
|
808
|
-
this.tinycloudHosts = resolved.hosts;
|
|
818
|
+
get registryRecordPresent() {
|
|
819
|
+
return this.registryVerdict?.status === "registered";
|
|
809
820
|
}
|
|
810
|
-
/**
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
*/
|
|
819
|
-
async assertMayCreateSpace() {
|
|
820
|
-
if (this.registryPolicy !== "fail-closed") return;
|
|
821
|
-
if (this._address === void 0) {
|
|
822
|
-
throw new Error("Must be signed in to create a space");
|
|
823
|
-
}
|
|
824
|
-
await this.ensureTinyCloudHosts();
|
|
825
|
-
const subject = (0, import_sdk_core5.registryOwnerSubjectV1)(this._address, this.registryChainId);
|
|
826
|
-
let verdict = this.registryVerdict;
|
|
827
|
-
if (verdict?.subject !== subject || verdict.status === "unavailable") {
|
|
828
|
-
verdict = await (0, import_sdk_core5.lookupOwnerRegistryVerdict)(subject, {
|
|
829
|
-
registryUrl: this.tinycloudRegistryUrl,
|
|
830
|
-
sequenceStore: this.registrySequenceStore
|
|
831
|
-
});
|
|
832
|
-
this.registryVerdict = verdict;
|
|
821
|
+
/** Refresh membership before hosting; a saved no-entry verdict never authorizes a later creation. */
|
|
822
|
+
async assertMayCreateSpace(spaceId = this._tinyCloudSession?.spaceId, host = this.primaryTinyCloudHost) {
|
|
823
|
+
if (!spaceId) throw new Error("Must be signed in to create a space");
|
|
824
|
+
const destinations = await this.resolveResourceDestinations(spaceId, "host");
|
|
825
|
+
if (!destinations.some((destination) => destination.url === host)) {
|
|
826
|
+
const subject = (0, import_sdk_core5.parseSpaceUri)(spaceId)?.owner;
|
|
827
|
+
if (!subject || !this.registryVerdict) throw new Error("Cannot resolve space owner");
|
|
828
|
+
(0, import_sdk_core5.assertSpaceCreationAllowed)(this.registryVerdict, host, spaceId);
|
|
833
829
|
}
|
|
834
|
-
(0, import_sdk_core5.assertSpaceCreationAllowed)(verdict, this.primaryTinyCloudHost);
|
|
835
830
|
}
|
|
836
831
|
requireTinyCloudHosts() {
|
|
837
832
|
if (!this.tinycloudHosts || this.tinycloudHosts.length === 0) {
|
|
@@ -1261,23 +1256,60 @@ var NodeUserAuthorization = class {
|
|
|
1261
1256
|
* Create the space on the TinyCloud server (host delegation).
|
|
1262
1257
|
* This registers the user as the owner of the space.
|
|
1263
1258
|
*/
|
|
1264
|
-
async hostSpace(targetSpaceId, purpose, signal) {
|
|
1265
|
-
|
|
1259
|
+
async hostSpace(targetSpaceId, purpose, signal, assertCurrent, siweParameters) {
|
|
1260
|
+
const context = typeof targetSpaceId === "object" ? targetSpaceId : void 0;
|
|
1261
|
+
const address = context?.address ?? this._address;
|
|
1262
|
+
const chainId = context?.chainId ?? this._chainId;
|
|
1263
|
+
if (!address || chainId === void 0 || !this._tinyCloudSession) {
|
|
1266
1264
|
throw new Error("Must be signed in to host space");
|
|
1267
1265
|
}
|
|
1266
|
+
const checkCurrent = () => {
|
|
1267
|
+
signal?.throwIfAborted();
|
|
1268
|
+
assertCurrent?.();
|
|
1269
|
+
};
|
|
1270
|
+
checkCurrent();
|
|
1268
1271
|
await this.ensureTinyCloudHosts();
|
|
1269
|
-
|
|
1270
|
-
const
|
|
1272
|
+
checkCurrent();
|
|
1273
|
+
const host = context?.host ?? this.primaryTinyCloudHost;
|
|
1274
|
+
const spaceId = context?.spaceId ?? (typeof targetSpaceId === "string" ? targetSpaceId : this._tinyCloudSession.spaceId);
|
|
1275
|
+
const destinations = await this.resolveResourceDestinations(spaceId, "host");
|
|
1276
|
+
if (this.registryVerdict?.status === "registered") {
|
|
1277
|
+
const results = [];
|
|
1278
|
+
for (const destination of destinations) {
|
|
1279
|
+
checkCurrent();
|
|
1280
|
+
try {
|
|
1281
|
+
await (0, import_sdk_services2.verifyResourceDestination)(destination, globalThis.fetch.bind(globalThis));
|
|
1282
|
+
const result = await (0, import_sdk_core5.activateSessionWithHost)(destination.url, this._tinyCloudSession.delegationHeader, signal);
|
|
1283
|
+
results.push(result.skipped?.includes(spaceId) ? { ...result, success: false, status: 403, error: "The session does not activate the requested space" } : result);
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
if ((0, import_sdk_services2.routingFailure)(error) || signal?.aborted) throw error;
|
|
1286
|
+
throw new import_sdk_services2.NodeNotRespondingError([destination.url], error);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
const failed = results.flatMap((result, index) => result.success ? [] : [{ url: destinations[index].url, status: result.status }]);
|
|
1290
|
+
if (failed.length) {
|
|
1291
|
+
if (destinations.length === 1) return results[0];
|
|
1292
|
+
throw new import_sdk_services2.PartialNodeWriteError(destinations.filter((_, index) => results[index].success).map(({ url }) => url), failed);
|
|
1293
|
+
}
|
|
1294
|
+
return {
|
|
1295
|
+
...results[0],
|
|
1296
|
+
activated: [...new Set(results.flatMap((result) => result.activated ?? []))],
|
|
1297
|
+
skipped: [...new Set(results.flatMap((result) => result.skipped ?? []))]
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1271
1300
|
const peerId = await (0, import_sdk_core5.fetchPeerId)(host, spaceId, signal);
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1301
|
+
checkCurrent();
|
|
1302
|
+
const siwe = this.wasm.generateHostSIWEMessage(
|
|
1303
|
+
context && siweParameters ? siweParameters(peerId) : {
|
|
1304
|
+
address,
|
|
1305
|
+
chainId,
|
|
1306
|
+
domain: this.domain,
|
|
1307
|
+
issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1308
|
+
spaceId,
|
|
1309
|
+
peerId
|
|
1310
|
+
}
|
|
1311
|
+
);
|
|
1312
|
+
checkCurrent();
|
|
1281
1313
|
const signing = this.signMessage(siwe, purpose);
|
|
1282
1314
|
let signature;
|
|
1283
1315
|
if (!signal) {
|
|
@@ -1296,8 +1328,9 @@ var NodeUserAuthorization = class {
|
|
|
1296
1328
|
signal.removeEventListener("abort", onAbort);
|
|
1297
1329
|
}
|
|
1298
1330
|
}
|
|
1299
|
-
|
|
1331
|
+
checkCurrent();
|
|
1300
1332
|
const headers = this.wasm.siweToDelegationHeaders({ siwe, signature });
|
|
1333
|
+
checkCurrent();
|
|
1301
1334
|
return (0, import_sdk_core5.submitHostDelegation)(host, headers, signal);
|
|
1302
1335
|
}
|
|
1303
1336
|
/**
|
|
@@ -1334,13 +1367,45 @@ var NodeUserAuthorization = class {
|
|
|
1334
1367
|
if (!this._tinyCloudSession) {
|
|
1335
1368
|
throw new Error("Must be signed in to ensure space exists");
|
|
1336
1369
|
}
|
|
1337
|
-
await this.ensureTinyCloudHosts();
|
|
1338
|
-
const host = this.primaryTinyCloudHost;
|
|
1339
1370
|
const primarySpaceId = this._tinyCloudSession.spaceId;
|
|
1340
|
-
const
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
)
|
|
1371
|
+
const primary = await this.resolveResourceDestinations(primarySpaceId, "read");
|
|
1372
|
+
this.tinycloudHosts = primary.map(({ url }) => url);
|
|
1373
|
+
const targets = new Map(primary.map((destination) => [destination.url, destination]));
|
|
1374
|
+
if (this.registryVerdict?.status === "registered" && this.registryVerdict.record) {
|
|
1375
|
+
const record = this.registryVerdict.record;
|
|
1376
|
+
const resources = Object.keys((0, import_sdk_core5.extractRecapAttenuations)(this._tinyCloudSession.siwe ?? ""));
|
|
1377
|
+
for (const space of record.spaces) {
|
|
1378
|
+
const registeredSpace = (0, import_sdk_core5.parseSpaceUri)(space.space);
|
|
1379
|
+
if (!resources.some((resource) => {
|
|
1380
|
+
const fullSpace = resource.split("/")[0];
|
|
1381
|
+
const requestedSpace = (0, import_sdk_core5.parseSpaceUri)(fullSpace);
|
|
1382
|
+
return fullSpace === space.space || registeredSpace !== null && requestedSpace !== null && registeredSpace.owner === requestedSpace.owner && registeredSpace.name === requestedSpace.name;
|
|
1383
|
+
})) continue;
|
|
1384
|
+
for (const membership of space.nodes) {
|
|
1385
|
+
const node = record.nodes.find((candidate) => candidate.did === membership.did);
|
|
1386
|
+
targets.set(node.url, { url: node.url, nodeDid: node.did });
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
if (record.encryptionNode && resources.some((resource) => resource.startsWith("urn:tinycloud:encryption:"))) {
|
|
1390
|
+
const node = record.nodes.find((candidate) => candidate.did === record.encryptionNode);
|
|
1391
|
+
targets.set(node.url, { url: node.url, nodeDid: node.did });
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
let result;
|
|
1395
|
+
for (const destination of targets.values()) {
|
|
1396
|
+
await (0, import_sdk_services2.verifyResourceDestination)(destination, globalThis.fetch.bind(globalThis));
|
|
1397
|
+
let activated;
|
|
1398
|
+
try {
|
|
1399
|
+
activated = await (0, import_sdk_core5.activateSessionWithHost)(destination.url, this._tinyCloudSession.delegationHeader);
|
|
1400
|
+
} catch (error) {
|
|
1401
|
+
throw new import_sdk_services2.NodeNotRespondingError([destination.url], error);
|
|
1402
|
+
}
|
|
1403
|
+
if (!activated.success && activated.status !== 404) {
|
|
1404
|
+
throw Object.assign(new Error(`Failed to activate session: ${describeHostFailure(activated)}`), { cause: activated });
|
|
1405
|
+
}
|
|
1406
|
+
if (destination.url === primary[0].url) result = activated;
|
|
1407
|
+
}
|
|
1408
|
+
if (!result) throw new Error("Primary space activation did not return a result");
|
|
1344
1409
|
this.recordActivationSkippedSpaces(result, primarySpaceId);
|
|
1345
1410
|
if (!result.success && result.status !== 404) {
|
|
1346
1411
|
throw Object.assign(
|
|
@@ -1359,43 +1424,36 @@ var NodeUserAuthorization = class {
|
|
|
1359
1424
|
*
|
|
1360
1425
|
* @throws Error if the creation handler fails or times out, or hosting fails
|
|
1361
1426
|
*/
|
|
1362
|
-
async ensurePrimarySpaceHosted(hosting) {
|
|
1363
|
-
if (hosting !== "not-hosted") {
|
|
1364
|
-
return;
|
|
1365
|
-
}
|
|
1427
|
+
async ensurePrimarySpaceHosted(hosting, signal) {
|
|
1366
1428
|
const session = this._tinyCloudSession;
|
|
1367
|
-
if (
|
|
1368
|
-
|
|
1369
|
-
}
|
|
1429
|
+
if (hosting !== "not-hosted") return;
|
|
1430
|
+
if (!session) throw new Error("Must be signed in to host the primary space");
|
|
1370
1431
|
const handler = this.spaceCreationHandler ?? (this.autoCreateSpace ? new import_sdk_core5.AutoApproveSpaceCreationHandler() : void 0);
|
|
1371
|
-
if (!handler)
|
|
1372
|
-
return;
|
|
1373
|
-
}
|
|
1374
|
-
await this.ensureTinyCloudHosts();
|
|
1375
|
-
const host = this.primaryTinyCloudHost;
|
|
1376
|
-
const primarySpaceId = session.spaceId;
|
|
1377
|
-
const creationContext = {
|
|
1378
|
-
spaceId: primarySpaceId,
|
|
1379
|
-
address: this._address,
|
|
1380
|
-
chainId: this._chainId,
|
|
1381
|
-
host
|
|
1382
|
-
};
|
|
1432
|
+
if (!handler) return;
|
|
1383
1433
|
const { createPrimarySpace } = await import("./space-hosting.cjs");
|
|
1384
1434
|
await createPrimarySpace({
|
|
1385
1435
|
handler,
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1436
|
+
session,
|
|
1437
|
+
currentSession: () => this._tinyCloudSession,
|
|
1438
|
+
signerAddress: () => this.signer.getAddress(),
|
|
1439
|
+
resolveHost: async () => {
|
|
1440
|
+
await this.ensureTinyCloudHosts();
|
|
1441
|
+
return this.primaryTinyCloudHost;
|
|
1442
|
+
},
|
|
1443
|
+
domain: this.domain,
|
|
1444
|
+
guard: (context) => this.guardSpaceCreation(handler, context),
|
|
1445
|
+
host: (context, assertCurrent, siweParameters) => this.hostSpace(context, void 0, signal, assertCurrent, siweParameters),
|
|
1389
1446
|
onHosted: () => {
|
|
1390
1447
|
this._spaceHosting = "hosted";
|
|
1391
1448
|
},
|
|
1392
|
-
activate: () => (0, import_sdk_core5.activateSessionWithHost)(host, session.delegationHeader)
|
|
1449
|
+
activate: (context) => (0, import_sdk_core5.activateSessionWithHost)(context.host, session.delegationHeader),
|
|
1450
|
+
signal
|
|
1393
1451
|
});
|
|
1394
1452
|
}
|
|
1395
1453
|
/** {@link assertMayCreateSpace}, reporting a refusal to the creation handler before rethrowing it. */
|
|
1396
1454
|
async guardSpaceCreation(handler, context) {
|
|
1397
1455
|
try {
|
|
1398
|
-
await this.assertMayCreateSpace();
|
|
1456
|
+
await this.assertMayCreateSpace(context.spaceId, context.host);
|
|
1399
1457
|
} catch (error) {
|
|
1400
1458
|
const failure = error instanceof Error ? error : new Error(String(error));
|
|
1401
1459
|
handler.onSpaceCreationFailed?.(context, failure);
|
|
@@ -2539,6 +2597,7 @@ function rememberInvokeAny(invokeAny, sink, pending) {
|
|
|
2539
2597
|
|
|
2540
2598
|
// src/delegation.ts
|
|
2541
2599
|
var import_sdk_core6 = require("@tinycloud/sdk-core");
|
|
2600
|
+
var import_sdk_services4 = require("@tinycloud/sdk-services");
|
|
2542
2601
|
var RuntimeDelegationRejectedError = class extends Error {
|
|
2543
2602
|
constructor(reason, message) {
|
|
2544
2603
|
super(message);
|
|
@@ -2565,7 +2624,8 @@ var SERVICE_BY_SHORT_NAME = {
|
|
|
2565
2624
|
kv: "tinycloud.kv",
|
|
2566
2625
|
sql: "tinycloud.sql",
|
|
2567
2626
|
duckdb: "tinycloud.duckdb",
|
|
2568
|
-
hooks: "tinycloud.hooks"
|
|
2627
|
+
hooks: "tinycloud.hooks",
|
|
2628
|
+
capabilities: "tinycloud.capabilities"
|
|
2569
2629
|
};
|
|
2570
2630
|
function authorizationWithoutBearer(authorization) {
|
|
2571
2631
|
return authorization.replace(/^Bearer /i, "");
|
|
@@ -2696,8 +2756,8 @@ function signedAuthorityFromCompactUcan(authorization) {
|
|
|
2696
2756
|
));
|
|
2697
2757
|
continue;
|
|
2698
2758
|
}
|
|
2699
|
-
const match = /^(?:tinycloud:\/\/([^/]+)|(tinycloud:[^/]+))\/(
|
|
2700
|
-
if (!match) {
|
|
2759
|
+
const match = /^(?:tinycloud:\/\/([^/]+)|(tinycloud:[^/]+))\/([^/]+)(?:\/|$)(.*)$/.exec(resource);
|
|
2760
|
+
if (!match || !Object.prototype.hasOwnProperty.call(SERVICE_BY_SHORT_NAME, match[3])) {
|
|
2701
2761
|
throw new Error(
|
|
2702
2762
|
`Validated runtime delegation has an unsupported signed resource '${resource}'.`
|
|
2703
2763
|
);
|
|
@@ -2842,13 +2902,8 @@ function resourcesMatch(actual, expected) {
|
|
|
2842
2902
|
return JSON.stringify(actual.map(comparable)) === JSON.stringify(expected.map(comparable));
|
|
2843
2903
|
}
|
|
2844
2904
|
async function activateValidatedRuntimeDelegation(node, delegation, options) {
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
reject(
|
|
2848
|
-
"host_mismatch",
|
|
2849
|
-
`Runtime delegation host '${delegation.host}' does not match expected host '${options.host}'.`
|
|
2850
|
-
);
|
|
2851
|
-
}
|
|
2905
|
+
let host = normalizedHost(options.host);
|
|
2906
|
+
const differentHost = delegation.host !== void 0 && normalizedHost(delegation.host) !== host;
|
|
2852
2907
|
if (!(delegation.expiry instanceof Date) || Number.isNaN(delegation.expiry.getTime())) {
|
|
2853
2908
|
reject("authority_invalid", "Runtime delegation has an invalid expiry.");
|
|
2854
2909
|
}
|
|
@@ -2892,6 +2947,13 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
|
|
|
2892
2947
|
if (options.authorize !== void 0 && !options.authorize(signed.permissions)) {
|
|
2893
2948
|
throw new Error("Runtime delegation is not authorized for this runtime.");
|
|
2894
2949
|
}
|
|
2950
|
+
if (differentHost) {
|
|
2951
|
+
const registeredHost = await node.resolveRegisteredDelegationHost?.(signed.permissions, host);
|
|
2952
|
+
if (registeredHost === void 0) {
|
|
2953
|
+
reject("host_mismatch", `Runtime delegation host '${delegation.host}' does not match expected host '${options.host}'.`);
|
|
2954
|
+
}
|
|
2955
|
+
host = normalizedHost(registeredHost);
|
|
2956
|
+
}
|
|
2895
2957
|
const previouslyInstalled = node.getRuntimePermissionDelegations().find((candidate) => candidate.cid === cid);
|
|
2896
2958
|
if (previouslyInstalled !== void 0 && previouslyInstalled.delegationHeader.Authorization !== authorization) {
|
|
2897
2959
|
reject(
|
|
@@ -2935,6 +2997,7 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
|
|
|
2935
2997
|
await node.useRuntimeDelegation(installedCandidate);
|
|
2936
2998
|
}
|
|
2937
2999
|
} catch (error) {
|
|
3000
|
+
if ((0, import_sdk_services4.routingFailure)(error)) throw error;
|
|
2938
3001
|
reject(
|
|
2939
3002
|
activationRejectionReason(error),
|
|
2940
3003
|
error instanceof Error ? error.message : String(error)
|
|
@@ -2953,6 +3016,7 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
|
|
|
2953
3016
|
"Runtime delegation activation installed authority that differs from the validated authority."
|
|
2954
3017
|
);
|
|
2955
3018
|
}
|
|
3019
|
+
node.refreshRegistryForCapabilities?.(signed.permissions);
|
|
2956
3020
|
return {
|
|
2957
3021
|
cid,
|
|
2958
3022
|
delegation: installed,
|
|
@@ -3016,10 +3080,11 @@ function deserializeDelegation(data) {
|
|
|
3016
3080
|
}
|
|
3017
3081
|
|
|
3018
3082
|
// src/TinyCloudNode.ts
|
|
3083
|
+
var import_sdk_services5 = require("@tinycloud/sdk-services");
|
|
3019
3084
|
var import_siwe2 = require("siwe");
|
|
3020
3085
|
var import_share_envelope = require("@tinycloud/share-envelope");
|
|
3021
3086
|
var import_sdk_core11 = require("@tinycloud/sdk-core");
|
|
3022
|
-
var
|
|
3087
|
+
var import_sdk_services6 = require("@tinycloud/sdk-services");
|
|
3023
3088
|
var import_requestLog2 = require("@tinycloud/sdk-services/telemetry/requestLog");
|
|
3024
3089
|
var import_resource2 = require("@tinycloud/sdk-services/encryption/resource");
|
|
3025
3090
|
|
|
@@ -3995,6 +4060,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3995
4060
|
* ```
|
|
3996
4061
|
*/
|
|
3997
4062
|
constructor(config = {}) {
|
|
4063
|
+
this.registryRefreshOwners = /* @__PURE__ */ new Set();
|
|
3998
4064
|
this.signer = null;
|
|
3999
4065
|
this.auth = null;
|
|
4000
4066
|
this.consumedOpenKeyPendings = /* @__PURE__ */ new WeakSet();
|
|
@@ -4158,8 +4224,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4158
4224
|
this.config = {
|
|
4159
4225
|
...config,
|
|
4160
4226
|
host: config.host ?? DEFAULT_HOST,
|
|
4227
|
+
registryPolicy: "fail-closed",
|
|
4161
4228
|
// One store for every authorization this client creates.
|
|
4162
|
-
registrySequenceStore: config.registrySequenceStore ?? (0, import_sdk_core11.createInMemoryRegistrySequenceStore)()
|
|
4229
|
+
registrySequenceStore: config.registrySequenceStore ?? (0, import_sdk_core11.createInMemoryRegistrySequenceStore)(),
|
|
4230
|
+
registryCacheStore: config.registryCacheStore ?? (0, import_sdk_core11.createInMemoryRegistryCacheStore)()
|
|
4163
4231
|
};
|
|
4164
4232
|
if (this.config.replication?.enabled) {
|
|
4165
4233
|
const runtime = getNodeReplicationLoaders().runtime().then(({ ReplicationRuntime }) => {
|
|
@@ -4406,6 +4474,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4406
4474
|
return "unknown";
|
|
4407
4475
|
}
|
|
4408
4476
|
}
|
|
4477
|
+
/** Run the existing primary-space creation flow for the restored session. */
|
|
4478
|
+
async ensurePrimarySpaceHosted(hosting) {
|
|
4479
|
+
const graph = this._serviceGraph;
|
|
4480
|
+
const epoch = this.sessionEpoch;
|
|
4481
|
+
graph.assertActive();
|
|
4482
|
+
this.assertSessionEpoch(epoch, "Space hosting");
|
|
4483
|
+
const auth = this.auth;
|
|
4484
|
+
if (!auth || !this.session) return;
|
|
4485
|
+
await auth.ensurePrimarySpaceHosted(hosting, graph.signal);
|
|
4486
|
+
graph.assertActive();
|
|
4487
|
+
this.assertSessionEpoch(epoch, "Space hosting");
|
|
4488
|
+
}
|
|
4409
4489
|
/**
|
|
4410
4490
|
* The node's last answer for the primary space: recorded at sign-in from the
|
|
4411
4491
|
* activation, or by {@link checkSpaceHosting}. `unknown` after a restore until
|
|
@@ -4451,7 +4531,11 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4451
4531
|
// A session saved but never registered on this node is refused: it registers once.
|
|
4452
4532
|
activate: (signal) => {
|
|
4453
4533
|
assertCurrent();
|
|
4454
|
-
|
|
4534
|
+
const activationSignal = AbortSignal.any([signal, graph.signal]);
|
|
4535
|
+
if (primary && primary.delegationCid === session.delegationCid) {
|
|
4536
|
+
return this.activateSignedSession(primary, primary.siwe, host, activationSignal);
|
|
4537
|
+
}
|
|
4538
|
+
return this.activateResourceSession(session.delegationHeader, [spaceId], host, activationSignal);
|
|
4455
4539
|
}
|
|
4456
4540
|
});
|
|
4457
4541
|
assertCurrent();
|
|
@@ -4587,14 +4671,38 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4587
4671
|
get requests() {
|
|
4588
4672
|
return this._requestLog === void 0 ? void 0 : (0, import_requestLog2.readOnlyRequestLog)(this._requestLog);
|
|
4589
4673
|
}
|
|
4590
|
-
|
|
4674
|
+
throwRegistryRefusal(status, text) {
|
|
4675
|
+
if (status !== 403 && status !== 503 || !text.startsWith("registry_unavailable:") && !text.startsWith("registry_hosting_denied:")) return;
|
|
4676
|
+
const code = status === 503 ? "registry_unavailable" : "node_registry_entry_exists";
|
|
4677
|
+
throw Object.assign(new Error(status === 503 ? "The location registry is unavailable for this resource." : "The registry does not authorize this node for the requested resource."), { code, meta: { status } });
|
|
4678
|
+
}
|
|
4679
|
+
createServiceGraphLifetime(session) {
|
|
4680
|
+
const routedFetch = (0, import_sdk_services5.createResourceRoutingFetch)(
|
|
4681
|
+
async (url, init) => {
|
|
4682
|
+
try {
|
|
4683
|
+
const response = await globalThis.fetch(url, init);
|
|
4684
|
+
if (response.status === 403 || response.status === 503) {
|
|
4685
|
+
this.throwRegistryRefusal(response.status, await response.clone().text());
|
|
4686
|
+
}
|
|
4687
|
+
return response;
|
|
4688
|
+
} catch (error) {
|
|
4689
|
+
if ((0, import_sdk_services5.routingFailure)(error)) throw error;
|
|
4690
|
+
if (new URL(url).pathname.startsWith("/encryption/") && !init?.signal?.aborted) {
|
|
4691
|
+
throw new import_sdk_services5.NodeNotRespondingError([new URL(url).origin], error);
|
|
4692
|
+
}
|
|
4693
|
+
throw error;
|
|
4694
|
+
}
|
|
4695
|
+
},
|
|
4696
|
+
{
|
|
4697
|
+
resolveResource: (resource, access) => this.routingDestinations(resource, access),
|
|
4698
|
+
bindAudience: (authorization, nodeDid) => this.bindRoutedAudience(authorization, nodeDid, session),
|
|
4699
|
+
verifyDestination: (target) => (0, import_sdk_services5.verifyResourceDestination)(target, globalThis.fetch.bind(globalThis))
|
|
4700
|
+
}
|
|
4701
|
+
);
|
|
4591
4702
|
return new ServiceGraphLifetime(
|
|
4592
4703
|
this.invokeWithRuntimePermissions,
|
|
4593
4704
|
this.invokeAnyWithRuntimePermissions,
|
|
4594
|
-
|
|
4595
|
-
// signal while preserving the SDK's existing injectable global fetch
|
|
4596
|
-
// behavior (including adapters that install it after construction).
|
|
4597
|
-
(url, init) => globalThis.fetch(url, init),
|
|
4705
|
+
routedFetch,
|
|
4598
4706
|
(context) => {
|
|
4599
4707
|
this.storageFull.observe(context);
|
|
4600
4708
|
if (this._requestLog) (0, import_requestLog2.observeReplicaReads)(context, this._requestLog);
|
|
@@ -4602,6 +4710,75 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4602
4710
|
this._requestLog
|
|
4603
4711
|
);
|
|
4604
4712
|
}
|
|
4713
|
+
async routingDestinations(resource, access, noEntryHosts) {
|
|
4714
|
+
const session = this.currentTinyCloudSession();
|
|
4715
|
+
if (session) this.refreshRegistryOwner((0, import_sdk_core11.pkhDid)(session.address, session.chainId));
|
|
4716
|
+
if (this.auth) return this.auth.resolveResourceDestinations(resource, access, noEntryHosts);
|
|
4717
|
+
const owner = resource.startsWith("urn:tinycloud:encryption:") ? (0, import_sdk_core11.parseNetworkId)(resource.split("/")[0]).ownerDid : (0, import_sdk_core11.parseSpaceUri)(resource)?.owner ?? (() => {
|
|
4718
|
+
const key = /^tinycloud:key:(z[^:]+):[^/]+$/.exec(resource);
|
|
4719
|
+
return key ? `did:key:${key[1]}` : void 0;
|
|
4720
|
+
})();
|
|
4721
|
+
if (!owner) throw new Error(`Cannot determine registry owner for ${resource}`);
|
|
4722
|
+
const subject = owner.startsWith("did:pkh:") ? (0, import_sdk_core11.pkhDid)(owner.slice(owner.lastIndexOf(":") + 1), this.config.registryChainId ?? 1) : owner;
|
|
4723
|
+
const resolved = await (0, import_sdk_core11.resolveRegistryResource)(subject, resource, access, {
|
|
4724
|
+
registryUrl: this.config.tinycloudRegistryUrl,
|
|
4725
|
+
registryChainId: this.config.registryChainId,
|
|
4726
|
+
sequenceStore: this.config.registrySequenceStore,
|
|
4727
|
+
cacheStore: this.config.registryCacheStore,
|
|
4728
|
+
onRegistryFallback: this.config.onRegistryFallback
|
|
4729
|
+
});
|
|
4730
|
+
if (resolved.verdict.status === "unregistered") {
|
|
4731
|
+
const hint = noEntryHosts === void 0 ? this.explicitHost ?? this.config.host : noEntryHosts[0];
|
|
4732
|
+
const host = hint ?? this.config.newUserHost ?? (this.config.tinycloudFallbackHosts === void 0 ? DEFAULT_HOST : this.config.tinycloudFallbackHosts?.[0]);
|
|
4733
|
+
if (!host || !hint && this.config.newUserHost === null) throw new import_sdk_core11.NodeNotFoundError(subject, resolved.verdict);
|
|
4734
|
+
const url = (0, import_sdk_core11.exactHttpOrigin)(host, "new-user host");
|
|
4735
|
+
(0, import_sdk_core11.warnRegistryDefaultNode)(resolved.verdict, this.config.registryCacheStore, this.config.onRegistryFallback);
|
|
4736
|
+
return [{ url }];
|
|
4737
|
+
}
|
|
4738
|
+
const destinations = resolved.hosts.flatMap((host) => host.urls.map((url) => ({ url, nodeDid: host.nodeDid })));
|
|
4739
|
+
return destinations;
|
|
4740
|
+
}
|
|
4741
|
+
/** Transport hints cannot override verified full-resource registry routing. */
|
|
4742
|
+
async resolveRegisteredDelegationHost(permissions, noEntryHost) {
|
|
4743
|
+
const resources = /* @__PURE__ */ new Map();
|
|
4744
|
+
let hasData = false;
|
|
4745
|
+
for (const permission of permissions) {
|
|
4746
|
+
const encryption = this.isEncryptionNetworkOperation(this.invocationServiceName(permission.service), permission.path, permission.space);
|
|
4747
|
+
const resource = encryption ? permission.path.split("/")[0] : permission.space;
|
|
4748
|
+
if (!resource) throw new import_sdk_services5.ResourceNotRoutedError("delegation");
|
|
4749
|
+
resources.set(resource, encryption ? "encryption" : "host");
|
|
4750
|
+
hasData || (hasData = !encryption);
|
|
4751
|
+
}
|
|
4752
|
+
let dataHost;
|
|
4753
|
+
let encryptionHost;
|
|
4754
|
+
let unserved;
|
|
4755
|
+
for (const [resource, access] of resources) {
|
|
4756
|
+
try {
|
|
4757
|
+
const destinations = await this.routingDestinations(resource, access, [noEntryHost]);
|
|
4758
|
+
if (destinations.some(({ nodeDid }) => nodeDid === void 0)) return void 0;
|
|
4759
|
+
if (access === "host") dataHost ?? (dataHost = destinations[0]?.url);
|
|
4760
|
+
else encryptionHost ?? (encryptionHost = destinations[0]?.url);
|
|
4761
|
+
} catch (error) {
|
|
4762
|
+
if (!(error instanceof import_sdk_core11.NodeNotFoundError) || error.verdict.status !== "registered") throw error;
|
|
4763
|
+
unserved ?? (unserved = error);
|
|
4764
|
+
}
|
|
4765
|
+
}
|
|
4766
|
+
const host = hasData ? dataHost : encryptionHost;
|
|
4767
|
+
if (!host) throw unserved ?? new import_sdk_services5.ResourceNotRoutedError("delegation");
|
|
4768
|
+
return host;
|
|
4769
|
+
}
|
|
4770
|
+
async bindRoutedAudience(authorization, nodeDid, stagedSession) {
|
|
4771
|
+
const payload = JSON.parse(new TextDecoder().decode(base64UrlDecode(authorization.split(".")[1])));
|
|
4772
|
+
const issuer = typeof payload === "object" && payload !== null && "iss" in payload ? payload.iss : void 0;
|
|
4773
|
+
const session = [
|
|
4774
|
+
stagedSession,
|
|
4775
|
+
this._serviceContext?.session,
|
|
4776
|
+
this.auth?.tinyCloudSession,
|
|
4777
|
+
...this.runtimePermissionGrants.map((grant) => grant.session)
|
|
4778
|
+
].find((candidate) => candidate?.verificationMethod === issuer);
|
|
4779
|
+
if (!session) throw new Error("Invocation signing session is not active");
|
|
4780
|
+
return rewriteInvocationAudience(authorization, nodeDid, session.jwk);
|
|
4781
|
+
}
|
|
4605
4782
|
syncResolvedHostFromAuth() {
|
|
4606
4783
|
const host = this.auth?.hosts[0];
|
|
4607
4784
|
if (host) {
|
|
@@ -4715,6 +4892,29 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4715
4892
|
const session = this.currentTinyCloudSession();
|
|
4716
4893
|
return session?.siwe ? this.projectSignedRecapCapabilities(session.siwe) : [];
|
|
4717
4894
|
}
|
|
4895
|
+
/** Start one background refresh for each owner derived from verified authority. */
|
|
4896
|
+
refreshRegistryForCapabilities(permissions) {
|
|
4897
|
+
for (const permission of permissions) {
|
|
4898
|
+
try {
|
|
4899
|
+
const owner = permission.service === "tinycloud.encryption" && permission.path.startsWith("urn:tinycloud:encryption:") ? (0, import_sdk_core11.parseNetworkId)(permission.path.split("/")[0]).ownerDid : permission.space ? this.ownerDidFromSpaceId(permission.space) : void 0;
|
|
4900
|
+
if (owner) this.refreshRegistryOwner(owner);
|
|
4901
|
+
} catch {
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4904
|
+
}
|
|
4905
|
+
refreshRegistryOwner(owner) {
|
|
4906
|
+
if (this.config.tinycloudRegistryUrl === null) return;
|
|
4907
|
+
const subject = owner.startsWith("did:pkh:") ? (0, import_sdk_core11.pkhDid)(owner.slice(owner.lastIndexOf(":") + 1), this.config.registryChainId ?? 1) : owner;
|
|
4908
|
+
const key = (0, import_sdk_core11.registryOwnerKeyV2)(subject);
|
|
4909
|
+
if (this.registryRefreshOwners.has(key)) return;
|
|
4910
|
+
this.registryRefreshOwners.add(key);
|
|
4911
|
+
void (0, import_sdk_core11.refreshOwnerRegistry)(subject, {
|
|
4912
|
+
registryUrl: this.config.tinycloudRegistryUrl,
|
|
4913
|
+
registryChainId: this.config.registryChainId,
|
|
4914
|
+
sequenceStore: this.config.registrySequenceStore,
|
|
4915
|
+
cacheStore: this.config.registryCacheStore
|
|
4916
|
+
}).catch(() => void 0);
|
|
4917
|
+
}
|
|
4718
4918
|
/** Normalize signed capabilities without collapsing nested encryption into raw authority. */
|
|
4719
4919
|
projectSignedRecapCapabilities(siwe) {
|
|
4720
4920
|
const projected = this.parseRecapWithCaveats(siwe).map((entry) => {
|
|
@@ -5146,6 +5346,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5146
5346
|
const primarySession = this.currentTinyCloudSession();
|
|
5147
5347
|
if (primarySession) {
|
|
5148
5348
|
this.registerPrimarySessionGrant(primarySession);
|
|
5349
|
+
this.refreshRegistryOwner((0, import_sdk_core11.pkhDid)(primarySession.address, primarySession.chainId));
|
|
5350
|
+
this.refreshRegistryForCapabilities(this.getVerifiedSessionCapabilities());
|
|
5149
5351
|
if (this.auth?.spaceHosting === "unknown") {
|
|
5150
5352
|
await this.checkSpaceHosting();
|
|
5151
5353
|
this.assertSessionEpoch(epoch, "Sign-in");
|
|
@@ -5368,8 +5570,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5368
5570
|
const primarySession = auth.tinyCloudSession;
|
|
5369
5571
|
const defaultSpaceId = this.ownedSpaceId("default");
|
|
5370
5572
|
const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core11.BOOTSTRAP_SESSION_REQUESTS.default;
|
|
5371
|
-
|
|
5372
|
-
await this.assertMayCreateSpace();
|
|
5573
|
+
for (const step of steps) {
|
|
5574
|
+
if (step.kind === "host") await this.assertMayCreateSpace(step.spaceId);
|
|
5373
5575
|
}
|
|
5374
5576
|
for (const step of steps) {
|
|
5375
5577
|
if (step.kind !== "session") continue;
|
|
@@ -5418,10 +5620,20 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5418
5620
|
if (!session) {
|
|
5419
5621
|
throw new Error(`Missing bootstrap session for ${step.space}`);
|
|
5420
5622
|
}
|
|
5421
|
-
const
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5623
|
+
const destinations = await this.routingDestinations(step.spaceId, "host");
|
|
5624
|
+
let activated;
|
|
5625
|
+
for (const destination of destinations) {
|
|
5626
|
+
try {
|
|
5627
|
+
await (0, import_sdk_services5.verifyResourceDestination)(destination, globalThis.fetch.bind(globalThis));
|
|
5628
|
+
const result = await (0, import_sdk_core11.activateSessionWithHost)(destination.url, session.delegationHeader, graph.signal);
|
|
5629
|
+
if (!result.success) throw Object.assign(new Error("Bootstrap activation failed"), { cause: result });
|
|
5630
|
+
activated = result;
|
|
5631
|
+
} catch (error) {
|
|
5632
|
+
graph.assertActive();
|
|
5633
|
+
throw error;
|
|
5634
|
+
}
|
|
5635
|
+
}
|
|
5636
|
+
if (!activated) throw new Error("Bootstrap space has no destination");
|
|
5425
5637
|
graph.assertActive();
|
|
5426
5638
|
if (!activated.success || activated.skipped?.includes(step.spaceId)) {
|
|
5427
5639
|
throw Object.assign(
|
|
@@ -5751,7 +5963,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5751
5963
|
if (!this.currentSessionCoversAccountRegistry()) {
|
|
5752
5964
|
if (!_TinyCloudNode.accountRegistrySkipLogged) {
|
|
5753
5965
|
_TinyCloudNode.accountRegistrySkipLogged = true;
|
|
5754
|
-
|
|
5966
|
+
import_sdk_services6.tinyCloudDebugLogger.log("registry.skip");
|
|
5755
5967
|
}
|
|
5756
5968
|
return;
|
|
5757
5969
|
}
|
|
@@ -6004,6 +6216,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6004
6216
|
if (!session) {
|
|
6005
6217
|
throw new Error("Owned space hosting requires an active session");
|
|
6006
6218
|
}
|
|
6219
|
+
await this.assertMayCreateSpace(spaceId);
|
|
6220
|
+
if (this.auth.registryRecordPresent) {
|
|
6221
|
+
const hosted = await this.hostOwnedSpaceOnce(spaceId, signal);
|
|
6222
|
+
if (!hosted.success) throw Object.assign(new Error(`Failed to activate listed space ${spaceId}: ${describeHostFailure2(hosted)}`), { cause: hosted });
|
|
6223
|
+
if (this.auth.tinyCloudSession === session) this.confirmedHostedSpaceIds.add(spaceId);
|
|
6224
|
+
return;
|
|
6225
|
+
}
|
|
6007
6226
|
if (this.confirmedHostedSpaceIds.has(spaceId) || this.hostedOwnedSpaceIds.has(spaceId)) {
|
|
6008
6227
|
return;
|
|
6009
6228
|
}
|
|
@@ -6022,7 +6241,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6022
6241
|
{ cause: activation }
|
|
6023
6242
|
);
|
|
6024
6243
|
}
|
|
6025
|
-
await this.assertMayCreateSpace();
|
|
6244
|
+
await this.assertMayCreateSpace(spaceId);
|
|
6026
6245
|
if (signal?.aborted) throw signal.reason;
|
|
6027
6246
|
const created = await this.hostOwnedSpaceOnce(spaceId, signal);
|
|
6028
6247
|
if (!created.success) {
|
|
@@ -6083,17 +6302,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6083
6302
|
{ cause: hosted }
|
|
6084
6303
|
);
|
|
6085
6304
|
}
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
if (!activation.success || activation.skipped?.includes(spaceId)) {
|
|
6091
|
-
throw Object.assign(
|
|
6092
|
-
new Error(
|
|
6093
|
-
`Failed to activate session for owned space ${spaceId}: ${activation.success ? "space was skipped" : describeHostFailure2(activation)}`
|
|
6094
|
-
),
|
|
6095
|
-
{ cause: activation }
|
|
6305
|
+
if (!this.auth.registryRecordPresent) {
|
|
6306
|
+
const activation = await (0, import_sdk_core11.activateSessionWithHost)(
|
|
6307
|
+
host,
|
|
6308
|
+
session.delegationHeader
|
|
6096
6309
|
);
|
|
6310
|
+
if (!activation.success || activation.skipped?.includes(spaceId)) {
|
|
6311
|
+
throw Object.assign(
|
|
6312
|
+
new Error(
|
|
6313
|
+
`Failed to activate session for owned space ${spaceId}: ${activation.success ? "space was skipped" : describeHostFailure2(activation)}`
|
|
6314
|
+
),
|
|
6315
|
+
{ cause: activation }
|
|
6316
|
+
);
|
|
6317
|
+
}
|
|
6097
6318
|
}
|
|
6098
6319
|
if (this.auth?.tinyCloudSession === session) this.hostedOwnedSpaceIds.add(spaceId);
|
|
6099
6320
|
try {
|
|
@@ -6137,11 +6358,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6137
6358
|
* session's recap doesn't cover it and the registry has no record; the host
|
|
6138
6359
|
* SIWE is idempotent server-side. Must be called after {@link signIn}.
|
|
6139
6360
|
*
|
|
6140
|
-
*
|
|
6141
|
-
*
|
|
6142
|
-
*
|
|
6143
|
-
* verdict. {@link hostOwnedSpace} itself is an explicit action and is not
|
|
6144
|
-
* guarded.
|
|
6361
|
+
* Current signed per-space membership is checked before both automatic and
|
|
6362
|
+
* explicit hosting. Registered replicas use the session grant; no-entry
|
|
6363
|
+
* onboarding retains the host-SIWE flow.
|
|
6145
6364
|
*
|
|
6146
6365
|
* @param name - The owned space name (e.g. `"secrets"`).
|
|
6147
6366
|
* @returns The hosted owned-space URI.
|
|
@@ -6151,27 +6370,20 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6151
6370
|
throw new Error("Not signed in. Call signIn() first.");
|
|
6152
6371
|
}
|
|
6153
6372
|
const spaceId = this.ownedSpaceId(name);
|
|
6373
|
+
await this.assertMayCreateSpace(spaceId);
|
|
6154
6374
|
if (this.hostedOwnedSpaceIds.has(spaceId) || await this.isOwnedSpaceRegistered(spaceId)) {
|
|
6155
6375
|
return spaceId;
|
|
6156
6376
|
}
|
|
6157
|
-
await this.assertMayCreateSpace();
|
|
6158
6377
|
return this.hostOwnedSpace(name);
|
|
6159
6378
|
}
|
|
6160
|
-
/**
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
* {@link ensurePublicSpace}. Only `registryPolicy: "fail-closed"` consults
|
|
6164
|
-
* the registry ({@link NodeUserAuthorization.assertMayCreateSpace}); the
|
|
6165
|
-
* default policy performs no lookup.
|
|
6166
|
-
*/
|
|
6167
|
-
async assertMayCreateSpace() {
|
|
6168
|
-
if (this.config.registryPolicy !== "fail-closed") return;
|
|
6169
|
-
await this.auth.assertMayCreateSpace();
|
|
6379
|
+
/** Refresh full-space membership before any automatic or explicit hosting. */
|
|
6380
|
+
async assertMayCreateSpace(spaceId) {
|
|
6381
|
+
await this.routingDestinations(spaceId, "host");
|
|
6170
6382
|
}
|
|
6171
6383
|
/** Registry-policy settings shared by every authorization this client creates. */
|
|
6172
6384
|
registryPolicyConfig() {
|
|
6173
|
-
const { registryPolicy, newUserHost, registryChainId, registrySequenceStore, onNodeNotFound } = this.config;
|
|
6174
|
-
return { registryPolicy, newUserHost, registryChainId, registrySequenceStore, onNodeNotFound };
|
|
6385
|
+
const { registryPolicy, newUserHost, registryChainId, registrySequenceStore, registryCacheStore, onNodeNotFound, onRegistryFallback } = this.config;
|
|
6386
|
+
return { registryPolicy, newUserHost, registryChainId, registrySequenceStore, registryCacheStore, onNodeNotFound, onRegistryFallback };
|
|
6175
6387
|
}
|
|
6176
6388
|
/**
|
|
6177
6389
|
* Submit the host delegation for an owned space, sharing one in-flight
|
|
@@ -6377,12 +6589,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6377
6589
|
}
|
|
6378
6590
|
stagedSessionExpiry = signedExpiry ?? persistedPolicyExpiry ?? persistedExpiry(void 0);
|
|
6379
6591
|
}
|
|
6380
|
-
const
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
sessionData.chainId
|
|
6384
|
-
);
|
|
6385
|
-
const stagedHost = resolvedHost ?? this.config.host;
|
|
6592
|
+
const restoreHints = this.explicitHost ? [this.explicitHost] : sessionData.tinycloudHosts ?? [];
|
|
6593
|
+
const resolvedHost = this.config.replication?.enabled ? (await this.routingDestinations(sessionData.spaceId, "read", restoreHints))[0]?.url : void 0;
|
|
6594
|
+
const stagedHost = resolvedHost ?? (0, import_sdk_core11.exactHttpOrigin)(restoreHints[0] ?? this.config.host, "restored host hint");
|
|
6386
6595
|
let restoredNodeFeatures;
|
|
6387
6596
|
let replicaProtocolMismatch = false;
|
|
6388
6597
|
if (this.config.replication?.enabled) {
|
|
@@ -6499,7 +6708,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6499
6708
|
this.sessionManager = stagedManager;
|
|
6500
6709
|
this.sessionKeyId = stagedKeyId;
|
|
6501
6710
|
this.sessionKeyJwk = stagedJwk;
|
|
6502
|
-
|
|
6711
|
+
this.config.host = stagedHost;
|
|
6503
6712
|
if (spaceOwnerKey(serviceSession.spaceId) !== this.currentStorageOwner()) {
|
|
6504
6713
|
this.storageFull.clear();
|
|
6505
6714
|
this._requestLog?.clear();
|
|
@@ -6566,6 +6775,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6566
6775
|
if (attempt === this.latestSessionAttempt) await this.endSession();
|
|
6567
6776
|
this.assertSessionEpoch(epoch, "Session restore");
|
|
6568
6777
|
}
|
|
6778
|
+
if (this.config.replication?.enabled) {
|
|
6779
|
+
if (stagedAddress !== void 0) this.refreshRegistryOwner((0, import_sdk_core11.pkhDid)(stagedAddress, stagedChainId));
|
|
6780
|
+
this.refreshRegistryForCapabilities(this.getVerifiedSessionCapabilities());
|
|
6781
|
+
}
|
|
6569
6782
|
}
|
|
6570
6783
|
stagePrimarySessionState(session, verificationMethod, host, sessionExpiry, recap) {
|
|
6571
6784
|
if (!session?.siwe) return { cache: void 0, grants: [] };
|
|
@@ -6614,7 +6827,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6614
6827
|
};
|
|
6615
6828
|
}
|
|
6616
6829
|
stageRestoredServiceGraph(input) {
|
|
6617
|
-
const graph = this.createServiceGraphLifetime();
|
|
6830
|
+
const graph = this.createServiceGraphLifetime(input.serviceSession);
|
|
6618
6831
|
const core = this.auth ? new import_sdk_core11.TinyCloud(this.auth, {
|
|
6619
6832
|
invokeAny: graph.invokeAny,
|
|
6620
6833
|
telemetry: this.config.telemetry,
|
|
@@ -6839,56 +7052,6 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
6839
7052
|
spaceService.updateConfig({ sharingService });
|
|
6840
7053
|
return { core, graph, serviceContext, kv, sql, duckdb, hooks, vault, encryption, capabilityRegistry, keyProvider, sharingService, delegationManager, spaceService };
|
|
6841
7054
|
}
|
|
6842
|
-
/**
|
|
6843
|
-
* Resolve the host a restored session should target.
|
|
6844
|
-
*
|
|
6845
|
-
* Mirrors fresh sign-in host resolution but for the restore path:
|
|
6846
|
-
* an explicit/pinned host always wins, then the hosts the session was
|
|
6847
|
-
* persisted with, then a lazy registry/fallback resolution for sessions
|
|
6848
|
-
* that predate the persisted `tinycloudHosts` field. Returns `undefined`
|
|
6849
|
-
* only when there's nothing to resolve from (no explicit host, no
|
|
6850
|
-
* persisted hosts, and no address/chainId) — in which case the existing
|
|
6851
|
-
* `config.host` (default) is left in place.
|
|
6852
|
-
*
|
|
6853
|
-
* Resolution failures are surfaced, not swallowed: a genuinely broken
|
|
6854
|
-
* registry lookup throws rather than silently falling back to a wrong host.
|
|
6855
|
-
*/
|
|
6856
|
-
async resolveRestoredHost(persistedHosts, address, chainId) {
|
|
6857
|
-
if (this.explicitHost) {
|
|
6858
|
-
return this.explicitHost;
|
|
6859
|
-
}
|
|
6860
|
-
if (persistedHosts && persistedHosts.length > 0) {
|
|
6861
|
-
return persistedHosts[0];
|
|
6862
|
-
}
|
|
6863
|
-
if (address === void 0 || chainId === void 0) {
|
|
6864
|
-
return void 0;
|
|
6865
|
-
}
|
|
6866
|
-
if (this.config.registryPolicy === "fail-closed") {
|
|
6867
|
-
const resolved2 = await (0, import_sdk_core11.resolveFailClosedTinyCloudHosts)(address, {
|
|
6868
|
-
registryUrl: this.config.tinycloudRegistryUrl,
|
|
6869
|
-
registryChainId: this.config.registryChainId,
|
|
6870
|
-
newUserHost: this.config.newUserHost,
|
|
6871
|
-
sequenceStore: this.config.registrySequenceStore,
|
|
6872
|
-
onNodeNotFound: this.config.onNodeNotFound,
|
|
6873
|
-
autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
|
|
6874
|
-
localNodeUrl: this.config.localNodeUrl,
|
|
6875
|
-
localLinkName: this.config.localLinkName,
|
|
6876
|
-
expectedNodeDid: this.config.expectedNodeDid,
|
|
6877
|
-
localNodeIdentityStore: this.config.localNodeIdentityStore
|
|
6878
|
-
});
|
|
6879
|
-
return resolved2.hosts[0];
|
|
6880
|
-
}
|
|
6881
|
-
const resolved = await (0, import_sdk_core11.resolveTinyCloudHosts)((0, import_sdk_core11.pkhDid)(address, chainId), {
|
|
6882
|
-
registryUrl: this.config.tinycloudRegistryUrl,
|
|
6883
|
-
fallbackHosts: this.config.tinycloudFallbackHosts,
|
|
6884
|
-
autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
|
|
6885
|
-
localNodeUrl: this.config.localNodeUrl,
|
|
6886
|
-
localLinkName: this.config.localLinkName,
|
|
6887
|
-
expectedNodeDid: this.config.expectedNodeDid,
|
|
6888
|
-
localNodeIdentityStore: this.config.localNodeIdentityStore
|
|
6889
|
-
});
|
|
6890
|
-
return resolved.hosts[0];
|
|
6891
|
-
}
|
|
6892
7055
|
/**
|
|
6893
7056
|
* Resolve the currently-active TinyCloudSession, preferring the auth
|
|
6894
7057
|
* layer's value (wallet mode) and falling back to the node-level
|
|
@@ -7363,10 +7526,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7363
7526
|
* second time. Only a value recorded for this exact host qualifies; older
|
|
7364
7527
|
* nodes that omit `nodeId` fall through to the fetch.
|
|
7365
7528
|
*/
|
|
7366
|
-
async fetchNodeId() {
|
|
7367
|
-
const cached = this.auth?.nodeIdForHost(
|
|
7529
|
+
async fetchNodeId(host = this.config.host) {
|
|
7530
|
+
const cached = this.auth?.nodeIdForHost(host);
|
|
7368
7531
|
if (cached) return cached;
|
|
7369
|
-
const response = await fetch(`${
|
|
7532
|
+
const response = await fetch(`${host}/info`);
|
|
7370
7533
|
if (!response.ok) {
|
|
7371
7534
|
throw await (0, import_sdk_core11.httpResponseError)(response, "Failed to fetch node info");
|
|
7372
7535
|
}
|
|
@@ -7414,10 +7577,24 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7414
7577
|
)
|
|
7415
7578
|
};
|
|
7416
7579
|
}
|
|
7417
|
-
async
|
|
7418
|
-
const
|
|
7419
|
-
|
|
7420
|
-
);
|
|
7580
|
+
async encryptionDestination(networkId) {
|
|
7581
|
+
const destination = (await this.routingDestinations(networkId, "encryption"))[0];
|
|
7582
|
+
if (!destination) throw new Error("No encryption destination is registered");
|
|
7583
|
+
await (0, import_sdk_services5.verifyResourceDestination)(destination, globalThis.fetch.bind(globalThis));
|
|
7584
|
+
return { ...destination, nodeDid: destination.nodeDid ?? await this.fetchNodeId(destination.url) };
|
|
7585
|
+
}
|
|
7586
|
+
async fetchEncryptionNetworkAt(host, networkId, fetchFn, callerSignal) {
|
|
7587
|
+
let response;
|
|
7588
|
+
const timeout = AbortSignal.timeout(5e3);
|
|
7589
|
+
try {
|
|
7590
|
+
response = await fetchFn(`${host}/encryption/networks/${encodeURIComponent(networkId)}`, {
|
|
7591
|
+
signal: callerSignal ? AbortSignal.any([callerSignal, timeout]) : timeout,
|
|
7592
|
+
redirect: "error"
|
|
7593
|
+
});
|
|
7594
|
+
} catch (error) {
|
|
7595
|
+
if ((0, import_sdk_services5.routingFailure)(error) || callerSignal?.aborted || !timeout.aborted && error instanceof Error && error.name === "AbortError") throw error;
|
|
7596
|
+
throw new import_sdk_services5.NodeNotRespondingError([host], error);
|
|
7597
|
+
}
|
|
7421
7598
|
if (response.status === 404) return null;
|
|
7422
7599
|
if (!response.ok) {
|
|
7423
7600
|
throw await (0, import_sdk_core11.httpResponseError)(response, `Failed to fetch encryption network ${networkId}`);
|
|
@@ -7427,18 +7604,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7427
7604
|
}
|
|
7428
7605
|
createEncryptionService(binding) {
|
|
7429
7606
|
const graph = binding?.graph ?? this._serviceGraph;
|
|
7430
|
-
const host = binding?.host ?? this.config.host;
|
|
7431
7607
|
const session = binding?.session ?? this.requireEncryptionSession();
|
|
7432
7608
|
const did = binding?.did ?? this.did;
|
|
7433
7609
|
const address = binding?.address ?? this._address;
|
|
7434
7610
|
const chainId = binding?.chainId ?? this._chainId;
|
|
7435
7611
|
const crypto2 = this.createEncryptionCrypto();
|
|
7436
|
-
const descriptorCache = /* @__PURE__ */ new Map();
|
|
7437
7612
|
const transport = {
|
|
7438
|
-
postDecrypt: async ({ networkId, authorization, canonicalBody, signal }) => {
|
|
7613
|
+
postDecrypt: async ({ targetNode, networkId, authorization, canonicalBody, signal }) => {
|
|
7439
7614
|
graph.assertActive();
|
|
7615
|
+
const destination = await this.encryptionDestination(networkId);
|
|
7616
|
+
if (destination.nodeDid !== targetNode) throw new import_sdk_services5.NodeIdentityMismatchError(destination.url, destination.nodeDid, targetNode);
|
|
7440
7617
|
const response = await graph.fetch(
|
|
7441
|
-
`${
|
|
7618
|
+
`${destination.url}/encryption/networks/${encodeURIComponent(networkId)}/decrypt`,
|
|
7442
7619
|
{
|
|
7443
7620
|
method: "POST",
|
|
7444
7621
|
headers: {
|
|
@@ -7451,7 +7628,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7451
7628
|
);
|
|
7452
7629
|
graph.assertActive();
|
|
7453
7630
|
if (!response.ok) {
|
|
7454
|
-
const permissionHint = response.status === 401 || response.status === 403 ? (0,
|
|
7631
|
+
const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services6.parsePermissionHint)({
|
|
7455
7632
|
service: "tinycloud.encryption",
|
|
7456
7633
|
path: networkId,
|
|
7457
7634
|
actions: ["tinycloud.encryption/decrypt"]
|
|
@@ -7466,6 +7643,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7466
7643
|
}
|
|
7467
7644
|
};
|
|
7468
7645
|
return new import_sdk_core11.EncryptionService({
|
|
7646
|
+
resolveTargetNode: async (networkId) => (await this.encryptionDestination(networkId)).nodeDid,
|
|
7469
7647
|
crypto: crypto2,
|
|
7470
7648
|
signer: {
|
|
7471
7649
|
signDecryptInvocation: async (input) => {
|
|
@@ -7489,18 +7667,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7489
7667
|
node: {
|
|
7490
7668
|
fetchByNetworkId: async (networkId) => {
|
|
7491
7669
|
graph.assertActive();
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
pending = this.fetchEncryptionNetworkAt(host, networkId, graph.fetch).then((descriptor2) => {
|
|
7495
|
-
if (descriptor2 === null) descriptorCache.delete(networkId);
|
|
7496
|
-
return descriptor2;
|
|
7497
|
-
}).catch((error) => {
|
|
7498
|
-
descriptorCache.delete(networkId);
|
|
7499
|
-
throw error;
|
|
7500
|
-
});
|
|
7501
|
-
descriptorCache.set(networkId, pending);
|
|
7502
|
-
}
|
|
7503
|
-
const descriptor = await pending;
|
|
7670
|
+
const destination = await this.encryptionDestination(networkId);
|
|
7671
|
+
const descriptor = await this.fetchEncryptionNetworkAt(destination.url, networkId, graph.fetch, graph.signal);
|
|
7504
7672
|
graph.assertActive();
|
|
7505
7673
|
return descriptor;
|
|
7506
7674
|
}
|
|
@@ -7508,13 +7676,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7508
7676
|
wellKnown: {
|
|
7509
7677
|
fetchWellKnown: async (principal, discoveryKey) => {
|
|
7510
7678
|
graph.assertActive();
|
|
7679
|
+
const destination = await this.encryptionDestination(this.getDefaultEncryptionNetworkId());
|
|
7680
|
+
if (this.auth?.registryRecordPresent) return null;
|
|
7511
7681
|
if (!address || !didPrincipalMatches2(principal, did)) {
|
|
7512
7682
|
return null;
|
|
7513
7683
|
}
|
|
7514
7684
|
const publicSpaceId = (0, import_sdk_core11.makePublicSpaceId)(address, chainId);
|
|
7515
7685
|
const encodedKey = discoveryKey.split("/").map(encodeURIComponent).join("/");
|
|
7516
7686
|
const response = await graph.fetch(
|
|
7517
|
-
`${
|
|
7687
|
+
`${destination.url}/public/${encodeURIComponent(publicSpaceId)}/kv/${encodedKey}`,
|
|
7518
7688
|
{ method: "GET" }
|
|
7519
7689
|
);
|
|
7520
7690
|
graph.assertActive();
|
|
@@ -7884,7 +8054,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
7884
8054
|
const signature = await this.signer.signMessage(prepared.siwe);
|
|
7885
8055
|
assertOwnerGraphActive();
|
|
7886
8056
|
const delegationSession = this.wasmBindings.completeSessionSetup({ ...prepared, signature });
|
|
7887
|
-
const activation = await (
|
|
8057
|
+
const activation = await this.activateSignedSession(delegationSession, prepared.siwe, host);
|
|
7888
8058
|
assertOwnerGraphActive();
|
|
7889
8059
|
if (!activation.success) {
|
|
7890
8060
|
throw Object.assign(
|
|
@@ -8203,15 +8373,16 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8203
8373
|
async getEncryptionNetwork(nameOrNetworkId = this.getDefaultEncryptionNetworkId()) {
|
|
8204
8374
|
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
8205
8375
|
return this.fetchEncryptionNetworkAt(
|
|
8206
|
-
this.
|
|
8376
|
+
(await this.encryptionDestination(networkId)).url,
|
|
8207
8377
|
networkId,
|
|
8208
8378
|
globalThis.fetch.bind(globalThis)
|
|
8209
8379
|
);
|
|
8210
8380
|
}
|
|
8211
8381
|
async createEncryptionNetwork(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
8212
|
-
const targetNode = await this.fetchNodeId();
|
|
8213
8382
|
const ownerDid = this.did;
|
|
8214
8383
|
const networkId = this.getDefaultEncryptionNetworkId(name);
|
|
8384
|
+
const destination = await this.encryptionDestination(networkId);
|
|
8385
|
+
const targetNode = destination.nodeDid;
|
|
8215
8386
|
const body = {
|
|
8216
8387
|
name,
|
|
8217
8388
|
ownerDid,
|
|
@@ -8234,7 +8405,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8234
8405
|
action: NETWORK_CREATE_ACTION2,
|
|
8235
8406
|
facts
|
|
8236
8407
|
});
|
|
8237
|
-
const response = await fetch(`${
|
|
8408
|
+
const response = await this._serviceGraph.fetch(`${destination.url}/encryption/networks`, {
|
|
8238
8409
|
method: "POST",
|
|
8239
8410
|
headers: {
|
|
8240
8411
|
Authorization: signed.authorization,
|
|
@@ -8327,7 +8498,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8327
8498
|
);
|
|
8328
8499
|
if (result.status !== "ok") {
|
|
8329
8500
|
if (result.status === "permission_required") {
|
|
8330
|
-
const hint = (0,
|
|
8501
|
+
const hint = (0, import_sdk_services6.parsePermissionHint)(result.hint);
|
|
8331
8502
|
if (hint === void 0) return { status: "read_failed" };
|
|
8332
8503
|
return {
|
|
8333
8504
|
status: "permission_required",
|
|
@@ -8574,6 +8745,97 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8574
8745
|
}
|
|
8575
8746
|
return { recap: exactVerifiedRecap(verified), expiresAt };
|
|
8576
8747
|
}
|
|
8748
|
+
async activateResourceSession(delegationHeader, resources, hostHint, signal) {
|
|
8749
|
+
const targets = /* @__PURE__ */ new Map();
|
|
8750
|
+
const routedSpaces = [];
|
|
8751
|
+
let unserved;
|
|
8752
|
+
let requestedResource;
|
|
8753
|
+
for (const resource of new Set(resources)) {
|
|
8754
|
+
requestedResource ?? (requestedResource = resource);
|
|
8755
|
+
signal?.throwIfAborted();
|
|
8756
|
+
try {
|
|
8757
|
+
const encryption = resource.startsWith("urn:tinycloud:encryption:");
|
|
8758
|
+
const destinations = await this.routingDestinations(
|
|
8759
|
+
resource,
|
|
8760
|
+
encryption ? "encryption" : "host",
|
|
8761
|
+
[hostHint ?? this.config.host]
|
|
8762
|
+
);
|
|
8763
|
+
if (!encryption && destinations.some(({ nodeDid }) => nodeDid !== void 0)) routedSpaces.push(resource);
|
|
8764
|
+
for (const destination of destinations) {
|
|
8765
|
+
let target = targets.get(destination.url);
|
|
8766
|
+
if (!target) {
|
|
8767
|
+
target = { destination, spaces: [] };
|
|
8768
|
+
targets.set(destination.url, target);
|
|
8769
|
+
}
|
|
8770
|
+
if (!encryption && destination.nodeDid !== void 0) target.spaces.push(resource);
|
|
8771
|
+
}
|
|
8772
|
+
} catch (error) {
|
|
8773
|
+
if (!(error instanceof import_sdk_core11.NodeNotFoundError)) throw error;
|
|
8774
|
+
unserved ?? (unserved = error);
|
|
8775
|
+
}
|
|
8776
|
+
}
|
|
8777
|
+
if (targets.size === 0) throw unserved ?? new import_sdk_services5.ResourceNotRoutedError(requestedResource ?? "session grant");
|
|
8778
|
+
const succeeded = [];
|
|
8779
|
+
const accepted = [];
|
|
8780
|
+
const failed = [];
|
|
8781
|
+
let refusal;
|
|
8782
|
+
for (const { destination: target, spaces } of targets.values()) {
|
|
8783
|
+
signal?.throwIfAborted();
|
|
8784
|
+
try {
|
|
8785
|
+
await (0, import_sdk_services5.verifyResourceDestination)(target, globalThis.fetch.bind(globalThis));
|
|
8786
|
+
const timeout = AbortSignal.timeout(5e3);
|
|
8787
|
+
const result = await (0, import_sdk_core11.activateSessionWithHost)(
|
|
8788
|
+
target.url,
|
|
8789
|
+
delegationHeader,
|
|
8790
|
+
signal ? AbortSignal.any([signal, timeout]) : timeout
|
|
8791
|
+
);
|
|
8792
|
+
this.throwRegistryRefusal(result.status, result.error ?? "");
|
|
8793
|
+
if (result.success) {
|
|
8794
|
+
const skipped = result.skipped?.find((space) => spaces.some((expected) => this.spaceIdsEqual(space, expected)));
|
|
8795
|
+
if (skipped) {
|
|
8796
|
+
failed.push({ url: target.url, status: result.status, cause: new import_sdk_services5.ResourceNotRoutedError(skipped) });
|
|
8797
|
+
continue;
|
|
8798
|
+
}
|
|
8799
|
+
succeeded.push(target.url);
|
|
8800
|
+
accepted.push(result);
|
|
8801
|
+
} else {
|
|
8802
|
+
refusal = result;
|
|
8803
|
+
failed.push({ url: target.url, status: result.status, cause: result });
|
|
8804
|
+
}
|
|
8805
|
+
} catch (error) {
|
|
8806
|
+
if (signal?.aborted) throw error;
|
|
8807
|
+
failed.push({ url: target.url, cause: (0, import_sdk_services5.routingFailure)(error) ? error : new import_sdk_services5.NodeNotRespondingError([target.url], error) });
|
|
8808
|
+
}
|
|
8809
|
+
}
|
|
8810
|
+
if (failed.length > 0) {
|
|
8811
|
+
if (targets.size > 1) throw new import_sdk_services5.PartialNodeWriteError(succeeded, failed);
|
|
8812
|
+
if (refusal) return refusal;
|
|
8813
|
+
throw failed[0].cause;
|
|
8814
|
+
}
|
|
8815
|
+
const activated = new Set(accepted.flatMap((result) => result.activated ?? []));
|
|
8816
|
+
return {
|
|
8817
|
+
...accepted[0],
|
|
8818
|
+
activated: [...activated],
|
|
8819
|
+
skipped: [...new Set(accepted.flatMap((result) => result.skipped ?? []))].filter((space) => !activated.has(space) && !routedSpaces.some((expected) => this.spaceIdsEqual(space, expected)))
|
|
8820
|
+
};
|
|
8821
|
+
}
|
|
8822
|
+
activateRoutedDelegation(delegation, signal) {
|
|
8823
|
+
const resources = this.operationsFromDelegation(delegation).map(
|
|
8824
|
+
(operation) => operation.resource?.startsWith("urn:tinycloud:encryption:") ? operation.resource.split("/")[0] : operation.spaceId ?? delegation.spaceId
|
|
8825
|
+
);
|
|
8826
|
+
return this.activateResourceSession(delegation.delegationHeader, resources, delegation.host, signal);
|
|
8827
|
+
}
|
|
8828
|
+
activateSignedSession(session, siwe, hostHint, signal) {
|
|
8829
|
+
const resources = this.parseRecapWithCaveats(siwe).map(
|
|
8830
|
+
(entry) => this.isEncryptionNetworkOperation(this.invocationServiceName(entry.service), entry.path, entry.space) ? entry.path.split("/")[0] : entry.space.startsWith("tinycloud:") ? entry.space : session.spaceId
|
|
8831
|
+
);
|
|
8832
|
+
return this.activateResourceSession(
|
|
8833
|
+
session.delegationHeader,
|
|
8834
|
+
resources.length > 0 ? resources : [session.spaceId],
|
|
8835
|
+
hostHint,
|
|
8836
|
+
signal
|
|
8837
|
+
);
|
|
8838
|
+
}
|
|
8577
8839
|
/**
|
|
8578
8840
|
* Install a portable runtime permission delegation into this SDK instance so
|
|
8579
8841
|
* matching service calls and downstream `delegateTo()` calls can use it.
|
|
@@ -8593,16 +8855,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8593
8855
|
`Runtime delegation targets ${delegation.delegateDID} but this session key is ${session.verificationMethod}.`
|
|
8594
8856
|
);
|
|
8595
8857
|
}
|
|
8596
|
-
const targetHost = delegation.host ?? this.config.host;
|
|
8597
8858
|
let activateResult;
|
|
8598
8859
|
try {
|
|
8599
|
-
activateResult = await (
|
|
8600
|
-
targetHost,
|
|
8601
|
-
delegation.delegationHeader,
|
|
8602
|
-
graph.signal
|
|
8603
|
-
);
|
|
8860
|
+
activateResult = await this.activateRoutedDelegation(delegation, graph.signal);
|
|
8604
8861
|
} catch (cause) {
|
|
8605
8862
|
graph.assertActive();
|
|
8863
|
+
if ((0, import_sdk_services5.routingFailure)(cause)) throw cause;
|
|
8606
8864
|
throw Object.assign(
|
|
8607
8865
|
new Error("The TinyCloud host could not be reached to activate the delegation."),
|
|
8608
8866
|
{ code: "ACTIVATION_TRANSPORT_FAILED", cause }
|
|
@@ -8758,11 +9016,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8758
9016
|
...prepared,
|
|
8759
9017
|
signature
|
|
8760
9018
|
});
|
|
8761
|
-
const
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
9019
|
+
const delegation = this.runtimeDelegationFromSession(
|
|
9020
|
+
delegatedSession,
|
|
9021
|
+
delegatedEntries,
|
|
9022
|
+
spaceId,
|
|
9023
|
+
captured,
|
|
9024
|
+
expiresAt,
|
|
9025
|
+
{ siwe: prepared.siwe, signature }
|
|
9026
|
+
);
|
|
9027
|
+
const activateResult = await this.activateRoutedDelegation(delegation, graph.signal).catch((error) => {
|
|
8766
9028
|
graph.assertActive();
|
|
8767
9029
|
throw error;
|
|
8768
9030
|
});
|
|
@@ -8778,14 +9040,6 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8778
9040
|
{ cause: activateResult }
|
|
8779
9041
|
);
|
|
8780
9042
|
}
|
|
8781
|
-
const delegation = this.runtimeDelegationFromSession(
|
|
8782
|
-
delegatedSession,
|
|
8783
|
-
delegatedEntries,
|
|
8784
|
-
spaceId,
|
|
8785
|
-
captured,
|
|
8786
|
-
expiresAt,
|
|
8787
|
-
{ siwe: prepared.siwe, signature }
|
|
8788
|
-
);
|
|
8789
9043
|
graph.assertActive();
|
|
8790
9044
|
assertCapturedKey?.();
|
|
8791
9045
|
this.runtimePermissionGrants.push({
|
|
@@ -8930,7 +9184,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8930
9184
|
if (!publicSpaceId) {
|
|
8931
9185
|
throw new Error("Public space not enabled. Set enablePublicSpace: true in config.");
|
|
8932
9186
|
}
|
|
8933
|
-
await this.assertMayCreateSpace();
|
|
9187
|
+
await this.assertMayCreateSpace(publicSpaceId);
|
|
8934
9188
|
await this.auth.hostPublicSpace(publicSpaceId);
|
|
8935
9189
|
const kvActions = [import_sdk_core11.KV.PUT, import_sdk_core11.KV.GET, import_sdk_core11.KV.DEL, import_sdk_core11.KV.LIST, import_sdk_core11.KV.METADATA];
|
|
8936
9190
|
const abilities = { kv: { "": kvActions } };
|
|
@@ -8953,10 +9207,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
8953
9207
|
...prepared,
|
|
8954
9208
|
signature
|
|
8955
9209
|
});
|
|
8956
|
-
const activateResult = await (
|
|
8957
|
-
this.config.host,
|
|
8958
|
-
delegationSession.delegationHeader
|
|
8959
|
-
);
|
|
9210
|
+
const activateResult = await this.activateSignedSession(delegationSession, prepared.siwe);
|
|
8960
9211
|
if (!activateResult.success) {
|
|
8961
9212
|
throw Object.assign(
|
|
8962
9213
|
new Error(`Failed to activate public space delegation: ${describeHostFailure2(activateResult)}`),
|
|
@@ -9506,10 +9757,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
9506
9757
|
if (onPrepared) {
|
|
9507
9758
|
await onPrepared(delegation);
|
|
9508
9759
|
}
|
|
9509
|
-
const activateResult = await (
|
|
9510
|
-
this.config.host,
|
|
9511
|
-
delegationHeader
|
|
9512
|
-
);
|
|
9760
|
+
const activateResult = await this.activateRoutedDelegation(delegation);
|
|
9513
9761
|
assertDelegationActivated(activateResult, delegation, requireActivation);
|
|
9514
9762
|
return delegation;
|
|
9515
9763
|
}
|
|
@@ -9543,10 +9791,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
9543
9791
|
if (onPrepared) {
|
|
9544
9792
|
await onPrepared(delegation);
|
|
9545
9793
|
}
|
|
9546
|
-
const activateResult = await (
|
|
9547
|
-
targetHost,
|
|
9548
|
-
delegationHeader
|
|
9549
|
-
);
|
|
9794
|
+
const activateResult = await this.activateRoutedDelegation(delegation);
|
|
9550
9795
|
assertDelegationActivated(activateResult, delegation, requireActivation);
|
|
9551
9796
|
return delegation;
|
|
9552
9797
|
}
|
|
@@ -10198,10 +10443,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
10198
10443
|
...prepared,
|
|
10199
10444
|
signature
|
|
10200
10445
|
});
|
|
10201
|
-
const activateResult = await (
|
|
10202
|
-
this.config.host,
|
|
10203
|
-
delegationSession.delegationHeader
|
|
10204
|
-
);
|
|
10446
|
+
const activateResult = await this.activateSignedSession(delegationSession, prepared.siwe);
|
|
10205
10447
|
if (!activateResult.success) {
|
|
10206
10448
|
throw Object.assign(
|
|
10207
10449
|
new Error(`Failed to activate delegation: ${describeHostFailure2(activateResult)}`),
|
|
@@ -10246,10 +10488,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
10246
10488
|
...publicPrepared,
|
|
10247
10489
|
signature: publicSignature
|
|
10248
10490
|
});
|
|
10249
|
-
const publicActivateResult = await (
|
|
10250
|
-
this.config.host,
|
|
10251
|
-
publicSession.delegationHeader
|
|
10252
|
-
);
|
|
10491
|
+
const publicActivateResult = await this.activateSignedSession(publicSession, publicPrepared.siwe);
|
|
10253
10492
|
if (publicActivateResult.success) {
|
|
10254
10493
|
result.publicDelegation = {
|
|
10255
10494
|
cid: publicSession.delegationCid,
|
|
@@ -10355,11 +10594,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
10355
10594
|
...prepared,
|
|
10356
10595
|
signature
|
|
10357
10596
|
});
|
|
10358
|
-
const activateResult = await (
|
|
10359
|
-
targetHost,
|
|
10360
|
-
invokerSession.delegationHeader,
|
|
10361
|
-
graph.signal
|
|
10362
|
-
).catch((error) => {
|
|
10597
|
+
const activateResult = await this.activateSignedSession(invokerSession, prepared.siwe, targetHost, graph.signal).catch((error) => {
|
|
10363
10598
|
graph.assertActive();
|
|
10364
10599
|
throw error;
|
|
10365
10600
|
});
|
|
@@ -10486,10 +10721,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
10486
10721
|
...prepared,
|
|
10487
10722
|
signature
|
|
10488
10723
|
});
|
|
10489
|
-
const activateResult = await (
|
|
10490
|
-
targetHost,
|
|
10491
|
-
subDelegationSession.delegationHeader
|
|
10492
|
-
);
|
|
10724
|
+
const activateResult = await this.activateSignedSession(subDelegationSession, prepared.siwe, targetHost);
|
|
10493
10725
|
if (!activateResult.success) {
|
|
10494
10726
|
throw Object.assign(
|
|
10495
10727
|
new Error(`Failed to activate sub-delegation: ${describeHostFailure2(activateResult)}`),
|
|
@@ -10569,7 +10801,10 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
|
|
|
10569
10801
|
KVService,
|
|
10570
10802
|
ManifestValidationError,
|
|
10571
10803
|
MemorySessionStorage,
|
|
10804
|
+
NodeIdentityMismatchError,
|
|
10805
|
+
NodeNotRespondingError,
|
|
10572
10806
|
NodeUserAuthorization,
|
|
10807
|
+
PartialNodeWriteError,
|
|
10573
10808
|
PermissionNotInManifestError,
|
|
10574
10809
|
PrefixedKVService,
|
|
10575
10810
|
ProtocolMismatchError,
|