@tinycloud/node-sdk 2.7.0-beta.3 → 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-DGFXEW74.d.cts → core-D_KNrE_y.d.cts} +151 -6
- package/dist/{core-DGFXEW74.d.ts → core-D_KNrE_y.d.ts} +151 -6
- package/dist/core.cjs +1150 -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 +1081 -181
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1468 -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 +1359 -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
|
*/
|
|
@@ -2166,6 +2395,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2166
2395
|
this._hooks = void 0;
|
|
2167
2396
|
this._vault = void 0;
|
|
2168
2397
|
this._encryption = void 0;
|
|
2398
|
+
this._baseVaults.clear();
|
|
2169
2399
|
this._baseSecrets.clear();
|
|
2170
2400
|
this._secrets.clear();
|
|
2171
2401
|
this._spaceService = void 0;
|
|
@@ -2173,6 +2403,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2173
2403
|
this.runtimePermissionGrants = [];
|
|
2174
2404
|
await this.tc.signIn(options);
|
|
2175
2405
|
this.syncResolvedHostFromAuth();
|
|
2406
|
+
const oldGraph = this._serviceGraph;
|
|
2407
|
+
this._serviceGraph = this.createServiceGraphLifetime();
|
|
2408
|
+
oldGraph.retire();
|
|
2409
|
+
this.tc.retireServices();
|
|
2176
2410
|
const signedInSession = this.currentTinyCloudSession();
|
|
2177
2411
|
if (signedInSession) {
|
|
2178
2412
|
this.sessionKeyId = signedInSession.sessionKey;
|
|
@@ -2457,7 +2691,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2457
2691
|
}
|
|
2458
2692
|
let operations = [];
|
|
2459
2693
|
try {
|
|
2460
|
-
const entries = this.
|
|
2694
|
+
const entries = this.parseRecapWithCaveats(siwe);
|
|
2461
2695
|
if (Array.isArray(entries)) {
|
|
2462
2696
|
operations = entries.flatMap((entry) => {
|
|
2463
2697
|
const service = this.invocationServiceName(entry.service);
|
|
@@ -2465,7 +2699,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2465
2699
|
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId: entry.space },
|
|
2466
2700
|
service,
|
|
2467
2701
|
path: entry.path,
|
|
2468
|
-
action
|
|
2702
|
+
action,
|
|
2703
|
+
caveats: cloneRecapCaveats(entry.caveats)
|
|
2469
2704
|
}));
|
|
2470
2705
|
});
|
|
2471
2706
|
}
|
|
@@ -2818,86 +3053,441 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
2818
3053
|
*/
|
|
2819
3054
|
async restoreSession(sessionData) {
|
|
2820
3055
|
await this.wasmBindings.ensureInitialized?.();
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
this.
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
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.");
|
|
2835
3089
|
}
|
|
2836
|
-
|
|
2837
|
-
|
|
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);
|
|
2838
3149
|
}
|
|
2839
3150
|
const resolvedHost = await this.resolveRestoredHost(
|
|
2840
3151
|
sessionData.tinycloudHosts,
|
|
2841
3152
|
restoredAddress,
|
|
2842
3153
|
sessionData.chainId
|
|
2843
3154
|
);
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
invoke: this.invokeWithRuntimePermissions,
|
|
2849
|
-
invokeAny: this.invokeAnyWithRuntimePermissions,
|
|
2850
|
-
fetch: globalThis.fetch.bind(globalThis),
|
|
2851
|
-
hosts: [this.config.host],
|
|
2852
|
-
telemetry: this.config.telemetry
|
|
2853
|
-
});
|
|
2854
|
-
this._kv = new import_sdk_core8.KVService({});
|
|
2855
|
-
this._kv.initialize(this._serviceContext);
|
|
2856
|
-
this._serviceContext.registerService("kv", this._kv);
|
|
2857
|
-
this._sql = new import_sdk_core8.SQLService({});
|
|
2858
|
-
this._sql.initialize(this._serviceContext);
|
|
2859
|
-
this._serviceContext.registerService("sql", this._sql);
|
|
2860
|
-
this._duckdb = new import_sdk_core8.DuckDbService({});
|
|
2861
|
-
this._duckdb.initialize(this._serviceContext);
|
|
2862
|
-
this._serviceContext.registerService("duckdb", this._duckdb);
|
|
2863
|
-
this._hooks = new import_sdk_core8.HooksService({});
|
|
2864
|
-
this._hooks.initialize(this._serviceContext);
|
|
2865
|
-
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;
|
|
2866
3159
|
const serviceSession = {
|
|
2867
3160
|
delegationHeader: sessionData.delegationHeader,
|
|
2868
3161
|
delegationCid: sessionData.delegationCid,
|
|
2869
3162
|
spaceId: sessionData.spaceId,
|
|
2870
|
-
verificationMethod:
|
|
2871
|
-
jwk:
|
|
3163
|
+
verificationMethod: restoredVerificationMethod,
|
|
3164
|
+
jwk: stagedJwk
|
|
2872
3165
|
};
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
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);
|
|
2898
3353
|
}
|
|
2899
|
-
this.registerPrimarySessionGrant(tcSession);
|
|
2900
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 };
|
|
2901
3491
|
}
|
|
2902
3492
|
/**
|
|
2903
3493
|
* Resolve the host a restored session should target.
|
|
@@ -3059,14 +3649,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3059
3649
|
if (!session) {
|
|
3060
3650
|
return;
|
|
3061
3651
|
}
|
|
3062
|
-
this.tc.initializeServices(
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
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,
|
|
3067
3662
|
hosts: [this.config.host],
|
|
3068
3663
|
telemetry: this.config.telemetry
|
|
3069
|
-
});
|
|
3664
|
+
}));
|
|
3070
3665
|
this._kv = new import_sdk_core8.KVService({});
|
|
3071
3666
|
this._kv.initialize(this._serviceContext);
|
|
3072
3667
|
this._serviceContext.registerService("kv", this._kv);
|
|
@@ -3101,12 +3696,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3101
3696
|
createSpaceScopedKVService(spaceId) {
|
|
3102
3697
|
const kvService = new import_sdk_core8.KVService({});
|
|
3103
3698
|
if (this._serviceContext) {
|
|
3104
|
-
const spaceScopedContext = new import_sdk_core8.ServiceContext({
|
|
3699
|
+
const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
3105
3700
|
invoke: this._serviceContext.invoke,
|
|
3106
3701
|
fetch: this._serviceContext.fetch,
|
|
3107
3702
|
hosts: this._serviceContext.hosts,
|
|
3108
3703
|
telemetry: this.config.telemetry
|
|
3109
|
-
});
|
|
3704
|
+
}));
|
|
3110
3705
|
const session = this._serviceContext.session;
|
|
3111
3706
|
if (session) {
|
|
3112
3707
|
spaceScopedContext.setSession({ ...session, spaceId });
|
|
@@ -3139,6 +3734,18 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3139
3734
|
}
|
|
3140
3735
|
return session;
|
|
3141
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
|
+
}
|
|
3142
3749
|
createEncryptionCrypto() {
|
|
3143
3750
|
const wasm = this.wasmBindings;
|
|
3144
3751
|
const columnEncrypt = (key, plaintext) => {
|
|
@@ -3194,14 +3801,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3194
3801
|
}
|
|
3195
3802
|
return info.nodeId;
|
|
3196
3803
|
}
|
|
3197
|
-
async signRawNetworkAuthorization(input) {
|
|
3804
|
+
async signRawNetworkAuthorization(input, binding) {
|
|
3805
|
+
binding?.graph.assertActive();
|
|
3198
3806
|
if (!this.wasmBindings.invokeAny) {
|
|
3199
3807
|
throw new Error("WASM binding does not support raw-resource invokeAny");
|
|
3200
3808
|
}
|
|
3201
3809
|
if (!this.wasmBindings.computeCid) {
|
|
3202
3810
|
throw new Error("WASM binding does not support invocation CID computation");
|
|
3203
3811
|
}
|
|
3204
|
-
const session = this.
|
|
3812
|
+
const session = binding?.session ?? this.requireEncryptionSession();
|
|
3205
3813
|
const headers = this.invokeAnyWithRuntimePermissions(
|
|
3206
3814
|
session,
|
|
3207
3815
|
[
|
|
@@ -3220,6 +3828,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3220
3828
|
input.targetNode,
|
|
3221
3829
|
session.jwk
|
|
3222
3830
|
);
|
|
3831
|
+
binding?.graph.assertActive();
|
|
3223
3832
|
return {
|
|
3224
3833
|
authorization: audienceBound,
|
|
3225
3834
|
invocationCid: this.wasmBindings.computeCid(
|
|
@@ -3228,25 +3837,55 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3228
3837
|
)
|
|
3229
3838
|
};
|
|
3230
3839
|
}
|
|
3231
|
-
|
|
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;
|
|
3232
3860
|
const crypto = this.createEncryptionCrypto();
|
|
3233
3861
|
const transport = {
|
|
3234
|
-
postDecrypt: async ({ networkId, authorization, canonicalBody }) => {
|
|
3235
|
-
|
|
3236
|
-
|
|
3862
|
+
postDecrypt: async ({ networkId, authorization, canonicalBody, signal }) => {
|
|
3863
|
+
graph.assertActive();
|
|
3864
|
+
const response = await graph.fetch(
|
|
3865
|
+
`${host}/encryption/networks/${encodeURIComponent(networkId)}/decrypt`,
|
|
3237
3866
|
{
|
|
3238
3867
|
method: "POST",
|
|
3239
3868
|
headers: {
|
|
3240
3869
|
Authorization: authorization,
|
|
3241
3870
|
"Content-Type": "application/json"
|
|
3242
3871
|
},
|
|
3243
|
-
body: canonicalBody
|
|
3872
|
+
body: canonicalBody,
|
|
3873
|
+
signal
|
|
3244
3874
|
}
|
|
3245
3875
|
);
|
|
3876
|
+
graph.assertActive();
|
|
3246
3877
|
if (!response.ok) {
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
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);
|
|
3250
3889
|
}
|
|
3251
3890
|
return await response.json();
|
|
3252
3891
|
}
|
|
@@ -3255,12 +3894,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3255
3894
|
crypto,
|
|
3256
3895
|
signer: {
|
|
3257
3896
|
signDecryptInvocation: async (input) => {
|
|
3897
|
+
graph.assertActive();
|
|
3258
3898
|
const signed = await this.signRawNetworkAuthorization({
|
|
3259
3899
|
targetNode: input.targetNode,
|
|
3260
3900
|
networkId: input.networkId,
|
|
3261
3901
|
action: DECRYPT_ACTION2,
|
|
3262
3902
|
facts: input.facts
|
|
3263
|
-
});
|
|
3903
|
+
}, { graph, session });
|
|
3904
|
+
graph.assertActive();
|
|
3264
3905
|
return {
|
|
3265
3906
|
...signed,
|
|
3266
3907
|
canonicalBody: (0, import_sdk_core8.canonicalizeEncryptionJson)(
|
|
@@ -3271,25 +3912,35 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3271
3912
|
},
|
|
3272
3913
|
transport,
|
|
3273
3914
|
node: {
|
|
3274
|
-
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
|
+
}
|
|
3275
3921
|
},
|
|
3276
3922
|
wellKnown: {
|
|
3277
3923
|
fetchWellKnown: async (principal, discoveryKey) => {
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
}
|
|
3281
|
-
if (!this.config.host) {
|
|
3924
|
+
graph.assertActive();
|
|
3925
|
+
if (!address || !didPrincipalMatches2(principal, did)) {
|
|
3282
3926
|
return null;
|
|
3283
3927
|
}
|
|
3284
|
-
const publicSpaceId = (0, import_sdk_core8.makePublicSpaceId)(
|
|
3285
|
-
const
|
|
3286
|
-
|
|
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) {
|
|
3287
3936
|
return null;
|
|
3288
3937
|
}
|
|
3289
|
-
const body =
|
|
3938
|
+
const body = await response.json();
|
|
3939
|
+
graph.assertActive();
|
|
3290
3940
|
return "descriptor" in body && body.descriptor ? body.descriptor : body;
|
|
3291
3941
|
}
|
|
3292
|
-
}
|
|
3942
|
+
},
|
|
3943
|
+
assertActive: () => graph.assertActive()
|
|
3293
3944
|
});
|
|
3294
3945
|
}
|
|
3295
3946
|
getEncryptionService() {
|
|
@@ -3303,8 +3954,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3303
3954
|
}
|
|
3304
3955
|
return this._encryption;
|
|
3305
3956
|
}
|
|
3306
|
-
createVaultService(spaceId, kv) {
|
|
3957
|
+
createVaultService(spaceId, kv, encryptionService = this.getEncryptionService(), nodeContext) {
|
|
3307
3958
|
const wasm = this.wasmBindings;
|
|
3959
|
+
const serviceGraph = nodeContext?.serviceGraph ?? this._serviceGraph;
|
|
3308
3960
|
const vaultCrypto = (0, import_sdk_core8.createVaultCrypto)({
|
|
3309
3961
|
vault_encrypt: wasm.vault_encrypt,
|
|
3310
3962
|
vault_decrypt: wasm.vault_decrypt,
|
|
@@ -3315,12 +3967,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3315
3967
|
vault_sha256: wasm.vault_sha256
|
|
3316
3968
|
});
|
|
3317
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;
|
|
3318
3975
|
return new import_sdk_core8.DataVaultService({
|
|
3319
3976
|
spaceId,
|
|
3320
3977
|
crypto: vaultCrypto,
|
|
3321
3978
|
encryption: {
|
|
3322
|
-
networkId:
|
|
3323
|
-
service:
|
|
3979
|
+
networkId: `urn:tinycloud:encryption:${ownerDid}:${DEFAULT_ENCRYPTION_NETWORK_NAME}`,
|
|
3980
|
+
service: encryptionService,
|
|
3324
3981
|
decryptCapabilityProof: () => ({
|
|
3325
3982
|
proofs: [this.requireServiceSession().delegationCid]
|
|
3326
3983
|
})
|
|
@@ -3329,6 +3986,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3329
3986
|
kv,
|
|
3330
3987
|
ensurePublicSpace: async () => {
|
|
3331
3988
|
try {
|
|
3989
|
+
serviceGraph.assertActive();
|
|
3332
3990
|
await self.ensurePublicSpace();
|
|
3333
3991
|
return { ok: true, data: void 0 };
|
|
3334
3992
|
} catch (error) {
|
|
@@ -3336,14 +3994,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3336
3994
|
}
|
|
3337
3995
|
},
|
|
3338
3996
|
get publicKV() {
|
|
3997
|
+
serviceGraph.assertActive();
|
|
3339
3998
|
return self._publicKV ?? self.tc.publicKV;
|
|
3340
3999
|
},
|
|
3341
|
-
readPublicSpace: (
|
|
4000
|
+
readPublicSpace: (host2, targetSpaceId, key) => import_sdk_core8.TinyCloud.readPublicSpace(host2, targetSpaceId, key),
|
|
3342
4001
|
makePublicSpaceId: import_sdk_core8.TinyCloud.makePublicSpaceId,
|
|
3343
|
-
did
|
|
3344
|
-
address:
|
|
3345
|
-
chainId
|
|
3346
|
-
hosts: [
|
|
4002
|
+
did,
|
|
4003
|
+
address: address ?? "",
|
|
4004
|
+
chainId,
|
|
4005
|
+
hosts: [host]
|
|
3347
4006
|
}
|
|
3348
4007
|
});
|
|
3349
4008
|
}
|
|
@@ -3352,6 +4011,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3352
4011
|
* @internal
|
|
3353
4012
|
*/
|
|
3354
4013
|
initializeV2Services(serviceSession) {
|
|
4014
|
+
const graph = this._serviceGraph;
|
|
3355
4015
|
this._capabilityRegistry = new import_sdk_core8.CapabilityKeyRegistry();
|
|
3356
4016
|
const tcSession = this.auth?.tinyCloudSession;
|
|
3357
4017
|
if (tcSession && this._address) {
|
|
@@ -3396,21 +4056,23 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3396
4056
|
hosts: [this.config.host],
|
|
3397
4057
|
accountSpaceId: this.accountSpaceId,
|
|
3398
4058
|
session: serviceSession,
|
|
3399
|
-
invoke:
|
|
3400
|
-
invokeAny:
|
|
3401
|
-
fetch:
|
|
4059
|
+
invoke: graph.invoke,
|
|
4060
|
+
invokeAny: graph.invokeAny,
|
|
4061
|
+
fetch: graph.fetch
|
|
3402
4062
|
});
|
|
3403
4063
|
this._spaceService = new import_sdk_core8.SpaceService({
|
|
3404
4064
|
hosts: [this.config.host],
|
|
3405
4065
|
session: serviceSession,
|
|
3406
|
-
invoke:
|
|
3407
|
-
fetch:
|
|
4066
|
+
invoke: graph.invoke,
|
|
4067
|
+
fetch: graph.fetch,
|
|
3408
4068
|
capabilityRegistry: this._capabilityRegistry,
|
|
3409
4069
|
userDid: this.did,
|
|
3410
4070
|
createKVService: (spaceId) => {
|
|
4071
|
+
graph.assertActive();
|
|
3411
4072
|
return this.createSpaceScopedKVService(spaceId);
|
|
3412
4073
|
},
|
|
3413
4074
|
createVaultService: (spaceId) => {
|
|
4075
|
+
graph.assertActive();
|
|
3414
4076
|
const kvService = this.createSpaceScopedKVService(spaceId);
|
|
3415
4077
|
const vaultService = this.createVaultService(spaceId, kvService);
|
|
3416
4078
|
if (this._serviceContext) {
|
|
@@ -3419,11 +4081,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3419
4081
|
return vaultService;
|
|
3420
4082
|
},
|
|
3421
4083
|
createSecretsService: (spaceId) => {
|
|
4084
|
+
graph.assertActive();
|
|
3422
4085
|
return this.secretsForSpace(spaceId);
|
|
3423
4086
|
},
|
|
3424
4087
|
// Enable space.delegations.create() via SIWE-based delegation
|
|
3425
4088
|
createDelegation: async (params) => {
|
|
3426
4089
|
try {
|
|
4090
|
+
graph.assertActive();
|
|
3427
4091
|
const portableDelegation = await this.createDelegation({
|
|
3428
4092
|
delegateDID: params.delegateDID,
|
|
3429
4093
|
path: params.path,
|
|
@@ -3457,18 +4121,50 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3457
4121
|
}
|
|
3458
4122
|
},
|
|
3459
4123
|
onSpaceRegistered: async (space) => {
|
|
4124
|
+
graph.assertActive();
|
|
3460
4125
|
await this.account.spaces.register(space);
|
|
3461
4126
|
}
|
|
3462
4127
|
});
|
|
3463
|
-
this._sharingService.
|
|
4128
|
+
this._sharingService = new import_sdk_core8.SharingService({
|
|
4129
|
+
hosts: [this.config.host],
|
|
3464
4130
|
session: serviceSession,
|
|
4131
|
+
invoke: graph.invoke,
|
|
4132
|
+
fetch: graph.fetch,
|
|
4133
|
+
assertActive: () => graph.assertActive(),
|
|
4134
|
+
keyProvider: this._keyProvider,
|
|
4135
|
+
registry: this._capabilityRegistry,
|
|
3465
4136
|
delegationManager: this._delegationManager,
|
|
3466
4137
|
sessionExpiry: this.getSessionExpiry(),
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
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
|
|
3472
4168
|
});
|
|
3473
4169
|
this._spaceService.updateConfig({
|
|
3474
4170
|
sharingService: this._sharingService
|
|
@@ -3535,7 +4231,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3535
4231
|
* with expiry longer than the current session.
|
|
3536
4232
|
* @internal
|
|
3537
4233
|
*/
|
|
3538
|
-
async createOwnerDelegation(params) {
|
|
4234
|
+
async createOwnerDelegation(params, assertActive) {
|
|
4235
|
+
const assertOwnerGraphActive = assertActive ?? this._serviceGraph.assertActive.bind(this._serviceGraph);
|
|
4236
|
+
assertOwnerGraphActive();
|
|
3539
4237
|
if (!params.delegateDid.startsWith("did:key:") || params.actions.length === 0 || params.path.length === 0) {
|
|
3540
4238
|
throw new Error("Owner delegation requires an external did:key audience and bounded capabilities");
|
|
3541
4239
|
}
|
|
@@ -3560,8 +4258,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3560
4258
|
delegateUri: params.delegateDid
|
|
3561
4259
|
});
|
|
3562
4260
|
const signature = await this.signer.signMessage(prepared.siwe);
|
|
4261
|
+
assertOwnerGraphActive();
|
|
3563
4262
|
const delegationSession = this.wasmBindings.completeSessionSetup({ ...prepared, signature });
|
|
3564
4263
|
const activation = await (0, import_sdk_core8.activateSessionWithHost)(host, delegationSession.delegationHeader);
|
|
4264
|
+
assertOwnerGraphActive();
|
|
3565
4265
|
if (!activation.success) {
|
|
3566
4266
|
throw new Error(`Owner delegation import failed: ${activation.status} ${activation.error ?? ""}`.trim());
|
|
3567
4267
|
}
|
|
@@ -3589,7 +4289,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3589
4289
|
}
|
|
3590
4290
|
};
|
|
3591
4291
|
}
|
|
3592
|
-
async createRootDelegationForSharing(params) {
|
|
4292
|
+
async createRootDelegationForSharing(params, assertActive) {
|
|
3593
4293
|
try {
|
|
3594
4294
|
return (await this.createOwnerDelegation({
|
|
3595
4295
|
delegateDid: params.shareKeyDID,
|
|
@@ -3597,8 +4297,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3597
4297
|
path: params.path,
|
|
3598
4298
|
actions: params.actions,
|
|
3599
4299
|
expiresAt: params.requestedExpiry
|
|
3600
|
-
})).delegation;
|
|
4300
|
+
}, assertActive)).delegation;
|
|
3601
4301
|
} catch {
|
|
4302
|
+
assertActive?.();
|
|
3602
4303
|
return void 0;
|
|
3603
4304
|
}
|
|
3604
4305
|
}
|
|
@@ -3670,13 +4371,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3670
4371
|
throw new Error("Not signed in. Call signIn() first.");
|
|
3671
4372
|
}
|
|
3672
4373
|
const sql = new import_sdk_core8.SQLService({});
|
|
3673
|
-
const spaceScopedContext = new import_sdk_core8.ServiceContext({
|
|
4374
|
+
const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
3674
4375
|
invoke: this._serviceContext.invoke,
|
|
3675
4376
|
invokeAny: this._serviceContext.invokeAny,
|
|
3676
4377
|
fetch: this._serviceContext.fetch,
|
|
3677
4378
|
hosts: this._serviceContext.hosts,
|
|
3678
4379
|
telemetry: this.config.telemetry
|
|
3679
|
-
});
|
|
4380
|
+
}));
|
|
3680
4381
|
spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
|
|
3681
4382
|
sql.initialize(spaceScopedContext);
|
|
3682
4383
|
return sql;
|
|
@@ -3700,12 +4401,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3700
4401
|
throw new Error("Not signed in. Call signIn() first.");
|
|
3701
4402
|
}
|
|
3702
4403
|
const kv = new import_sdk_core8.KVService({});
|
|
3703
|
-
const spaceScopedContext = new import_sdk_core8.ServiceContext({
|
|
4404
|
+
const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
3704
4405
|
invoke: this._serviceContext.invoke,
|
|
3705
4406
|
invokeAny: this._serviceContext.invokeAny,
|
|
3706
4407
|
fetch: this._serviceContext.fetch,
|
|
3707
4408
|
hosts: this._serviceContext.hosts
|
|
3708
|
-
});
|
|
4409
|
+
}));
|
|
3709
4410
|
spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
|
|
3710
4411
|
kv.initialize(spaceScopedContext);
|
|
3711
4412
|
return kv;
|
|
@@ -3741,19 +4442,11 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3741
4442
|
}
|
|
3742
4443
|
async getEncryptionNetwork(nameOrNetworkId = this.getDefaultEncryptionNetworkId()) {
|
|
3743
4444
|
const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
|
|
3744
|
-
|
|
3745
|
-
|
|
4445
|
+
return this.fetchEncryptionNetworkAt(
|
|
4446
|
+
this.config.host,
|
|
4447
|
+
networkId,
|
|
4448
|
+
globalThis.fetch.bind(globalThis)
|
|
3746
4449
|
);
|
|
3747
|
-
if (response.status === 404) {
|
|
3748
|
-
return null;
|
|
3749
|
-
}
|
|
3750
|
-
if (!response.ok) {
|
|
3751
|
-
throw new Error(
|
|
3752
|
-
`Failed to fetch encryption network ${networkId}: HTTP ${response.status} ${await response.text()}`
|
|
3753
|
-
);
|
|
3754
|
-
}
|
|
3755
|
-
const body = await response.json();
|
|
3756
|
-
return "descriptor" in body && body.descriptor ? body.descriptor : body;
|
|
3757
4450
|
}
|
|
3758
4451
|
async createEncryptionNetwork(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
|
|
3759
4452
|
const targetNode = await this.fetchNodeId();
|
|
@@ -3847,6 +4540,38 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3847
4540
|
}
|
|
3848
4541
|
return secrets;
|
|
3849
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
|
+
}
|
|
3850
4575
|
getBaseSecrets(spaceId) {
|
|
3851
4576
|
if (!this._spaceService) {
|
|
3852
4577
|
throw new Error("Not signed in. Call signIn() first.");
|
|
@@ -3854,16 +4579,29 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3854
4579
|
const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
|
|
3855
4580
|
let secrets = this._baseSecrets.get(resolvedSpace);
|
|
3856
4581
|
if (!secrets) {
|
|
3857
|
-
|
|
3858
|
-
const vaultService = this.createVaultService(resolvedSpace, kvService);
|
|
3859
|
-
if (this._serviceContext) {
|
|
3860
|
-
vaultService.initialize(this._serviceContext);
|
|
3861
|
-
}
|
|
3862
|
-
secrets = new import_sdk_core8.SecretsService(() => vaultService);
|
|
4582
|
+
secrets = new import_sdk_core8.SecretsService(() => this.getBaseVault(resolvedSpace));
|
|
3863
4583
|
this._baseSecrets.set(resolvedSpace, secrets);
|
|
3864
4584
|
}
|
|
3865
4585
|
return secrets;
|
|
3866
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
|
+
}
|
|
3867
4605
|
/**
|
|
3868
4606
|
* Hooks write stream subscription API.
|
|
3869
4607
|
*/
|
|
@@ -3968,6 +4706,63 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
3968
4706
|
(grant) => grant.delegation
|
|
3969
4707
|
);
|
|
3970
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
|
+
}
|
|
3971
4766
|
/**
|
|
3972
4767
|
* Install a portable runtime permission delegation into this SDK instance so
|
|
3973
4768
|
* matching service calls and downstream `delegateTo()` calls can use it.
|
|
@@ -4036,6 +4831,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4036
4831
|
"grantRuntimePermissions requires wallet mode with a signer or privateKey."
|
|
4037
4832
|
);
|
|
4038
4833
|
}
|
|
4834
|
+
this.assertDelegationCaveatsPreservable(expanded);
|
|
4039
4835
|
const rawEntries = expanded.filter(
|
|
4040
4836
|
(entry) => this.isEncryptionPermissionEntry(entry)
|
|
4041
4837
|
);
|
|
@@ -4297,12 +5093,12 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4297
5093
|
}
|
|
4298
5094
|
if (this._serviceContext) {
|
|
4299
5095
|
const publicKV = new import_sdk_core8.KVService({ prefix: "" });
|
|
4300
|
-
const publicContext = new import_sdk_core8.ServiceContext({
|
|
4301
|
-
invoke: this.
|
|
4302
|
-
fetch: this.
|
|
5096
|
+
const publicContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
|
|
5097
|
+
invoke: this._serviceGraph.invoke,
|
|
5098
|
+
fetch: this._serviceGraph.fetch,
|
|
4303
5099
|
hosts: this._serviceContext.hosts,
|
|
4304
5100
|
telemetry: this.config.telemetry
|
|
4305
|
-
});
|
|
5101
|
+
}));
|
|
4306
5102
|
publicContext.setSession({
|
|
4307
5103
|
delegationHeader: delegationSession.delegationHeader,
|
|
4308
5104
|
delegationCid: delegationSession.delegationCid,
|
|
@@ -4369,13 +5165,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4369
5165
|
async getDelegationStatus(cid) {
|
|
4370
5166
|
return this.delegationManager.status(cid);
|
|
4371
5167
|
}
|
|
4372
|
-
/** Compute the canonical CID of a compact delegation authorization. */
|
|
5168
|
+
/** Compute the canonical CID of a compact UCAN or DAG-CBOR delegation authorization. */
|
|
4373
5169
|
computeDelegationCid(authorization) {
|
|
4374
5170
|
if (!authorization || !this.wasmBindings.computeCid) {
|
|
4375
5171
|
throw new Error("Delegation CID computation is unavailable");
|
|
4376
5172
|
}
|
|
5173
|
+
const compact = authorization.replace(/^Bearer /i, "");
|
|
4377
5174
|
return this.wasmBindings.computeCid(
|
|
4378
|
-
new TextEncoder().encode(authorization),
|
|
5175
|
+
compact.includes(".") ? new TextEncoder().encode(compact) : decodeAuthorizationBytes(authorization),
|
|
4379
5176
|
0x55n
|
|
4380
5177
|
);
|
|
4381
5178
|
}
|
|
@@ -4467,6 +5264,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4467
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."
|
|
4468
5265
|
);
|
|
4469
5266
|
}
|
|
5267
|
+
this.assertDelegationCaveatsPreservable(expandedEntries);
|
|
4470
5268
|
const delegation2 = await this.createDelegationLegacyWalletPath(
|
|
4471
5269
|
did,
|
|
4472
5270
|
expandedEntries[0],
|
|
@@ -4475,13 +5273,14 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4475
5273
|
return { delegation: delegation2, prompted: true };
|
|
4476
5274
|
}
|
|
4477
5275
|
const granted = (0, import_sdk_core8.parseRecapCapabilities)(
|
|
4478
|
-
(siwe) => this.
|
|
5276
|
+
(siwe) => this.parseRecapWithCaveats(siwe),
|
|
4479
5277
|
session.siwe
|
|
4480
5278
|
);
|
|
4481
5279
|
const { subset, missing } = (0, import_sdk_core8.isCapabilitySubset)(expandedEntries, granted);
|
|
4482
5280
|
if (!subset) {
|
|
5281
|
+
const runtimeOperations = this.permissionEntriesToOperations(expandedEntries, session);
|
|
4483
5282
|
const runtimeGrant = this.findGrantForOperations(
|
|
4484
|
-
|
|
5283
|
+
runtimeOperations,
|
|
4485
5284
|
{ excludePrimary: true }
|
|
4486
5285
|
);
|
|
4487
5286
|
if (runtimeGrant) {
|
|
@@ -4494,7 +5293,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4494
5293
|
did,
|
|
4495
5294
|
expandedEntries,
|
|
4496
5295
|
runtimeExpiration,
|
|
4497
|
-
runtimeGrant
|
|
5296
|
+
runtimeGrant,
|
|
5297
|
+
runtimeOperations
|
|
4498
5298
|
);
|
|
4499
5299
|
return { delegation: delegation2, prompted: false };
|
|
4500
5300
|
}
|
|
@@ -4564,6 +5364,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4564
5364
|
"createDelegationViaWasmPath requires a non-empty entries array"
|
|
4565
5365
|
);
|
|
4566
5366
|
}
|
|
5367
|
+
this.assertDelegationCaveatsPreservable(entries);
|
|
4567
5368
|
const resolvedSpaces = /* @__PURE__ */ new Set();
|
|
4568
5369
|
for (const entry of entries) {
|
|
4569
5370
|
if (this.isEncryptionPermissionEntry(entry)) {
|
|
@@ -4644,7 +5445,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4644
5445
|
host: this.config.host
|
|
4645
5446
|
};
|
|
4646
5447
|
}
|
|
4647
|
-
async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant) {
|
|
5448
|
+
async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations) {
|
|
5449
|
+
this.assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant);
|
|
5450
|
+
this.assertDelegationCaveatsPreservable(entries);
|
|
4648
5451
|
const result = this.createDelegationWrapper({
|
|
4649
5452
|
session: grant.session,
|
|
4650
5453
|
delegateDID: did,
|
|
@@ -4698,6 +5501,74 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4698
5501
|
expandPermissionEntries(permissions) {
|
|
4699
5502
|
return (0, import_sdk_core8.expandPermissionEntries)(permissions);
|
|
4700
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
|
+
}
|
|
4701
5572
|
shortServiceName(service) {
|
|
4702
5573
|
const short = import_sdk_core8.SERVICE_LONG_TO_SHORT[service];
|
|
4703
5574
|
if (short === void 0) {
|
|
@@ -4752,14 +5623,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4752
5623
|
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
4753
5624
|
service,
|
|
4754
5625
|
path: entry.path,
|
|
4755
|
-
action
|
|
5626
|
+
action,
|
|
5627
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
4756
5628
|
}));
|
|
4757
5629
|
});
|
|
4758
5630
|
}
|
|
4759
5631
|
sessionCoversPermissionEntries(session, entries) {
|
|
4760
5632
|
try {
|
|
4761
5633
|
const granted = (0, import_sdk_core8.parseRecapCapabilities)(
|
|
4762
|
-
(siwe) => this.
|
|
5634
|
+
(siwe) => this.parseRecapWithCaveats(siwe),
|
|
4763
5635
|
session.siwe
|
|
4764
5636
|
);
|
|
4765
5637
|
return (0, import_sdk_core8.isCapabilitySubset)(entries, granted).subset;
|
|
@@ -4775,7 +5647,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4775
5647
|
...this.isEncryptionNetworkOperation(service, entry.path) ? { resource: entry.path } : { spaceId },
|
|
4776
5648
|
service,
|
|
4777
5649
|
path: entry.path,
|
|
4778
|
-
action
|
|
5650
|
+
action,
|
|
5651
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
4779
5652
|
}));
|
|
4780
5653
|
});
|
|
4781
5654
|
}
|
|
@@ -4851,7 +5724,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4851
5724
|
service: this.shortServiceName(entry.service),
|
|
4852
5725
|
space: this.isEncryptionPermissionEntry(entry) ? "encryption" : spaceId,
|
|
4853
5726
|
path: entry.path,
|
|
4854
|
-
actions: [...entry.actions]
|
|
5727
|
+
actions: [...entry.actions],
|
|
5728
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
4855
5729
|
}));
|
|
4856
5730
|
}
|
|
4857
5731
|
operationsFromDelegation(delegation) {
|
|
@@ -4862,7 +5736,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4862
5736
|
...this.isEncryptionNetworkOperation(service, resource.path) ? { resource: resource.path } : { spaceId: resource.space },
|
|
4863
5737
|
service,
|
|
4864
5738
|
path: resource.path,
|
|
4865
|
-
action
|
|
5739
|
+
action,
|
|
5740
|
+
caveats: cloneRecapCaveats(resource.caveats)
|
|
4866
5741
|
}));
|
|
4867
5742
|
});
|
|
4868
5743
|
}
|
|
@@ -4878,7 +5753,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4878
5753
|
service,
|
|
4879
5754
|
space: delegation.spaceId,
|
|
4880
5755
|
path: delegation.path,
|
|
4881
|
-
actions
|
|
5756
|
+
actions,
|
|
5757
|
+
...delegation.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(delegation.caveats) }
|
|
4882
5758
|
}));
|
|
4883
5759
|
}
|
|
4884
5760
|
/**
|
|
@@ -4979,6 +5855,9 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
4979
5855
|
if (granted.service !== requested.service || !this.actionContains(granted.action, requested.action)) {
|
|
4980
5856
|
return false;
|
|
4981
5857
|
}
|
|
5858
|
+
if (requested.caveats !== void 0 && !(0, import_sdk_core8.recapCaveatsEqual)(granted.caveats, requested.caveats)) {
|
|
5859
|
+
return false;
|
|
5860
|
+
}
|
|
4982
5861
|
if (granted.resource !== void 0 || requested.resource !== void 0) {
|
|
4983
5862
|
return granted.resource !== void 0 && requested.resource !== void 0 && granted.resource === requested.resource && this.pathContains(granted.path, requested.path);
|
|
4984
5863
|
}
|
|
@@ -5013,6 +5892,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5013
5892
|
invocationServiceName(service) {
|
|
5014
5893
|
return service.startsWith("tinycloud.") ? this.shortServiceName(service) : service;
|
|
5015
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
|
+
}
|
|
5016
5899
|
isEncryptionNetworkOperation(service, path) {
|
|
5017
5900
|
return service === "encryption" && path.startsWith("urn:tinycloud:encryption:");
|
|
5018
5901
|
}
|
|
@@ -5023,7 +5906,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5023
5906
|
resource: entry.resource,
|
|
5024
5907
|
service,
|
|
5025
5908
|
path: entry.path,
|
|
5026
|
-
action: entry.action
|
|
5909
|
+
action: entry.action,
|
|
5910
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
5027
5911
|
};
|
|
5028
5912
|
}
|
|
5029
5913
|
if (this.isEncryptionNetworkOperation(service, entry.path)) {
|
|
@@ -5031,7 +5915,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5031
5915
|
resource: entry.path,
|
|
5032
5916
|
service,
|
|
5033
5917
|
path: entry.path,
|
|
5034
|
-
action: entry.action
|
|
5918
|
+
action: entry.action,
|
|
5919
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
5035
5920
|
};
|
|
5036
5921
|
}
|
|
5037
5922
|
if (typeof entry.spaceId === "string") {
|
|
@@ -5039,7 +5924,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5039
5924
|
spaceId: entry.spaceId,
|
|
5040
5925
|
service,
|
|
5041
5926
|
path: entry.path,
|
|
5042
|
-
action: entry.action
|
|
5927
|
+
action: entry.action,
|
|
5928
|
+
...entry.caveats === void 0 ? {} : { caveats: cloneRecapCaveats(entry.caveats) }
|
|
5043
5929
|
};
|
|
5044
5930
|
}
|
|
5045
5931
|
return void 0;
|
|
@@ -5379,6 +6265,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
5379
6265
|
* @returns A portable delegation for the sub-delegate
|
|
5380
6266
|
*/
|
|
5381
6267
|
async createSubDelegation(parentDelegation, params) {
|
|
6268
|
+
this.assertPortableDelegationCaveatsPreservable(parentDelegation);
|
|
5382
6269
|
if (!this.signer) {
|
|
5383
6270
|
throw new Error("Cannot createSubDelegation() in session-only mode. Requires wallet mode.");
|
|
5384
6271
|
}
|
|
@@ -5471,9 +6358,10 @@ _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS = 6e4;
|
|
|
5471
6358
|
var TinyCloudNode = _TinyCloudNode;
|
|
5472
6359
|
|
|
5473
6360
|
// src/core.ts
|
|
5474
|
-
var
|
|
6361
|
+
var import_sdk_core12 = require("@tinycloud/sdk-core");
|
|
5475
6362
|
|
|
5476
6363
|
// src/delegation.ts
|
|
6364
|
+
var import_sdk_core9 = require("@tinycloud/sdk-core");
|
|
5477
6365
|
function serializeDelegation(delegation) {
|
|
5478
6366
|
return JSON.stringify({
|
|
5479
6367
|
...delegation,
|
|
@@ -5490,7 +6378,6 @@ function deserializeDelegation(data) {
|
|
|
5490
6378
|
}
|
|
5491
6379
|
|
|
5492
6380
|
// src/core.ts
|
|
5493
|
-
var import_sdk_core12 = require("@tinycloud/sdk-core");
|
|
5494
6381
|
var import_sdk_core13 = require("@tinycloud/sdk-core");
|
|
5495
6382
|
var import_sdk_core14 = require("@tinycloud/sdk-core");
|
|
5496
6383
|
var import_sdk_core15 = require("@tinycloud/sdk-core");
|
|
@@ -5499,6 +6386,7 @@ var import_sdk_core17 = require("@tinycloud/sdk-core");
|
|
|
5499
6386
|
var import_sdk_core18 = require("@tinycloud/sdk-core");
|
|
5500
6387
|
var import_sdk_core19 = require("@tinycloud/sdk-core");
|
|
5501
6388
|
var import_sdk_core20 = require("@tinycloud/sdk-core");
|
|
6389
|
+
var import_sdk_core21 = require("@tinycloud/sdk-core");
|
|
5502
6390
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5503
6391
|
0 && (module.exports = {
|
|
5504
6392
|
ACCOUNT_REGISTRY_PATH,
|
|
@@ -5507,6 +6395,7 @@ var import_sdk_core20 = require("@tinycloud/sdk-core");
|
|
|
5507
6395
|
AutoApproveSpaceCreationHandler,
|
|
5508
6396
|
CapabilityKeyRegistry,
|
|
5509
6397
|
CapabilityKeyRegistryErrorCodes,
|
|
6398
|
+
CaveatedDelegationUnsupportedError,
|
|
5510
6399
|
DEFAULT_MANIFEST_SPACE,
|
|
5511
6400
|
DEFAULT_MANIFEST_VERSION,
|
|
5512
6401
|
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
@@ -5542,6 +6431,7 @@ var import_sdk_core20 = require("@tinycloud/sdk-core");
|
|
|
5542
6431
|
TinyCloudDebugLogger,
|
|
5543
6432
|
TinyCloudNode,
|
|
5544
6433
|
UnsupportedFeatureError,
|
|
6434
|
+
UnsupportedSessionRestoreError,
|
|
5545
6435
|
VAULT_PERMISSION_SERVICE,
|
|
5546
6436
|
VaultHeaders,
|
|
5547
6437
|
VaultPublicSpaceKVActions,
|