@tinycloud/node-sdk 2.2.0-beta.0 → 2.2.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.cjs CHANGED
@@ -20,70 +20,77 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/core.ts
21
21
  var core_exports = {};
22
22
  __export(core_exports, {
23
- ACCOUNT_REGISTRY_PATH: () => import_sdk_core8.ACCOUNT_REGISTRY_PATH,
24
- ACCOUNT_REGISTRY_SPACE: () => import_sdk_core8.ACCOUNT_REGISTRY_SPACE,
25
- AutoApproveSpaceCreationHandler: () => import_sdk_core7.AutoApproveSpaceCreationHandler,
26
- CapabilityKeyRegistry: () => import_sdk_core14.CapabilityKeyRegistry,
27
- CapabilityKeyRegistryErrorCodes: () => import_sdk_core14.CapabilityKeyRegistryErrorCodes,
28
- DEFAULT_MANIFEST_SPACE: () => import_sdk_core8.DEFAULT_MANIFEST_SPACE,
29
- DEFAULT_MANIFEST_VERSION: () => import_sdk_core8.DEFAULT_MANIFEST_VERSION,
30
- DataVaultService: () => import_sdk_core12.DataVaultService,
31
- DatabaseHandle: () => import_sdk_core10.DatabaseHandle,
23
+ ACCOUNT_REGISTRY_PATH: () => import_sdk_core9.ACCOUNT_REGISTRY_PATH,
24
+ ACCOUNT_REGISTRY_SPACE: () => import_sdk_core9.ACCOUNT_REGISTRY_SPACE,
25
+ AutoApproveSpaceCreationHandler: () => import_sdk_core8.AutoApproveSpaceCreationHandler,
26
+ CapabilityKeyRegistry: () => import_sdk_core15.CapabilityKeyRegistry,
27
+ CapabilityKeyRegistryErrorCodes: () => import_sdk_core15.CapabilityKeyRegistryErrorCodes,
28
+ DEFAULT_MANIFEST_SPACE: () => import_sdk_core9.DEFAULT_MANIFEST_SPACE,
29
+ DEFAULT_MANIFEST_VERSION: () => import_sdk_core9.DEFAULT_MANIFEST_VERSION,
30
+ DataVaultService: () => import_sdk_core13.DataVaultService,
31
+ DatabaseHandle: () => import_sdk_core11.DatabaseHandle,
32
32
  DelegatedAccess: () => DelegatedAccess,
33
- DelegationErrorCodes: () => import_sdk_core13.DelegationErrorCodes,
34
- DelegationManager: () => import_sdk_core13.DelegationManager,
35
- DuckDbAction: () => import_sdk_core11.DuckDbAction,
36
- DuckDbDatabaseHandle: () => import_sdk_core11.DuckDbDatabaseHandle,
37
- DuckDbService: () => import_sdk_core11.DuckDbService,
33
+ DelegationErrorCodes: () => import_sdk_core14.DelegationErrorCodes,
34
+ DelegationManager: () => import_sdk_core14.DelegationManager,
35
+ DuckDbAction: () => import_sdk_core12.DuckDbAction,
36
+ DuckDbDatabaseHandle: () => import_sdk_core12.DuckDbDatabaseHandle,
37
+ DuckDbService: () => import_sdk_core12.DuckDbService,
38
38
  FileSessionStorage: () => FileSessionStorage,
39
- KVService: () => import_sdk_core9.KVService,
40
- ManifestValidationError: () => import_sdk_core8.ManifestValidationError,
39
+ KVService: () => import_sdk_core10.KVService,
40
+ ManifestValidationError: () => import_sdk_core9.ManifestValidationError,
41
41
  MemorySessionStorage: () => MemorySessionStorage,
42
42
  NodeUserAuthorization: () => NodeUserAuthorization,
43
- PermissionNotInManifestError: () => import_sdk_core8.PermissionNotInManifestError,
44
- PrefixedKVService: () => import_sdk_core9.PrefixedKVService,
45
- ProtocolMismatchError: () => import_sdk_core16.ProtocolMismatchError,
46
- SQLAction: () => import_sdk_core10.SQLAction,
47
- SQLService: () => import_sdk_core10.SQLService,
48
- ServiceContext: () => import_sdk_core17.ServiceContext,
49
- SessionExpiredError: () => import_sdk_core8.SessionExpiredError,
50
- SharingService: () => import_sdk_core13.SharingService,
51
- SilentNotificationHandler: () => import_sdk_core7.SilentNotificationHandler,
52
- Space: () => import_sdk_core15.Space,
53
- SpaceErrorCodes: () => import_sdk_core15.SpaceErrorCodes,
54
- SpaceService: () => import_sdk_core15.SpaceService,
55
- TinyCloud: () => import_sdk_core6.TinyCloud,
43
+ PermissionNotInManifestError: () => import_sdk_core9.PermissionNotInManifestError,
44
+ PrefixedKVService: () => import_sdk_core10.PrefixedKVService,
45
+ ProtocolMismatchError: () => import_sdk_core17.ProtocolMismatchError,
46
+ SECRET_NAME_RE: () => import_sdk_core13.SECRET_NAME_RE,
47
+ SQLAction: () => import_sdk_core11.SQLAction,
48
+ SQLService: () => import_sdk_core11.SQLService,
49
+ SecretsService: () => import_sdk_core13.SecretsService,
50
+ ServiceContext: () => import_sdk_core18.ServiceContext,
51
+ SessionExpiredError: () => import_sdk_core9.SessionExpiredError,
52
+ SharingService: () => import_sdk_core14.SharingService,
53
+ SilentNotificationHandler: () => import_sdk_core8.SilentNotificationHandler,
54
+ Space: () => import_sdk_core16.Space,
55
+ SpaceErrorCodes: () => import_sdk_core16.SpaceErrorCodes,
56
+ SpaceService: () => import_sdk_core16.SpaceService,
57
+ TinyCloud: () => import_sdk_core7.TinyCloud,
56
58
  TinyCloudNode: () => TinyCloudNode,
57
- UnsupportedFeatureError: () => import_sdk_core16.UnsupportedFeatureError,
58
- VaultHeaders: () => import_sdk_core12.VaultHeaders,
59
- VaultPublicSpaceKVActions: () => import_sdk_core12.VaultPublicSpaceKVActions,
60
- VersionCheckError: () => import_sdk_core16.VersionCheckError,
59
+ UnsupportedFeatureError: () => import_sdk_core17.UnsupportedFeatureError,
60
+ VAULT_PERMISSION_SERVICE: () => import_sdk_core9.VAULT_PERMISSION_SERVICE,
61
+ VaultHeaders: () => import_sdk_core13.VaultHeaders,
62
+ VaultPublicSpaceKVActions: () => import_sdk_core13.VaultPublicSpaceKVActions,
63
+ VersionCheckError: () => import_sdk_core17.VersionCheckError,
61
64
  WasmKeyProvider: () => WasmKeyProvider,
62
- buildSpaceUri: () => import_sdk_core15.buildSpaceUri,
63
- checkNodeInfo: () => import_sdk_core16.checkNodeInfo,
64
- composeManifestRequest: () => import_sdk_core8.composeManifestRequest,
65
- createCapabilityKeyRegistry: () => import_sdk_core14.createCapabilityKeyRegistry,
66
- createSharingService: () => import_sdk_core13.createSharingService,
67
- createSpaceService: () => import_sdk_core15.createSpaceService,
68
- createVaultCrypto: () => import_sdk_core12.createVaultCrypto,
65
+ buildSpaceUri: () => import_sdk_core16.buildSpaceUri,
66
+ canonicalizeSecretScope: () => import_sdk_core13.canonicalizeSecretScope,
67
+ checkNodeInfo: () => import_sdk_core17.checkNodeInfo,
68
+ composeManifestRequest: () => import_sdk_core9.composeManifestRequest,
69
+ createCapabilityKeyRegistry: () => import_sdk_core15.createCapabilityKeyRegistry,
70
+ createSharingService: () => import_sdk_core14.createSharingService,
71
+ createSpaceService: () => import_sdk_core16.createSpaceService,
72
+ createVaultCrypto: () => import_sdk_core13.createVaultCrypto,
69
73
  createWasmKeyProvider: () => createWasmKeyProvider,
70
74
  defaultSignStrategy: () => defaultSignStrategy,
71
- defaultSpaceCreationHandler: () => import_sdk_core7.defaultSpaceCreationHandler,
75
+ defaultSpaceCreationHandler: () => import_sdk_core8.defaultSpaceCreationHandler,
72
76
  deserializeDelegation: () => deserializeDelegation,
73
- expandActionShortNames: () => import_sdk_core8.expandActionShortNames,
74
- isCapabilitySubset: () => import_sdk_core8.isCapabilitySubset,
75
- loadManifest: () => import_sdk_core8.loadManifest,
76
- makePublicSpaceId: () => import_sdk_core15.makePublicSpaceId,
77
- parseExpiry: () => import_sdk_core8.parseExpiry,
78
- parseSpaceUri: () => import_sdk_core15.parseSpaceUri,
79
- resolveManifest: () => import_sdk_core8.resolveManifest,
80
- resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core8.resourceCapabilitiesToSpaceAbilitiesMap,
77
+ expandActionShortNames: () => import_sdk_core9.expandActionShortNames,
78
+ expandPermissionEntries: () => import_sdk_core9.expandPermissionEntries,
79
+ expandPermissionEntry: () => import_sdk_core9.expandPermissionEntry,
80
+ isCapabilitySubset: () => import_sdk_core9.isCapabilitySubset,
81
+ loadManifest: () => import_sdk_core9.loadManifest,
82
+ makePublicSpaceId: () => import_sdk_core16.makePublicSpaceId,
83
+ parseExpiry: () => import_sdk_core9.parseExpiry,
84
+ parseSpaceUri: () => import_sdk_core16.parseSpaceUri,
85
+ resolveManifest: () => import_sdk_core9.resolveManifest,
86
+ resolveSecretPath: () => import_sdk_core13.resolveSecretPath,
87
+ resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core9.resourceCapabilitiesToSpaceAbilitiesMap,
81
88
  serializeDelegation: () => serializeDelegation,
82
- validateManifest: () => import_sdk_core8.validateManifest
89
+ validateManifest: () => import_sdk_core9.validateManifest
83
90
  });
84
91
  module.exports = __toCommonJS(core_exports);
85
- var import_sdk_core6 = require("@tinycloud/sdk-core");
86
92
  var import_sdk_core7 = require("@tinycloud/sdk-core");
93
+ var import_sdk_core8 = require("@tinycloud/sdk-core");
87
94
 
88
95
  // src/storage/MemorySessionStorage.ts
89
96
  var MemorySessionStorage = class {
@@ -339,9 +346,9 @@ var NodeUserAuthorization = class {
339
346
  this.sessionExpirationMs = config.sessionExpirationMs ?? 60 * 60 * 1e3;
340
347
  this.autoCreateSpace = config.autoCreateSpace ?? false;
341
348
  this.spaceCreationHandler = config.spaceCreationHandler;
342
- this.tinycloudHosts = config.tinycloudHosts ?? [
343
- "https://node.tinycloud.xyz"
344
- ];
349
+ this.tinycloudHosts = config.tinycloudHosts;
350
+ this.tinycloudRegistryUrl = config.tinycloudRegistryUrl;
351
+ this.tinycloudFallbackHosts = config.tinycloudFallbackHosts;
345
352
  this.enablePublicSpace = config.enablePublicSpace ?? true;
346
353
  this.nonce = config.nonce;
347
354
  this.siweConfig = config.siweConfig;
@@ -362,6 +369,9 @@ var NodeUserAuthorization = class {
362
369
  get capabilityRequest() {
363
370
  return this.getCapabilityRequest();
364
371
  }
372
+ get hosts() {
373
+ return this.tinycloudHosts ? [...this.tinycloudHosts] : [];
374
+ }
365
375
  /**
366
376
  * Install or replace the stored manifest. Takes effect on the next
367
377
  * `signIn()` call — the current session (if any) is not touched.
@@ -386,6 +396,26 @@ var NodeUserAuthorization = class {
386
396
  get tinyCloudSession() {
387
397
  return this._tinyCloudSession;
388
398
  }
399
+ async resolveTinyCloudHostsForSignIn(address, chainId) {
400
+ if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
401
+ return;
402
+ }
403
+ const subject = `did:pkh:eip155:${chainId}:${address}`;
404
+ const resolved = await (0, import_sdk_core2.resolveTinyCloudHosts)(subject, {
405
+ registryUrl: this.tinycloudRegistryUrl,
406
+ fallbackHosts: this.tinycloudFallbackHosts
407
+ });
408
+ this.tinycloudHosts = resolved.hosts;
409
+ }
410
+ requireTinyCloudHosts() {
411
+ if (!this.tinycloudHosts || this.tinycloudHosts.length === 0) {
412
+ throw new Error("TinyCloud hosts have not been resolved. Call signIn() first.");
413
+ }
414
+ return this.tinycloudHosts;
415
+ }
416
+ get primaryTinyCloudHost() {
417
+ return this.requireTinyCloudHosts()[0];
418
+ }
389
419
  get nodeFeatures() {
390
420
  return this._nodeFeatures;
391
421
  }
@@ -517,7 +547,7 @@ var NodeUserAuthorization = class {
517
547
  if (!this._tinyCloudSession || !this._address || !this._chainId) {
518
548
  throw new Error("Must be signed in to host space");
519
549
  }
520
- const host = this.tinycloudHosts[0];
550
+ const host = this.primaryTinyCloudHost;
521
551
  const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
522
552
  const peerId = await (0, import_sdk_core2.fetchPeerId)(host, spaceId);
523
553
  const siwe = this.wasm.generateHostSIWEMessage({
@@ -559,7 +589,7 @@ var NodeUserAuthorization = class {
559
589
  if (!this._tinyCloudSession) {
560
590
  throw new Error("Must be signed in to ensure space exists");
561
591
  }
562
- const host = this.tinycloudHosts[0];
592
+ const host = this.primaryTinyCloudHost;
563
593
  const primarySpaceId = this._tinyCloudSession.spaceId;
564
594
  const result = await (0, import_sdk_core2.activateSessionWithHost)(
565
595
  host,
@@ -668,6 +698,7 @@ var NodeUserAuthorization = class {
668
698
  this._chainId = await this.signer.getChainId();
669
699
  const address = this.wasm.ensureEip55(this._address);
670
700
  const chainId = this._chainId;
701
+ await this.resolveTinyCloudHostsForSignIn(address, chainId);
671
702
  const keyId = `session-${Date.now()}`;
672
703
  this.sessionManager.renameSessionKeyId("default", keyId);
673
704
  const jwkString = this.sessionManager.jwk(keyId);
@@ -746,7 +777,7 @@ var NodeUserAuthorization = class {
746
777
  this._address = address;
747
778
  this._chainId = chainId;
748
779
  const nodeInfo = await (0, import_sdk_core2.checkNodeInfo)(
749
- this.tinycloudHosts[0],
780
+ this.primaryTinyCloudHost,
750
781
  this.wasm.protocolVersion()
751
782
  );
752
783
  this._nodeFeatures = nodeInfo.features;
@@ -862,6 +893,7 @@ var NodeUserAuthorization = class {
862
893
  });
863
894
  const address = this.wasm.ensureEip55(await this.signer.getAddress());
864
895
  const chainId = await this.signer.getChainId();
896
+ await this.resolveTinyCloudHostsForSignIn(address, chainId);
865
897
  const clientSession = {
866
898
  address,
867
899
  walletAddress: address,
@@ -911,7 +943,7 @@ var NodeUserAuthorization = class {
911
943
  this._address = address;
912
944
  this._chainId = chainId;
913
945
  const nodeInfo = await (0, import_sdk_core2.checkNodeInfo)(
914
- this.tinycloudHosts[0],
946
+ this.primaryTinyCloudHost,
915
947
  this.wasm.protocolVersion()
916
948
  );
917
949
  this._nodeFeatures = nodeInfo.features;
@@ -994,7 +1026,7 @@ var NodeUserAuthorization = class {
994
1026
  };
995
1027
 
996
1028
  // src/TinyCloudNode.ts
997
- var import_sdk_core5 = require("@tinycloud/sdk-core");
1029
+ var import_sdk_core6 = require("@tinycloud/sdk-core");
998
1030
 
999
1031
  // src/DelegatedAccess.ts
1000
1032
  var import_sdk_core3 = require("@tinycloud/sdk-core");
@@ -1072,6 +1104,24 @@ var DelegatedAccess = class {
1072
1104
  get hooks() {
1073
1105
  return this._hooks;
1074
1106
  }
1107
+ /**
1108
+ * Export the handles needed to rehydrate this activated delegation via
1109
+ * `TinyCloudNode.restoreSession(...)` in another process or after a
1110
+ * restart.
1111
+ *
1112
+ * See `RestorableSession` for lifetime caveats.
1113
+ */
1114
+ get restorable() {
1115
+ return {
1116
+ delegationHeader: this.session.delegationHeader,
1117
+ delegationCid: this.session.delegationCid,
1118
+ spaceId: this.session.spaceId,
1119
+ jwk: this.session.jwk,
1120
+ verificationMethod: this.session.verificationMethod,
1121
+ address: this.session.address,
1122
+ chainId: this.session.chainId
1123
+ };
1124
+ }
1075
1125
  };
1076
1126
 
1077
1127
  // src/keys/WasmKeyProvider.ts
@@ -1209,6 +1259,148 @@ function extractSiweExpiration(siwe) {
1209
1259
  return d;
1210
1260
  }
1211
1261
 
1262
+ // src/NodeSecretsService.ts
1263
+ var import_sdk_core5 = require("@tinycloud/sdk-core");
1264
+ var SECRETS_SPACE = "secrets";
1265
+ function ok() {
1266
+ return { ok: true, data: void 0 };
1267
+ }
1268
+ function secretsError(code, message, cause) {
1269
+ return {
1270
+ ok: false,
1271
+ error: {
1272
+ code,
1273
+ service: "secrets",
1274
+ message,
1275
+ ...cause ? { cause } : {}
1276
+ }
1277
+ };
1278
+ }
1279
+ function displayActionUrn(action) {
1280
+ return action === "put" ? "tinycloud.vault/write" : "tinycloud.vault/delete";
1281
+ }
1282
+ function kvActionUrn(action) {
1283
+ return `tinycloud.kv/${action}`;
1284
+ }
1285
+ function vaultMutationAction(action) {
1286
+ return action === "put" ? "write" : "delete";
1287
+ }
1288
+ function secretPermissionEntries(name, options, action) {
1289
+ const secretPath = (0, import_sdk_core5.resolveSecretPath)(name, options);
1290
+ return [
1291
+ {
1292
+ service: "tinycloud.vault",
1293
+ space: SECRETS_SPACE,
1294
+ path: secretPath.vaultKey,
1295
+ actions: [vaultMutationAction(action)],
1296
+ skipPrefix: true
1297
+ }
1298
+ ];
1299
+ }
1300
+ function isSecretsSpace(space) {
1301
+ return space === SECRETS_SPACE || space.endsWith(`:${SECRETS_SPACE}`);
1302
+ }
1303
+ var NodeSecretsService = class {
1304
+ constructor(config) {
1305
+ this.config = config;
1306
+ this.shouldRestoreUnlock = false;
1307
+ }
1308
+ get vault() {
1309
+ return this.service.vault;
1310
+ }
1311
+ get isUnlocked() {
1312
+ return this.service.isUnlocked;
1313
+ }
1314
+ async unlock(signer) {
1315
+ const effectiveSigner = signer ?? this.config.getUnlockSigner?.();
1316
+ if (effectiveSigner !== void 0) {
1317
+ this.unlockSigner = effectiveSigner;
1318
+ }
1319
+ const result = await this.service.unlock(effectiveSigner);
1320
+ if (result.ok) {
1321
+ this.shouldRestoreUnlock = true;
1322
+ }
1323
+ return result;
1324
+ }
1325
+ lock() {
1326
+ this.shouldRestoreUnlock = false;
1327
+ this.service.lock();
1328
+ }
1329
+ get(name, options) {
1330
+ return options === void 0 ? this.service.get(name) : this.service.get(name, options);
1331
+ }
1332
+ async put(name, value, options) {
1333
+ const permission = await this.ensureMutationPermission(name, options, "put");
1334
+ if (!permission.ok) return permission;
1335
+ return options === void 0 ? this.service.put(name, value) : this.service.put(name, value, options);
1336
+ }
1337
+ async delete(name, options) {
1338
+ const permission = await this.ensureMutationPermission(name, options, "del");
1339
+ if (!permission.ok) return permission;
1340
+ return options === void 0 ? this.service.delete(name) : this.service.delete(name, options);
1341
+ }
1342
+ list(options) {
1343
+ return options === void 0 ? this.service.list() : this.service.list(options);
1344
+ }
1345
+ get service() {
1346
+ return this.config.getService();
1347
+ }
1348
+ async ensureMutationPermission(name, options, action) {
1349
+ let permissionEntries;
1350
+ try {
1351
+ permissionEntries = secretPermissionEntries(name, options, action);
1352
+ } catch (error) {
1353
+ return secretsError(
1354
+ import_sdk_core5.ErrorCodes.INVALID_INPUT,
1355
+ error instanceof Error ? error.message : String(error),
1356
+ error instanceof Error ? error : void 0
1357
+ );
1358
+ }
1359
+ if (this.hasMutationPermission(name, options, action)) {
1360
+ return ok();
1361
+ }
1362
+ if (!this.config.canEscalate()) {
1363
+ return secretsError(
1364
+ import_sdk_core5.ErrorCodes.PERMISSION_DENIED,
1365
+ `Cannot autosign ${displayActionUrn(action)} for ${name}; TinyCloudNode needs wallet mode with a signer or privateKey.`
1366
+ );
1367
+ }
1368
+ try {
1369
+ await this.config.grantPermissions(permissionEntries);
1370
+ return this.restoreUnlockAfterEscalation();
1371
+ } catch (error) {
1372
+ return secretsError(
1373
+ import_sdk_core5.ErrorCodes.PERMISSION_DENIED,
1374
+ error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${name} failed.`,
1375
+ error instanceof Error ? error : void 0
1376
+ );
1377
+ }
1378
+ }
1379
+ async restoreUnlockAfterEscalation() {
1380
+ if (!this.shouldRestoreUnlock) {
1381
+ return ok();
1382
+ }
1383
+ return this.service.unlock(this.unlockSigner);
1384
+ }
1385
+ hasMutationPermission(name, options, action) {
1386
+ const manifest = this.config.getManifest();
1387
+ if (manifest === void 0) {
1388
+ return false;
1389
+ }
1390
+ const manifests = Array.isArray(manifest) ? manifest : [manifest];
1391
+ const requiredAction = kvActionUrn(action);
1392
+ const secretPath = (0, import_sdk_core5.resolveSecretPath)(name, options);
1393
+ return manifests.some((entry) => {
1394
+ const resolved = (0, import_sdk_core5.resolveManifest)(entry);
1395
+ return ["keys", "vault"].every(
1396
+ (base) => resolved.resources.some(
1397
+ (resource) => resource.service === "tinycloud.kv" && isSecretsSpace(resource.space) && resource.path === secretPath.permissionPaths[base] && resource.actions.includes(requiredAction)
1398
+ )
1399
+ );
1400
+ });
1401
+ }
1402
+ };
1403
+
1212
1404
  // src/TinyCloudNode.ts
1213
1405
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
1214
1406
  var _TinyCloudNode = class _TinyCloudNode {
@@ -1240,6 +1432,31 @@ var _TinyCloudNode = class _TinyCloudNode {
1240
1432
  this.auth = null;
1241
1433
  this.tc = null;
1242
1434
  this._chainId = 1;
1435
+ this.runtimePermissionGrants = [];
1436
+ this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
1437
+ return this.wasmBindings.invoke(
1438
+ this.selectInvocationSession(session, service, path, action),
1439
+ service,
1440
+ path,
1441
+ action,
1442
+ facts
1443
+ );
1444
+ };
1445
+ this.invokeAnyWithRuntimePermissions = (session, entries, facts) => {
1446
+ if (!this.wasmBindings.invokeAny) {
1447
+ throw new Error("WASM binding does not support invokeAny");
1448
+ }
1449
+ const grant = this.findGrantForOperations(
1450
+ entries.map((entry) => ({
1451
+ spaceId: entry.spaceId,
1452
+ service: this.invocationServiceName(entry.service),
1453
+ path: entry.path,
1454
+ action: entry.action
1455
+ }))
1456
+ );
1457
+ return this.wasmBindings.invokeAny(grant?.session ?? session, entries, facts);
1458
+ };
1459
+ this.explicitHost = config.host;
1243
1460
  this.config = {
1244
1461
  ...config,
1245
1462
  host: config.host ?? DEFAULT_HOST
@@ -1266,23 +1483,23 @@ var _TinyCloudNode = class _TinyCloudNode {
1266
1483
  throw new Error("Failed to get session key JWK");
1267
1484
  }
1268
1485
  this.sessionKeyJwk = JSON.parse(jwkStr);
1269
- this._capabilityRegistry = new import_sdk_core5.CapabilityKeyRegistry();
1486
+ this._capabilityRegistry = new import_sdk_core6.CapabilityKeyRegistry();
1270
1487
  this._keyProvider = new WasmKeyProvider({
1271
1488
  sessionManager: this.sessionManager
1272
1489
  });
1273
- this.notificationHandler = config.notificationHandler ?? new import_sdk_core5.SilentNotificationHandler();
1274
- this._sharingService = new import_sdk_core5.SharingService({
1490
+ this.notificationHandler = config.notificationHandler ?? new import_sdk_core6.SilentNotificationHandler();
1491
+ this._sharingService = new import_sdk_core6.SharingService({
1275
1492
  hosts: [this.config.host],
1276
1493
  // session: undefined - not needed for receive()
1277
- invoke: this.wasmBindings.invoke,
1494
+ invoke: this.invokeWithRuntimePermissions,
1278
1495
  fetch: globalThis.fetch.bind(globalThis),
1279
1496
  keyProvider: this._keyProvider,
1280
1497
  registry: this._capabilityRegistry,
1281
1498
  // delegationManager: undefined - not needed for receive()
1282
1499
  createKVService: (config2) => {
1283
1500
  const prefix = config2.pathPrefix?.replace(/\/$/, "");
1284
- const kvService = new import_sdk_core5.KVService({ prefix });
1285
- const kvContext = new import_sdk_core5.ServiceContext({
1501
+ const kvService = new import_sdk_core6.KVService({ prefix });
1502
+ const kvContext = new import_sdk_core6.ServiceContext({
1286
1503
  invoke: config2.invoke,
1287
1504
  fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
1288
1505
  hosts: config2.hosts
@@ -1321,7 +1538,6 @@ var _TinyCloudNode = class _TinyCloudNode {
1321
1538
  * @internal
1322
1539
  */
1323
1540
  setupAuth(config) {
1324
- const host = this.config.host;
1325
1541
  this.auth = new NodeUserAuthorization({
1326
1542
  signer: this.signer,
1327
1543
  signStrategy: { type: "auto-sign" },
@@ -1330,7 +1546,9 @@ var _TinyCloudNode = class _TinyCloudNode {
1330
1546
  domain: this.siweDomain,
1331
1547
  spacePrefix: config.prefix,
1332
1548
  sessionExpirationMs: config.sessionExpirationMs ?? 60 * 60 * 1e3,
1333
- tinycloudHosts: [host],
1549
+ tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
1550
+ tinycloudRegistryUrl: config.tinycloudRegistryUrl,
1551
+ tinycloudFallbackHosts: config.tinycloudFallbackHosts,
1334
1552
  autoCreateSpace: config.autoCreateSpace,
1335
1553
  enablePublicSpace: config.enablePublicSpace ?? true,
1336
1554
  spaceCreationHandler: config.spaceCreationHandler,
@@ -1340,10 +1558,16 @@ var _TinyCloudNode = class _TinyCloudNode {
1340
1558
  capabilityRequest: config.capabilityRequest,
1341
1559
  includeAccountRegistryPermissions: config.includeAccountRegistryPermissions
1342
1560
  });
1343
- this.tc = new import_sdk_core5.TinyCloud(this.auth, {
1344
- invokeAny: this.wasmBindings.invokeAny
1561
+ this.tc = new import_sdk_core6.TinyCloud(this.auth, {
1562
+ invokeAny: this.invokeAnyWithRuntimePermissions
1345
1563
  });
1346
1564
  }
1565
+ syncResolvedHostFromAuth() {
1566
+ const host = this.auth?.hosts[0];
1567
+ if (host) {
1568
+ this.config.host = host;
1569
+ }
1570
+ }
1347
1571
  /**
1348
1572
  * Install or replace the manifest that drives the SIWE recap at
1349
1573
  * sign-in. Takes effect on the next `signIn()` call — the current
@@ -1381,6 +1605,10 @@ var _TinyCloudNode = class _TinyCloudNode {
1381
1605
  get capabilityRequest() {
1382
1606
  return this.auth?.capabilityRequest;
1383
1607
  }
1608
+ get hosts() {
1609
+ const authHosts = this.auth?.hosts ?? [];
1610
+ return authHosts.length > 0 ? authHosts : [this.config.host];
1611
+ }
1384
1612
  /**
1385
1613
  * Get the primary identity DID for this user.
1386
1614
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -1451,8 +1679,14 @@ var _TinyCloudNode = class _TinyCloudNode {
1451
1679
  this._sql = void 0;
1452
1680
  this._duckdb = void 0;
1453
1681
  this._hooks = void 0;
1682
+ this._vault = void 0;
1683
+ this._baseSecrets = void 0;
1684
+ this._secrets = void 0;
1685
+ this._spaceService = void 0;
1454
1686
  this._serviceContext = void 0;
1687
+ this.runtimePermissionGrants = [];
1455
1688
  await this.tc.signIn(options);
1689
+ this.syncResolvedHostFromAuth();
1456
1690
  this.initializeServices();
1457
1691
  await this.writeManifestRegistryRecords();
1458
1692
  this.notificationHandler.success("Successfully signed in");
@@ -1471,8 +1705,8 @@ var _TinyCloudNode = class _TinyCloudNode {
1471
1705
  if (!this.auth || !this.signer) {
1472
1706
  throw new Error("Manifest registry write requires wallet mode");
1473
1707
  }
1474
- const accountSpaceId = this.ownedSpaceId(import_sdk_core5.ACCOUNT_REGISTRY_SPACE);
1475
- await this.auth.hostOwnedSpace(accountSpaceId);
1708
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core6.ACCOUNT_REGISTRY_SPACE);
1709
+ await this.ensureOwnedSpaceHosted(accountSpaceId);
1476
1710
  const accountKV = this.spaces.get(accountSpaceId).kv;
1477
1711
  for (const record of request.registryRecords) {
1478
1712
  const result = await accountKV.put(record.key, {
@@ -1487,6 +1721,39 @@ var _TinyCloudNode = class _TinyCloudNode {
1487
1721
  }
1488
1722
  }
1489
1723
  }
1724
+ async ensureOwnedSpaceHosted(spaceId) {
1725
+ if (!this.auth) {
1726
+ throw new Error("Owned space hosting requires wallet mode");
1727
+ }
1728
+ const session = this.auth.tinyCloudSession;
1729
+ if (!session) {
1730
+ throw new Error("Owned space hosting requires an active session");
1731
+ }
1732
+ const host = this.hosts[0] ?? this.config.host;
1733
+ if (!host) {
1734
+ throw new Error("Owned space hosting requires a TinyCloud host");
1735
+ }
1736
+ const activation = await (0, import_sdk_core6.activateSessionWithHost)(host, session.delegationHeader);
1737
+ if (activation.success && !activation.skipped?.includes(spaceId)) {
1738
+ return;
1739
+ }
1740
+ if (!activation.success && activation.status !== 404) {
1741
+ throw new Error(
1742
+ `Failed to check owned space ${spaceId}: ${activation.error ?? activation.status}`
1743
+ );
1744
+ }
1745
+ const created = await this.auth.hostOwnedSpace(spaceId);
1746
+ if (!created) {
1747
+ throw new Error(`Failed to create owned space: ${spaceId}`);
1748
+ }
1749
+ await new Promise((resolve) => setTimeout(resolve, 100));
1750
+ const retry = await (0, import_sdk_core6.activateSessionWithHost)(host, session.delegationHeader);
1751
+ if (!retry.success || retry.skipped?.includes(spaceId)) {
1752
+ throw new Error(
1753
+ `Failed to activate session after creating owned space ${spaceId}: ${retry.error ?? "space was skipped"}`
1754
+ );
1755
+ }
1756
+ }
1490
1757
  /**
1491
1758
  * Restore a previously established session from stored delegation data.
1492
1759
  *
@@ -1502,29 +1769,34 @@ var _TinyCloudNode = class _TinyCloudNode {
1502
1769
  this._sql = void 0;
1503
1770
  this._duckdb = void 0;
1504
1771
  this._hooks = void 0;
1772
+ this._vault = void 0;
1773
+ this._baseSecrets = void 0;
1774
+ this._secrets = void 0;
1775
+ this._spaceService = void 0;
1505
1776
  this._serviceContext = void 0;
1777
+ this.runtimePermissionGrants = [];
1506
1778
  if (sessionData.address) {
1507
1779
  this._address = sessionData.address;
1508
1780
  }
1509
1781
  if (sessionData.chainId) {
1510
1782
  this._chainId = sessionData.chainId;
1511
1783
  }
1512
- this._serviceContext = new import_sdk_core5.ServiceContext({
1513
- invoke: this.wasmBindings.invoke,
1514
- invokeAny: this.wasmBindings.invokeAny,
1784
+ this._serviceContext = new import_sdk_core6.ServiceContext({
1785
+ invoke: this.invokeWithRuntimePermissions,
1786
+ invokeAny: this.invokeAnyWithRuntimePermissions,
1515
1787
  fetch: globalThis.fetch.bind(globalThis),
1516
1788
  hosts: [this.config.host]
1517
1789
  });
1518
- this._kv = new import_sdk_core5.KVService({});
1790
+ this._kv = new import_sdk_core6.KVService({});
1519
1791
  this._kv.initialize(this._serviceContext);
1520
1792
  this._serviceContext.registerService("kv", this._kv);
1521
- this._sql = new import_sdk_core5.SQLService({});
1793
+ this._sql = new import_sdk_core6.SQLService({});
1522
1794
  this._sql.initialize(this._serviceContext);
1523
1795
  this._serviceContext.registerService("sql", this._sql);
1524
- this._duckdb = new import_sdk_core5.DuckDbService({});
1796
+ this._duckdb = new import_sdk_core6.DuckDbService({});
1525
1797
  this._duckdb.initialize(this._serviceContext);
1526
1798
  this._serviceContext.registerService("duckdb", this._duckdb);
1527
- this._hooks = new import_sdk_core5.HooksService({});
1799
+ this._hooks = new import_sdk_core6.HooksService({});
1528
1800
  this._hooks.initialize(this._serviceContext);
1529
1801
  this._serviceContext.registerService("hooks", this._hooks);
1530
1802
  const serviceSession = {
@@ -1535,41 +1807,7 @@ var _TinyCloudNode = class _TinyCloudNode {
1535
1807
  jwk: sessionData.jwk
1536
1808
  };
1537
1809
  this._serviceContext.setSession(serviceSession);
1538
- const wasm = this.wasmBindings;
1539
- const vaultCrypto = (0, import_sdk_core5.createVaultCrypto)({
1540
- vault_encrypt: wasm.vault_encrypt,
1541
- vault_decrypt: wasm.vault_decrypt,
1542
- vault_derive_key: wasm.vault_derive_key,
1543
- vault_x25519_from_seed: wasm.vault_x25519_from_seed,
1544
- vault_x25519_dh: wasm.vault_x25519_dh,
1545
- vault_random_bytes: wasm.vault_random_bytes,
1546
- vault_sha256: wasm.vault_sha256
1547
- });
1548
- const self = this;
1549
- this._vault = new import_sdk_core5.DataVaultService({
1550
- spaceId: sessionData.spaceId,
1551
- crypto: vaultCrypto,
1552
- tc: {
1553
- kv: this._kv,
1554
- ensurePublicSpace: async () => {
1555
- try {
1556
- await self.ensurePublicSpace();
1557
- return { ok: true, data: void 0 };
1558
- } catch (error) {
1559
- return { ok: false, error: { code: "STORAGE_ERROR", message: error instanceof Error ? error.message : String(error), service: "vault" } };
1560
- }
1561
- },
1562
- get publicKV() {
1563
- return self._publicKV ?? self.tc.publicKV;
1564
- },
1565
- readPublicSpace: (host, spaceId, key) => import_sdk_core5.TinyCloud.readPublicSpace(host, spaceId, key),
1566
- makePublicSpaceId: import_sdk_core5.TinyCloud.makePublicSpaceId,
1567
- did: this.did,
1568
- address: sessionData.address ?? this._address ?? "",
1569
- chainId: sessionData.chainId ?? this._chainId,
1570
- hosts: [this.config.host]
1571
- }
1572
- });
1810
+ this._vault = this.createVaultService(sessionData.spaceId, this._kv);
1573
1811
  this._vault.initialize(this._serviceContext);
1574
1812
  this._serviceContext.registerService("vault", this._vault);
1575
1813
  this.initializeV2Services(serviceSession);
@@ -1604,7 +1842,6 @@ var _TinyCloudNode = class _TinyCloudNode {
1604
1842
  throw new Error("Wallet already connected. Cannot connect another wallet.");
1605
1843
  }
1606
1844
  const prefix = options?.prefix ?? "default";
1607
- const host = this.config.host;
1608
1845
  if (!_TinyCloudNode.nodeDefaults) {
1609
1846
  throw new Error(
1610
1847
  "connectWallet() requires PrivateKeySigner. Use connectSigner() instead, or import from '@tinycloud/node-sdk' (not '/core') for automatic Node.js defaults."
@@ -1619,7 +1856,9 @@ var _TinyCloudNode = class _TinyCloudNode {
1619
1856
  domain: this.siweDomain,
1620
1857
  spacePrefix: prefix,
1621
1858
  sessionExpirationMs: this.config.sessionExpirationMs ?? 60 * 60 * 1e3,
1622
- tinycloudHosts: [host],
1859
+ tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
1860
+ tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
1861
+ tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
1623
1862
  autoCreateSpace: this.config.autoCreateSpace,
1624
1863
  enablePublicSpace: this.config.enablePublicSpace ?? true,
1625
1864
  spaceCreationHandler: this.config.spaceCreationHandler,
@@ -1629,8 +1868,8 @@ var _TinyCloudNode = class _TinyCloudNode {
1629
1868
  capabilityRequest: this.config.capabilityRequest,
1630
1869
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
1631
1870
  });
1632
- this.tc = new import_sdk_core5.TinyCloud(this.auth, {
1633
- invokeAny: this.wasmBindings.invokeAny
1871
+ this.tc = new import_sdk_core6.TinyCloud(this.auth, {
1872
+ invokeAny: this.invokeAnyWithRuntimePermissions
1634
1873
  });
1635
1874
  this.config.prefix = prefix;
1636
1875
  }
@@ -1652,7 +1891,6 @@ var _TinyCloudNode = class _TinyCloudNode {
1652
1891
  throw new Error("Signer already connected. Cannot connect another signer.");
1653
1892
  }
1654
1893
  const prefix = options?.prefix ?? "default";
1655
- const host = this.config.host;
1656
1894
  this.signer = signer;
1657
1895
  this.auth = new NodeUserAuthorization({
1658
1896
  signer: this.signer,
@@ -1662,7 +1900,9 @@ var _TinyCloudNode = class _TinyCloudNode {
1662
1900
  domain: this.siweDomain,
1663
1901
  spacePrefix: prefix,
1664
1902
  sessionExpirationMs: this.config.sessionExpirationMs ?? 60 * 60 * 1e3,
1665
- tinycloudHosts: [host],
1903
+ tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
1904
+ tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
1905
+ tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
1666
1906
  autoCreateSpace: this.config.autoCreateSpace,
1667
1907
  enablePublicSpace: this.config.enablePublicSpace ?? true,
1668
1908
  spaceCreationHandler: this.config.spaceCreationHandler,
@@ -1672,8 +1912,8 @@ var _TinyCloudNode = class _TinyCloudNode {
1672
1912
  capabilityRequest: this.config.capabilityRequest,
1673
1913
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
1674
1914
  });
1675
- this.tc = new import_sdk_core5.TinyCloud(this.auth, {
1676
- invokeAny: this.wasmBindings.invokeAny
1915
+ this.tc = new import_sdk_core6.TinyCloud(this.auth, {
1916
+ invokeAny: this.invokeAnyWithRuntimePermissions
1677
1917
  });
1678
1918
  this.config.prefix = prefix;
1679
1919
  }
@@ -1686,28 +1926,28 @@ var _TinyCloudNode = class _TinyCloudNode {
1686
1926
  if (!session) {
1687
1927
  return;
1688
1928
  }
1689
- this.tc.initializeServices(this.wasmBindings.invoke, [this.config.host]);
1690
- this._serviceContext = new import_sdk_core5.ServiceContext({
1691
- invoke: this.wasmBindings.invoke,
1692
- invokeAny: this.wasmBindings.invokeAny,
1929
+ this.tc.initializeServices(this.invokeWithRuntimePermissions, [this.config.host]);
1930
+ this._serviceContext = new import_sdk_core6.ServiceContext({
1931
+ invoke: this.invokeWithRuntimePermissions,
1932
+ invokeAny: this.invokeAnyWithRuntimePermissions,
1693
1933
  fetch: globalThis.fetch.bind(globalThis),
1694
1934
  hosts: [this.config.host]
1695
1935
  });
1696
- this._kv = new import_sdk_core5.KVService({});
1936
+ this._kv = new import_sdk_core6.KVService({});
1697
1937
  this._kv.initialize(this._serviceContext);
1698
1938
  this._serviceContext.registerService("kv", this._kv);
1699
1939
  const features = this.nodeFeatures;
1700
1940
  if (features.length === 0 || features.includes("sql")) {
1701
- this._sql = new import_sdk_core5.SQLService({});
1941
+ this._sql = new import_sdk_core6.SQLService({});
1702
1942
  this._sql.initialize(this._serviceContext);
1703
1943
  this._serviceContext.registerService("sql", this._sql);
1704
1944
  }
1705
1945
  if (features.length === 0 || features.includes("duckdb")) {
1706
- this._duckdb = new import_sdk_core5.DuckDbService({});
1946
+ this._duckdb = new import_sdk_core6.DuckDbService({});
1707
1947
  this._duckdb.initialize(this._serviceContext);
1708
1948
  this._serviceContext.registerService("duckdb", this._duckdb);
1709
1949
  }
1710
- this._hooks = new import_sdk_core5.HooksService({});
1950
+ this._hooks = new import_sdk_core6.HooksService({});
1711
1951
  this._hooks.initialize(this._serviceContext);
1712
1952
  this._serviceContext.registerService("hooks", this._hooks);
1713
1953
  const serviceSession = {
@@ -1719,8 +1959,30 @@ var _TinyCloudNode = class _TinyCloudNode {
1719
1959
  };
1720
1960
  this._serviceContext.setSession(serviceSession);
1721
1961
  this.tc.serviceContext.setSession(serviceSession);
1962
+ this._vault = this.createVaultService(session.spaceId, this._kv);
1963
+ this._vault.initialize(this._serviceContext);
1964
+ this._serviceContext.registerService("vault", this._vault);
1965
+ this.initializeV2Services(serviceSession);
1966
+ }
1967
+ createSpaceScopedKVService(spaceId) {
1968
+ const kvService = new import_sdk_core6.KVService({});
1969
+ if (this._serviceContext) {
1970
+ const spaceScopedContext = new import_sdk_core6.ServiceContext({
1971
+ invoke: this._serviceContext.invoke,
1972
+ fetch: this._serviceContext.fetch,
1973
+ hosts: this._serviceContext.hosts
1974
+ });
1975
+ const session = this._serviceContext.session;
1976
+ if (session) {
1977
+ spaceScopedContext.setSession({ ...session, spaceId });
1978
+ }
1979
+ kvService.initialize(spaceScopedContext);
1980
+ }
1981
+ return kvService;
1982
+ }
1983
+ createVaultService(spaceId, kv) {
1722
1984
  const wasm = this.wasmBindings;
1723
- const vaultCrypto = (0, import_sdk_core5.createVaultCrypto)({
1985
+ const vaultCrypto = (0, import_sdk_core6.createVaultCrypto)({
1724
1986
  vault_encrypt: wasm.vault_encrypt,
1725
1987
  vault_decrypt: wasm.vault_decrypt,
1726
1988
  vault_derive_key: wasm.vault_derive_key,
@@ -1730,11 +1992,11 @@ var _TinyCloudNode = class _TinyCloudNode {
1730
1992
  vault_sha256: wasm.vault_sha256
1731
1993
  });
1732
1994
  const self = this;
1733
- this._vault = new import_sdk_core5.DataVaultService({
1734
- spaceId: session.spaceId,
1995
+ return new import_sdk_core6.DataVaultService({
1996
+ spaceId,
1735
1997
  crypto: vaultCrypto,
1736
1998
  tc: {
1737
- kv: this._kv,
1999
+ kv,
1738
2000
  ensurePublicSpace: async () => {
1739
2001
  try {
1740
2002
  await self.ensurePublicSpace();
@@ -1746,24 +2008,21 @@ var _TinyCloudNode = class _TinyCloudNode {
1746
2008
  get publicKV() {
1747
2009
  return self._publicKV ?? self.tc.publicKV;
1748
2010
  },
1749
- readPublicSpace: (host, spaceId, key) => import_sdk_core5.TinyCloud.readPublicSpace(host, spaceId, key),
1750
- makePublicSpaceId: import_sdk_core5.TinyCloud.makePublicSpaceId,
2011
+ readPublicSpace: (host, targetSpaceId, key) => import_sdk_core6.TinyCloud.readPublicSpace(host, targetSpaceId, key),
2012
+ makePublicSpaceId: import_sdk_core6.TinyCloud.makePublicSpaceId,
1751
2013
  did: this.did,
1752
- address: this._address,
2014
+ address: this._address ?? "",
1753
2015
  chainId: this._chainId,
1754
2016
  hosts: [this.config.host]
1755
2017
  }
1756
2018
  });
1757
- this._vault.initialize(this._serviceContext);
1758
- this._serviceContext.registerService("vault", this._vault);
1759
- this.initializeV2Services(serviceSession);
1760
2019
  }
1761
2020
  /**
1762
2021
  * Initialize the v2 delegation system services.
1763
2022
  * @internal
1764
2023
  */
1765
2024
  initializeV2Services(serviceSession) {
1766
- this._capabilityRegistry = new import_sdk_core5.CapabilityKeyRegistry();
2025
+ this._capabilityRegistry = new import_sdk_core6.CapabilityKeyRegistry();
1767
2026
  const tcSession = this.auth?.tinyCloudSession;
1768
2027
  if (tcSession && this._address) {
1769
2028
  const sessionKey = {
@@ -1837,13 +2096,13 @@ var _TinyCloudNode = class _TinyCloudNode {
1837
2096
  }
1838
2097
  this._capabilityRegistry.registerKey(sessionKey, delegations);
1839
2098
  }
1840
- this._delegationManager = new import_sdk_core5.DelegationManager({
2099
+ this._delegationManager = new import_sdk_core6.DelegationManager({
1841
2100
  hosts: [this.config.host],
1842
2101
  session: serviceSession,
1843
- invoke: this.wasmBindings.invoke,
2102
+ invoke: this.invokeWithRuntimePermissions,
1844
2103
  fetch: globalThis.fetch.bind(globalThis)
1845
2104
  });
1846
- this._spaceService = new import_sdk_core5.SpaceService({
2105
+ this._spaceService = new import_sdk_core6.SpaceService({
1847
2106
  hosts: [this.config.host],
1848
2107
  session: serviceSession,
1849
2108
  invoke: this.wasmBindings.invoke,
@@ -1851,20 +2110,15 @@ var _TinyCloudNode = class _TinyCloudNode {
1851
2110
  capabilityRegistry: this._capabilityRegistry,
1852
2111
  userDid: this.did,
1853
2112
  createKVService: (spaceId) => {
1854
- const kvService = new import_sdk_core5.KVService({});
2113
+ return this.createSpaceScopedKVService(spaceId);
2114
+ },
2115
+ createVaultService: (spaceId) => {
2116
+ const kvService = this.createSpaceScopedKVService(spaceId);
2117
+ const vaultService = this.createVaultService(spaceId, kvService);
1855
2118
  if (this._serviceContext) {
1856
- const spaceScopedContext = new import_sdk_core5.ServiceContext({
1857
- invoke: this._serviceContext.invoke,
1858
- fetch: this._serviceContext.fetch,
1859
- hosts: this._serviceContext.hosts
1860
- });
1861
- const session = this._serviceContext.session;
1862
- if (session) {
1863
- spaceScopedContext.setSession({ ...session, spaceId });
1864
- }
1865
- kvService.initialize(spaceScopedContext);
2119
+ vaultService.initialize(this._serviceContext);
1866
2120
  }
1867
- return kvService;
2121
+ return vaultService;
1868
2122
  },
1869
2123
  // Enable space.delegations.create() via SIWE-based delegation
1870
2124
  createDelegation: async (params) => {
@@ -2005,7 +2259,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2005
2259
  ...prepared,
2006
2260
  signature
2007
2261
  });
2008
- const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
2262
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2009
2263
  host,
2010
2264
  delegationSession.delegationHeader
2011
2265
  );
@@ -2072,7 +2326,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2072
2326
  if (!this._sql) {
2073
2327
  const features = this.nodeFeatures;
2074
2328
  if (features.length > 0 && !features.includes("sql")) {
2075
- throw new import_sdk_core5.UnsupportedFeatureError("sql", this.config.host, features);
2329
+ throw new import_sdk_core6.UnsupportedFeatureError("sql", this.config.host, features);
2076
2330
  }
2077
2331
  throw new Error("Not signed in. Call signIn() first.");
2078
2332
  }
@@ -2085,7 +2339,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2085
2339
  if (!this._duckdb) {
2086
2340
  const features = this.nodeFeatures;
2087
2341
  if (features.length > 0 && !features.includes("duckdb")) {
2088
- throw new import_sdk_core5.UnsupportedFeatureError("duckdb", this.config.host, features);
2342
+ throw new import_sdk_core6.UnsupportedFeatureError("duckdb", this.config.host, features);
2089
2343
  }
2090
2344
  throw new Error("Not signed in. Call signIn() first.");
2091
2345
  }
@@ -2101,6 +2355,33 @@ var _TinyCloudNode = class _TinyCloudNode {
2101
2355
  }
2102
2356
  return this._vault;
2103
2357
  }
2358
+ /**
2359
+ * App-facing secrets API backed by the `secrets` space vault.
2360
+ */
2361
+ get secrets() {
2362
+ if (!this._spaceService) {
2363
+ throw new Error("Not signed in. Call signIn() first.");
2364
+ }
2365
+ if (!this._secrets) {
2366
+ this._secrets = new NodeSecretsService({
2367
+ getService: () => this.getBaseSecrets(),
2368
+ getManifest: () => this.manifest,
2369
+ grantPermissions: (additional) => this.grantRuntimePermissions(additional),
2370
+ canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
2371
+ getUnlockSigner: () => this.signer ?? void 0
2372
+ });
2373
+ }
2374
+ return this._secrets;
2375
+ }
2376
+ getBaseSecrets() {
2377
+ if (!this._spaceService) {
2378
+ throw new Error("Not signed in. Call signIn() first.");
2379
+ }
2380
+ if (!this._baseSecrets) {
2381
+ this._baseSecrets = new import_sdk_core6.SecretsService(() => this.space("secrets").vault);
2382
+ }
2383
+ return this._baseSecrets;
2384
+ }
2104
2385
  /**
2105
2386
  * Hooks write stream subscription API.
2106
2387
  */
@@ -2171,6 +2452,171 @@ var _TinyCloudNode = class _TinyCloudNode {
2171
2452
  }
2172
2453
  };
2173
2454
  }
2455
+ /**
2456
+ * Check whether the current session or an approved runtime delegation covers
2457
+ * every requested permission.
2458
+ */
2459
+ hasRuntimePermissions(permissions) {
2460
+ const session = this.auth?.tinyCloudSession;
2461
+ if (!session || !Array.isArray(permissions) || permissions.length === 0) {
2462
+ return false;
2463
+ }
2464
+ const expanded = this.expandPermissionEntries(permissions);
2465
+ if (this.sessionCoversPermissionEntries(session, expanded)) {
2466
+ return true;
2467
+ }
2468
+ return this.findRuntimeGrantsForPermissionEntries(expanded, session).length > 0;
2469
+ }
2470
+ /**
2471
+ * Return installed runtime permission delegations. When `permissions` is
2472
+ * provided, only delegations currently covering those permissions are
2473
+ * returned. Base-session manifest permissions are not represented here.
2474
+ */
2475
+ getRuntimePermissionDelegations(permissions) {
2476
+ this.pruneExpiredRuntimePermissionGrants();
2477
+ if (permissions === void 0) {
2478
+ return this.runtimePermissionGrants.map((grant) => grant.delegation);
2479
+ }
2480
+ const session = this.auth?.tinyCloudSession;
2481
+ if (!session || !Array.isArray(permissions) || permissions.length === 0) {
2482
+ return [];
2483
+ }
2484
+ const expanded = this.expandPermissionEntries(permissions);
2485
+ return this.findRuntimeGrantsForPermissionEntries(expanded, session).map(
2486
+ (grant) => grant.delegation
2487
+ );
2488
+ }
2489
+ /**
2490
+ * Install a portable runtime permission delegation into this SDK instance so
2491
+ * matching service calls and downstream `delegateTo()` calls can use it.
2492
+ */
2493
+ async useRuntimeDelegation(delegation) {
2494
+ const session = this.auth?.tinyCloudSession;
2495
+ if (!session) {
2496
+ throw new import_sdk_core6.SessionExpiredError(/* @__PURE__ */ new Date(0));
2497
+ }
2498
+ if (delegation.expiry.getTime() <= Date.now()) {
2499
+ throw new import_sdk_core6.SessionExpiredError(delegation.expiry);
2500
+ }
2501
+ const expectedDids = /* @__PURE__ */ new Set([session.verificationMethod, this.sessionDid]);
2502
+ if (!expectedDids.has(delegation.delegateDID)) {
2503
+ throw new Error(
2504
+ `Runtime delegation targets ${delegation.delegateDID} but this session key is ${session.verificationMethod}.`
2505
+ );
2506
+ }
2507
+ const targetHost = delegation.host ?? this.config.host;
2508
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2509
+ targetHost,
2510
+ delegation.delegationHeader
2511
+ );
2512
+ if (!activateResult.success) {
2513
+ throw new Error(
2514
+ `Failed to activate runtime permission delegation: ${activateResult.error}`
2515
+ );
2516
+ }
2517
+ this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
2518
+ (grant) => grant.delegation.cid !== delegation.cid
2519
+ );
2520
+ this.runtimePermissionGrants.push(
2521
+ this.runtimeGrantFromDelegation(delegation, session)
2522
+ );
2523
+ }
2524
+ /**
2525
+ * Store additional permissions as narrow delegations to the current session
2526
+ * key. Future service invocations automatically use a stored delegation when
2527
+ * its `(space, service, path, action)` covers the request.
2528
+ */
2529
+ async grantRuntimePermissions(permissions, options) {
2530
+ if (!Array.isArray(permissions) || permissions.length === 0) {
2531
+ throw new Error("grantRuntimePermissions requires a non-empty permissions array");
2532
+ }
2533
+ const session = this.auth?.tinyCloudSession;
2534
+ if (!session) {
2535
+ throw new import_sdk_core6.SessionExpiredError(/* @__PURE__ */ new Date(0));
2536
+ }
2537
+ const sessionExpiry = extractSiweExpiration(session.siwe);
2538
+ if (sessionExpiry !== void 0) {
2539
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
2540
+ if (sessionExpiry.getTime() <= Date.now() + marginMs) {
2541
+ throw new import_sdk_core6.SessionExpiredError(sessionExpiry);
2542
+ }
2543
+ }
2544
+ const expanded = this.expandPermissionEntries(permissions);
2545
+ if (this.sessionCoversPermissionEntries(session, expanded)) {
2546
+ return [];
2547
+ }
2548
+ const existingGrants = this.findRuntimeGrantsForPermissionEntries(expanded, session);
2549
+ if (existingGrants.length > 0) {
2550
+ return existingGrants.map((grant) => grant.delegation);
2551
+ }
2552
+ if (!this.signer) {
2553
+ throw new Error(
2554
+ "grantRuntimePermissions requires wallet mode with a signer or privateKey."
2555
+ );
2556
+ }
2557
+ const bySpace = /* @__PURE__ */ new Map();
2558
+ for (const entry of expanded) {
2559
+ const spaceId = this.resolvePermissionSpace(entry.space, session);
2560
+ const current = bySpace.get(spaceId) ?? [];
2561
+ current.push(entry);
2562
+ bySpace.set(spaceId, current);
2563
+ }
2564
+ const now = /* @__PURE__ */ new Date();
2565
+ const requestedExpiryMs = resolveExpiryMs(options?.expiry);
2566
+ let expiresAt = new Date(now.getTime() + requestedExpiryMs);
2567
+ if (sessionExpiry !== void 0 && sessionExpiry < expiresAt) {
2568
+ expiresAt = sessionExpiry;
2569
+ }
2570
+ const delegations = [];
2571
+ for (const [spaceId, entries] of bySpace) {
2572
+ const abilities = this.permissionsToAbilities(entries);
2573
+ const prepared = this.wasmBindings.prepareSession({
2574
+ abilities,
2575
+ address: this.wasmBindings.ensureEip55(session.address),
2576
+ chainId: session.chainId,
2577
+ domain: this.siweDomain,
2578
+ issuedAt: now.toISOString(),
2579
+ expirationTime: expiresAt.toISOString(),
2580
+ spaceId,
2581
+ jwk: session.jwk
2582
+ });
2583
+ const signature = await this.signer.signMessage(prepared.siwe);
2584
+ const delegatedSession = this.wasmBindings.completeSessionSetup({
2585
+ ...prepared,
2586
+ signature
2587
+ });
2588
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2589
+ this.config.host,
2590
+ delegatedSession.delegationHeader
2591
+ );
2592
+ if (!activateResult.success) {
2593
+ throw new Error(
2594
+ `Failed to activate runtime permission delegation: ${activateResult.error}`
2595
+ );
2596
+ }
2597
+ const delegation = this.runtimeDelegationFromSession(
2598
+ delegatedSession,
2599
+ entries,
2600
+ spaceId,
2601
+ session,
2602
+ expiresAt
2603
+ );
2604
+ this.runtimePermissionGrants.push({
2605
+ session: {
2606
+ delegationHeader: delegatedSession.delegationHeader,
2607
+ delegationCid: delegatedSession.delegationCid,
2608
+ spaceId,
2609
+ verificationMethod: session.verificationMethod,
2610
+ jwk: session.jwk
2611
+ },
2612
+ delegation,
2613
+ operations: this.permissionOperations(entries, spaceId),
2614
+ expiresAt
2615
+ });
2616
+ delegations.push(delegation);
2617
+ }
2618
+ return delegations;
2619
+ }
2174
2620
  /**
2175
2621
  * Get the DelegationManager for delegation CRUD operations.
2176
2622
  *
@@ -2239,6 +2685,12 @@ var _TinyCloudNode = class _TinyCloudNode {
2239
2685
  get spaceService() {
2240
2686
  return this.spaces;
2241
2687
  }
2688
+ /**
2689
+ * Get a Space object by short name or full URI.
2690
+ */
2691
+ space(nameOrUri) {
2692
+ return this.spaces.get(nameOrUri);
2693
+ }
2242
2694
  /**
2243
2695
  * Get the SharingService for creating and receiving v2 sharing links.
2244
2696
  *
@@ -2324,7 +2776,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2324
2776
  ...prepared,
2325
2777
  signature
2326
2778
  });
2327
- const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
2779
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2328
2780
  this.config.host,
2329
2781
  delegationSession.delegationHeader
2330
2782
  );
@@ -2351,9 +2803,9 @@ var _TinyCloudNode = class _TinyCloudNode {
2351
2803
  }]);
2352
2804
  }
2353
2805
  if (this._serviceContext) {
2354
- const publicKV = new import_sdk_core5.KVService({ prefix: "" });
2355
- const publicContext = new import_sdk_core5.ServiceContext({
2356
- invoke: this.wasmBindings.invoke,
2806
+ const publicKV = new import_sdk_core6.KVService({ prefix: "" });
2807
+ const publicContext = new import_sdk_core6.ServiceContext({
2808
+ invoke: this.invokeWithRuntimePermissions,
2357
2809
  fetch: this._serviceContext.fetch,
2358
2810
  hosts: this._serviceContext.hosts
2359
2811
  });
@@ -2441,8 +2893,9 @@ var _TinyCloudNode = class _TinyCloudNode {
2441
2893
  * Issue a delegation using the capability-chain flow.
2442
2894
  *
2443
2895
  * When every requested permission is a subset of the current
2444
- * session's recap, the delegation is signed by the session key via
2445
- * WASM no wallet prompt. When at least one is NOT derivable, a
2896
+ * session's recap, or of one installed runtime permission delegation,
2897
+ * the delegation is signed by the session key via WASM no wallet
2898
+ * prompt. When at least one is NOT derivable, a
2446
2899
  * {@link PermissionNotInManifestError} is raised (carrying the
2447
2900
  * missing entries) so the caller can trigger an escalation flow
2448
2901
  * (e.g. `TinyCloudWeb.requestPermissions`). Passing
@@ -2477,14 +2930,14 @@ var _TinyCloudNode = class _TinyCloudNode {
2477
2930
  async delegateTo(did, permissions, options) {
2478
2931
  const session = this.auth?.tinyCloudSession;
2479
2932
  if (!session) {
2480
- throw new import_sdk_core5.SessionExpiredError(/* @__PURE__ */ new Date(0));
2933
+ throw new import_sdk_core6.SessionExpiredError(/* @__PURE__ */ new Date(0));
2481
2934
  }
2482
2935
  const sessionExpiry = extractSiweExpiration(session.siwe);
2483
2936
  if (sessionExpiry !== void 0) {
2484
2937
  const now2 = Date.now();
2485
2938
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
2486
2939
  if (sessionExpiry.getTime() <= now2 + marginMs) {
2487
- throw new import_sdk_core5.SessionExpiredError(sessionExpiry);
2940
+ throw new import_sdk_core6.SessionExpiredError(sessionExpiry);
2488
2941
  }
2489
2942
  }
2490
2943
  if (!Array.isArray(permissions) || permissions.length === 0) {
@@ -2492,10 +2945,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2492
2945
  "delegateTo requires a non-empty permissions array"
2493
2946
  );
2494
2947
  }
2495
- const expandedEntries = permissions.map((entry) => ({
2496
- ...entry,
2497
- actions: (0, import_sdk_core5.expandActionShortNames)(entry.service, entry.actions)
2498
- }));
2948
+ const expandedEntries = this.expandPermissionEntries(permissions);
2499
2949
  const now = /* @__PURE__ */ new Date();
2500
2950
  const expiryMs = resolveExpiryMs(options?.expiry);
2501
2951
  const expirationTime = new Date(now.getTime() + expiryMs);
@@ -2516,13 +2966,30 @@ var _TinyCloudNode = class _TinyCloudNode {
2516
2966
  );
2517
2967
  return { delegation: delegation2, prompted: true };
2518
2968
  }
2519
- const granted = (0, import_sdk_core5.parseRecapCapabilities)(
2969
+ const granted = (0, import_sdk_core6.parseRecapCapabilities)(
2520
2970
  (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
2521
2971
  session.siwe
2522
2972
  );
2523
- const { subset, missing } = (0, import_sdk_core5.isCapabilitySubset)(expandedEntries, granted);
2973
+ const { subset, missing } = (0, import_sdk_core6.isCapabilitySubset)(expandedEntries, granted);
2524
2974
  if (!subset) {
2525
- throw new import_sdk_core5.PermissionNotInManifestError(missing, granted);
2975
+ const runtimeGrant = this.findGrantForOperations(
2976
+ this.permissionEntriesToOperations(expandedEntries, session)
2977
+ );
2978
+ if (runtimeGrant) {
2979
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
2980
+ if (runtimeGrant.expiresAt.getTime() <= Date.now() + marginMs) {
2981
+ throw new import_sdk_core6.SessionExpiredError(runtimeGrant.expiresAt);
2982
+ }
2983
+ const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
2984
+ const delegation2 = await this.createDelegationViaRuntimeGrant(
2985
+ did,
2986
+ expandedEntries,
2987
+ runtimeExpiration,
2988
+ runtimeGrant
2989
+ );
2990
+ return { delegation: delegation2, prompted: false };
2991
+ }
2992
+ throw new import_sdk_core6.PermissionNotInManifestError(missing, granted);
2526
2993
  }
2527
2994
  const delegation = await this.createDelegationViaWasmPath(
2528
2995
  did,
@@ -2602,7 +3069,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2602
3069
  const spaceId = [...resolvedSpaces][0];
2603
3070
  const abilities = {};
2604
3071
  for (const entry of entries) {
2605
- const shortService = import_sdk_core5.SERVICE_LONG_TO_SHORT[entry.service];
3072
+ const shortService = import_sdk_core6.SERVICE_LONG_TO_SHORT[entry.service];
2606
3073
  if (shortService === void 0) {
2607
3074
  throw new Error(
2608
3075
  `delegateTo: unknown service '${entry.service}' \u2014 no short-form mapping`
@@ -2642,7 +3109,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2642
3109
  });
2643
3110
  const primary = result.resources[0];
2644
3111
  const delegationHeader = { Authorization: result.delegation };
2645
- const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
3112
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2646
3113
  this.config.host,
2647
3114
  delegationHeader
2648
3115
  );
@@ -2666,6 +3133,41 @@ var _TinyCloudNode = class _TinyCloudNode {
2666
3133
  host: this.config.host
2667
3134
  };
2668
3135
  }
3136
+ async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant) {
3137
+ const result = this.createDelegationWrapper({
3138
+ session: grant.session,
3139
+ delegateDID: did,
3140
+ spaceId: grant.session.spaceId,
3141
+ abilities: this.permissionsToAbilities(entries),
3142
+ expirationSecs: Math.floor(expirationTime.getTime() / 1e3)
3143
+ });
3144
+ const primary = result.resources[0];
3145
+ const delegationHeader = { Authorization: result.delegation };
3146
+ const targetHost = grant.delegation.host ?? this.config.host;
3147
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
3148
+ targetHost,
3149
+ delegationHeader
3150
+ );
3151
+ if (!activateResult.success) {
3152
+ throw new Error(
3153
+ `Failed to activate delegation with host: ${activateResult.error}`
3154
+ );
3155
+ }
3156
+ return {
3157
+ cid: result.cid,
3158
+ delegationHeader,
3159
+ spaceId: grant.session.spaceId,
3160
+ path: primary.path,
3161
+ actions: primary.actions,
3162
+ resources: result.resources,
3163
+ disableSubDelegation: false,
3164
+ expiry: result.expiry,
3165
+ delegateDID: did,
3166
+ ownerAddress: grant.delegation.ownerAddress,
3167
+ chainId: grant.delegation.chainId,
3168
+ host: targetHost
3169
+ };
3170
+ }
2669
3171
  resolvePermissionSpace(space, session) {
2670
3172
  if (space === void 0) {
2671
3173
  return this.wasmBindings.makeSpaceId(
@@ -2682,6 +3184,220 @@ var _TinyCloudNode = class _TinyCloudNode {
2682
3184
  }
2683
3185
  return this.wasmBindings.makeSpaceId(session.address, session.chainId, space);
2684
3186
  }
3187
+ expandPermissionEntries(permissions) {
3188
+ return (0, import_sdk_core6.expandPermissionEntries)(permissions);
3189
+ }
3190
+ shortServiceName(service) {
3191
+ const short = import_sdk_core6.SERVICE_LONG_TO_SHORT[service];
3192
+ if (short === void 0) {
3193
+ throw new Error(
3194
+ `unknown service '${service}' \u2014 no short-form mapping`
3195
+ );
3196
+ }
3197
+ return short;
3198
+ }
3199
+ permissionsToAbilities(entries) {
3200
+ const abilities = {};
3201
+ for (const entry of entries) {
3202
+ const service = this.shortServiceName(entry.service);
3203
+ abilities[service] ?? (abilities[service] = {});
3204
+ const existing = abilities[service][entry.path] ?? [];
3205
+ const seen = new Set(existing);
3206
+ for (const action of entry.actions) {
3207
+ if (!seen.has(action)) {
3208
+ existing.push(action);
3209
+ seen.add(action);
3210
+ }
3211
+ }
3212
+ abilities[service][entry.path] = existing;
3213
+ }
3214
+ return abilities;
3215
+ }
3216
+ permissionOperations(entries, spaceId) {
3217
+ return entries.flatMap((entry) => {
3218
+ const service = this.shortServiceName(entry.service);
3219
+ return entry.actions.map((action) => ({
3220
+ spaceId,
3221
+ service,
3222
+ path: entry.path,
3223
+ action
3224
+ }));
3225
+ });
3226
+ }
3227
+ sessionCoversPermissionEntries(session, entries) {
3228
+ try {
3229
+ const granted = (0, import_sdk_core6.parseRecapCapabilities)(
3230
+ (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
3231
+ session.siwe
3232
+ );
3233
+ return (0, import_sdk_core6.isCapabilitySubset)(entries, granted).subset;
3234
+ } catch {
3235
+ return false;
3236
+ }
3237
+ }
3238
+ permissionEntriesToOperations(entries, session) {
3239
+ return entries.flatMap((entry) => {
3240
+ const spaceId = this.resolvePermissionSpace(entry.space, session);
3241
+ const service = this.shortServiceName(entry.service);
3242
+ return entry.actions.map((action) => ({
3243
+ spaceId,
3244
+ service,
3245
+ path: entry.path,
3246
+ action
3247
+ }));
3248
+ });
3249
+ }
3250
+ findRuntimeGrantsForPermissionEntries(entries, session) {
3251
+ const grants = [];
3252
+ const operations = this.permissionEntriesToOperations(entries, session);
3253
+ if (operations.length === 0) {
3254
+ return grants;
3255
+ }
3256
+ for (const operation of operations) {
3257
+ const grant = this.findGrantForOperation(operation);
3258
+ if (!grant) {
3259
+ return [];
3260
+ }
3261
+ if (!grants.includes(grant)) {
3262
+ grants.push(grant);
3263
+ }
3264
+ }
3265
+ return grants;
3266
+ }
3267
+ runtimeDelegationFromSession(delegatedSession, entries, spaceId, session, expiresAt) {
3268
+ const resources = this.delegatedResourcesForEntries(entries, spaceId);
3269
+ const primary = resources[0];
3270
+ return {
3271
+ cid: delegatedSession.delegationCid,
3272
+ delegationHeader: delegatedSession.delegationHeader,
3273
+ spaceId,
3274
+ path: primary.path,
3275
+ actions: primary.actions,
3276
+ resources,
3277
+ disableSubDelegation: false,
3278
+ expiry: expiresAt,
3279
+ delegateDID: session.verificationMethod,
3280
+ ownerAddress: session.address,
3281
+ chainId: session.chainId,
3282
+ host: this.config.host
3283
+ };
3284
+ }
3285
+ runtimeGrantFromDelegation(delegation, session) {
3286
+ const operations = this.operationsFromDelegation(delegation);
3287
+ return {
3288
+ session: {
3289
+ delegationHeader: delegation.delegationHeader,
3290
+ delegationCid: delegation.cid,
3291
+ spaceId: delegation.spaceId,
3292
+ verificationMethod: session.verificationMethod,
3293
+ jwk: session.jwk
3294
+ },
3295
+ delegation,
3296
+ operations,
3297
+ expiresAt: delegation.expiry
3298
+ };
3299
+ }
3300
+ delegatedResourcesForEntries(entries, spaceId) {
3301
+ return entries.map((entry) => ({
3302
+ service: this.shortServiceName(entry.service),
3303
+ space: spaceId,
3304
+ path: entry.path,
3305
+ actions: [...entry.actions]
3306
+ }));
3307
+ }
3308
+ operationsFromDelegation(delegation) {
3309
+ const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
3310
+ return resources.flatMap(
3311
+ (resource) => resource.actions.map((action) => ({
3312
+ spaceId: resource.space,
3313
+ service: this.invocationServiceName(resource.service),
3314
+ path: resource.path,
3315
+ action
3316
+ }))
3317
+ );
3318
+ }
3319
+ flatDelegationResources(delegation) {
3320
+ const byService = /* @__PURE__ */ new Map();
3321
+ for (const action of delegation.actions) {
3322
+ const service = this.shortServiceName(action.split("/")[0]);
3323
+ const actions = byService.get(service) ?? [];
3324
+ actions.push(action);
3325
+ byService.set(service, actions);
3326
+ }
3327
+ return [...byService.entries()].map(([service, actions]) => ({
3328
+ service,
3329
+ space: delegation.spaceId,
3330
+ path: delegation.path,
3331
+ actions
3332
+ }));
3333
+ }
3334
+ selectInvocationSession(fallback, service, path, action) {
3335
+ const grant = this.findGrantForOperation({
3336
+ spaceId: fallback.spaceId,
3337
+ service: this.invocationServiceName(service),
3338
+ path,
3339
+ action
3340
+ });
3341
+ return grant?.session ?? fallback;
3342
+ }
3343
+ findGrantForOperations(operations) {
3344
+ if (operations.length === 0) {
3345
+ return void 0;
3346
+ }
3347
+ this.pruneExpiredRuntimePermissionGrants();
3348
+ return this.runtimePermissionGrants.find((grant) => {
3349
+ return operations.every(
3350
+ (operation) => grant.operations.some(
3351
+ (granted) => this.operationCovers(granted, operation)
3352
+ )
3353
+ );
3354
+ });
3355
+ }
3356
+ findGrantForOperation(operation) {
3357
+ return this.findGrantForOperations([operation]);
3358
+ }
3359
+ pruneExpiredRuntimePermissionGrants() {
3360
+ const now = Date.now();
3361
+ this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
3362
+ (grant) => grant.expiresAt.getTime() > now
3363
+ );
3364
+ }
3365
+ operationCovers(granted, requested) {
3366
+ return granted.spaceId === requested.spaceId && granted.service === requested.service && this.actionContains(granted.action, requested.action) && this.pathContains(granted.path, requested.path);
3367
+ }
3368
+ actionContains(grantedAction, requestedAction) {
3369
+ if (grantedAction === requestedAction) {
3370
+ return true;
3371
+ }
3372
+ if (grantedAction.endsWith("/*")) {
3373
+ const prefix = grantedAction.slice(0, -2);
3374
+ return requestedAction.startsWith(`${prefix}/`);
3375
+ }
3376
+ return false;
3377
+ }
3378
+ invocationServiceName(service) {
3379
+ return service.startsWith("tinycloud.") ? this.shortServiceName(service) : service;
3380
+ }
3381
+ pathContains(grantedPath, requestedPath) {
3382
+ if (grantedPath === "" || grantedPath === "/") {
3383
+ return true;
3384
+ }
3385
+ if (grantedPath.endsWith("/**")) {
3386
+ return requestedPath.startsWith(grantedPath.slice(0, -3));
3387
+ }
3388
+ if (grantedPath.endsWith("/*")) {
3389
+ const prefix = grantedPath.slice(0, -2);
3390
+ if (!requestedPath.startsWith(prefix)) {
3391
+ return false;
3392
+ }
3393
+ const remainder = requestedPath.slice(prefix.length);
3394
+ return !remainder.includes("/") || remainder === "/";
3395
+ }
3396
+ if (grantedPath.endsWith("/")) {
3397
+ return requestedPath.startsWith(grantedPath);
3398
+ }
3399
+ return grantedPath === requestedPath;
3400
+ }
2685
3401
  /**
2686
3402
  * Issue a delegation via the legacy wallet-signed SIWE path for a single
2687
3403
  * {@link PermissionEntry}. Shares the implementation with the public
@@ -2738,7 +3454,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2738
3454
  );
2739
3455
  return result.delegation;
2740
3456
  } catch (err) {
2741
- if (err instanceof import_sdk_core5.PermissionNotInManifestError) {
3457
+ if (err instanceof import_sdk_core6.PermissionNotInManifestError) {
2742
3458
  } else {
2743
3459
  throw err;
2744
3460
  }
@@ -2795,7 +3511,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2795
3511
  ...prepared,
2796
3512
  signature
2797
3513
  });
2798
- const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
3514
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2799
3515
  this.config.host,
2800
3516
  delegationSession.delegationHeader
2801
3517
  );
@@ -2817,7 +3533,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2817
3533
  };
2818
3534
  const hasKvActions = params.actions.some((a) => a.startsWith("tinycloud.kv/"));
2819
3535
  if (hasKvActions && params.includePublicSpace !== false) {
2820
- const publicSpaceId = (0, import_sdk_core5.makePublicSpaceId)(
3536
+ const publicSpaceId = (0, import_sdk_core6.makePublicSpaceId)(
2821
3537
  this.wasmBindings.ensureEip55(session.address),
2822
3538
  session.chainId
2823
3539
  );
@@ -2840,7 +3556,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2840
3556
  ...publicPrepared,
2841
3557
  signature: publicSignature
2842
3558
  });
2843
- const publicActivateResult = await (0, import_sdk_core5.activateSessionWithHost)(
3559
+ const publicActivateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2844
3560
  this.config.host,
2845
3561
  publicSession.delegationHeader
2846
3562
  );
@@ -2939,7 +3655,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2939
3655
  ...prepared,
2940
3656
  signature
2941
3657
  });
2942
- const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
3658
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2943
3659
  targetHost,
2944
3660
  invokerSession.delegationHeader
2945
3661
  );
@@ -3028,7 +3744,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3028
3744
  ...prepared,
3029
3745
  signature
3030
3746
  });
3031
- const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
3747
+ const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
3032
3748
  targetHost,
3033
3749
  subDelegationSession.delegationHeader
3034
3750
  );
@@ -3064,7 +3780,7 @@ _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS = 6e4;
3064
3780
  var TinyCloudNode = _TinyCloudNode;
3065
3781
 
3066
3782
  // src/core.ts
3067
- var import_sdk_core8 = require("@tinycloud/sdk-core");
3783
+ var import_sdk_core9 = require("@tinycloud/sdk-core");
3068
3784
 
3069
3785
  // src/delegation.ts
3070
3786
  function serializeDelegation(delegation) {
@@ -3083,7 +3799,6 @@ function deserializeDelegation(data) {
3083
3799
  }
3084
3800
 
3085
3801
  // src/core.ts
3086
- var import_sdk_core9 = require("@tinycloud/sdk-core");
3087
3802
  var import_sdk_core10 = require("@tinycloud/sdk-core");
3088
3803
  var import_sdk_core11 = require("@tinycloud/sdk-core");
3089
3804
  var import_sdk_core12 = require("@tinycloud/sdk-core");
@@ -3092,6 +3807,7 @@ var import_sdk_core14 = require("@tinycloud/sdk-core");
3092
3807
  var import_sdk_core15 = require("@tinycloud/sdk-core");
3093
3808
  var import_sdk_core16 = require("@tinycloud/sdk-core");
3094
3809
  var import_sdk_core17 = require("@tinycloud/sdk-core");
3810
+ var import_sdk_core18 = require("@tinycloud/sdk-core");
3095
3811
  // Annotate the CommonJS export names for ESM import in node:
3096
3812
  0 && (module.exports = {
3097
3813
  ACCOUNT_REGISTRY_PATH,
@@ -3117,8 +3833,10 @@ var import_sdk_core17 = require("@tinycloud/sdk-core");
3117
3833
  PermissionNotInManifestError,
3118
3834
  PrefixedKVService,
3119
3835
  ProtocolMismatchError,
3836
+ SECRET_NAME_RE,
3120
3837
  SQLAction,
3121
3838
  SQLService,
3839
+ SecretsService,
3122
3840
  ServiceContext,
3123
3841
  SessionExpiredError,
3124
3842
  SharingService,
@@ -3129,11 +3847,13 @@ var import_sdk_core17 = require("@tinycloud/sdk-core");
3129
3847
  TinyCloud,
3130
3848
  TinyCloudNode,
3131
3849
  UnsupportedFeatureError,
3850
+ VAULT_PERMISSION_SERVICE,
3132
3851
  VaultHeaders,
3133
3852
  VaultPublicSpaceKVActions,
3134
3853
  VersionCheckError,
3135
3854
  WasmKeyProvider,
3136
3855
  buildSpaceUri,
3856
+ canonicalizeSecretScope,
3137
3857
  checkNodeInfo,
3138
3858
  composeManifestRequest,
3139
3859
  createCapabilityKeyRegistry,
@@ -3145,12 +3865,15 @@ var import_sdk_core17 = require("@tinycloud/sdk-core");
3145
3865
  defaultSpaceCreationHandler,
3146
3866
  deserializeDelegation,
3147
3867
  expandActionShortNames,
3868
+ expandPermissionEntries,
3869
+ expandPermissionEntry,
3148
3870
  isCapabilitySubset,
3149
3871
  loadManifest,
3150
3872
  makePublicSpaceId,
3151
3873
  parseExpiry,
3152
3874
  parseSpaceUri,
3153
3875
  resolveManifest,
3876
+ resolveSecretPath,
3154
3877
  resourceCapabilitiesToSpaceAbilitiesMap,
3155
3878
  serializeDelegation,
3156
3879
  validateManifest