@tinycloud/node-sdk 2.7.0-beta.2 → 2.7.0-beta.4
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/{core-BfqzTbfY.d.cts → core-D_KNrE_y.d.cts} +153 -8
- package/dist/{core-BfqzTbfY.d.ts → core-D_KNrE_y.d.ts} +153 -8
- package/dist/core.cjs +1152 -260
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1083 -181
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1470 -301
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +1361 -181
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/core.cjs
CHANGED
|
@@ -30,103 +30,105 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/core.ts
|
|
31
31
|
var core_exports = {};
|
|
32
32
|
__export(core_exports, {
|
|
33
|
-
ACCOUNT_REGISTRY_PATH: () =>
|
|
34
|
-
ACCOUNT_REGISTRY_SPACE: () =>
|
|
33
|
+
ACCOUNT_REGISTRY_PATH: () => import_sdk_core12.ACCOUNT_REGISTRY_PATH,
|
|
34
|
+
ACCOUNT_REGISTRY_SPACE: () => import_sdk_core12.ACCOUNT_REGISTRY_SPACE,
|
|
35
35
|
AccountService: () => import_sdk_core4.AccountService,
|
|
36
|
-
AutoApproveSpaceCreationHandler: () =>
|
|
37
|
-
CapabilityKeyRegistry: () =>
|
|
38
|
-
CapabilityKeyRegistryErrorCodes: () =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
AutoApproveSpaceCreationHandler: () => import_sdk_core11.AutoApproveSpaceCreationHandler,
|
|
37
|
+
CapabilityKeyRegistry: () => import_sdk_core18.CapabilityKeyRegistry,
|
|
38
|
+
CapabilityKeyRegistryErrorCodes: () => import_sdk_core18.CapabilityKeyRegistryErrorCodes,
|
|
39
|
+
CaveatedDelegationUnsupportedError: () => import_sdk_core12.CaveatedDelegationUnsupportedError,
|
|
40
|
+
DEFAULT_MANIFEST_SPACE: () => import_sdk_core12.DEFAULT_MANIFEST_SPACE,
|
|
41
|
+
DEFAULT_MANIFEST_VERSION: () => import_sdk_core12.DEFAULT_MANIFEST_VERSION,
|
|
42
|
+
DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => import_sdk_core13.DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
43
|
+
DataVaultService: () => import_sdk_core16.DataVaultService,
|
|
44
|
+
DatabaseHandle: () => import_sdk_core14.DatabaseHandle,
|
|
44
45
|
DelegatedAccess: () => DelegatedAccess,
|
|
45
|
-
DelegationErrorCodes: () =>
|
|
46
|
-
DelegationManager: () =>
|
|
47
|
-
DuckDbAction: () =>
|
|
48
|
-
DuckDbDatabaseHandle: () =>
|
|
49
|
-
DuckDbService: () =>
|
|
46
|
+
DelegationErrorCodes: () => import_sdk_core17.DelegationErrorCodes,
|
|
47
|
+
DelegationManager: () => import_sdk_core17.DelegationManager,
|
|
48
|
+
DuckDbAction: () => import_sdk_core15.DuckDbAction,
|
|
49
|
+
DuckDbDatabaseHandle: () => import_sdk_core15.DuckDbDatabaseHandle,
|
|
50
|
+
DuckDbService: () => import_sdk_core15.DuckDbService,
|
|
50
51
|
FileSessionStorage: () => FileSessionStorage,
|
|
51
|
-
IdentityParseError: () =>
|
|
52
|
-
KVService: () =>
|
|
53
|
-
ManifestValidationError: () =>
|
|
52
|
+
IdentityParseError: () => import_sdk_core11.IdentityParseError,
|
|
53
|
+
KVService: () => import_sdk_core13.KVService,
|
|
54
|
+
ManifestValidationError: () => import_sdk_core12.ManifestValidationError,
|
|
54
55
|
MemorySessionStorage: () => MemorySessionStorage,
|
|
55
56
|
NodeUserAuthorization: () => NodeUserAuthorization,
|
|
56
|
-
PermissionNotInManifestError: () =>
|
|
57
|
-
PrefixedKVService: () =>
|
|
58
|
-
ProtocolMismatchError: () =>
|
|
59
|
-
SECRET_NAME_RE: () =>
|
|
60
|
-
SQLAction: () =>
|
|
61
|
-
SQLService: () =>
|
|
62
|
-
SecretsService: () =>
|
|
63
|
-
ServiceContext: () =>
|
|
64
|
-
SessionExpiredError: () =>
|
|
65
|
-
SharingService: () =>
|
|
66
|
-
SilentNotificationHandler: () =>
|
|
67
|
-
Space: () =>
|
|
68
|
-
SpaceErrorCodes: () =>
|
|
69
|
-
SpaceService: () =>
|
|
70
|
-
TinyCloud: () =>
|
|
71
|
-
TinyCloudDebugLogger: () =>
|
|
57
|
+
PermissionNotInManifestError: () => import_sdk_core12.PermissionNotInManifestError,
|
|
58
|
+
PrefixedKVService: () => import_sdk_core13.PrefixedKVService,
|
|
59
|
+
ProtocolMismatchError: () => import_sdk_core20.ProtocolMismatchError,
|
|
60
|
+
SECRET_NAME_RE: () => import_sdk_core16.SECRET_NAME_RE,
|
|
61
|
+
SQLAction: () => import_sdk_core14.SQLAction,
|
|
62
|
+
SQLService: () => import_sdk_core14.SQLService,
|
|
63
|
+
SecretsService: () => import_sdk_core16.SecretsService,
|
|
64
|
+
ServiceContext: () => import_sdk_core21.ServiceContext,
|
|
65
|
+
SessionExpiredError: () => import_sdk_core12.SessionExpiredError,
|
|
66
|
+
SharingService: () => import_sdk_core17.SharingService,
|
|
67
|
+
SilentNotificationHandler: () => import_sdk_core11.SilentNotificationHandler,
|
|
68
|
+
Space: () => import_sdk_core19.Space,
|
|
69
|
+
SpaceErrorCodes: () => import_sdk_core19.SpaceErrorCodes,
|
|
70
|
+
SpaceService: () => import_sdk_core19.SpaceService,
|
|
71
|
+
TinyCloud: () => import_sdk_core10.TinyCloud,
|
|
72
|
+
TinyCloudDebugLogger: () => import_sdk_core11.TinyCloudDebugLogger,
|
|
72
73
|
TinyCloudNode: () => TinyCloudNode,
|
|
73
|
-
UnsupportedFeatureError: () =>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
UnsupportedFeatureError: () => import_sdk_core20.UnsupportedFeatureError,
|
|
75
|
+
UnsupportedSessionRestoreError: () => UnsupportedSessionRestoreError,
|
|
76
|
+
VAULT_PERMISSION_SERVICE: () => import_sdk_core12.VAULT_PERMISSION_SERVICE,
|
|
77
|
+
VaultHeaders: () => import_sdk_core16.VaultHeaders,
|
|
78
|
+
VaultPublicSpaceKVActions: () => import_sdk_core16.VaultPublicSpaceKVActions,
|
|
79
|
+
VersionCheckError: () => import_sdk_core20.VersionCheckError,
|
|
78
80
|
WasmKeyProvider: () => WasmKeyProvider,
|
|
79
|
-
addressStorageKey: () =>
|
|
80
|
-
buildSpaceUri: () =>
|
|
81
|
-
canonicalizeAddress: () =>
|
|
82
|
-
canonicalizeDid: () =>
|
|
83
|
-
canonicalizeDidUrl: () =>
|
|
84
|
-
canonicalizeNetworkId: () =>
|
|
85
|
-
canonicalizeSecretScope: () =>
|
|
86
|
-
checkNodeInfo: () =>
|
|
87
|
-
clearTinyCloudDebugLogs: () =>
|
|
88
|
-
composeManifestRequest: () =>
|
|
89
|
-
createCapabilityKeyRegistry: () =>
|
|
81
|
+
addressStorageKey: () => import_sdk_core11.addressStorageKey,
|
|
82
|
+
buildSpaceUri: () => import_sdk_core19.buildSpaceUri,
|
|
83
|
+
canonicalizeAddress: () => import_sdk_core11.canonicalizeAddress,
|
|
84
|
+
canonicalizeDid: () => import_sdk_core11.canonicalizeDid,
|
|
85
|
+
canonicalizeDidUrl: () => import_sdk_core11.canonicalizeDidUrl,
|
|
86
|
+
canonicalizeNetworkId: () => import_sdk_core11.canonicalizeNetworkId,
|
|
87
|
+
canonicalizeSecretScope: () => import_sdk_core16.canonicalizeSecretScope,
|
|
88
|
+
checkNodeInfo: () => import_sdk_core20.checkNodeInfo,
|
|
89
|
+
clearTinyCloudDebugLogs: () => import_sdk_core11.clearTinyCloudDebugLogs,
|
|
90
|
+
composeManifestRequest: () => import_sdk_core12.composeManifestRequest,
|
|
91
|
+
createCapabilityKeyRegistry: () => import_sdk_core18.createCapabilityKeyRegistry,
|
|
90
92
|
createOpenKeyCallbackSigningStrategy: () => import_sdk_core2.createOpenKeyCallbackSigningStrategy,
|
|
91
|
-
createSharingService: () =>
|
|
92
|
-
createSpaceService: () =>
|
|
93
|
-
createVaultCrypto: () =>
|
|
93
|
+
createSharingService: () => import_sdk_core17.createSharingService,
|
|
94
|
+
createSpaceService: () => import_sdk_core19.createSpaceService,
|
|
95
|
+
createVaultCrypto: () => import_sdk_core16.createVaultCrypto,
|
|
94
96
|
createWasmKeyProvider: () => createWasmKeyProvider,
|
|
95
97
|
defaultSignStrategy: () => defaultSignStrategy,
|
|
96
|
-
defaultSpaceCreationHandler: () =>
|
|
98
|
+
defaultSpaceCreationHandler: () => import_sdk_core11.defaultSpaceCreationHandler,
|
|
97
99
|
deserializeDelegation: () => deserializeDelegation,
|
|
98
|
-
didCacheKey: () =>
|
|
99
|
-
didEquals: () =>
|
|
100
|
-
disableTinyCloudDebug: () =>
|
|
101
|
-
enableTinyCloudDebug: () =>
|
|
102
|
-
expandActionShortNames: () =>
|
|
103
|
-
expandPermissionEntries: () =>
|
|
104
|
-
expandPermissionEntry: () =>
|
|
105
|
-
getTinyCloudDebugLogs: () =>
|
|
106
|
-
installTinyCloudDebugGlobals: () =>
|
|
107
|
-
isCapabilitySubset: () =>
|
|
108
|
-
isEvmAddress: () =>
|
|
109
|
-
loadManifest: () =>
|
|
110
|
-
makePkhSpaceId: () =>
|
|
111
|
-
makePublicSpaceId: () =>
|
|
112
|
-
parseCanonicalNetworkId: () =>
|
|
113
|
-
parseExpiry: () =>
|
|
114
|
-
parsePkhDid: () =>
|
|
115
|
-
parseSpaceUri: () =>
|
|
116
|
-
pkhDid: () =>
|
|
117
|
-
principalDid: () =>
|
|
118
|
-
principalDidEquals: () =>
|
|
119
|
-
resolveManifest: () =>
|
|
120
|
-
resolveSecretListPrefix: () =>
|
|
121
|
-
resolveSecretPath: () =>
|
|
122
|
-
resourceCapabilitiesToSpaceAbilitiesMap: () =>
|
|
100
|
+
didCacheKey: () => import_sdk_core11.didCacheKey,
|
|
101
|
+
didEquals: () => import_sdk_core11.didEquals,
|
|
102
|
+
disableTinyCloudDebug: () => import_sdk_core11.disableTinyCloudDebug,
|
|
103
|
+
enableTinyCloudDebug: () => import_sdk_core11.enableTinyCloudDebug,
|
|
104
|
+
expandActionShortNames: () => import_sdk_core12.expandActionShortNames,
|
|
105
|
+
expandPermissionEntries: () => import_sdk_core12.expandPermissionEntries,
|
|
106
|
+
expandPermissionEntry: () => import_sdk_core12.expandPermissionEntry,
|
|
107
|
+
getTinyCloudDebugLogs: () => import_sdk_core11.getTinyCloudDebugLogs,
|
|
108
|
+
installTinyCloudDebugGlobals: () => import_sdk_core11.installTinyCloudDebugGlobals,
|
|
109
|
+
isCapabilitySubset: () => import_sdk_core12.isCapabilitySubset,
|
|
110
|
+
isEvmAddress: () => import_sdk_core11.isEvmAddress,
|
|
111
|
+
loadManifest: () => import_sdk_core12.loadManifest,
|
|
112
|
+
makePkhSpaceId: () => import_sdk_core11.makePkhSpaceId,
|
|
113
|
+
makePublicSpaceId: () => import_sdk_core19.makePublicSpaceId,
|
|
114
|
+
parseCanonicalNetworkId: () => import_sdk_core11.parseCanonicalNetworkId,
|
|
115
|
+
parseExpiry: () => import_sdk_core12.parseExpiry,
|
|
116
|
+
parsePkhDid: () => import_sdk_core11.parsePkhDid,
|
|
117
|
+
parseSpaceUri: () => import_sdk_core19.parseSpaceUri,
|
|
118
|
+
pkhDid: () => import_sdk_core11.pkhDid,
|
|
119
|
+
principalDid: () => import_sdk_core11.principalDid,
|
|
120
|
+
principalDidEquals: () => import_sdk_core11.principalDidEquals,
|
|
121
|
+
resolveManifest: () => import_sdk_core12.resolveManifest,
|
|
122
|
+
resolveSecretListPrefix: () => import_sdk_core16.resolveSecretListPrefix,
|
|
123
|
+
resolveSecretPath: () => import_sdk_core16.resolveSecretPath,
|
|
124
|
+
resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core12.resourceCapabilitiesToSpaceAbilitiesMap,
|
|
123
125
|
serializeDelegation: () => serializeDelegation,
|
|
124
|
-
tinyCloudDebugLogger: () =>
|
|
125
|
-
validateManifest: () =>
|
|
126
|
+
tinyCloudDebugLogger: () => import_sdk_core11.tinyCloudDebugLogger,
|
|
127
|
+
validateManifest: () => import_sdk_core12.validateManifest
|
|
126
128
|
});
|
|
127
129
|
module.exports = __toCommonJS(core_exports);
|
|
128
|
-
var import_sdk_core9 = require("@tinycloud/sdk-core");
|
|
129
130
|
var import_sdk_core10 = require("@tinycloud/sdk-core");
|
|
131
|
+
var import_sdk_core11 = require("@tinycloud/sdk-core");
|
|
130
132
|
|
|
131
133
|
// src/storage/MemorySessionStorage.ts
|
|
132
134
|
var MemorySessionStorage = class {
|
|
@@ -467,6 +469,30 @@ var NodeUserAuthorization = class {
|
|
|
467
469
|
this.tinycloudHosts = [...hosts];
|
|
468
470
|
}
|
|
469
471
|
}
|
|
472
|
+
/** @internal Atomically adopt the state staged by TinyCloudNode.restoreSession. */
|
|
473
|
+
installRestoredSession(sessionManager, session, hosts) {
|
|
474
|
+
this.sessionManager = sessionManager;
|
|
475
|
+
this.tinycloudHosts = hosts && hosts.length > 0 ? [...hosts] : void 0;
|
|
476
|
+
this._lastActivationSkippedSpaceIds = [];
|
|
477
|
+
if (!session) {
|
|
478
|
+
this._session = void 0;
|
|
479
|
+
this._tinyCloudSession = void 0;
|
|
480
|
+
this._address = void 0;
|
|
481
|
+
this._chainId = void 0;
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
this._tinyCloudSession = { ...session };
|
|
485
|
+
this._address = session.address;
|
|
486
|
+
this._chainId = session.chainId;
|
|
487
|
+
this._session = {
|
|
488
|
+
address: session.address,
|
|
489
|
+
walletAddress: session.address,
|
|
490
|
+
chainId: session.chainId,
|
|
491
|
+
sessionKey: session.sessionKey,
|
|
492
|
+
siwe: session.siwe,
|
|
493
|
+
signature: session.signature
|
|
494
|
+
};
|
|
495
|
+
}
|
|
470
496
|
/**
|
|
471
497
|
* Ensure `tinycloudHosts` are resolved before a host-needing call.
|
|
472
498
|
*
|
|
@@ -1239,6 +1265,7 @@ var NodeUserAuthorization = class {
|
|
|
1239
1265
|
|
|
1240
1266
|
// src/TinyCloudNode.ts
|
|
1241
1267
|
var import_sdk_core8 = require("@tinycloud/sdk-core");
|
|
1268
|
+
var import_sdk_services = require("@tinycloud/sdk-services");
|
|
1242
1269
|
|
|
1243
1270
|
// src/account/AccountService.ts
|
|
1244
1271
|
var import_sdk_core4 = require("@tinycloud/sdk-core");
|
|
@@ -1661,6 +1688,9 @@ var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
|
|
|
1661
1688
|
var NETWORK_CREATE_ACTION2 = import_sdk_core8.ENCRYPTION.NETWORK_CREATE;
|
|
1662
1689
|
var DECRYPT_ACTION2 = import_sdk_core8.ENCRYPTION.DECRYPT;
|
|
1663
1690
|
var NETWORK_ADMIN_TYPE = "tinycloud.encryption.network-admin/v1";
|
|
1691
|
+
function isSecretPayload(value) {
|
|
1692
|
+
return typeof value === "object" && value !== null && "value" in value && typeof value.value === "string" && "createdAt" in value && typeof value.createdAt === "string" && "updatedAt" in value && typeof value.updatedAt === "string";
|
|
1693
|
+
}
|
|
1664
1694
|
var ROOT_DELEGATION_ACTIONS = [
|
|
1665
1695
|
import_sdk_core8.KV.PUT,
|
|
1666
1696
|
import_sdk_core8.KV.GET,
|
|
@@ -1715,6 +1745,141 @@ function didPrincipalMatches2(actual, expected) {
|
|
|
1715
1745
|
return actual === expected;
|
|
1716
1746
|
}
|
|
1717
1747
|
}
|
|
1748
|
+
function clonePersistedSessionJwk(jwk) {
|
|
1749
|
+
if (jwk === null || typeof jwk !== "object" || Array.isArray(jwk)) {
|
|
1750
|
+
throw new Error("Persisted session has an invalid private Ed25519 session key.");
|
|
1751
|
+
}
|
|
1752
|
+
try {
|
|
1753
|
+
const serialized = JSON.stringify(jwk);
|
|
1754
|
+
const cloned = serialized === void 0 ? void 0 : JSON.parse(serialized);
|
|
1755
|
+
if (cloned === null || typeof cloned !== "object" || Array.isArray(cloned)) {
|
|
1756
|
+
throw new Error("invalid JWK object");
|
|
1757
|
+
}
|
|
1758
|
+
return cloned;
|
|
1759
|
+
} catch {
|
|
1760
|
+
throw new Error("Persisted session has an invalid private Ed25519 session key.");
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
function cloneRecapCaveats(caveats) {
|
|
1764
|
+
if (!caveats) return [];
|
|
1765
|
+
const cloneJson = (value) => {
|
|
1766
|
+
if (value === null || typeof value === "boolean" || typeof value === "string") {
|
|
1767
|
+
return value;
|
|
1768
|
+
}
|
|
1769
|
+
if (typeof value === "number") {
|
|
1770
|
+
if (Number.isFinite(value)) return value;
|
|
1771
|
+
throw new Error("ReCap caveats must contain only JSON values.");
|
|
1772
|
+
}
|
|
1773
|
+
if (Array.isArray(value)) return value.map(cloneJson);
|
|
1774
|
+
if (typeof value === "object") {
|
|
1775
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1776
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
1777
|
+
throw new Error("ReCap caveats must contain only JSON values.");
|
|
1778
|
+
}
|
|
1779
|
+
const copy = /* @__PURE__ */ Object.create(null);
|
|
1780
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
1781
|
+
copy[key] = cloneJson(nested);
|
|
1782
|
+
}
|
|
1783
|
+
return copy;
|
|
1784
|
+
}
|
|
1785
|
+
throw new Error("ReCap caveats must contain only JSON values.");
|
|
1786
|
+
};
|
|
1787
|
+
try {
|
|
1788
|
+
return JSON.parse(JSON.stringify(caveats.map(cloneJson)));
|
|
1789
|
+
} catch {
|
|
1790
|
+
throw new Error("Verified persisted session ReCap contains invalid caveats.");
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
var ServiceGraphLifetime = class {
|
|
1794
|
+
constructor(invokeFn, invokeAnyFn, fetchFn) {
|
|
1795
|
+
this.invokeFn = invokeFn;
|
|
1796
|
+
this.invokeAnyFn = invokeAnyFn;
|
|
1797
|
+
this.fetchFn = fetchFn;
|
|
1798
|
+
this.abortController = new AbortController();
|
|
1799
|
+
this.contexts = /* @__PURE__ */ new Set();
|
|
1800
|
+
this.retired = false;
|
|
1801
|
+
this.invoke = (session, service, path, action, facts) => {
|
|
1802
|
+
this.assertActive();
|
|
1803
|
+
return this.invokeFn(session, service, path, action, facts);
|
|
1804
|
+
};
|
|
1805
|
+
this.invokeAny = (session, entries, facts) => {
|
|
1806
|
+
this.assertActive();
|
|
1807
|
+
return this.invokeAnyFn(session, entries, facts);
|
|
1808
|
+
};
|
|
1809
|
+
this.fetch = (url, init) => {
|
|
1810
|
+
this.assertActive();
|
|
1811
|
+
return this.fetchFn(url, {
|
|
1812
|
+
...init,
|
|
1813
|
+
signal: this.combineSignals(init?.signal)
|
|
1814
|
+
});
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
track(context) {
|
|
1818
|
+
this.assertActive();
|
|
1819
|
+
this.contexts.add(context);
|
|
1820
|
+
return context;
|
|
1821
|
+
}
|
|
1822
|
+
retire() {
|
|
1823
|
+
if (this.retired) return;
|
|
1824
|
+
this.retired = true;
|
|
1825
|
+
this.abortController.abort();
|
|
1826
|
+
try {
|
|
1827
|
+
for (const context of this.contexts) {
|
|
1828
|
+
try {
|
|
1829
|
+
const retire = context.retire;
|
|
1830
|
+
if (retire) retire.call(context);
|
|
1831
|
+
else context.abort();
|
|
1832
|
+
} catch (error) {
|
|
1833
|
+
console.error("Error retiring service graph context:", error);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
} finally {
|
|
1837
|
+
this.contexts.clear();
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
assertActive() {
|
|
1841
|
+
if (this.retired) {
|
|
1842
|
+
throw new Error("Service graph has been retired by session replacement.");
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
combineSignals(signal) {
|
|
1846
|
+
if (!signal) return this.abortController.signal;
|
|
1847
|
+
const combined = new AbortController();
|
|
1848
|
+
const abort = () => combined.abort();
|
|
1849
|
+
if (signal.aborted || this.abortController.signal.aborted) {
|
|
1850
|
+
abort();
|
|
1851
|
+
} else {
|
|
1852
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
1853
|
+
this.abortController.signal.addEventListener("abort", abort, { once: true });
|
|
1854
|
+
}
|
|
1855
|
+
return combined.signal;
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
var UnsupportedSessionRestoreError = class extends Error {
|
|
1859
|
+
constructor(reason = "it cannot replace and enumerate every live session signer") {
|
|
1860
|
+
super(`Persisted session restore is unsupported by this WASM binding because ${reason}.`);
|
|
1861
|
+
this.code = "RESTORE_SESSION_KEY_REPLACEMENT_UNSUPPORTED";
|
|
1862
|
+
this.name = "UnsupportedSessionRestoreError";
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
function canonicalRestoredVerificationMethod(canonicalVerificationMethod, persistedVerificationMethod) {
|
|
1866
|
+
if (typeof persistedVerificationMethod !== "string") return void 0;
|
|
1867
|
+
const principal = canonicalVerificationMethod.split("#", 1)[0];
|
|
1868
|
+
return persistedVerificationMethod === principal || persistedVerificationMethod === canonicalVerificationMethod ? canonicalVerificationMethod : void 0;
|
|
1869
|
+
}
|
|
1870
|
+
function persistedExpiry(value) {
|
|
1871
|
+
if (typeof value !== "string") {
|
|
1872
|
+
throw new Error("Persisted session without a SIWE expiration must include expiresAt.");
|
|
1873
|
+
}
|
|
1874
|
+
const expiry = new Date(value);
|
|
1875
|
+
if (!Number.isFinite(expiry.getTime()) || expiry.getTime() <= Date.now()) {
|
|
1876
|
+
throw new Error("Persisted session expiry is invalid or expired.");
|
|
1877
|
+
}
|
|
1878
|
+
return expiry;
|
|
1879
|
+
}
|
|
1880
|
+
function sameInstant(left, right) {
|
|
1881
|
+
return left.getTime() === right.getTime();
|
|
1882
|
+
}
|
|
1718
1883
|
function sharingActionsToAbilities(path, actions) {
|
|
1719
1884
|
var _a;
|
|
1720
1885
|
const abilities = {};
|
|
@@ -1841,6 +2006,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
1841
2006
|
this.auth = null;
|
|
1842
2007
|
this.tc = null;
|
|
1843
2008
|
this._chainId = 1;
|
|
2009
|
+
this._baseVaults = /* @__PURE__ */ new Map();
|
|
1844
2010
|
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
1845
2011
|
this._secrets = /* @__PURE__ */ new Map();
|
|
1846
2012
|
this.runtimePermissionGrants = [];
|
|
@@ -1860,26 +2026,55 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
1860
2026
|
skipped: false
|
|
1861
2027
|
};
|
|
1862
2028
|
this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
service,
|
|
2029
|
+
const operation = {
|
|
2030
|
+
spaceId: session.spaceId,
|
|
2031
|
+
service: this.invocationServiceName(service),
|
|
1866
2032
|
path,
|
|
1867
|
-
action
|
|
1868
|
-
|
|
2033
|
+
action
|
|
2034
|
+
};
|
|
2035
|
+
const grant = this.findGrantForOperation(operation);
|
|
2036
|
+
const grantedOperation = grant?.operations.find(
|
|
2037
|
+
(candidate) => this.operationCovers(candidate, operation)
|
|
1869
2038
|
);
|
|
2039
|
+
const invocationSession = !grant || grant.provenance === "primary" ? session : grant.session;
|
|
2040
|
+
if ((grantedOperation?.caveats?.length ?? 0) > 0) {
|
|
2041
|
+
if (!this.wasmBindings.invokeAny) {
|
|
2042
|
+
throw new Error("WASM binding does not support caveat-preserving invocation");
|
|
2043
|
+
}
|
|
2044
|
+
return this.wasmBindings.invokeAny(invocationSession, [{
|
|
2045
|
+
spaceId: invocationSession.spaceId,
|
|
2046
|
+
service,
|
|
2047
|
+
path,
|
|
2048
|
+
action,
|
|
2049
|
+
caveats: cloneRecapCaveats(grantedOperation.caveats)
|
|
2050
|
+
}], facts);
|
|
2051
|
+
}
|
|
2052
|
+
return this.wasmBindings.invoke(invocationSession, service, path, action, facts);
|
|
1870
2053
|
};
|
|
1871
2054
|
this.invokeAnyWithRuntimePermissions = (session, entries, facts) => {
|
|
1872
2055
|
if (!this.wasmBindings.invokeAny) {
|
|
1873
2056
|
throw new Error("WASM binding does not support invokeAny");
|
|
1874
2057
|
}
|
|
1875
|
-
const
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
);
|
|
2058
|
+
const operations = entries.flatMap((entry) => {
|
|
2059
|
+
const operation = this.operationFromInvokeAnyEntry(entry);
|
|
2060
|
+
return operation ? [operation] : [];
|
|
2061
|
+
});
|
|
2062
|
+
const grant = this.findGrantForOperations(operations);
|
|
1881
2063
|
const invocationSession = !grant || grant.provenance === "primary" ? session : grant.session;
|
|
1882
|
-
|
|
2064
|
+
const caveatPreservingEntries = grant ? entries.map((entry) => {
|
|
2065
|
+
const requested = this.operationFromInvokeAnyEntry(entry);
|
|
2066
|
+
const granted = requested && grant.operations.find(
|
|
2067
|
+
(candidate) => this.operationCovers(candidate, requested)
|
|
2068
|
+
);
|
|
2069
|
+
if (!granted?.caveats?.length) {
|
|
2070
|
+
return entry;
|
|
2071
|
+
}
|
|
2072
|
+
if (entry.caveats !== void 0 && !(0, import_sdk_core8.recapCaveatsEqual)(entry.caveats, granted.caveats)) {
|
|
2073
|
+
throw new Error("Invocation caveats do not match signed ReCap authority.");
|
|
2074
|
+
}
|
|
2075
|
+
return { ...entry, caveats: cloneRecapCaveats(granted.caveats) };
|
|
2076
|
+
}) : entries;
|
|
2077
|
+
return this.wasmBindings.invokeAny(invocationSession, caveatPreservingEntries, facts);
|
|
1883
2078
|
};
|
|
1884
2079
|
this.explicitHost = config.host;
|
|
1885
2080
|
this.config = {
|
|
@@ -1908,16 +2103,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
1908
2103
|
throw new Error("Failed to get session key JWK");
|
|
1909
2104
|
}
|
|
1910
2105
|
this.sessionKeyJwk = JSON.parse(jwkStr);
|
|
2106
|
+
this._serviceGraph = this.createServiceGraphLifetime();
|
|
1911
2107
|
this._capabilityRegistry = new import_sdk_core8.CapabilityKeyRegistry();
|
|
1912
2108
|
this._keyProvider = new WasmKeyProvider({
|
|
1913
2109
|
sessionManager: this.sessionManager
|
|
1914
2110
|
});
|
|
1915
2111
|
this.notificationHandler = config.notificationHandler ?? new import_sdk_core8.SilentNotificationHandler();
|
|
2112
|
+
const receiveOnlyGraph = this._serviceGraph;
|
|
1916
2113
|
this._sharingService = new import_sdk_core8.SharingService({
|
|
1917
2114
|
hosts: [this.config.host],
|
|
1918
2115
|
// session: undefined - not needed for receive()
|
|
1919
|
-
invoke:
|
|
1920
|
-
fetch:
|
|
2116
|
+
invoke: receiveOnlyGraph.invoke,
|
|
2117
|
+
fetch: receiveOnlyGraph.fetch,
|
|
2118
|
+
assertActive: () => receiveOnlyGraph.assertActive(),
|
|
1921
2119
|
keyProvider: this._keyProvider,
|
|
1922
2120
|
registry: this._capabilityRegistry,
|
|
1923
2121
|
createDelegationWasm: (params) => this.createDelegationWrapper(params),
|
|
@@ -1929,12 +2127,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
1929
2127
|
createKVService: (config2) => {
|
|
1930
2128
|
const prefix = config2.pathPrefix?.replace(/\/$/, "");
|
|
1931
2129
|
const kvService = new import_sdk_core8.KVService({ prefix });
|
|
1932
|
-
const kvContext = new import_sdk_core8.ServiceContext({
|
|
2130
|
+
const kvContext = receiveOnlyGraph.track(new import_sdk_core8.ServiceContext({
|
|
1933
2131
|
invoke: config2.invoke,
|
|
1934
2132
|
fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
|
|
1935
2133
|
hosts: config2.hosts,
|
|
1936
2134
|
telemetry: this.config.telemetry
|
|
1937
|
-
});
|
|
2135
|
+
}));
|
|
1938
2136
|
kvContext.setSession(config2.session);
|
|
1939
2137
|
kvService.initialize(kvContext);
|
|
1940
2138
|
return kvService;
|
|
@@ -2008,6 +2206,16 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2008
2206
|
shouldUseBootstrapSignInRequest(config) {
|
|
2009
2207
|
return config.autoBootstrapAccount !== false && config.manifest === void 0 && config.capabilityRequest === void 0 && (config.prefix ?? "default") === "default" && isOpenKeyAutoSignStrategy(config.signStrategy);
|
|
2010
2208
|
}
|
|
2209
|
+
createServiceGraphLifetime() {
|
|
2210
|
+
return new ServiceGraphLifetime(
|
|
2211
|
+
this.invokeWithRuntimePermissions,
|
|
2212
|
+
this.invokeAnyWithRuntimePermissions,
|
|
2213
|
+
// Resolve fetch at request time. This keeps the graph-owned lifetime
|
|
2214
|
+
// signal while preserving the SDK's existing injectable global fetch
|
|
2215
|
+
// behavior (including adapters that install it after construction).
|
|
2216
|
+
(url, init) => globalThis.fetch(url, init)
|
|
2217
|
+
);
|
|
2218
|
+
}
|
|
2011
2219
|
syncResolvedHostFromAuth() {
|
|
2012
2220
|
const host = this.auth?.hosts[0];
|
|
2013
2221
|
if (host) {
|
|
@@ -2077,6 +2285,27 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2077
2285
|
get sessionDid() {
|
|
2078
2286
|
return this.sessionManager.getDID(this.sessionKeyId);
|
|
2079
2287
|
}
|
|
2288
|
+
/**
|
|
2289
|
+
* Return the current session's signed ReCap capabilities after the session
|
|
2290
|
+
* has been authenticated or restored. This is intentionally distinct from
|
|
2291
|
+
* installed runtime delegations: it reports base-session authority only.
|
|
2292
|
+
*
|
|
2293
|
+
* Invalid or unparseable signed ReCap material throws so callers fail closed
|
|
2294
|
+
* rather than treating a malformed session as unrestricted authority.
|
|
2295
|
+
*/
|
|
2296
|
+
getVerifiedSessionCapabilities() {
|
|
2297
|
+
const session = this.currentTinyCloudSession();
|
|
2298
|
+
if (!session || !session.siwe) return [];
|
|
2299
|
+
return (0, import_sdk_core8.parseRecapCapabilities)(
|
|
2300
|
+
(siwe) => this.parseRecapWithCaveats(siwe),
|
|
2301
|
+
session.siwe
|
|
2302
|
+
).map((entry) => entry.service === "tinycloud.encryption" ? {
|
|
2303
|
+
service: entry.service,
|
|
2304
|
+
path: entry.path,
|
|
2305
|
+
actions: [...entry.actions],
|
|
2306
|
+
...entry.caveats === void 0 ? {} : { caveats: entry.caveats }
|
|
2307
|
+
} : entry);
|
|
2308
|
+
}
|
|
2080
2309
|
/**
|
|
2081
2310
|
* Get the Ethereum address for this user.
|
|
2082
2311
|
*/
|
|
@@ -2119,6 +2348,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2119
2348
|
getPrimarySpaceId: () => this.spaceId,
|
|
2120
2349
|
getAccountSpaceId: () => this.accountSpaceId,
|
|
2121
2350
|
getSpaces: () => this.spaces,
|
|
2351
|
+
getDelegationManager: () => this.delegationManager,
|
|
2122
2352
|
getAccountDb: () => this.accountSpaceId ? this.sqlForSpace(this.accountSpaceId).db("account") : void 0,
|
|
2123
2353
|
ensureAccountSpaceHosted: async () => {
|
|
2124
2354
|
if (this.accountSpaceId && this.auth) {
|
|
@@ -2165,6 +2395,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2165
2395
|
this._hooks = void 0;
|
|
2166
2396
|
this._vault = void 0;
|
|
2167
2397
|
this._encryption = void 0;
|
|
2398
|
+
this._baseVaults.clear();
|
|
2168
2399
|
this._baseSecrets.clear();
|
|
2169
2400
|
this._secrets.clear();
|
|
2170
2401
|
this._spaceService = void 0;
|
|
@@ -2172,6 +2403,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2172
2403
|
this.runtimePermissionGrants = [];
|
|
2173
2404
|
await this.tc.signIn(options);
|
|
2174
2405
|
this.syncResolvedHostFromAuth();
|
|
2406
|
+
const oldGraph = this._serviceGraph;
|
|
2407
|
+
this._serviceGraph = this.createServiceGraphLifetime();
|
|
2408
|
+
oldGraph.retire();
|
|
2409
|
+
this.tc.retireServices();
|
|
2175
2410
|
const signedInSession = this.currentTinyCloudSession();
|
|
2176
2411
|
if (signedInSession) {
|
|
2177
2412
|
this.sessionKeyId = signedInSession.sessionKey;
|
|
@@ -2456,7 +2691,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2456
2691
|
}
|
|
2457
2692
|
let operations = [];
|
|
2458
2693
|
try {
|
|
2459
|
-
const entries = this.
|
|
2694
|
+
const entries = this.parseRecapWithCaveats(siwe);
|
|
2460
2695
|
if (Array.isArray(entries)) {
|
|
2461
2696
|
operations = entries.flatMap((entry) => {
|
|
2462
2697
|
const service = this.invocationServiceName(entry.service);
|
|
@@ -2464,7 +2699,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2464
2699
|
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId: entry.space },
|
|
2465
2700
|
service,
|
|
2466
2701
|
path: entry.path,
|
|
2467
|
-
action
|
|
2702
|
+
action,
|
|
2703
|
+
caveats: cloneRecapCaveats(entry.caveats)
|
|
2468
2704
|
}));
|
|
2469
2705
|
});
|
|
2470
2706
|
}
|
|
@@ -2817,86 +3053,441 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2817
3053
|
*/
|
|
2818
3054
|
async restoreSession(sessionData) {
|
|
2819
3055
|
await this.wasmBindings.ensureInitialized?.();
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
this.
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
3056
|
+
const restoredJwk = clonePersistedSessionJwk(sessionData.jwk);
|
|
3057
|
+
if (sessionData.chainId !== void 0 && (!Number.isSafeInteger(sessionData.chainId) || sessionData.chainId <= 0)) {
|
|
3058
|
+
throw new Error("Persisted session chain ID must be a positive safe integer.");
|
|
3059
|
+
}
|
|
3060
|
+
const stagedManager = this.wasmBindings.createSessionManager();
|
|
3061
|
+
const stagedReplace = stagedManager.replaceSessionKey;
|
|
3062
|
+
const liveKeys = this.sessionManager.listSessionKeys;
|
|
3063
|
+
const stagedKeys = stagedManager.listSessionKeys;
|
|
3064
|
+
if (typeof stagedReplace !== "function" || typeof liveKeys !== "function" || typeof stagedKeys !== "function") {
|
|
3065
|
+
throw new UnsupportedSessionRestoreError();
|
|
3066
|
+
}
|
|
3067
|
+
let stagedKeyId;
|
|
3068
|
+
let stagedJwk;
|
|
3069
|
+
let canonicalVerificationMethod;
|
|
3070
|
+
try {
|
|
3071
|
+
const keyIds = liveKeys.call(this.sessionManager);
|
|
3072
|
+
if (!Array.isArray(keyIds) || !keyIds.every((keyId) => typeof keyId === "string")) {
|
|
3073
|
+
throw new UnsupportedSessionRestoreError("it cannot reliably enumerate every live session signer");
|
|
3074
|
+
}
|
|
3075
|
+
for (const keyId of keyIds) {
|
|
3076
|
+
if (keyId === this.sessionKeyId) continue;
|
|
3077
|
+
const jwk = this.sessionManager.jwk(keyId);
|
|
3078
|
+
if (!jwk) throw new Error("missing live session key");
|
|
3079
|
+
stagedReplace.call(stagedManager, clonePersistedSessionJwk(JSON.parse(jwk)), keyId);
|
|
3080
|
+
}
|
|
3081
|
+
stagedKeyId = stagedReplace.call(stagedManager, restoredJwk, this.sessionKeyId);
|
|
3082
|
+
const stagedJwkJson = stagedManager.jwk(stagedKeyId);
|
|
3083
|
+
if (!stagedJwkJson) throw new Error("missing restored session key");
|
|
3084
|
+
stagedJwk = clonePersistedSessionJwk(JSON.parse(stagedJwkJson));
|
|
3085
|
+
canonicalVerificationMethod = stagedManager.getDID(stagedKeyId);
|
|
3086
|
+
} catch (error) {
|
|
3087
|
+
if (error instanceof UnsupportedSessionRestoreError) throw error;
|
|
3088
|
+
throw new Error("Persisted session has an invalid private Ed25519 session key.");
|
|
2834
3089
|
}
|
|
2835
|
-
|
|
2836
|
-
|
|
3090
|
+
const restoredVerificationMethod = canonicalRestoredVerificationMethod(
|
|
3091
|
+
canonicalVerificationMethod,
|
|
3092
|
+
sessionData.verificationMethod
|
|
3093
|
+
);
|
|
3094
|
+
if (!restoredVerificationMethod) {
|
|
3095
|
+
throw new Error(
|
|
3096
|
+
"Persisted session verification method does not match its private Ed25519 session key."
|
|
3097
|
+
);
|
|
3098
|
+
}
|
|
3099
|
+
const proofValues = [
|
|
3100
|
+
sessionData.siwe,
|
|
3101
|
+
sessionData.signature,
|
|
3102
|
+
sessionData.address,
|
|
3103
|
+
sessionData.chainId
|
|
3104
|
+
];
|
|
3105
|
+
const hasPersistedProof = proofValues.every((value) => value !== void 0);
|
|
3106
|
+
if (!hasPersistedProof && (proofValues.some((value) => value !== void 0) || sessionData.expiresAt !== void 0)) {
|
|
3107
|
+
throw new Error("Persisted session authority metadata is incomplete.");
|
|
3108
|
+
}
|
|
3109
|
+
const restoredAddress = hasPersistedProof ? (0, import_sdk_core8.canonicalizeAddress)(sessionData.address) : void 0;
|
|
3110
|
+
let stagedSessionExpiry = /* @__PURE__ */ new Date(0);
|
|
3111
|
+
let stagedRecap = [];
|
|
3112
|
+
if (hasPersistedProof) {
|
|
3113
|
+
if (typeof this.wasmBindings.validatePersistedSession !== "function") {
|
|
3114
|
+
throw new UnsupportedSessionRestoreError("it cannot verify persisted SIWE authority");
|
|
3115
|
+
}
|
|
3116
|
+
const verified = this.wasmBindings.validatePersistedSession({
|
|
3117
|
+
delegationHeader: sessionData.delegationHeader,
|
|
3118
|
+
delegationCid: sessionData.delegationCid,
|
|
3119
|
+
spaceId: sessionData.spaceId,
|
|
3120
|
+
jwk: stagedJwk,
|
|
3121
|
+
address: restoredAddress,
|
|
3122
|
+
chainId: sessionData.chainId,
|
|
3123
|
+
siwe: sessionData.siwe,
|
|
3124
|
+
signature: sessionData.signature
|
|
3125
|
+
});
|
|
3126
|
+
const exactRecap = verified.verifiedRecap;
|
|
3127
|
+
if (!Array.isArray(exactRecap) || !exactRecap.every(
|
|
3128
|
+
(entry) => entry !== null && typeof entry === "object" && typeof entry.service === "string" && typeof entry.space === "string" && typeof entry.path === "string" && Array.isArray(entry.actions) && entry.actions.every((action) => typeof action === "string") && Array.isArray(entry.caveats) && entry.caveats.every(
|
|
3129
|
+
(caveat) => caveat !== null && typeof caveat === "object" && !Array.isArray(caveat)
|
|
3130
|
+
)
|
|
3131
|
+
)) {
|
|
3132
|
+
throw new UnsupportedSessionRestoreError(
|
|
3133
|
+
"it cannot reconstruct caveat-preserving persisted ReCap authority"
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
3136
|
+
stagedRecap = exactRecap.map((entry) => ({
|
|
3137
|
+
service: entry.service,
|
|
3138
|
+
space: entry.space,
|
|
3139
|
+
path: entry.path,
|
|
3140
|
+
actions: [...entry.actions],
|
|
3141
|
+
caveats: cloneRecapCaveats(entry.caveats)
|
|
3142
|
+
}));
|
|
3143
|
+
const signedExpiry = verified.expiresAt === void 0 ? void 0 : persistedExpiry(verified.expiresAt);
|
|
3144
|
+
const persistedPolicyExpiry = sessionData.expiresAt === void 0 ? void 0 : persistedExpiry(sessionData.expiresAt);
|
|
3145
|
+
if (signedExpiry && persistedPolicyExpiry && !sameInstant(signedExpiry, persistedPolicyExpiry)) {
|
|
3146
|
+
throw new Error("Persisted session expiry does not match its signed SIWE authority.");
|
|
3147
|
+
}
|
|
3148
|
+
stagedSessionExpiry = signedExpiry ?? persistedPolicyExpiry ?? persistedExpiry(void 0);
|
|
2837
3149
|
}
|
|
2838
3150
|
const resolvedHost = await this.resolveRestoredHost(
|
|
2839
3151
|
sessionData.tinycloudHosts,
|
|
2840
3152
|
restoredAddress,
|
|
2841
3153
|
sessionData.chainId
|
|
2842
3154
|
);
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
invoke: this.invokeWithRuntimePermissions,
|
|
2848
|
-
invokeAny: this.invokeAnyWithRuntimePermissions,
|
|
2849
|
-
fetch: globalThis.fetch.bind(globalThis),
|
|
2850
|
-
hosts: [this.config.host],
|
|
2851
|
-
telemetry: this.config.telemetry
|
|
2852
|
-
});
|
|
2853
|
-
this._kv = new import_sdk_core8.KVService({});
|
|
2854
|
-
this._kv.initialize(this._serviceContext);
|
|
2855
|
-
this._serviceContext.registerService("kv", this._kv);
|
|
2856
|
-
this._sql = new import_sdk_core8.SQLService({});
|
|
2857
|
-
this._sql.initialize(this._serviceContext);
|
|
2858
|
-
this._serviceContext.registerService("sql", this._sql);
|
|
2859
|
-
this._duckdb = new import_sdk_core8.DuckDbService({});
|
|
2860
|
-
this._duckdb.initialize(this._serviceContext);
|
|
2861
|
-
this._serviceContext.registerService("duckdb", this._duckdb);
|
|
2862
|
-
this._hooks = new import_sdk_core8.HooksService({});
|
|
2863
|
-
this._hooks.initialize(this._serviceContext);
|
|
2864
|
-
this._serviceContext.registerService("hooks", this._hooks);
|
|
3155
|
+
const stagedHost = resolvedHost ?? this.config.host;
|
|
3156
|
+
const stagedAddress = restoredAddress;
|
|
3157
|
+
const stagedChainId = sessionData.chainId ?? 1;
|
|
3158
|
+
const stagedNodeDid = stagedAddress ? (0, import_sdk_core8.pkhDid)(stagedAddress, stagedChainId) : canonicalVerificationMethod;
|
|
2865
3159
|
const serviceSession = {
|
|
2866
3160
|
delegationHeader: sessionData.delegationHeader,
|
|
2867
3161
|
delegationCid: sessionData.delegationCid,
|
|
2868
3162
|
spaceId: sessionData.spaceId,
|
|
2869
|
-
verificationMethod:
|
|
2870
|
-
jwk:
|
|
3163
|
+
verificationMethod: restoredVerificationMethod,
|
|
3164
|
+
jwk: stagedJwk
|
|
2871
3165
|
};
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
3166
|
+
const stagedTcSession = hasPersistedProof ? {
|
|
3167
|
+
address: restoredAddress,
|
|
3168
|
+
chainId: sessionData.chainId,
|
|
3169
|
+
sessionKey: JSON.stringify(stagedJwk),
|
|
3170
|
+
spaceId: sessionData.spaceId,
|
|
3171
|
+
spaces: sessionData.spaces,
|
|
3172
|
+
delegationCid: sessionData.delegationCid,
|
|
3173
|
+
delegationHeader: sessionData.delegationHeader,
|
|
3174
|
+
verificationMethod: restoredVerificationMethod,
|
|
3175
|
+
jwk: stagedJwk,
|
|
3176
|
+
siwe: sessionData.siwe,
|
|
3177
|
+
signature: sessionData.signature
|
|
3178
|
+
} : void 0;
|
|
3179
|
+
const stagedPrimary = this.stagePrimarySessionState(
|
|
3180
|
+
stagedTcSession,
|
|
3181
|
+
stagedNodeDid,
|
|
3182
|
+
stagedHost,
|
|
3183
|
+
stagedSessionExpiry,
|
|
3184
|
+
stagedRecap
|
|
3185
|
+
);
|
|
3186
|
+
const stagedGraph = this.stageRestoredServiceGraph({
|
|
3187
|
+
host: stagedHost,
|
|
3188
|
+
manager: stagedManager,
|
|
3189
|
+
serviceSession,
|
|
3190
|
+
verificationMethod: canonicalVerificationMethod,
|
|
3191
|
+
nodeDid: stagedNodeDid,
|
|
3192
|
+
address: stagedAddress,
|
|
3193
|
+
chainId: stagedChainId,
|
|
3194
|
+
tinyCloudSession: stagedTcSession,
|
|
3195
|
+
sessionExpiry: stagedSessionExpiry,
|
|
3196
|
+
recap: stagedRecap
|
|
3197
|
+
});
|
|
3198
|
+
const oldGraph = this._serviceGraph;
|
|
3199
|
+
const oldCore = this.tc;
|
|
3200
|
+
this.sessionManager = stagedManager;
|
|
3201
|
+
this.sessionKeyId = stagedKeyId;
|
|
3202
|
+
this.sessionKeyJwk = stagedJwk;
|
|
3203
|
+
if (resolvedHost) this.config.host = resolvedHost;
|
|
3204
|
+
this._address = stagedAddress;
|
|
3205
|
+
this._chainId = stagedChainId;
|
|
3206
|
+
this._serviceContext = stagedGraph.serviceContext;
|
|
3207
|
+
this._kv = stagedGraph.kv;
|
|
3208
|
+
this._sql = stagedGraph.sql;
|
|
3209
|
+
this._duckdb = stagedGraph.duckdb;
|
|
3210
|
+
this._hooks = stagedGraph.hooks;
|
|
3211
|
+
this._vault = stagedGraph.vault;
|
|
3212
|
+
this._encryption = stagedGraph.encryption;
|
|
3213
|
+
this._capabilityRegistry = stagedGraph.capabilityRegistry;
|
|
3214
|
+
this._keyProvider = stagedGraph.keyProvider;
|
|
3215
|
+
this._sharingService = stagedGraph.sharingService;
|
|
3216
|
+
this._delegationManager = stagedGraph.delegationManager;
|
|
3217
|
+
this._spaceService = stagedGraph.spaceService;
|
|
3218
|
+
this._serviceGraph = stagedGraph.graph;
|
|
3219
|
+
this._baseSecrets = /* @__PURE__ */ new Map();
|
|
3220
|
+
this._secrets = /* @__PURE__ */ new Map();
|
|
3221
|
+
this._publicKV = void 0;
|
|
3222
|
+
this._account = void 0;
|
|
3223
|
+
this.tc = stagedGraph.core;
|
|
3224
|
+
this._recapOperationsCache = stagedPrimary.cache;
|
|
3225
|
+
this.runtimePermissionGrants = stagedPrimary.grants;
|
|
3226
|
+
if (this.auth) {
|
|
3227
|
+
this.auth.installRestoredSession(stagedManager, stagedTcSession, [stagedHost]);
|
|
3228
|
+
this._restoredTcSession = void 0;
|
|
3229
|
+
} else {
|
|
3230
|
+
this._restoredTcSession = stagedTcSession;
|
|
3231
|
+
}
|
|
3232
|
+
oldGraph.retire();
|
|
3233
|
+
oldCore?.retireServices?.();
|
|
3234
|
+
}
|
|
3235
|
+
stagePrimarySessionState(session, verificationMethod, host, sessionExpiry, recap) {
|
|
3236
|
+
if (!session?.siwe) return { cache: void 0, grants: [] };
|
|
3237
|
+
let operations = [];
|
|
3238
|
+
operations = recap.flatMap((entry) => {
|
|
3239
|
+
const service = this.invocationServiceName(entry.service);
|
|
3240
|
+
return entry.actions.map((action) => ({
|
|
3241
|
+
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId: entry.space },
|
|
3242
|
+
service,
|
|
3243
|
+
path: entry.path,
|
|
3244
|
+
action,
|
|
3245
|
+
caveats: cloneRecapCaveats(entry.caveats)
|
|
3246
|
+
}));
|
|
3247
|
+
});
|
|
3248
|
+
const cache = { siwe: session.siwe, operations };
|
|
3249
|
+
if (operations.length === 0) return { cache, grants: [] };
|
|
3250
|
+
const expiresAt = sessionExpiry;
|
|
3251
|
+
return {
|
|
3252
|
+
cache,
|
|
3253
|
+
grants: [{
|
|
3254
|
+
session: {
|
|
3255
|
+
delegationHeader: session.delegationHeader,
|
|
3256
|
+
delegationCid: session.delegationCid,
|
|
3257
|
+
spaceId: session.spaceId,
|
|
3258
|
+
verificationMethod: session.verificationMethod,
|
|
3259
|
+
jwk: session.jwk
|
|
3260
|
+
},
|
|
3261
|
+
delegation: {
|
|
3262
|
+
cid: session.delegationCid,
|
|
3263
|
+
delegationHeader: session.delegationHeader,
|
|
3264
|
+
delegateDID: session.verificationMethod,
|
|
3265
|
+
delegatorDID: verificationMethod,
|
|
3266
|
+
spaceId: session.spaceId,
|
|
3267
|
+
path: "",
|
|
3268
|
+
actions: [...new Set(operations.map((operation) => operation.action))],
|
|
3269
|
+
expiry: expiresAt,
|
|
3270
|
+
allowSubDelegation: true,
|
|
3271
|
+
ownerAddress: session.address,
|
|
3272
|
+
chainId: session.chainId,
|
|
3273
|
+
host
|
|
3274
|
+
},
|
|
3275
|
+
operations,
|
|
3276
|
+
expiresAt,
|
|
3277
|
+
provenance: "primary"
|
|
3278
|
+
}]
|
|
3279
|
+
};
|
|
3280
|
+
}
|
|
3281
|
+
stageRestoredServiceGraph(input) {
|
|
3282
|
+
const graph = this.createServiceGraphLifetime();
|
|
3283
|
+
const core = this.auth ? new import_sdk_core8.TinyCloud(this.auth, {
|
|
3284
|
+
invokeAny: graph.invokeAny,
|
|
3285
|
+
telemetry: this.config.telemetry
|
|
3286
|
+
}) : null;
|
|
3287
|
+
if (core) {
|
|
3288
|
+
core.initializeServices(graph.invoke, [input.host], graph.fetch);
|
|
3289
|
+
const coreContext = graph.track(core.serviceContext);
|
|
3290
|
+
coreContext.setSession(input.serviceSession);
|
|
3291
|
+
}
|
|
3292
|
+
const serviceContext = graph.track(new import_sdk_core8.ServiceContext({
|
|
3293
|
+
invoke: graph.invoke,
|
|
3294
|
+
invokeAny: graph.invokeAny,
|
|
3295
|
+
fetch: graph.fetch,
|
|
3296
|
+
hosts: [input.host],
|
|
3297
|
+
telemetry: this.config.telemetry
|
|
3298
|
+
}));
|
|
3299
|
+
const kv = new import_sdk_core8.KVService({});
|
|
3300
|
+
kv.initialize(serviceContext);
|
|
3301
|
+
serviceContext.registerService("kv", kv);
|
|
3302
|
+
const sql = new import_sdk_core8.SQLService({});
|
|
3303
|
+
sql.initialize(serviceContext);
|
|
3304
|
+
serviceContext.registerService("sql", sql);
|
|
3305
|
+
const duckdb = new import_sdk_core8.DuckDbService({});
|
|
3306
|
+
duckdb.initialize(serviceContext);
|
|
3307
|
+
serviceContext.registerService("duckdb", duckdb);
|
|
3308
|
+
const hooks = new import_sdk_core8.HooksService({});
|
|
3309
|
+
hooks.initialize(serviceContext);
|
|
3310
|
+
serviceContext.registerService("hooks", hooks);
|
|
3311
|
+
serviceContext.setSession(input.serviceSession);
|
|
3312
|
+
const encryption = this.createEncryptionService({
|
|
3313
|
+
graph,
|
|
3314
|
+
host: input.host,
|
|
3315
|
+
session: input.serviceSession,
|
|
3316
|
+
did: input.nodeDid,
|
|
3317
|
+
address: input.address,
|
|
3318
|
+
chainId: input.chainId
|
|
3319
|
+
});
|
|
3320
|
+
encryption.initialize(serviceContext);
|
|
3321
|
+
serviceContext.registerService("encryption", encryption);
|
|
3322
|
+
const vault = this.createVaultService(input.serviceSession.spaceId, kv, encryption, {
|
|
3323
|
+
host: input.host,
|
|
3324
|
+
did: input.nodeDid,
|
|
3325
|
+
address: input.address,
|
|
3326
|
+
chainId: input.chainId,
|
|
3327
|
+
serviceGraph: graph
|
|
3328
|
+
});
|
|
3329
|
+
vault.initialize(serviceContext);
|
|
3330
|
+
serviceContext.registerService("vault", vault);
|
|
3331
|
+
const capabilityRegistry = new import_sdk_core8.CapabilityKeyRegistry();
|
|
3332
|
+
if (input.tinyCloudSession) {
|
|
3333
|
+
const session = input.tinyCloudSession;
|
|
3334
|
+
const delegations = input.recap.map((entry) => ({
|
|
3335
|
+
cid: session.delegationCid,
|
|
3336
|
+
delegateDID: session.verificationMethod,
|
|
3337
|
+
spaceId: entry.space,
|
|
3338
|
+
path: entry.path,
|
|
3339
|
+
actions: [...entry.actions],
|
|
3340
|
+
caveats: cloneRecapCaveats(entry.caveats),
|
|
3341
|
+
expiry: input.sessionExpiry,
|
|
3342
|
+
isRevoked: false,
|
|
3343
|
+
allowSubDelegation: true
|
|
3344
|
+
}));
|
|
3345
|
+
if (delegations.length > 0) {
|
|
3346
|
+
capabilityRegistry.registerKey({
|
|
3347
|
+
id: session.sessionKey,
|
|
3348
|
+
did: session.verificationMethod,
|
|
3349
|
+
type: "session",
|
|
3350
|
+
jwk: session.jwk,
|
|
3351
|
+
priority: 0
|
|
3352
|
+
}, delegations);
|
|
2897
3353
|
}
|
|
2898
|
-
this.registerPrimarySessionGrant(tcSession);
|
|
2899
3354
|
}
|
|
3355
|
+
const delegationManager = new import_sdk_core8.DelegationManager({
|
|
3356
|
+
hosts: [input.host],
|
|
3357
|
+
session: input.serviceSession,
|
|
3358
|
+
invoke: graph.invoke,
|
|
3359
|
+
invokeAny: graph.invokeAny,
|
|
3360
|
+
fetch: graph.fetch
|
|
3361
|
+
});
|
|
3362
|
+
const keyProvider = new WasmKeyProvider({ sessionManager: input.manager });
|
|
3363
|
+
const sharingService = new import_sdk_core8.SharingService({
|
|
3364
|
+
hosts: [input.host],
|
|
3365
|
+
invoke: graph.invoke,
|
|
3366
|
+
fetch: graph.fetch,
|
|
3367
|
+
assertActive: () => graph.assertActive(),
|
|
3368
|
+
keyProvider,
|
|
3369
|
+
registry: capabilityRegistry,
|
|
3370
|
+
createDelegationWasm: (params) => this.createDelegationWrapper(params),
|
|
3371
|
+
computeCid: (data, codec) => {
|
|
3372
|
+
if (!this.wasmBindings.computeCid) throw new Error("computeCid is unavailable");
|
|
3373
|
+
return this.wasmBindings.computeCid(data, codec);
|
|
3374
|
+
},
|
|
3375
|
+
createKVService: (config) => {
|
|
3376
|
+
const service = new import_sdk_core8.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
|
|
3377
|
+
const context = graph.track(new import_sdk_core8.ServiceContext({
|
|
3378
|
+
invoke: config.invoke,
|
|
3379
|
+
fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
3380
|
+
hosts: config.hosts,
|
|
3381
|
+
telemetry: this.config.telemetry
|
|
3382
|
+
}));
|
|
3383
|
+
context.setSession(config.session);
|
|
3384
|
+
service.initialize(context);
|
|
3385
|
+
return service;
|
|
3386
|
+
}
|
|
3387
|
+
});
|
|
3388
|
+
sharingService.updateConfig({
|
|
3389
|
+
session: input.serviceSession,
|
|
3390
|
+
delegationManager,
|
|
3391
|
+
sessionExpiry: input.sessionExpiry,
|
|
3392
|
+
createDelegationWasm: (params) => {
|
|
3393
|
+
graph.assertActive();
|
|
3394
|
+
return this.createDelegationWrapper(params);
|
|
3395
|
+
},
|
|
3396
|
+
onRootDelegationNeeded: this.signer ? async (params) => {
|
|
3397
|
+
graph.assertActive();
|
|
3398
|
+
const delegation = await this.createRootDelegationForSharing(
|
|
3399
|
+
params,
|
|
3400
|
+
() => graph.assertActive()
|
|
3401
|
+
);
|
|
3402
|
+
graph.assertActive();
|
|
3403
|
+
return delegation;
|
|
3404
|
+
} : void 0
|
|
3405
|
+
});
|
|
3406
|
+
const spaceService = new import_sdk_core8.SpaceService({
|
|
3407
|
+
hosts: [input.host],
|
|
3408
|
+
session: input.serviceSession,
|
|
3409
|
+
invoke: graph.invoke,
|
|
3410
|
+
fetch: graph.fetch,
|
|
3411
|
+
capabilityRegistry,
|
|
3412
|
+
userDid: input.nodeDid,
|
|
3413
|
+
createKVService: (spaceId) => {
|
|
3414
|
+
graph.assertActive();
|
|
3415
|
+
const scopedKv = new import_sdk_core8.KVService({});
|
|
3416
|
+
const context = graph.track(new import_sdk_core8.ServiceContext({
|
|
3417
|
+
invoke: graph.invoke,
|
|
3418
|
+
invokeAny: graph.invokeAny,
|
|
3419
|
+
fetch: graph.fetch,
|
|
3420
|
+
hosts: [input.host],
|
|
3421
|
+
telemetry: this.config.telemetry
|
|
3422
|
+
}));
|
|
3423
|
+
context.setSession({ ...input.serviceSession, spaceId });
|
|
3424
|
+
scopedKv.initialize(context);
|
|
3425
|
+
return scopedKv;
|
|
3426
|
+
},
|
|
3427
|
+
createVaultService: (spaceId) => {
|
|
3428
|
+
graph.assertActive();
|
|
3429
|
+
const scopedKv = new import_sdk_core8.KVService({});
|
|
3430
|
+
const context = graph.track(new import_sdk_core8.ServiceContext({
|
|
3431
|
+
invoke: graph.invoke,
|
|
3432
|
+
invokeAny: graph.invokeAny,
|
|
3433
|
+
fetch: graph.fetch,
|
|
3434
|
+
hosts: [input.host],
|
|
3435
|
+
telemetry: this.config.telemetry
|
|
3436
|
+
}));
|
|
3437
|
+
context.setSession({ ...input.serviceSession, spaceId });
|
|
3438
|
+
scopedKv.initialize(context);
|
|
3439
|
+
const scopedVault = this.createVaultService(spaceId, scopedKv, encryption, {
|
|
3440
|
+
host: input.host,
|
|
3441
|
+
did: input.nodeDid,
|
|
3442
|
+
address: input.address,
|
|
3443
|
+
chainId: input.chainId,
|
|
3444
|
+
serviceGraph: graph
|
|
3445
|
+
});
|
|
3446
|
+
scopedVault.initialize(context);
|
|
3447
|
+
return scopedVault;
|
|
3448
|
+
},
|
|
3449
|
+
createSecretsService: (spaceId) => {
|
|
3450
|
+
graph.assertActive();
|
|
3451
|
+
return this.secretsForSpace(spaceId);
|
|
3452
|
+
},
|
|
3453
|
+
createDelegation: async (params) => {
|
|
3454
|
+
graph.assertActive();
|
|
3455
|
+
try {
|
|
3456
|
+
const portableDelegation = await this.createDelegation({
|
|
3457
|
+
delegateDID: params.delegateDID,
|
|
3458
|
+
path: params.path,
|
|
3459
|
+
actions: params.actions,
|
|
3460
|
+
disableSubDelegation: params.disableSubDelegation,
|
|
3461
|
+
expiryMs: params.expiry ? params.expiry.getTime() - Date.now() : void 0
|
|
3462
|
+
});
|
|
3463
|
+
return { ok: true, data: {
|
|
3464
|
+
cid: portableDelegation.cid,
|
|
3465
|
+
delegateDID: portableDelegation.delegateDID,
|
|
3466
|
+
delegatorDID: this.did,
|
|
3467
|
+
spaceId: portableDelegation.spaceId,
|
|
3468
|
+
path: portableDelegation.path,
|
|
3469
|
+
actions: portableDelegation.actions,
|
|
3470
|
+
expiry: portableDelegation.expiry,
|
|
3471
|
+
isRevoked: false,
|
|
3472
|
+
allowSubDelegation: !portableDelegation.disableSubDelegation,
|
|
3473
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
3474
|
+
authHeader: portableDelegation.delegationHeader.Authorization
|
|
3475
|
+
} };
|
|
3476
|
+
} catch (error) {
|
|
3477
|
+
return { ok: false, error: {
|
|
3478
|
+
code: "CREATION_FAILED",
|
|
3479
|
+
message: error instanceof Error ? error.message : String(error),
|
|
3480
|
+
service: "delegation"
|
|
3481
|
+
} };
|
|
3482
|
+
}
|
|
3483
|
+
},
|
|
3484
|
+
onSpaceRegistered: async (space) => {
|
|
3485
|
+
graph.assertActive();
|
|
3486
|
+
await this.account.spaces.register(space);
|
|
3487
|
+
}
|
|
3488
|
+
});
|
|
3489
|
+
spaceService.updateConfig({ sharingService });
|
|
3490
|
+
return { core, graph, serviceContext, kv, sql, duckdb, hooks, vault, encryption, capabilityRegistry, keyProvider, sharingService, delegationManager, spaceService };
|
|
2900
3491
|
}
|
|
2901
3492
|
/**
|
|
2902
3493
|
* Resolve the host a restored session should target.
|
|
@@ -3058,14 +3649,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3058
3649
|
if (!session) {
|
|
3059
3650
|
return;
|
|
3060
3651
|
}
|
|
3061
|
-
this.tc.initializeServices(
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3652
|
+
this.tc.initializeServices(
|
|
3653
|
+
this._serviceGraph.invoke,
|
|
3654
|
+
[this.config.host],
|
|
3655
|
+
this._serviceGraph.fetch
|
|
3656
|
+
);
|
|
3657
|
+
this._serviceGraph.track(this.tc.serviceContext);
|
|
3658
|
+
this._serviceContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
3659
|
+
invoke: this._serviceGraph.invoke,
|
|
3660
|
+
invokeAny: this._serviceGraph.invokeAny,
|
|
3661
|
+
fetch: this._serviceGraph.fetch,
|
|
3066
3662
|
hosts: [this.config.host],
|
|
3067
3663
|
telemetry: this.config.telemetry
|
|
3068
|
-
});
|
|
3664
|
+
}));
|
|
3069
3665
|
this._kv = new import_sdk_core8.KVService({});
|
|
3070
3666
|
this._kv.initialize(this._serviceContext);
|
|
3071
3667
|
this._serviceContext.registerService("kv", this._kv);
|
|
@@ -3100,12 +3696,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3100
3696
|
createSpaceScopedKVService(spaceId) {
|
|
3101
3697
|
const kvService = new import_sdk_core8.KVService({});
|
|
3102
3698
|
if (this._serviceContext) {
|
|
3103
|
-
const spaceScopedContext = new import_sdk_core8.ServiceContext({
|
|
3699
|
+
const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
3104
3700
|
invoke: this._serviceContext.invoke,
|
|
3105
3701
|
fetch: this._serviceContext.fetch,
|
|
3106
3702
|
hosts: this._serviceContext.hosts,
|
|
3107
3703
|
telemetry: this.config.telemetry
|
|
3108
|
-
});
|
|
3704
|
+
}));
|
|
3109
3705
|
const session = this._serviceContext.session;
|
|
3110
3706
|
if (session) {
|
|
3111
3707
|
spaceScopedContext.setSession({ ...session, spaceId });
|
|
@@ -3138,6 +3734,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3138
3734
|
}
|
|
3139
3735
|
return session;
|
|
3140
3736
|
}
|
|
3737
|
+
/**
|
|
3738
|
+
* Runtime-permission helpers can be used from an authenticated Node session
|
|
3739
|
+
* before its public ServiceContext is initialized. They still need the
|
|
3740
|
+
* current signed session, never an optional or stale authority object.
|
|
3741
|
+
*/
|
|
3742
|
+
requireEncryptionSession() {
|
|
3743
|
+
const session = this._serviceContext?.session ?? this.auth?.tinyCloudSession;
|
|
3744
|
+
if (!session) {
|
|
3745
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
3746
|
+
}
|
|
3747
|
+
return session;
|
|
3748
|
+
}
|
|
3141
3749
|
createEncryptionCrypto() {
|
|
3142
3750
|
const wasm = this.wasmBindings;
|
|
3143
3751
|
const columnEncrypt = (key, plaintext) => {
|
|
@@ -3193,14 +3801,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3193
3801
|
}
|
|
3194
3802
|
return info.nodeId;
|
|
3195
3803
|
}
|
|
3196
|
-
async signRawNetworkAuthorization(input) {
|
|
3804
|
+
async signRawNetworkAuthorization(input, binding) {
|
|
3805
|
+
binding?.graph.assertActive();
|
|
3197
3806
|
if (!this.wasmBindings.invokeAny) {
|
|
3198
3807
|
throw new Error("WASM binding does not support raw-resource invokeAny");
|
|
3199
3808
|
}
|
|
3200
3809
|
if (!this.wasmBindings.computeCid) {
|
|
3201
3810
|
throw new Error("WASM binding does not support invocation CID computation");
|
|
3202
3811
|
}
|
|
3203
|
-
const session = this.
|
|
3812
|
+
const session = binding?.session ?? this.requireEncryptionSession();
|
|
3204
3813
|
const headers = this.invokeAnyWithRuntimePermissions(
|
|
3205
3814
|
session,
|
|
3206
3815
|
[
|
|
@@ -3219,6 +3828,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3219
3828
|
input.targetNode,
|
|
3220
3829
|
session.jwk
|
|
3221
3830
|
);
|
|
3831
|
+
binding?.graph.assertActive();
|
|
3222
3832
|
return {
|
|
3223
3833
|
authorization: audienceBound,
|
|
3224
3834
|
invocationCid: this.wasmBindings.computeCid(
|
|
@@ -3227,25 +3837,55 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3227
3837
|
)
|
|
3228
3838
|
};
|
|
3229
3839
|
}
|
|
3230
|
-
|
|
3840
|
+
async fetchEncryptionNetworkAt(host, networkId, fetchFn) {
|
|
3841
|
+
const response = await fetchFn(
|
|
3842
|
+
`${host}/encryption/networks/${encodeURIComponent(networkId)}`
|
|
3843
|
+
);
|
|
3844
|
+
if (response.status === 404) return null;
|
|
3845
|
+
if (!response.ok) {
|
|
3846
|
+
throw new Error(
|
|
3847
|
+
`Failed to fetch encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
|
|
3848
|
+
);
|
|
3849
|
+
}
|
|
3850
|
+
const body = await response.json();
|
|
3851
|
+
return "descriptor" in body && body.descriptor ? body.descriptor : body;
|
|
3852
|
+
}
|
|
3853
|
+
createEncryptionService(binding) {
|
|
3854
|
+
const graph = binding?.graph ?? this._serviceGraph;
|
|
3855
|
+
const host = binding?.host ?? this.config.host;
|
|
3856
|
+
const session = binding?.session ?? this.requireEncryptionSession();
|
|
3857
|
+
const did = binding?.did ?? this.did;
|
|
3858
|
+
const address = binding?.address ?? this._address;
|
|
3859
|
+
const chainId = binding?.chainId ?? this._chainId;
|
|
3231
3860
|
const crypto = this.createEncryptionCrypto();
|
|
3232
3861
|
const transport = {
|
|
3233
|
-
postDecrypt: async ({ networkId, authorization, canonicalBody }) => {
|
|
3234
|
-
|
|
3235
|
-
|
|
3862
|
+
postDecrypt: async ({ networkId, authorization, canonicalBody, signal }) => {
|
|
3863
|
+
graph.assertActive();
|
|
3864
|
+
const response = await graph.fetch(
|
|
3865
|
+
`${host}/encryption/networks/${encodeURIComponent(networkId)}/decrypt`,
|
|
3236
3866
|
{
|
|
3237
3867
|
method: "POST",
|
|
3238
3868
|
headers: {
|
|
3239
3869
|
Authorization: authorization,
|
|
3240
3870
|
"Content-Type": "application/json"
|
|
3241
3871
|
},
|
|
3242
|
-
body: canonicalBody
|
|
3872
|
+
body: canonicalBody,
|
|
3873
|
+
signal
|
|
3243
3874
|
}
|
|
3244
3875
|
);
|
|
3876
|
+
graph.assertActive();
|
|
3245
3877
|
if (!response.ok) {
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3878
|
+
let permissionHint;
|
|
3879
|
+
if (response.status === 401 || response.status === 403) {
|
|
3880
|
+
try {
|
|
3881
|
+
const body = await response.json();
|
|
3882
|
+
const record = typeof body === "object" && body !== null ? body : void 0;
|
|
3883
|
+
const nested = typeof record?.error === "object" && record.error !== null ? record.error : void 0;
|
|
3884
|
+
permissionHint = (0, import_sdk_services.parsePermissionHint)(record?.permissionHint) ?? (0, import_sdk_services.parsePermissionHint)(nested?.permissionHint);
|
|
3885
|
+
} catch {
|
|
3886
|
+
}
|
|
3887
|
+
}
|
|
3888
|
+
throw new import_sdk_core8.DecryptTransportResponseError(response.status, permissionHint);
|
|
3249
3889
|
}
|
|
3250
3890
|
return await response.json();
|
|
3251
3891
|
}
|
|
@@ -3254,12 +3894,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3254
3894
|
crypto,
|
|
3255
3895
|
signer: {
|
|
3256
3896
|
signDecryptInvocation: async (input) => {
|
|
3897
|
+
graph.assertActive();
|
|
3257
3898
|
const signed = await this.signRawNetworkAuthorization({
|
|
3258
3899
|
targetNode: input.targetNode,
|
|
3259
3900
|
networkId: input.networkId,
|
|
3260
3901
|
action: DECRYPT_ACTION2,
|
|
3261
3902
|
facts: input.facts
|
|
3262
|
-
});
|
|
3903
|
+
}, { graph, session });
|
|
3904
|
+
graph.assertActive();
|
|
3263
3905
|
return {
|
|
3264
3906
|
...signed,
|
|
3265
3907
|
canonicalBody: (0, import_sdk_core8.canonicalizeEncryptionJson)(
|
|
@@ -3270,25 +3912,35 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3270
3912
|
},
|
|
3271
3913
|
transport,
|
|
3272
3914
|
node: {
|
|
3273
|
-
fetchByNetworkId: (networkId) =>
|
|
3915
|
+
fetchByNetworkId: async (networkId) => {
|
|
3916
|
+
graph.assertActive();
|
|
3917
|
+
const descriptor = await this.fetchEncryptionNetworkAt(host, networkId, graph.fetch);
|
|
3918
|
+
graph.assertActive();
|
|
3919
|
+
return descriptor;
|
|
3920
|
+
}
|
|
3274
3921
|
},
|
|
3275
3922
|
wellKnown: {
|
|
3276
3923
|
fetchWellKnown: async (principal, discoveryKey) => {
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
}
|
|
3280
|
-
if (!this.config.host) {
|
|
3924
|
+
graph.assertActive();
|
|
3925
|
+
if (!address || !didPrincipalMatches2(principal, did)) {
|
|
3281
3926
|
return null;
|
|
3282
3927
|
}
|
|
3283
|
-
const publicSpaceId = (0, import_sdk_core8.makePublicSpaceId)(
|
|
3284
|
-
const
|
|
3285
|
-
|
|
3928
|
+
const publicSpaceId = (0, import_sdk_core8.makePublicSpaceId)(address, chainId);
|
|
3929
|
+
const encodedKey = discoveryKey.split("/").map(encodeURIComponent).join("/");
|
|
3930
|
+
const response = await graph.fetch(
|
|
3931
|
+
`${host}/public/${encodeURIComponent(publicSpaceId)}/kv/${encodedKey}`,
|
|
3932
|
+
{ method: "GET" }
|
|
3933
|
+
);
|
|
3934
|
+
graph.assertActive();
|
|
3935
|
+
if (!response.ok) {
|
|
3286
3936
|
return null;
|
|
3287
3937
|
}
|
|
3288
|
-
const body =
|
|
3938
|
+
const body = await response.json();
|
|
3939
|
+
graph.assertActive();
|
|
3289
3940
|
return "descriptor" in body && body.descriptor ? body.descriptor : body;
|
|
3290
3941
|
}
|
|
3291
|
-
}
|
|
3942
|
+
},
|
|
3943
|
+
assertActive: () => graph.assertActive()
|
|
3292
3944
|
});
|
|
3293
3945
|
}
|
|
3294
3946
|
getEncryptionService() {
|
|
@@ -3302,8 +3954,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3302
3954
|
}
|
|
3303
3955
|
return this._encryption;
|
|
3304
3956
|
}
|
|
3305
|
-
createVaultService(spaceId, kv) {
|
|
3957
|
+
createVaultService(spaceId, kv, encryptionService = this.getEncryptionService(), nodeContext) {
|
|
3306
3958
|
const wasm = this.wasmBindings;
|
|
3959
|
+
const serviceGraph = nodeContext?.serviceGraph ?? this._serviceGraph;
|
|
3307
3960
|
const vaultCrypto = (0, import_sdk_core8.createVaultCrypto)({
|
|
3308
3961
|
vault_encrypt: wasm.vault_encrypt,
|
|
3309
3962
|
vault_decrypt: wasm.vault_decrypt,
|
|
@@ -3314,12 +3967,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3314
3967
|
vault_sha256: wasm.vault_sha256
|
|
3315
3968
|
});
|
|
3316
3969
|
const self = this;
|
|
3970
|
+
const did = nodeContext?.did ?? this.did;
|
|
3971
|
+
const address = nodeContext?.address ?? this._address;
|
|
3972
|
+
const chainId = nodeContext?.chainId ?? this._chainId;
|
|
3973
|
+
const host = nodeContext?.host ?? this.config.host;
|
|
3974
|
+
const ownerDid = this.ownerDidFromSpaceId(spaceId) ?? did;
|
|
3317
3975
|
return new import_sdk_core8.DataVaultService({
|
|
3318
3976
|
spaceId,
|
|
3319
3977
|
crypto: vaultCrypto,
|
|
3320
3978
|
encryption: {
|
|
3321
|
-
networkId:
|
|
3322
|
-
service:
|
|
3979
|
+
networkId: `urn:tinycloud:encryption:${ownerDid}:${DEFAULT_ENCRYPTION_NETWORK_NAME}`,
|
|
3980
|
+
service: encryptionService,
|
|
3323
3981
|
decryptCapabilityProof: () => ({
|
|
3324
3982
|
proofs: [this.requireServiceSession().delegationCid]
|
|
3325
3983
|
})
|
|
@@ -3328,6 +3986,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3328
3986
|
kv,
|
|
3329
3987
|
ensurePublicSpace: async () => {
|
|
3330
3988
|
try {
|
|
3989
|
+
serviceGraph.assertActive();
|
|
3331
3990
|
await self.ensurePublicSpace();
|
|
3332
3991
|
return { ok: true, data: void 0 };
|
|
3333
3992
|
} catch (error) {
|
|
@@ -3335,14 +3994,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3335
3994
|
}
|
|
3336
3995
|
},
|
|
3337
3996
|
get publicKV() {
|
|
3997
|
+
serviceGraph.assertActive();
|
|
3338
3998
|
return self._publicKV ?? self.tc.publicKV;
|
|
3339
3999
|
},
|
|
3340
|
-
readPublicSpace: (
|
|
4000
|
+
readPublicSpace: (host2, targetSpaceId, key) => import_sdk_core8.TinyCloud.readPublicSpace(host2, targetSpaceId, key),
|
|
3341
4001
|
makePublicSpaceId: import_sdk_core8.TinyCloud.makePublicSpaceId,
|
|
3342
|
-
did
|
|
3343
|
-
address:
|
|
3344
|
-
chainId
|
|
3345
|
-
hosts: [
|
|
4002
|
+
did,
|
|
4003
|
+
address: address ?? "",
|
|
4004
|
+
chainId,
|
|
4005
|
+
hosts: [host]
|
|
3346
4006
|
}
|
|
3347
4007
|
});
|
|
3348
4008
|
}
|
|
@@ -3351,6 +4011,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3351
4011
|
* @internal
|
|
3352
4012
|
*/
|
|
3353
4013
|
initializeV2Services(serviceSession) {
|
|
4014
|
+
const graph = this._serviceGraph;
|
|
3354
4015
|
this._capabilityRegistry = new import_sdk_core8.CapabilityKeyRegistry();
|
|
3355
4016
|
const tcSession = this.auth?.tinyCloudSession;
|
|
3356
4017
|
if (tcSession && this._address) {
|
|
@@ -3393,22 +4054,25 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3393
4054
|
}
|
|
3394
4055
|
this._delegationManager = new import_sdk_core8.DelegationManager({
|
|
3395
4056
|
hosts: [this.config.host],
|
|
4057
|
+
accountSpaceId: this.accountSpaceId,
|
|
3396
4058
|
session: serviceSession,
|
|
3397
|
-
invoke:
|
|
3398
|
-
invokeAny:
|
|
3399
|
-
fetch:
|
|
4059
|
+
invoke: graph.invoke,
|
|
4060
|
+
invokeAny: graph.invokeAny,
|
|
4061
|
+
fetch: graph.fetch
|
|
3400
4062
|
});
|
|
3401
4063
|
this._spaceService = new import_sdk_core8.SpaceService({
|
|
3402
4064
|
hosts: [this.config.host],
|
|
3403
4065
|
session: serviceSession,
|
|
3404
|
-
invoke:
|
|
3405
|
-
fetch:
|
|
4066
|
+
invoke: graph.invoke,
|
|
4067
|
+
fetch: graph.fetch,
|
|
3406
4068
|
capabilityRegistry: this._capabilityRegistry,
|
|
3407
4069
|
userDid: this.did,
|
|
3408
4070
|
createKVService: (spaceId) => {
|
|
4071
|
+
graph.assertActive();
|
|
3409
4072
|
return this.createSpaceScopedKVService(spaceId);
|
|
3410
4073
|
},
|
|
3411
4074
|
createVaultService: (spaceId) => {
|
|
4075
|
+
graph.assertActive();
|
|
3412
4076
|
const kvService = this.createSpaceScopedKVService(spaceId);
|
|
3413
4077
|
const vaultService = this.createVaultService(spaceId, kvService);
|
|
3414
4078
|
if (this._serviceContext) {
|
|
@@ -3417,11 +4081,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3417
4081
|
return vaultService;
|
|
3418
4082
|
},
|
|
3419
4083
|
createSecretsService: (spaceId) => {
|
|
4084
|
+
graph.assertActive();
|
|
3420
4085
|
return this.secretsForSpace(spaceId);
|
|
3421
4086
|
},
|
|
3422
4087
|
// Enable space.delegations.create() via SIWE-based delegation
|
|
3423
4088
|
createDelegation: async (params) => {
|
|
3424
4089
|
try {
|
|
4090
|
+
graph.assertActive();
|
|
3425
4091
|
const portableDelegation = await this.createDelegation({
|
|
3426
4092
|
delegateDID: params.delegateDID,
|
|
3427
4093
|
path: params.path,
|
|
@@ -3455,18 +4121,50 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3455
4121
|
}
|
|
3456
4122
|
},
|
|
3457
4123
|
onSpaceRegistered: async (space) => {
|
|
4124
|
+
graph.assertActive();
|
|
3458
4125
|
await this.account.spaces.register(space);
|
|
3459
4126
|
}
|
|
3460
4127
|
});
|
|
3461
|
-
this._sharingService.
|
|
4128
|
+
this._sharingService = new import_sdk_core8.SharingService({
|
|
4129
|
+
hosts: [this.config.host],
|
|
3462
4130
|
session: serviceSession,
|
|
4131
|
+
invoke: graph.invoke,
|
|
4132
|
+
fetch: graph.fetch,
|
|
4133
|
+
assertActive: () => graph.assertActive(),
|
|
4134
|
+
keyProvider: this._keyProvider,
|
|
4135
|
+
registry: this._capabilityRegistry,
|
|
3463
4136
|
delegationManager: this._delegationManager,
|
|
3464
4137
|
sessionExpiry: this.getSessionExpiry(),
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
4138
|
+
createDelegationWasm: (params) => {
|
|
4139
|
+
graph.assertActive();
|
|
4140
|
+
return this.createDelegationWrapper(params);
|
|
4141
|
+
},
|
|
4142
|
+
computeCid: (data, codec) => {
|
|
4143
|
+
if (!this.wasmBindings.computeCid) throw new Error("computeCid is unavailable");
|
|
4144
|
+
return this.wasmBindings.computeCid(data, codec);
|
|
4145
|
+
},
|
|
4146
|
+
createKVService: (config) => {
|
|
4147
|
+
graph.assertActive();
|
|
4148
|
+
const service = new import_sdk_core8.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
|
|
4149
|
+
const context = graph.track(new import_sdk_core8.ServiceContext({
|
|
4150
|
+
invoke: config.invoke,
|
|
4151
|
+
fetch: config.fetch ?? graph.fetch,
|
|
4152
|
+
hosts: config.hosts,
|
|
4153
|
+
telemetry: this.config.telemetry
|
|
4154
|
+
}));
|
|
4155
|
+
context.setSession(config.session);
|
|
4156
|
+
service.initialize(context);
|
|
4157
|
+
return service;
|
|
4158
|
+
},
|
|
4159
|
+
onRootDelegationNeeded: this.signer ? async (params) => {
|
|
4160
|
+
graph.assertActive();
|
|
4161
|
+
const delegation = await this.createRootDelegationForSharing(
|
|
4162
|
+
params,
|
|
4163
|
+
() => graph.assertActive()
|
|
4164
|
+
);
|
|
4165
|
+
graph.assertActive();
|
|
4166
|
+
return delegation;
|
|
4167
|
+
} : void 0
|
|
3470
4168
|
});
|
|
3471
4169
|
this._spaceService.updateConfig({
|
|
3472
4170
|
sharingService: this._sharingService
|
|
@@ -3533,7 +4231,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3533
4231
|
* with expiry longer than the current session.
|
|
3534
4232
|
* @internal
|
|
3535
4233
|
*/
|
|
3536
|
-
async createOwnerDelegation(params) {
|
|
4234
|
+
async createOwnerDelegation(params, assertActive) {
|
|
4235
|
+
const assertOwnerGraphActive = assertActive ?? this._serviceGraph.assertActive.bind(this._serviceGraph);
|
|
4236
|
+
assertOwnerGraphActive();
|
|
3537
4237
|
if (!params.delegateDid.startsWith("did:key:") || params.actions.length === 0 || params.path.length === 0) {
|
|
3538
4238
|
throw new Error("Owner delegation requires an external did:key audience and bounded capabilities");
|
|
3539
4239
|
}
|
|
@@ -3558,8 +4258,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3558
4258
|
delegateUri: params.delegateDid
|
|
3559
4259
|
});
|
|
3560
4260
|
const signature = await this.signer.signMessage(prepared.siwe);
|
|
4261
|
+
assertOwnerGraphActive();
|
|
3561
4262
|
const delegationSession = this.wasmBindings.completeSessionSetup({ ...prepared, signature });
|
|
3562
4263
|
const activation = await (0, import_sdk_core8.activateSessionWithHost)(host, delegationSession.delegationHeader);
|
|
4264
|
+
assertOwnerGraphActive();
|
|
3563
4265
|
if (!activation.success) {
|
|
3564
4266
|
throw new Error(`Owner delegation import failed: ${activation.status} ${activation.error ?? ""}`.trim());
|
|
3565
4267
|
}
|
|
@@ -3587,7 +4289,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3587
4289
|
}
|
|
3588
4290
|
};
|
|
3589
4291
|
}
|
|
3590
|
-
async createRootDelegationForSharing(params) {
|
|
4292
|
+
async createRootDelegationForSharing(params, assertActive) {
|
|
3591
4293
|
try {
|
|
3592
4294
|
return (await this.createOwnerDelegation({
|
|
3593
4295
|
delegateDid: params.shareKeyDID,
|
|
@@ -3595,8 +4297,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3595
4297
|
path: params.path,
|
|
3596
4298
|
actions: params.actions,
|
|
3597
4299
|
expiresAt: params.requestedExpiry
|
|
3598
|
-
})).delegation;
|
|
4300
|
+
}, assertActive)).delegation;
|
|
3599
4301
|
} catch {
|
|
4302
|
+
assertActive?.();
|
|
3600
4303
|
return void 0;
|
|
3601
4304
|
}
|
|
3602
4305
|
}
|
|
@@ -3668,13 +4371,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3668
4371
|
throw new Error("Not signed in. Call signIn() first.");
|
|
3669
4372
|
}
|
|
3670
4373
|
const sql = new import_sdk_core8.SQLService({});
|
|
3671
|
-
const spaceScopedContext = new import_sdk_core8.ServiceContext({
|
|
4374
|
+
const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
3672
4375
|
invoke: this._serviceContext.invoke,
|
|
3673
4376
|
invokeAny: this._serviceContext.invokeAny,
|
|
3674
4377
|
fetch: this._serviceContext.fetch,
|
|
3675
4378
|
hosts: this._serviceContext.hosts,
|
|
3676
4379
|
telemetry: this.config.telemetry
|
|
3677
|
-
});
|
|
4380
|
+
}));
|
|
3678
4381
|
spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
|
|
3679
4382
|
sql.initialize(spaceScopedContext);
|
|
3680
4383
|
return sql;
|
|
@@ -3698,12 +4401,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3698
4401
|
throw new Error("Not signed in. Call signIn() first.");
|
|
3699
4402
|
}
|
|
3700
4403
|
const kv = new import_sdk_core8.KVService({});
|
|
3701
|
-
const spaceScopedContext = new import_sdk_core8.ServiceContext({
|
|
4404
|
+
const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
3702
4405
|
invoke: this._serviceContext.invoke,
|
|
3703
4406
|
invokeAny: this._serviceContext.invokeAny,
|
|
3704
4407
|
fetch: this._serviceContext.fetch,
|
|
3705
4408
|
hosts: this._serviceContext.hosts
|
|
3706
|
-
});
|
|
4409
|
+
}));
|
|
3707
4410
|
spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
|
|
3708
4411
|
kv.initialize(spaceScopedContext);
|
|
3709
4412
|
return kv;
|
|
@@ -3739,19 +4442,11 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3739
4442
|
}
|
|
3740
4443
|
async getEncryptionNetwork(nameOrNetworkId = this.getDefaultEncryptionNetworkId()) {
|
|
3741
4444
|
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
3742
|
-
|
|
3743
|
-
|
|
4445
|
+
return this.fetchEncryptionNetworkAt(
|
|
4446
|
+
this.config.host,
|
|
4447
|
+
networkId,
|
|
4448
|
+
globalThis.fetch.bind(globalThis)
|
|
3744
4449
|
);
|
|
3745
|
-
if (response.status === 404) {
|
|
3746
|
-
return null;
|
|
3747
|
-
}
|
|
3748
|
-
if (!response.ok) {
|
|
3749
|
-
throw new Error(
|
|
3750
|
-
`Failed to fetch encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
|
|
3751
|
-
);
|
|
3752
|
-
}
|
|
3753
|
-
const body = await response.json();
|
|
3754
|
-
return "descriptor" in body && body.descriptor ? body.descriptor : body;
|
|
3755
4450
|
}
|
|
3756
4451
|
async createEncryptionNetwork(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
3757
4452
|
const targetNode = await this.fetchNodeId();
|
|
@@ -3845,6 +4540,38 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3845
4540
|
}
|
|
3846
4541
|
return secrets;
|
|
3847
4542
|
}
|
|
4543
|
+
/**
|
|
4544
|
+
* Read a secret from an explicit target space without requesting or
|
|
4545
|
+
* auto-signing authority. Active runtime delegations are selected by the
|
|
4546
|
+
* normal KV and encryption invocation paths.
|
|
4547
|
+
*/
|
|
4548
|
+
async readSecret(input) {
|
|
4549
|
+
const resolved = (0, import_sdk_core8.resolveSecretPath)(input.name, { scope: input.scope });
|
|
4550
|
+
const targetSpace = input.space.startsWith("tinycloud:") ? input.space : this.ownedSpaceId(input.space);
|
|
4551
|
+
const result = await this.getBaseVault(targetSpace).readNetworkEncrypted(
|
|
4552
|
+
resolved.vaultKey
|
|
4553
|
+
);
|
|
4554
|
+
if (result.status !== "ok") {
|
|
4555
|
+
if (result.status === "permission_required") {
|
|
4556
|
+
const hint = (0, import_sdk_services.parsePermissionHint)(result.hint);
|
|
4557
|
+
if (hint === void 0) return { status: "read_failed" };
|
|
4558
|
+
return {
|
|
4559
|
+
status: "permission_required",
|
|
4560
|
+
hint: {
|
|
4561
|
+
service: hint.service,
|
|
4562
|
+
...hint.space === void 0 ? {} : { space: hint.space },
|
|
4563
|
+
path: hint.path,
|
|
4564
|
+
actions: [...hint.actions]
|
|
4565
|
+
}
|
|
4566
|
+
};
|
|
4567
|
+
}
|
|
4568
|
+
return { status: result.status };
|
|
4569
|
+
}
|
|
4570
|
+
if (!isSecretPayload(result.entry.value)) {
|
|
4571
|
+
return { status: "invalid_payload" };
|
|
4572
|
+
}
|
|
4573
|
+
return { status: "ok", value: result.entry.value.value };
|
|
4574
|
+
}
|
|
3848
4575
|
getBaseSecrets(spaceId) {
|
|
3849
4576
|
if (!this._spaceService) {
|
|
3850
4577
|
throw new Error("Not signed in. Call signIn() first.");
|
|
@@ -3852,16 +4579,29 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3852
4579
|
const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
|
|
3853
4580
|
let secrets = this._baseSecrets.get(resolvedSpace);
|
|
3854
4581
|
if (!secrets) {
|
|
3855
|
-
|
|
3856
|
-
const vaultService = this.createVaultService(resolvedSpace, kvService);
|
|
3857
|
-
if (this._serviceContext) {
|
|
3858
|
-
vaultService.initialize(this._serviceContext);
|
|
3859
|
-
}
|
|
3860
|
-
secrets = new import_sdk_core8.SecretsService(() => vaultService);
|
|
4582
|
+
secrets = new import_sdk_core8.SecretsService(() => this.getBaseVault(resolvedSpace));
|
|
3861
4583
|
this._baseSecrets.set(resolvedSpace, secrets);
|
|
3862
4584
|
}
|
|
3863
4585
|
return secrets;
|
|
3864
4586
|
}
|
|
4587
|
+
getBaseVault(spaceId) {
|
|
4588
|
+
if (!this._spaceService) {
|
|
4589
|
+
throw new Error("Not signed in. Call signIn() first.");
|
|
4590
|
+
}
|
|
4591
|
+
const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
|
|
4592
|
+
let vault = this._baseVaults.get(resolvedSpace);
|
|
4593
|
+
if (!vault) {
|
|
4594
|
+
vault = this.createVaultService(
|
|
4595
|
+
resolvedSpace,
|
|
4596
|
+
this.createSpaceScopedKVService(resolvedSpace)
|
|
4597
|
+
);
|
|
4598
|
+
if (this._serviceContext) {
|
|
4599
|
+
vault.initialize(this._serviceContext);
|
|
4600
|
+
}
|
|
4601
|
+
this._baseVaults.set(resolvedSpace, vault);
|
|
4602
|
+
}
|
|
4603
|
+
return vault;
|
|
4604
|
+
}
|
|
3865
4605
|
/**
|
|
3866
4606
|
* Hooks write stream subscription API.
|
|
3867
4607
|
*/
|
|
@@ -3966,6 +4706,63 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3966
4706
|
(grant) => grant.delegation
|
|
3967
4707
|
);
|
|
3968
4708
|
}
|
|
4709
|
+
/**
|
|
4710
|
+
* Return the effective capabilities of installed runtime grants.
|
|
4711
|
+
*
|
|
4712
|
+
* The result is projected from the SDK's activated, expiry-pruned grant
|
|
4713
|
+
* operations rather than from PortableDelegation transport metadata. Base
|
|
4714
|
+
* session authority is intentionally omitted; callers that need the full
|
|
4715
|
+
* live authority must combine this with {@link getVerifiedSessionCapabilities}.
|
|
4716
|
+
*/
|
|
4717
|
+
getEffectiveRuntimePermissionEntries() {
|
|
4718
|
+
const session = this.currentTinyCloudSession();
|
|
4719
|
+
if (!session) return [];
|
|
4720
|
+
this.pruneExpiredRuntimePermissionGrants();
|
|
4721
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
4722
|
+
for (const grant of this.runtimePermissionGrants) {
|
|
4723
|
+
if (grant.provenance === "primary") continue;
|
|
4724
|
+
for (const operation of grant.operations) {
|
|
4725
|
+
const service = import_sdk_core8.SERVICE_SHORT_TO_LONG[operation.service];
|
|
4726
|
+
if (service === void 0 || typeof operation.path !== "string" || typeof operation.action !== "string") {
|
|
4727
|
+
continue;
|
|
4728
|
+
}
|
|
4729
|
+
let space;
|
|
4730
|
+
if (service !== "tinycloud.encryption") {
|
|
4731
|
+
if (typeof operation.spaceId !== "string") continue;
|
|
4732
|
+
try {
|
|
4733
|
+
space = this.resolvePermissionSpace(operation.spaceId, session);
|
|
4734
|
+
} catch {
|
|
4735
|
+
continue;
|
|
4736
|
+
}
|
|
4737
|
+
}
|
|
4738
|
+
const caveats = operation.caveats === void 0 || operation.caveats.length === 0 ? void 0 : cloneRecapCaveats(operation.caveats);
|
|
4739
|
+
const identity = JSON.stringify({
|
|
4740
|
+
service,
|
|
4741
|
+
...space === void 0 ? {} : { space },
|
|
4742
|
+
path: operation.path,
|
|
4743
|
+
caveats: (0, import_sdk_core8.canonicalizeRecapCaveats)(caveats)
|
|
4744
|
+
});
|
|
4745
|
+
const existing = grouped.get(identity);
|
|
4746
|
+
if (existing === void 0) {
|
|
4747
|
+
grouped.set(identity, {
|
|
4748
|
+
service,
|
|
4749
|
+
...space === void 0 ? {} : { space },
|
|
4750
|
+
path: operation.path,
|
|
4751
|
+
actions: [operation.action],
|
|
4752
|
+
...caveats === void 0 ? {} : { caveats }
|
|
4753
|
+
});
|
|
4754
|
+
continue;
|
|
4755
|
+
}
|
|
4756
|
+
if (!existing.actions.includes(operation.action)) {
|
|
4757
|
+
existing.actions.push(operation.action);
|
|
4758
|
+
existing.actions.sort();
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
return [...grouped.values()].sort(
|
|
4763
|
+
(left, right) => left.service.localeCompare(right.service) || (left.space ?? "").localeCompare(right.space ?? "") || left.path.localeCompare(right.path) || left.actions.join("\0").localeCompare(right.actions.join("\0"))
|
|
4764
|
+
);
|
|
4765
|
+
}
|
|
3969
4766
|
/**
|
|
3970
4767
|
* Install a portable runtime permission delegation into this SDK instance so
|
|
3971
4768
|
* matching service calls and downstream `delegateTo()` calls can use it.
|
|
@@ -4034,6 +4831,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4034
4831
|
"grantRuntimePermissions requires wallet mode with a signer or privateKey."
|
|
4035
4832
|
);
|
|
4036
4833
|
}
|
|
4834
|
+
this.assertDelegationCaveatsPreservable(expanded);
|
|
4037
4835
|
const rawEntries = expanded.filter(
|
|
4038
4836
|
(entry) => this.isEncryptionPermissionEntry(entry)
|
|
4039
4837
|
);
|
|
@@ -4295,12 +5093,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4295
5093
|
}
|
|
4296
5094
|
if (this._serviceContext) {
|
|
4297
5095
|
const publicKV = new import_sdk_core8.KVService({ prefix: "" });
|
|
4298
|
-
const publicContext = new import_sdk_core8.ServiceContext({
|
|
4299
|
-
invoke: this.
|
|
4300
|
-
fetch: this.
|
|
5096
|
+
const publicContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
5097
|
+
invoke: this._serviceGraph.invoke,
|
|
5098
|
+
fetch: this._serviceGraph.fetch,
|
|
4301
5099
|
hosts: this._serviceContext.hosts,
|
|
4302
5100
|
telemetry: this.config.telemetry
|
|
4303
|
-
});
|
|
5101
|
+
}));
|
|
4304
5102
|
publicContext.setSession({
|
|
4305
5103
|
delegationHeader: delegationSession.delegationHeader,
|
|
4306
5104
|
delegationCid: delegationSession.delegationCid,
|
|
@@ -4367,13 +5165,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4367
5165
|
async getDelegationStatus(cid) {
|
|
4368
5166
|
return this.delegationManager.status(cid);
|
|
4369
5167
|
}
|
|
4370
|
-
/** Compute the canonical CID of a compact delegation authorization. */
|
|
5168
|
+
/** Compute the canonical CID of a compact UCAN or DAG-CBOR delegation authorization. */
|
|
4371
5169
|
computeDelegationCid(authorization) {
|
|
4372
5170
|
if (!authorization || !this.wasmBindings.computeCid) {
|
|
4373
5171
|
throw new Error("Delegation CID computation is unavailable");
|
|
4374
5172
|
}
|
|
5173
|
+
const compact = authorization.replace(/^Bearer /i, "");
|
|
4375
5174
|
return this.wasmBindings.computeCid(
|
|
4376
|
-
new TextEncoder().encode(authorization),
|
|
5175
|
+
compact.includes(".") ? new TextEncoder().encode(compact) : decodeAuthorizationBytes(authorization),
|
|
4377
5176
|
0x55n
|
|
4378
5177
|
);
|
|
4379
5178
|
}
|
|
@@ -4465,6 +5264,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4465
5264
|
"delegateTo with forceWalletSign=true supports at most one PermissionEntry. Multi-entry requests must go through the session-key UCAN path (drop forceWalletSign) or the legacy createDelegation method."
|
|
4466
5265
|
);
|
|
4467
5266
|
}
|
|
5267
|
+
this.assertDelegationCaveatsPreservable(expandedEntries);
|
|
4468
5268
|
const delegation2 = await this.createDelegationLegacyWalletPath(
|
|
4469
5269
|
did,
|
|
4470
5270
|
expandedEntries[0],
|
|
@@ -4473,13 +5273,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4473
5273
|
return { delegation: delegation2, prompted: true };
|
|
4474
5274
|
}
|
|
4475
5275
|
const granted = (0, import_sdk_core8.parseRecapCapabilities)(
|
|
4476
|
-
(siwe) => this.
|
|
5276
|
+
(siwe) => this.parseRecapWithCaveats(siwe),
|
|
4477
5277
|
session.siwe
|
|
4478
5278
|
);
|
|
4479
5279
|
const { subset, missing } = (0, import_sdk_core8.isCapabilitySubset)(expandedEntries, granted);
|
|
4480
5280
|
if (!subset) {
|
|
5281
|
+
const runtimeOperations = this.permissionEntriesToOperations(expandedEntries, session);
|
|
4481
5282
|
const runtimeGrant = this.findGrantForOperations(
|
|
4482
|
-
|
|
5283
|
+
runtimeOperations,
|
|
4483
5284
|
{ excludePrimary: true }
|
|
4484
5285
|
);
|
|
4485
5286
|
if (runtimeGrant) {
|
|
@@ -4492,7 +5293,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4492
5293
|
did,
|
|
4493
5294
|
expandedEntries,
|
|
4494
5295
|
runtimeExpiration,
|
|
4495
|
-
runtimeGrant
|
|
5296
|
+
runtimeGrant,
|
|
5297
|
+
runtimeOperations
|
|
4496
5298
|
);
|
|
4497
5299
|
return { delegation: delegation2, prompted: false };
|
|
4498
5300
|
}
|
|
@@ -4562,6 +5364,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4562
5364
|
"createDelegationViaWasmPath requires a non-empty entries array"
|
|
4563
5365
|
);
|
|
4564
5366
|
}
|
|
5367
|
+
this.assertDelegationCaveatsPreservable(entries);
|
|
4565
5368
|
const resolvedSpaces = /* @__PURE__ */ new Set();
|
|
4566
5369
|
for (const entry of entries) {
|
|
4567
5370
|
if (this.isEncryptionPermissionEntry(entry)) {
|
|
@@ -4642,7 +5445,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4642
5445
|
host: this.config.host
|
|
4643
5446
|
};
|
|
4644
5447
|
}
|
|
4645
|
-
async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant) {
|
|
5448
|
+
async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations) {
|
|
5449
|
+
this.assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant);
|
|
5450
|
+
this.assertDelegationCaveatsPreservable(entries);
|
|
4646
5451
|
const result = this.createDelegationWrapper({
|
|
4647
5452
|
session: grant.session,
|
|
4648
5453
|
delegateDID: did,
|
|
@@ -4696,6 +5501,74 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4696
5501
|
expandPermissionEntries(permissions) {
|
|
4697
5502
|
return (0, import_sdk_core8.expandPermissionEntries)(permissions);
|
|
4698
5503
|
}
|
|
5504
|
+
/**
|
|
5505
|
+
* The current WASM child-delegation APIs accept action-only maps. Refuse any
|
|
5506
|
+
* constrained branch rather than signing a broader action-only child UCAN.
|
|
5507
|
+
*/
|
|
5508
|
+
assertDelegationCaveatsPreservable(entries) {
|
|
5509
|
+
const caveated = entries.filter(
|
|
5510
|
+
(entry) => !(0, import_sdk_core8.recapCaveatsEqual)(entry.caveats, void 0)
|
|
5511
|
+
);
|
|
5512
|
+
if (caveated.length > 0) {
|
|
5513
|
+
throw new import_sdk_core8.CaveatedDelegationUnsupportedError(caveated);
|
|
5514
|
+
}
|
|
5515
|
+
}
|
|
5516
|
+
/**
|
|
5517
|
+
* Runtime grant selection intentionally allows an uncaveated operation to
|
|
5518
|
+
* select a caveated grant so invocation can restore the signed caveat before
|
|
5519
|
+
* crossing the caveat-aware WASM boundary. Child delegation cannot do that:
|
|
5520
|
+
* it only accepts action maps, so reject the selected constrained branch.
|
|
5521
|
+
*/
|
|
5522
|
+
assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant) {
|
|
5523
|
+
let operationIndex = 0;
|
|
5524
|
+
const caveated = [];
|
|
5525
|
+
for (const entry of entries) {
|
|
5526
|
+
for (const action of entry.actions) {
|
|
5527
|
+
const requested = requestedOperations[operationIndex++];
|
|
5528
|
+
if (!requested) continue;
|
|
5529
|
+
const constrained = grant.operations.find(
|
|
5530
|
+
(granted) => this.operationCovers(granted, requested) && !(0, import_sdk_core8.recapCaveatsEqual)(granted.caveats, void 0)
|
|
5531
|
+
);
|
|
5532
|
+
if (constrained) {
|
|
5533
|
+
caveated.push({
|
|
5534
|
+
...entry,
|
|
5535
|
+
actions: [action],
|
|
5536
|
+
caveats: cloneRecapCaveats(constrained.caveats)
|
|
5537
|
+
});
|
|
5538
|
+
}
|
|
5539
|
+
}
|
|
5540
|
+
}
|
|
5541
|
+
if (caveated.length > 0) {
|
|
5542
|
+
throw new import_sdk_core8.CaveatedDelegationUnsupportedError(caveated);
|
|
5543
|
+
}
|
|
5544
|
+
}
|
|
5545
|
+
/** Reject caveated parent branches before action-only child signing. */
|
|
5546
|
+
assertPortableDelegationCaveatsPreservable(delegation) {
|
|
5547
|
+
const entries = [];
|
|
5548
|
+
const add = (service, space, path, actions, caveats) => {
|
|
5549
|
+
if ((0, import_sdk_core8.recapCaveatsEqual)(caveats, void 0)) return;
|
|
5550
|
+
entries.push({
|
|
5551
|
+
service: service.startsWith("tinycloud.") ? service : `tinycloud.${service}`,
|
|
5552
|
+
space,
|
|
5553
|
+
path,
|
|
5554
|
+
actions: [...actions],
|
|
5555
|
+
caveats: cloneRecapCaveats(caveats)
|
|
5556
|
+
});
|
|
5557
|
+
};
|
|
5558
|
+
add(
|
|
5559
|
+
delegation.actions[0]?.split("/", 1)[0] ?? "tinycloud.unknown",
|
|
5560
|
+
delegation.spaceId,
|
|
5561
|
+
delegation.path,
|
|
5562
|
+
delegation.actions,
|
|
5563
|
+
delegation.caveats
|
|
5564
|
+
);
|
|
5565
|
+
for (const resource of delegation.resources ?? []) {
|
|
5566
|
+
add(resource.service, resource.space, resource.path, resource.actions, resource.caveats);
|
|
5567
|
+
}
|
|
5568
|
+
if (entries.length > 0) {
|
|
5569
|
+
throw new import_sdk_core8.CaveatedDelegationUnsupportedError(entries);
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
4699
5572
|
shortServiceName(service) {
|
|
4700
5573
|
const short = import_sdk_core8.SERVICE_LONG_TO_SHORT[service];
|
|
4701
5574
|
if (short === void 0) {
|
|
@@ -4750,14 +5623,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4750
5623
|
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
4751
5624
|
service,
|
|
4752
5625
|
path: entry.path,
|
|
4753
|
-
action
|
|
5626
|
+
action,
|
|
5627
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
4754
5628
|
}));
|
|
4755
5629
|
});
|
|
4756
5630
|
}
|
|
4757
5631
|
sessionCoversPermissionEntries(session, entries) {
|
|
4758
5632
|
try {
|
|
4759
5633
|
const granted = (0, import_sdk_core8.parseRecapCapabilities)(
|
|
4760
|
-
(siwe) => this.
|
|
5634
|
+
(siwe) => this.parseRecapWithCaveats(siwe),
|
|
4761
5635
|
session.siwe
|
|
4762
5636
|
);
|
|
4763
5637
|
return (0, import_sdk_core8.isCapabilitySubset)(entries, granted).subset;
|
|
@@ -4773,7 +5647,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4773
5647
|
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
4774
5648
|
service,
|
|
4775
5649
|
path: entry.path,
|
|
4776
|
-
action
|
|
5650
|
+
action,
|
|
5651
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
4777
5652
|
}));
|
|
4778
5653
|
});
|
|
4779
5654
|
}
|
|
@@ -4849,7 +5724,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4849
5724
|
service: this.shortServiceName(entry.service),
|
|
4850
5725
|
space: this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
|
|
4851
5726
|
path: entry.path,
|
|
4852
|
-
actions: [...entry.actions]
|
|
5727
|
+
actions: [...entry.actions],
|
|
5728
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
4853
5729
|
}));
|
|
4854
5730
|
}
|
|
4855
5731
|
operationsFromDelegation(delegation) {
|
|
@@ -4860,7 +5736,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4860
5736
|
...this.isEncryptionNetworkOperation(service, resource.path) ? { resource: resource.path } : { spaceId: resource.space },
|
|
4861
5737
|
service,
|
|
4862
5738
|
path: resource.path,
|
|
4863
|
-
action
|
|
5739
|
+
action,
|
|
5740
|
+
caveats: cloneRecapCaveats(resource.caveats)
|
|
4864
5741
|
}));
|
|
4865
5742
|
});
|
|
4866
5743
|
}
|
|
@@ -4876,7 +5753,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4876
5753
|
service,
|
|
4877
5754
|
space: delegation.spaceId,
|
|
4878
5755
|
path: delegation.path,
|
|
4879
|
-
actions
|
|
5756
|
+
actions,
|
|
5757
|
+
...delegation.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(delegation.caveats) }
|
|
4880
5758
|
}));
|
|
4881
5759
|
}
|
|
4882
5760
|
/**
|
|
@@ -4977,6 +5855,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4977
5855
|
if (granted.service !== requested.service || !this.actionContains(granted.action, requested.action)) {
|
|
4978
5856
|
return false;
|
|
4979
5857
|
}
|
|
5858
|
+
if (requested.caveats !== void 0 && !(0, import_sdk_core8.recapCaveatsEqual)(granted.caveats, requested.caveats)) {
|
|
5859
|
+
return false;
|
|
5860
|
+
}
|
|
4980
5861
|
if (granted.resource !== void 0 || requested.resource !== void 0) {
|
|
4981
5862
|
return granted.resource !== void 0 && requested.resource !== void 0 && granted.resource === requested.resource && this.pathContains(granted.path, requested.path);
|
|
4982
5863
|
}
|
|
@@ -5011,6 +5892,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5011
5892
|
invocationServiceName(service) {
|
|
5012
5893
|
return service.startsWith("tinycloud.") ? this.shortServiceName(service) : service;
|
|
5013
5894
|
}
|
|
5895
|
+
/** Prefer the v2 caveat-preserving parser while retaining old custom WASM. */
|
|
5896
|
+
parseRecapWithCaveats(siwe) {
|
|
5897
|
+
return this.wasmBindings.parseVerifiedRecapFromSiwe?.(siwe) ?? this.wasmBindings.parseRecapFromSiwe(siwe);
|
|
5898
|
+
}
|
|
5014
5899
|
isEncryptionNetworkOperation(service, path) {
|
|
5015
5900
|
return service === "encryption" && path.startsWith("urn:tinycloud:encryption:");
|
|
5016
5901
|
}
|
|
@@ -5021,7 +5906,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5021
5906
|
resource: entry.resource,
|
|
5022
5907
|
service,
|
|
5023
5908
|
path: entry.path,
|
|
5024
|
-
action: entry.action
|
|
5909
|
+
action: entry.action,
|
|
5910
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
5025
5911
|
};
|
|
5026
5912
|
}
|
|
5027
5913
|
if (this.isEncryptionNetworkOperation(service, entry.path)) {
|
|
@@ -5029,7 +5915,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5029
5915
|
resource: entry.path,
|
|
5030
5916
|
service,
|
|
5031
5917
|
path: entry.path,
|
|
5032
|
-
action: entry.action
|
|
5918
|
+
action: entry.action,
|
|
5919
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
5033
5920
|
};
|
|
5034
5921
|
}
|
|
5035
5922
|
if (typeof entry.spaceId === "string") {
|
|
@@ -5037,7 +5924,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5037
5924
|
spaceId: entry.spaceId,
|
|
5038
5925
|
service,
|
|
5039
5926
|
path: entry.path,
|
|
5040
|
-
action: entry.action
|
|
5927
|
+
action: entry.action,
|
|
5928
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
5041
5929
|
};
|
|
5042
5930
|
}
|
|
5043
5931
|
return void 0;
|
|
@@ -5377,6 +6265,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5377
6265
|
* @returns A portable delegation for the sub-delegate
|
|
5378
6266
|
*/
|
|
5379
6267
|
async createSubDelegation(parentDelegation, params) {
|
|
6268
|
+
this.assertPortableDelegationCaveatsPreservable(parentDelegation);
|
|
5380
6269
|
if (!this.signer) {
|
|
5381
6270
|
throw new Error("Cannot createSubDelegation() in session-only mode. Requires wallet mode.");
|
|
5382
6271
|
}
|
|
@@ -5469,9 +6358,10 @@ _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS = 6e4;
|
|
|
5469
6358
|
var TinyCloudNode = _TinyCloudNode;
|
|
5470
6359
|
|
|
5471
6360
|
// src/core.ts
|
|
5472
|
-
var
|
|
6361
|
+
var import_sdk_core12 = require("@tinycloud/sdk-core");
|
|
5473
6362
|
|
|
5474
6363
|
// src/delegation.ts
|
|
6364
|
+
var import_sdk_core9 = require("@tinycloud/sdk-core");
|
|
5475
6365
|
function serializeDelegation(delegation) {
|
|
5476
6366
|
return JSON.stringify({
|
|
5477
6367
|
...delegation,
|
|
@@ -5488,7 +6378,6 @@ function deserializeDelegation(data) {
|
|
|
5488
6378
|
}
|
|
5489
6379
|
|
|
5490
6380
|
// src/core.ts
|
|
5491
|
-
var import_sdk_core12 = require("@tinycloud/sdk-core");
|
|
5492
6381
|
var import_sdk_core13 = require("@tinycloud/sdk-core");
|
|
5493
6382
|
var import_sdk_core14 = require("@tinycloud/sdk-core");
|
|
5494
6383
|
var import_sdk_core15 = require("@tinycloud/sdk-core");
|
|
@@ -5497,6 +6386,7 @@ var import_sdk_core17 = require("@tinycloud/sdk-core");
|
|
|
5497
6386
|
var import_sdk_core18 = require("@tinycloud/sdk-core");
|
|
5498
6387
|
var import_sdk_core19 = require("@tinycloud/sdk-core");
|
|
5499
6388
|
var import_sdk_core20 = require("@tinycloud/sdk-core");
|
|
6389
|
+
var import_sdk_core21 = require("@tinycloud/sdk-core");
|
|
5500
6390
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5501
6391
|
0 && (module.exports = {
|
|
5502
6392
|
ACCOUNT_REGISTRY_PATH,
|
|
@@ -5505,6 +6395,7 @@ var import_sdk_core20 = require("@tinycloud/sdk-core");
|
|
|
5505
6395
|
AutoApproveSpaceCreationHandler,
|
|
5506
6396
|
CapabilityKeyRegistry,
|
|
5507
6397
|
CapabilityKeyRegistryErrorCodes,
|
|
6398
|
+
CaveatedDelegationUnsupportedError,
|
|
5508
6399
|
DEFAULT_MANIFEST_SPACE,
|
|
5509
6400
|
DEFAULT_MANIFEST_VERSION,
|
|
5510
6401
|
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
@@ -5540,6 +6431,7 @@ var import_sdk_core20 = require("@tinycloud/sdk-core");
|
|
|
5540
6431
|
TinyCloudDebugLogger,
|
|
5541
6432
|
TinyCloudNode,
|
|
5542
6433
|
UnsupportedFeatureError,
|
|
6434
|
+
UnsupportedSessionRestoreError,
|
|
5543
6435
|
VAULT_PERMISSION_SERVICE,
|
|
5544
6436
|
VaultHeaders,
|
|
5545
6437
|
VaultPublicSpaceKVActions,
|