@tinycloud/node-sdk 2.2.0-beta.1 → 2.2.0-beta.11

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/index.cjs CHANGED
@@ -17025,69 +17025,76 @@ var require_utils2 = __commonJS({
17025
17025
  // src/index.ts
17026
17026
  var index_exports = {};
17027
17027
  __export(index_exports, {
17028
- ACCOUNT_REGISTRY_PATH: () => import_sdk_core8.ACCOUNT_REGISTRY_PATH,
17029
- ACCOUNT_REGISTRY_SPACE: () => import_sdk_core8.ACCOUNT_REGISTRY_SPACE,
17030
- AutoApproveSpaceCreationHandler: () => import_sdk_core7.AutoApproveSpaceCreationHandler,
17031
- CapabilityKeyRegistry: () => import_sdk_core15.CapabilityKeyRegistry,
17032
- CapabilityKeyRegistryErrorCodes: () => import_sdk_core15.CapabilityKeyRegistryErrorCodes,
17033
- DEFAULT_MANIFEST_SPACE: () => import_sdk_core8.DEFAULT_MANIFEST_SPACE,
17034
- DEFAULT_MANIFEST_VERSION: () => import_sdk_core8.DEFAULT_MANIFEST_VERSION,
17035
- DataVaultService: () => import_sdk_core12.DataVaultService,
17036
- DatabaseHandle: () => import_sdk_core10.DatabaseHandle,
17028
+ ACCOUNT_REGISTRY_PATH: () => import_sdk_core9.ACCOUNT_REGISTRY_PATH,
17029
+ ACCOUNT_REGISTRY_SPACE: () => import_sdk_core9.ACCOUNT_REGISTRY_SPACE,
17030
+ AutoApproveSpaceCreationHandler: () => import_sdk_core8.AutoApproveSpaceCreationHandler,
17031
+ CapabilityKeyRegistry: () => import_sdk_core16.CapabilityKeyRegistry,
17032
+ CapabilityKeyRegistryErrorCodes: () => import_sdk_core16.CapabilityKeyRegistryErrorCodes,
17033
+ DEFAULT_MANIFEST_SPACE: () => import_sdk_core9.DEFAULT_MANIFEST_SPACE,
17034
+ DEFAULT_MANIFEST_VERSION: () => import_sdk_core9.DEFAULT_MANIFEST_VERSION,
17035
+ DataVaultService: () => import_sdk_core13.DataVaultService,
17036
+ DatabaseHandle: () => import_sdk_core11.DatabaseHandle,
17037
17037
  DelegatedAccess: () => DelegatedAccess,
17038
- DelegationErrorCodes: () => import_sdk_core14.DelegationErrorCodes,
17039
- DelegationManager: () => import_sdk_core14.DelegationManager,
17040
- DuckDbAction: () => import_sdk_core11.DuckDbAction,
17041
- DuckDbDatabaseHandle: () => import_sdk_core11.DuckDbDatabaseHandle,
17042
- DuckDbService: () => import_sdk_core11.DuckDbService,
17038
+ DelegationErrorCodes: () => import_sdk_core15.DelegationErrorCodes,
17039
+ DelegationManager: () => import_sdk_core15.DelegationManager,
17040
+ DuckDbAction: () => import_sdk_core12.DuckDbAction,
17041
+ DuckDbDatabaseHandle: () => import_sdk_core12.DuckDbDatabaseHandle,
17042
+ DuckDbService: () => import_sdk_core12.DuckDbService,
17043
17043
  FileSessionStorage: () => FileSessionStorage,
17044
- HooksService: () => import_sdk_core13.HooksService,
17045
- KVService: () => import_sdk_core9.KVService,
17046
- ManifestValidationError: () => import_sdk_core8.ManifestValidationError,
17044
+ HooksService: () => import_sdk_core14.HooksService,
17045
+ KVService: () => import_sdk_core10.KVService,
17046
+ ManifestValidationError: () => import_sdk_core9.ManifestValidationError,
17047
17047
  MemorySessionStorage: () => MemorySessionStorage,
17048
17048
  NodeUserAuthorization: () => NodeUserAuthorization,
17049
17049
  NodeWasmBindings: () => NodeWasmBindings,
17050
- PermissionNotInManifestError: () => import_sdk_core8.PermissionNotInManifestError,
17051
- PrefixedKVService: () => import_sdk_core9.PrefixedKVService,
17050
+ PermissionNotInManifestError: () => import_sdk_core9.PermissionNotInManifestError,
17051
+ PrefixedKVService: () => import_sdk_core10.PrefixedKVService,
17052
17052
  PrivateKeySigner: () => PrivateKeySigner,
17053
- ProtocolMismatchError: () => import_sdk_core17.ProtocolMismatchError,
17054
- SQLAction: () => import_sdk_core10.SQLAction,
17055
- SQLService: () => import_sdk_core10.SQLService,
17056
- ServiceContext: () => import_sdk_core18.ServiceContext,
17057
- SessionExpiredError: () => import_sdk_core8.SessionExpiredError,
17058
- SharingService: () => import_sdk_core14.SharingService,
17059
- SilentNotificationHandler: () => import_sdk_core7.SilentNotificationHandler,
17060
- Space: () => import_sdk_core16.Space,
17061
- SpaceErrorCodes: () => import_sdk_core16.SpaceErrorCodes,
17062
- SpaceService: () => import_sdk_core16.SpaceService,
17063
- TinyCloud: () => import_sdk_core6.TinyCloud,
17053
+ ProtocolMismatchError: () => import_sdk_core18.ProtocolMismatchError,
17054
+ SECRET_NAME_RE: () => import_sdk_core13.SECRET_NAME_RE,
17055
+ SQLAction: () => import_sdk_core11.SQLAction,
17056
+ SQLService: () => import_sdk_core11.SQLService,
17057
+ SecretsService: () => import_sdk_core13.SecretsService,
17058
+ ServiceContext: () => import_sdk_core19.ServiceContext,
17059
+ SessionExpiredError: () => import_sdk_core9.SessionExpiredError,
17060
+ SharingService: () => import_sdk_core15.SharingService,
17061
+ SilentNotificationHandler: () => import_sdk_core8.SilentNotificationHandler,
17062
+ Space: () => import_sdk_core17.Space,
17063
+ SpaceErrorCodes: () => import_sdk_core17.SpaceErrorCodes,
17064
+ SpaceService: () => import_sdk_core17.SpaceService,
17065
+ TinyCloud: () => import_sdk_core7.TinyCloud,
17064
17066
  TinyCloudNode: () => TinyCloudNode,
17065
- UnsupportedFeatureError: () => import_sdk_core17.UnsupportedFeatureError,
17066
- VaultHeaders: () => import_sdk_core12.VaultHeaders,
17067
- VaultPublicSpaceKVActions: () => import_sdk_core12.VaultPublicSpaceKVActions,
17068
- VersionCheckError: () => import_sdk_core17.VersionCheckError,
17067
+ UnsupportedFeatureError: () => import_sdk_core18.UnsupportedFeatureError,
17068
+ VAULT_PERMISSION_SERVICE: () => import_sdk_core9.VAULT_PERMISSION_SERVICE,
17069
+ VaultHeaders: () => import_sdk_core13.VaultHeaders,
17070
+ VaultPublicSpaceKVActions: () => import_sdk_core13.VaultPublicSpaceKVActions,
17071
+ VersionCheckError: () => import_sdk_core18.VersionCheckError,
17069
17072
  WasmKeyProvider: () => WasmKeyProvider,
17070
- buildSpaceUri: () => import_sdk_core16.buildSpaceUri,
17071
- checkNodeInfo: () => import_sdk_core17.checkNodeInfo,
17072
- composeManifestRequest: () => import_sdk_core8.composeManifestRequest,
17073
- createCapabilityKeyRegistry: () => import_sdk_core15.createCapabilityKeyRegistry,
17074
- createSharingService: () => import_sdk_core14.createSharingService,
17075
- createSpaceService: () => import_sdk_core16.createSpaceService,
17076
- createVaultCrypto: () => import_sdk_core12.createVaultCrypto,
17073
+ buildSpaceUri: () => import_sdk_core17.buildSpaceUri,
17074
+ canonicalizeSecretScope: () => import_sdk_core13.canonicalizeSecretScope,
17075
+ checkNodeInfo: () => import_sdk_core18.checkNodeInfo,
17076
+ composeManifestRequest: () => import_sdk_core9.composeManifestRequest,
17077
+ createCapabilityKeyRegistry: () => import_sdk_core16.createCapabilityKeyRegistry,
17078
+ createSharingService: () => import_sdk_core15.createSharingService,
17079
+ createSpaceService: () => import_sdk_core17.createSpaceService,
17080
+ createVaultCrypto: () => import_sdk_core13.createVaultCrypto,
17077
17081
  createWasmKeyProvider: () => createWasmKeyProvider,
17078
17082
  defaultSignStrategy: () => defaultSignStrategy,
17079
- defaultSpaceCreationHandler: () => import_sdk_core7.defaultSpaceCreationHandler,
17083
+ defaultSpaceCreationHandler: () => import_sdk_core8.defaultSpaceCreationHandler,
17080
17084
  deserializeDelegation: () => deserializeDelegation,
17081
- expandActionShortNames: () => import_sdk_core8.expandActionShortNames,
17082
- isCapabilitySubset: () => import_sdk_core8.isCapabilitySubset,
17083
- loadManifest: () => import_sdk_core8.loadManifest,
17084
- makePublicSpaceId: () => import_sdk_core16.makePublicSpaceId,
17085
- parseExpiry: () => import_sdk_core8.parseExpiry,
17086
- parseSpaceUri: () => import_sdk_core16.parseSpaceUri,
17087
- resolveManifest: () => import_sdk_core8.resolveManifest,
17088
- resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core8.resourceCapabilitiesToSpaceAbilitiesMap,
17085
+ expandActionShortNames: () => import_sdk_core9.expandActionShortNames,
17086
+ expandPermissionEntries: () => import_sdk_core9.expandPermissionEntries,
17087
+ expandPermissionEntry: () => import_sdk_core9.expandPermissionEntry,
17088
+ isCapabilitySubset: () => import_sdk_core9.isCapabilitySubset,
17089
+ loadManifest: () => import_sdk_core9.loadManifest,
17090
+ makePublicSpaceId: () => import_sdk_core17.makePublicSpaceId,
17091
+ parseExpiry: () => import_sdk_core9.parseExpiry,
17092
+ parseSpaceUri: () => import_sdk_core17.parseSpaceUri,
17093
+ resolveManifest: () => import_sdk_core9.resolveManifest,
17094
+ resolveSecretPath: () => import_sdk_core13.resolveSecretPath,
17095
+ resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core9.resourceCapabilitiesToSpaceAbilitiesMap,
17089
17096
  serializeDelegation: () => serializeDelegation,
17090
- validateManifest: () => import_sdk_core8.validateManifest
17097
+ validateManifest: () => import_sdk_core9.validateManifest
17091
17098
  });
17092
17099
  module.exports = __toCommonJS(index_exports);
17093
17100
 
@@ -17191,7 +17198,7 @@ var PrivateKeySigner = class {
17191
17198
  };
17192
17199
 
17193
17200
  // src/TinyCloudNode.ts
17194
- var import_sdk_core4 = require("@tinycloud/sdk-core");
17201
+ var import_sdk_core5 = require("@tinycloud/sdk-core");
17195
17202
 
17196
17203
  // src/authorization/NodeUserAuthorization.ts
17197
17204
  var import_sdk_core = require("@tinycloud/sdk-core");
@@ -17324,12 +17331,12 @@ var NodeUserAuthorization = class {
17324
17331
  ]
17325
17332
  }
17326
17333
  };
17327
- this.sessionExpirationMs = config.sessionExpirationMs ?? 60 * 60 * 1e3;
17334
+ this.sessionExpirationMs = config.sessionExpirationMs ?? import_sdk_core.EXPIRY.SESSION_MS;
17328
17335
  this.autoCreateSpace = config.autoCreateSpace ?? false;
17329
17336
  this.spaceCreationHandler = config.spaceCreationHandler;
17330
- this.tinycloudHosts = config.tinycloudHosts ?? [
17331
- "https://node.tinycloud.xyz"
17332
- ];
17337
+ this.tinycloudHosts = config.tinycloudHosts;
17338
+ this.tinycloudRegistryUrl = config.tinycloudRegistryUrl;
17339
+ this.tinycloudFallbackHosts = config.tinycloudFallbackHosts;
17333
17340
  this.enablePublicSpace = config.enablePublicSpace ?? true;
17334
17341
  this.nonce = config.nonce;
17335
17342
  this.siweConfig = config.siweConfig;
@@ -17350,6 +17357,9 @@ var NodeUserAuthorization = class {
17350
17357
  get capabilityRequest() {
17351
17358
  return this.getCapabilityRequest();
17352
17359
  }
17360
+ get hosts() {
17361
+ return this.tinycloudHosts ? [...this.tinycloudHosts] : [];
17362
+ }
17353
17363
  /**
17354
17364
  * Install or replace the stored manifest. Takes effect on the next
17355
17365
  * `signIn()` call — the current session (if any) is not touched.
@@ -17374,6 +17384,26 @@ var NodeUserAuthorization = class {
17374
17384
  get tinyCloudSession() {
17375
17385
  return this._tinyCloudSession;
17376
17386
  }
17387
+ async resolveTinyCloudHostsForSignIn(address, chainId) {
17388
+ if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
17389
+ return;
17390
+ }
17391
+ const subject = `did:pkh:eip155:${chainId}:${address}`;
17392
+ const resolved = await (0, import_sdk_core.resolveTinyCloudHosts)(subject, {
17393
+ registryUrl: this.tinycloudRegistryUrl,
17394
+ fallbackHosts: this.tinycloudFallbackHosts
17395
+ });
17396
+ this.tinycloudHosts = resolved.hosts;
17397
+ }
17398
+ requireTinyCloudHosts() {
17399
+ if (!this.tinycloudHosts || this.tinycloudHosts.length === 0) {
17400
+ throw new Error("TinyCloud hosts have not been resolved. Call signIn() first.");
17401
+ }
17402
+ return this.tinycloudHosts;
17403
+ }
17404
+ get primaryTinyCloudHost() {
17405
+ return this.requireTinyCloudHosts()[0];
17406
+ }
17377
17407
  get nodeFeatures() {
17378
17408
  return this._nodeFeatures;
17379
17409
  }
@@ -17505,7 +17535,7 @@ var NodeUserAuthorization = class {
17505
17535
  if (!this._tinyCloudSession || !this._address || !this._chainId) {
17506
17536
  throw new Error("Must be signed in to host space");
17507
17537
  }
17508
- const host = this.tinycloudHosts[0];
17538
+ const host = this.primaryTinyCloudHost;
17509
17539
  const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
17510
17540
  const peerId = await (0, import_sdk_core.fetchPeerId)(host, spaceId);
17511
17541
  const siwe = this.wasm.generateHostSIWEMessage({
@@ -17547,7 +17577,7 @@ var NodeUserAuthorization = class {
17547
17577
  if (!this._tinyCloudSession) {
17548
17578
  throw new Error("Must be signed in to ensure space exists");
17549
17579
  }
17550
- const host = this.tinycloudHosts[0];
17580
+ const host = this.primaryTinyCloudHost;
17551
17581
  const primarySpaceId = this._tinyCloudSession.spaceId;
17552
17582
  const result = await (0, import_sdk_core.activateSessionWithHost)(
17553
17583
  host,
@@ -17656,6 +17686,7 @@ var NodeUserAuthorization = class {
17656
17686
  this._chainId = await this.signer.getChainId();
17657
17687
  const address = this.wasm.ensureEip55(this._address);
17658
17688
  const chainId = this._chainId;
17689
+ await this.resolveTinyCloudHostsForSignIn(address, chainId);
17659
17690
  const keyId = `session-${Date.now()}`;
17660
17691
  this.sessionManager.renameSessionKeyId("default", keyId);
17661
17692
  const jwkString = this.sessionManager.jwk(keyId);
@@ -17734,7 +17765,7 @@ var NodeUserAuthorization = class {
17734
17765
  this._address = address;
17735
17766
  this._chainId = chainId;
17736
17767
  const nodeInfo = await (0, import_sdk_core.checkNodeInfo)(
17737
- this.tinycloudHosts[0],
17768
+ this.primaryTinyCloudHost,
17738
17769
  this.wasm.protocolVersion()
17739
17770
  );
17740
17771
  this._nodeFeatures = nodeInfo.features;
@@ -17850,6 +17881,7 @@ var NodeUserAuthorization = class {
17850
17881
  });
17851
17882
  const address = this.wasm.ensureEip55(await this.signer.getAddress());
17852
17883
  const chainId = await this.signer.getChainId();
17884
+ await this.resolveTinyCloudHostsForSignIn(address, chainId);
17853
17885
  const clientSession = {
17854
17886
  address,
17855
17887
  walletAddress: address,
@@ -17899,7 +17931,7 @@ var NodeUserAuthorization = class {
17899
17931
  this._address = address;
17900
17932
  this._chainId = chainId;
17901
17933
  const nodeInfo = await (0, import_sdk_core.checkNodeInfo)(
17902
- this.tinycloudHosts[0],
17934
+ this.primaryTinyCloudHost,
17903
17935
  this.wasm.protocolVersion()
17904
17936
  );
17905
17937
  this._nodeFeatures = nodeInfo.features;
@@ -18057,6 +18089,24 @@ var DelegatedAccess = class {
18057
18089
  get hooks() {
18058
18090
  return this._hooks;
18059
18091
  }
18092
+ /**
18093
+ * Export the handles needed to rehydrate this activated delegation via
18094
+ * `TinyCloudNode.restoreSession(...)` in another process or after a
18095
+ * restart.
18096
+ *
18097
+ * See `RestorableSession` for lifetime caveats.
18098
+ */
18099
+ get restorable() {
18100
+ return {
18101
+ delegationHeader: this.session.delegationHeader,
18102
+ delegationCid: this.session.delegationCid,
18103
+ spaceId: this.session.spaceId,
18104
+ jwk: this.session.jwk,
18105
+ verificationMethod: this.session.verificationMethod,
18106
+ address: this.session.address,
18107
+ chainId: this.session.chainId
18108
+ };
18109
+ }
18060
18110
  };
18061
18111
 
18062
18112
  // src/keys/WasmKeyProvider.ts
@@ -18166,9 +18216,10 @@ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
18166
18216
  }
18167
18217
  return entries;
18168
18218
  }
18219
+ var DEFAULT_DELEGATION_EXPIRY_MS = import_sdk_core3.EXPIRY.SESSION_MS;
18169
18220
  function resolveExpiryMs(expiry) {
18170
18221
  if (expiry === void 0) {
18171
- return 60 * 60 * 1e3;
18222
+ return DEFAULT_DELEGATION_EXPIRY_MS;
18172
18223
  }
18173
18224
  if (typeof expiry === "number") {
18174
18225
  if (!Number.isFinite(expiry) || expiry <= 0) {
@@ -18194,8 +18245,151 @@ function extractSiweExpiration(siwe) {
18194
18245
  return d;
18195
18246
  }
18196
18247
 
18248
+ // src/NodeSecretsService.ts
18249
+ var import_sdk_core4 = require("@tinycloud/sdk-core");
18250
+ var SECRETS_SPACE = "secrets";
18251
+ function ok() {
18252
+ return { ok: true, data: void 0 };
18253
+ }
18254
+ function secretsError(code, message, cause) {
18255
+ return {
18256
+ ok: false,
18257
+ error: {
18258
+ code,
18259
+ service: "secrets",
18260
+ message,
18261
+ ...cause ? { cause } : {}
18262
+ }
18263
+ };
18264
+ }
18265
+ function displayActionUrn(action) {
18266
+ return action === "put" ? "tinycloud.vault/write" : "tinycloud.vault/delete";
18267
+ }
18268
+ function kvActionUrn(action) {
18269
+ return `tinycloud.kv/${action}`;
18270
+ }
18271
+ function vaultMutationAction(action) {
18272
+ return action === "put" ? "write" : "delete";
18273
+ }
18274
+ function secretPermissionEntries(name, options, action) {
18275
+ const secretPath = (0, import_sdk_core4.resolveSecretPath)(name, options);
18276
+ return [
18277
+ {
18278
+ service: "tinycloud.vault",
18279
+ space: SECRETS_SPACE,
18280
+ path: secretPath.vaultKey,
18281
+ actions: [vaultMutationAction(action)],
18282
+ skipPrefix: true
18283
+ }
18284
+ ];
18285
+ }
18286
+ function isSecretsSpace(space) {
18287
+ return space === SECRETS_SPACE || space.endsWith(`:${SECRETS_SPACE}`);
18288
+ }
18289
+ var NodeSecretsService = class {
18290
+ constructor(config) {
18291
+ this.config = config;
18292
+ this.shouldRestoreUnlock = false;
18293
+ }
18294
+ get vault() {
18295
+ return this.service.vault;
18296
+ }
18297
+ get isUnlocked() {
18298
+ return this.service.isUnlocked;
18299
+ }
18300
+ async unlock(signer) {
18301
+ const effectiveSigner = signer ?? this.config.getUnlockSigner?.();
18302
+ if (effectiveSigner !== void 0) {
18303
+ this.unlockSigner = effectiveSigner;
18304
+ }
18305
+ const result = await this.service.unlock(effectiveSigner);
18306
+ if (result.ok) {
18307
+ this.shouldRestoreUnlock = true;
18308
+ }
18309
+ return result;
18310
+ }
18311
+ lock() {
18312
+ this.shouldRestoreUnlock = false;
18313
+ this.service.lock();
18314
+ }
18315
+ get(name, options) {
18316
+ return options === void 0 ? this.service.get(name) : this.service.get(name, options);
18317
+ }
18318
+ async put(name, value, options) {
18319
+ const permission = await this.ensureMutationPermission(name, options, "put");
18320
+ if (!permission.ok) return permission;
18321
+ return options === void 0 ? this.service.put(name, value) : this.service.put(name, value, options);
18322
+ }
18323
+ async delete(name, options) {
18324
+ const permission = await this.ensureMutationPermission(name, options, "del");
18325
+ if (!permission.ok) return permission;
18326
+ return options === void 0 ? this.service.delete(name) : this.service.delete(name, options);
18327
+ }
18328
+ list(options) {
18329
+ return options === void 0 ? this.service.list() : this.service.list(options);
18330
+ }
18331
+ get service() {
18332
+ return this.config.getService();
18333
+ }
18334
+ async ensureMutationPermission(name, options, action) {
18335
+ let permissionEntries;
18336
+ try {
18337
+ permissionEntries = secretPermissionEntries(name, options, action);
18338
+ } catch (error) {
18339
+ return secretsError(
18340
+ import_sdk_core4.ErrorCodes.INVALID_INPUT,
18341
+ error instanceof Error ? error.message : String(error),
18342
+ error instanceof Error ? error : void 0
18343
+ );
18344
+ }
18345
+ if (this.hasMutationPermission(name, options, action)) {
18346
+ return ok();
18347
+ }
18348
+ if (!this.config.canEscalate()) {
18349
+ return secretsError(
18350
+ import_sdk_core4.ErrorCodes.PERMISSION_DENIED,
18351
+ `Cannot autosign ${displayActionUrn(action)} for ${name}; TinyCloudNode needs wallet mode with a signer or privateKey.`
18352
+ );
18353
+ }
18354
+ try {
18355
+ await this.config.grantPermissions(permissionEntries);
18356
+ return this.restoreUnlockAfterEscalation();
18357
+ } catch (error) {
18358
+ return secretsError(
18359
+ import_sdk_core4.ErrorCodes.PERMISSION_DENIED,
18360
+ error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${name} failed.`,
18361
+ error instanceof Error ? error : void 0
18362
+ );
18363
+ }
18364
+ }
18365
+ async restoreUnlockAfterEscalation() {
18366
+ if (!this.shouldRestoreUnlock) {
18367
+ return ok();
18368
+ }
18369
+ return this.service.unlock(this.unlockSigner);
18370
+ }
18371
+ hasMutationPermission(name, options, action) {
18372
+ const manifest = this.config.getManifest();
18373
+ if (manifest === void 0) {
18374
+ return false;
18375
+ }
18376
+ const manifests = Array.isArray(manifest) ? manifest : [manifest];
18377
+ const requiredAction = kvActionUrn(action);
18378
+ const secretPath = (0, import_sdk_core4.resolveSecretPath)(name, options);
18379
+ return manifests.some((entry) => {
18380
+ const resolved = (0, import_sdk_core4.resolveManifest)(entry);
18381
+ return ["keys", "vault"].every(
18382
+ (base2) => resolved.resources.some(
18383
+ (resource) => resource.service === "tinycloud.kv" && isSecretsSpace(resource.space) && resource.path === secretPath.permissionPaths[base2] && resource.actions.includes(requiredAction)
18384
+ )
18385
+ );
18386
+ });
18387
+ }
18388
+ };
18389
+
18197
18390
  // src/TinyCloudNode.ts
18198
18391
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
18392
+ var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core5.EXPIRY.SESSION_MS;
18199
18393
  var _TinyCloudNode = class _TinyCloudNode {
18200
18394
  /**
18201
18395
  * Create a new TinyCloudNode instance.
@@ -18225,6 +18419,31 @@ var _TinyCloudNode = class _TinyCloudNode {
18225
18419
  this.auth = null;
18226
18420
  this.tc = null;
18227
18421
  this._chainId = 1;
18422
+ this.runtimePermissionGrants = [];
18423
+ this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
18424
+ return this.wasmBindings.invoke(
18425
+ this.selectInvocationSession(session, service, path, action),
18426
+ service,
18427
+ path,
18428
+ action,
18429
+ facts
18430
+ );
18431
+ };
18432
+ this.invokeAnyWithRuntimePermissions = (session, entries, facts) => {
18433
+ if (!this.wasmBindings.invokeAny) {
18434
+ throw new Error("WASM binding does not support invokeAny");
18435
+ }
18436
+ const grant = this.findGrantForOperations(
18437
+ entries.map((entry) => ({
18438
+ spaceId: entry.spaceId,
18439
+ service: this.invocationServiceName(entry.service),
18440
+ path: entry.path,
18441
+ action: entry.action
18442
+ }))
18443
+ );
18444
+ return this.wasmBindings.invokeAny(grant?.session ?? session, entries, facts);
18445
+ };
18446
+ this.explicitHost = config.host;
18228
18447
  this.config = {
18229
18448
  ...config,
18230
18449
  host: config.host ?? DEFAULT_HOST
@@ -18251,23 +18470,23 @@ var _TinyCloudNode = class _TinyCloudNode {
18251
18470
  throw new Error("Failed to get session key JWK");
18252
18471
  }
18253
18472
  this.sessionKeyJwk = JSON.parse(jwkStr);
18254
- this._capabilityRegistry = new import_sdk_core4.CapabilityKeyRegistry();
18473
+ this._capabilityRegistry = new import_sdk_core5.CapabilityKeyRegistry();
18255
18474
  this._keyProvider = new WasmKeyProvider({
18256
18475
  sessionManager: this.sessionManager
18257
18476
  });
18258
- this.notificationHandler = config.notificationHandler ?? new import_sdk_core4.SilentNotificationHandler();
18259
- this._sharingService = new import_sdk_core4.SharingService({
18477
+ this.notificationHandler = config.notificationHandler ?? new import_sdk_core5.SilentNotificationHandler();
18478
+ this._sharingService = new import_sdk_core5.SharingService({
18260
18479
  hosts: [this.config.host],
18261
18480
  // session: undefined - not needed for receive()
18262
- invoke: this.wasmBindings.invoke,
18481
+ invoke: this.invokeWithRuntimePermissions,
18263
18482
  fetch: globalThis.fetch.bind(globalThis),
18264
18483
  keyProvider: this._keyProvider,
18265
18484
  registry: this._capabilityRegistry,
18266
18485
  // delegationManager: undefined - not needed for receive()
18267
18486
  createKVService: (config2) => {
18268
18487
  const prefix = config2.pathPrefix?.replace(/\/$/, "");
18269
- const kvService = new import_sdk_core4.KVService({ prefix });
18270
- const kvContext = new import_sdk_core4.ServiceContext({
18488
+ const kvService = new import_sdk_core5.KVService({ prefix });
18489
+ const kvContext = new import_sdk_core5.ServiceContext({
18271
18490
  invoke: config2.invoke,
18272
18491
  fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
18273
18492
  hosts: config2.hosts
@@ -18306,7 +18525,6 @@ var _TinyCloudNode = class _TinyCloudNode {
18306
18525
  * @internal
18307
18526
  */
18308
18527
  setupAuth(config) {
18309
- const host = this.config.host;
18310
18528
  this.auth = new NodeUserAuthorization({
18311
18529
  signer: this.signer,
18312
18530
  signStrategy: { type: "auto-sign" },
@@ -18314,8 +18532,10 @@ var _TinyCloudNode = class _TinyCloudNode {
18314
18532
  sessionStorage: config.sessionStorage ?? new MemorySessionStorage(),
18315
18533
  domain: this.siweDomain,
18316
18534
  spacePrefix: config.prefix,
18317
- sessionExpirationMs: config.sessionExpirationMs ?? 60 * 60 * 1e3,
18318
- tinycloudHosts: [host],
18535
+ sessionExpirationMs: config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
18536
+ tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
18537
+ tinycloudRegistryUrl: config.tinycloudRegistryUrl,
18538
+ tinycloudFallbackHosts: config.tinycloudFallbackHosts,
18319
18539
  autoCreateSpace: config.autoCreateSpace,
18320
18540
  enablePublicSpace: config.enablePublicSpace ?? true,
18321
18541
  spaceCreationHandler: config.spaceCreationHandler,
@@ -18325,10 +18545,16 @@ var _TinyCloudNode = class _TinyCloudNode {
18325
18545
  capabilityRequest: config.capabilityRequest,
18326
18546
  includeAccountRegistryPermissions: config.includeAccountRegistryPermissions
18327
18547
  });
18328
- this.tc = new import_sdk_core4.TinyCloud(this.auth, {
18329
- invokeAny: this.wasmBindings.invokeAny
18548
+ this.tc = new import_sdk_core5.TinyCloud(this.auth, {
18549
+ invokeAny: this.invokeAnyWithRuntimePermissions
18330
18550
  });
18331
18551
  }
18552
+ syncResolvedHostFromAuth() {
18553
+ const host = this.auth?.hosts[0];
18554
+ if (host) {
18555
+ this.config.host = host;
18556
+ }
18557
+ }
18332
18558
  /**
18333
18559
  * Install or replace the manifest that drives the SIWE recap at
18334
18560
  * sign-in. Takes effect on the next `signIn()` call — the current
@@ -18366,6 +18592,10 @@ var _TinyCloudNode = class _TinyCloudNode {
18366
18592
  get capabilityRequest() {
18367
18593
  return this.auth?.capabilityRequest;
18368
18594
  }
18595
+ get hosts() {
18596
+ const authHosts = this.auth?.hosts ?? [];
18597
+ return authHosts.length > 0 ? authHosts : [this.config.host];
18598
+ }
18369
18599
  /**
18370
18600
  * Get the primary identity DID for this user.
18371
18601
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -18436,8 +18666,14 @@ var _TinyCloudNode = class _TinyCloudNode {
18436
18666
  this._sql = void 0;
18437
18667
  this._duckdb = void 0;
18438
18668
  this._hooks = void 0;
18669
+ this._vault = void 0;
18670
+ this._baseSecrets = void 0;
18671
+ this._secrets = void 0;
18672
+ this._spaceService = void 0;
18439
18673
  this._serviceContext = void 0;
18674
+ this.runtimePermissionGrants = [];
18440
18675
  await this.tc.signIn(options);
18676
+ this.syncResolvedHostFromAuth();
18441
18677
  this.initializeServices();
18442
18678
  await this.writeManifestRegistryRecords();
18443
18679
  this.notificationHandler.success("Successfully signed in");
@@ -18456,8 +18692,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18456
18692
  if (!this.auth || !this.signer) {
18457
18693
  throw new Error("Manifest registry write requires wallet mode");
18458
18694
  }
18459
- const accountSpaceId = this.ownedSpaceId(import_sdk_core4.ACCOUNT_REGISTRY_SPACE);
18460
- await this.auth.hostOwnedSpace(accountSpaceId);
18695
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core5.ACCOUNT_REGISTRY_SPACE);
18696
+ await this.ensureOwnedSpaceHosted(accountSpaceId);
18461
18697
  const accountKV = this.spaces.get(accountSpaceId).kv;
18462
18698
  for (const record of request.registryRecords) {
18463
18699
  const result = await accountKV.put(record.key, {
@@ -18472,6 +18708,39 @@ var _TinyCloudNode = class _TinyCloudNode {
18472
18708
  }
18473
18709
  }
18474
18710
  }
18711
+ async ensureOwnedSpaceHosted(spaceId) {
18712
+ if (!this.auth) {
18713
+ throw new Error("Owned space hosting requires wallet mode");
18714
+ }
18715
+ const session = this.auth.tinyCloudSession;
18716
+ if (!session) {
18717
+ throw new Error("Owned space hosting requires an active session");
18718
+ }
18719
+ const host = this.hosts[0] ?? this.config.host;
18720
+ if (!host) {
18721
+ throw new Error("Owned space hosting requires a TinyCloud host");
18722
+ }
18723
+ const activation = await (0, import_sdk_core5.activateSessionWithHost)(host, session.delegationHeader);
18724
+ if (activation.success && !activation.skipped?.includes(spaceId)) {
18725
+ return;
18726
+ }
18727
+ if (!activation.success && activation.status !== 404) {
18728
+ throw new Error(
18729
+ `Failed to check owned space ${spaceId}: ${activation.error ?? activation.status}`
18730
+ );
18731
+ }
18732
+ const created = await this.auth.hostOwnedSpace(spaceId);
18733
+ if (!created) {
18734
+ throw new Error(`Failed to create owned space: ${spaceId}`);
18735
+ }
18736
+ await new Promise((resolve) => setTimeout(resolve, 100));
18737
+ const retry = await (0, import_sdk_core5.activateSessionWithHost)(host, session.delegationHeader);
18738
+ if (!retry.success || retry.skipped?.includes(spaceId)) {
18739
+ throw new Error(
18740
+ `Failed to activate session after creating owned space ${spaceId}: ${retry.error ?? "space was skipped"}`
18741
+ );
18742
+ }
18743
+ }
18475
18744
  /**
18476
18745
  * Restore a previously established session from stored delegation data.
18477
18746
  *
@@ -18487,29 +18756,34 @@ var _TinyCloudNode = class _TinyCloudNode {
18487
18756
  this._sql = void 0;
18488
18757
  this._duckdb = void 0;
18489
18758
  this._hooks = void 0;
18759
+ this._vault = void 0;
18760
+ this._baseSecrets = void 0;
18761
+ this._secrets = void 0;
18762
+ this._spaceService = void 0;
18490
18763
  this._serviceContext = void 0;
18764
+ this.runtimePermissionGrants = [];
18491
18765
  if (sessionData.address) {
18492
18766
  this._address = sessionData.address;
18493
18767
  }
18494
18768
  if (sessionData.chainId) {
18495
18769
  this._chainId = sessionData.chainId;
18496
18770
  }
18497
- this._serviceContext = new import_sdk_core4.ServiceContext({
18498
- invoke: this.wasmBindings.invoke,
18499
- invokeAny: this.wasmBindings.invokeAny,
18771
+ this._serviceContext = new import_sdk_core5.ServiceContext({
18772
+ invoke: this.invokeWithRuntimePermissions,
18773
+ invokeAny: this.invokeAnyWithRuntimePermissions,
18500
18774
  fetch: globalThis.fetch.bind(globalThis),
18501
18775
  hosts: [this.config.host]
18502
18776
  });
18503
- this._kv = new import_sdk_core4.KVService({});
18777
+ this._kv = new import_sdk_core5.KVService({});
18504
18778
  this._kv.initialize(this._serviceContext);
18505
18779
  this._serviceContext.registerService("kv", this._kv);
18506
- this._sql = new import_sdk_core4.SQLService({});
18780
+ this._sql = new import_sdk_core5.SQLService({});
18507
18781
  this._sql.initialize(this._serviceContext);
18508
18782
  this._serviceContext.registerService("sql", this._sql);
18509
- this._duckdb = new import_sdk_core4.DuckDbService({});
18783
+ this._duckdb = new import_sdk_core5.DuckDbService({});
18510
18784
  this._duckdb.initialize(this._serviceContext);
18511
18785
  this._serviceContext.registerService("duckdb", this._duckdb);
18512
- this._hooks = new import_sdk_core4.HooksService({});
18786
+ this._hooks = new import_sdk_core5.HooksService({});
18513
18787
  this._hooks.initialize(this._serviceContext);
18514
18788
  this._serviceContext.registerService("hooks", this._hooks);
18515
18789
  const serviceSession = {
@@ -18520,41 +18794,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18520
18794
  jwk: sessionData.jwk
18521
18795
  };
18522
18796
  this._serviceContext.setSession(serviceSession);
18523
- const wasm = this.wasmBindings;
18524
- const vaultCrypto = (0, import_sdk_core4.createVaultCrypto)({
18525
- vault_encrypt: wasm.vault_encrypt,
18526
- vault_decrypt: wasm.vault_decrypt,
18527
- vault_derive_key: wasm.vault_derive_key,
18528
- vault_x25519_from_seed: wasm.vault_x25519_from_seed,
18529
- vault_x25519_dh: wasm.vault_x25519_dh,
18530
- vault_random_bytes: wasm.vault_random_bytes,
18531
- vault_sha256: wasm.vault_sha256
18532
- });
18533
- const self2 = this;
18534
- this._vault = new import_sdk_core4.DataVaultService({
18535
- spaceId: sessionData.spaceId,
18536
- crypto: vaultCrypto,
18537
- tc: {
18538
- kv: this._kv,
18539
- ensurePublicSpace: async () => {
18540
- try {
18541
- await self2.ensurePublicSpace();
18542
- return { ok: true, data: void 0 };
18543
- } catch (error) {
18544
- return { ok: false, error: { code: "STORAGE_ERROR", message: error instanceof Error ? error.message : String(error), service: "vault" } };
18545
- }
18546
- },
18547
- get publicKV() {
18548
- return self2._publicKV ?? self2.tc.publicKV;
18549
- },
18550
- readPublicSpace: (host, spaceId, key2) => import_sdk_core4.TinyCloud.readPublicSpace(host, spaceId, key2),
18551
- makePublicSpaceId: import_sdk_core4.TinyCloud.makePublicSpaceId,
18552
- did: this.did,
18553
- address: sessionData.address ?? this._address ?? "",
18554
- chainId: sessionData.chainId ?? this._chainId,
18555
- hosts: [this.config.host]
18556
- }
18557
- });
18797
+ this._vault = this.createVaultService(sessionData.spaceId, this._kv);
18558
18798
  this._vault.initialize(this._serviceContext);
18559
18799
  this._serviceContext.registerService("vault", this._vault);
18560
18800
  this.initializeV2Services(serviceSession);
@@ -18589,7 +18829,6 @@ var _TinyCloudNode = class _TinyCloudNode {
18589
18829
  throw new Error("Wallet already connected. Cannot connect another wallet.");
18590
18830
  }
18591
18831
  const prefix = options?.prefix ?? "default";
18592
- const host = this.config.host;
18593
18832
  if (!_TinyCloudNode.nodeDefaults) {
18594
18833
  throw new Error(
18595
18834
  "connectWallet() requires PrivateKeySigner. Use connectSigner() instead, or import from '@tinycloud/node-sdk' (not '/core') for automatic Node.js defaults."
@@ -18603,8 +18842,10 @@ var _TinyCloudNode = class _TinyCloudNode {
18603
18842
  sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
18604
18843
  domain: this.siweDomain,
18605
18844
  spacePrefix: prefix,
18606
- sessionExpirationMs: this.config.sessionExpirationMs ?? 60 * 60 * 1e3,
18607
- tinycloudHosts: [host],
18845
+ sessionExpirationMs: this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
18846
+ tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
18847
+ tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
18848
+ tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
18608
18849
  autoCreateSpace: this.config.autoCreateSpace,
18609
18850
  enablePublicSpace: this.config.enablePublicSpace ?? true,
18610
18851
  spaceCreationHandler: this.config.spaceCreationHandler,
@@ -18614,8 +18855,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18614
18855
  capabilityRequest: this.config.capabilityRequest,
18615
18856
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
18616
18857
  });
18617
- this.tc = new import_sdk_core4.TinyCloud(this.auth, {
18618
- invokeAny: this.wasmBindings.invokeAny
18858
+ this.tc = new import_sdk_core5.TinyCloud(this.auth, {
18859
+ invokeAny: this.invokeAnyWithRuntimePermissions
18619
18860
  });
18620
18861
  this.config.prefix = prefix;
18621
18862
  }
@@ -18637,7 +18878,6 @@ var _TinyCloudNode = class _TinyCloudNode {
18637
18878
  throw new Error("Signer already connected. Cannot connect another signer.");
18638
18879
  }
18639
18880
  const prefix = options?.prefix ?? "default";
18640
- const host = this.config.host;
18641
18881
  this.signer = signer;
18642
18882
  this.auth = new NodeUserAuthorization({
18643
18883
  signer: this.signer,
@@ -18646,8 +18886,10 @@ var _TinyCloudNode = class _TinyCloudNode {
18646
18886
  sessionStorage: options?.sessionStorage ?? this.config.sessionStorage ?? new MemorySessionStorage(),
18647
18887
  domain: this.siweDomain,
18648
18888
  spacePrefix: prefix,
18649
- sessionExpirationMs: this.config.sessionExpirationMs ?? 60 * 60 * 1e3,
18650
- tinycloudHosts: [host],
18889
+ sessionExpirationMs: this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS,
18890
+ tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
18891
+ tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
18892
+ tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
18651
18893
  autoCreateSpace: this.config.autoCreateSpace,
18652
18894
  enablePublicSpace: this.config.enablePublicSpace ?? true,
18653
18895
  spaceCreationHandler: this.config.spaceCreationHandler,
@@ -18657,8 +18899,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18657
18899
  capabilityRequest: this.config.capabilityRequest,
18658
18900
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
18659
18901
  });
18660
- this.tc = new import_sdk_core4.TinyCloud(this.auth, {
18661
- invokeAny: this.wasmBindings.invokeAny
18902
+ this.tc = new import_sdk_core5.TinyCloud(this.auth, {
18903
+ invokeAny: this.invokeAnyWithRuntimePermissions
18662
18904
  });
18663
18905
  this.config.prefix = prefix;
18664
18906
  }
@@ -18671,28 +18913,28 @@ var _TinyCloudNode = class _TinyCloudNode {
18671
18913
  if (!session) {
18672
18914
  return;
18673
18915
  }
18674
- this.tc.initializeServices(this.wasmBindings.invoke, [this.config.host]);
18675
- this._serviceContext = new import_sdk_core4.ServiceContext({
18676
- invoke: this.wasmBindings.invoke,
18677
- invokeAny: this.wasmBindings.invokeAny,
18916
+ this.tc.initializeServices(this.invokeWithRuntimePermissions, [this.config.host]);
18917
+ this._serviceContext = new import_sdk_core5.ServiceContext({
18918
+ invoke: this.invokeWithRuntimePermissions,
18919
+ invokeAny: this.invokeAnyWithRuntimePermissions,
18678
18920
  fetch: globalThis.fetch.bind(globalThis),
18679
18921
  hosts: [this.config.host]
18680
18922
  });
18681
- this._kv = new import_sdk_core4.KVService({});
18923
+ this._kv = new import_sdk_core5.KVService({});
18682
18924
  this._kv.initialize(this._serviceContext);
18683
18925
  this._serviceContext.registerService("kv", this._kv);
18684
18926
  const features = this.nodeFeatures;
18685
18927
  if (features.length === 0 || features.includes("sql")) {
18686
- this._sql = new import_sdk_core4.SQLService({});
18928
+ this._sql = new import_sdk_core5.SQLService({});
18687
18929
  this._sql.initialize(this._serviceContext);
18688
18930
  this._serviceContext.registerService("sql", this._sql);
18689
18931
  }
18690
18932
  if (features.length === 0 || features.includes("duckdb")) {
18691
- this._duckdb = new import_sdk_core4.DuckDbService({});
18933
+ this._duckdb = new import_sdk_core5.DuckDbService({});
18692
18934
  this._duckdb.initialize(this._serviceContext);
18693
18935
  this._serviceContext.registerService("duckdb", this._duckdb);
18694
18936
  }
18695
- this._hooks = new import_sdk_core4.HooksService({});
18937
+ this._hooks = new import_sdk_core5.HooksService({});
18696
18938
  this._hooks.initialize(this._serviceContext);
18697
18939
  this._serviceContext.registerService("hooks", this._hooks);
18698
18940
  const serviceSession = {
@@ -18704,8 +18946,30 @@ var _TinyCloudNode = class _TinyCloudNode {
18704
18946
  };
18705
18947
  this._serviceContext.setSession(serviceSession);
18706
18948
  this.tc.serviceContext.setSession(serviceSession);
18949
+ this._vault = this.createVaultService(session.spaceId, this._kv);
18950
+ this._vault.initialize(this._serviceContext);
18951
+ this._serviceContext.registerService("vault", this._vault);
18952
+ this.initializeV2Services(serviceSession);
18953
+ }
18954
+ createSpaceScopedKVService(spaceId) {
18955
+ const kvService = new import_sdk_core5.KVService({});
18956
+ if (this._serviceContext) {
18957
+ const spaceScopedContext = new import_sdk_core5.ServiceContext({
18958
+ invoke: this._serviceContext.invoke,
18959
+ fetch: this._serviceContext.fetch,
18960
+ hosts: this._serviceContext.hosts
18961
+ });
18962
+ const session = this._serviceContext.session;
18963
+ if (session) {
18964
+ spaceScopedContext.setSession({ ...session, spaceId });
18965
+ }
18966
+ kvService.initialize(spaceScopedContext);
18967
+ }
18968
+ return kvService;
18969
+ }
18970
+ createVaultService(spaceId, kv) {
18707
18971
  const wasm = this.wasmBindings;
18708
- const vaultCrypto = (0, import_sdk_core4.createVaultCrypto)({
18972
+ const vaultCrypto = (0, import_sdk_core5.createVaultCrypto)({
18709
18973
  vault_encrypt: wasm.vault_encrypt,
18710
18974
  vault_decrypt: wasm.vault_decrypt,
18711
18975
  vault_derive_key: wasm.vault_derive_key,
@@ -18715,11 +18979,11 @@ var _TinyCloudNode = class _TinyCloudNode {
18715
18979
  vault_sha256: wasm.vault_sha256
18716
18980
  });
18717
18981
  const self2 = this;
18718
- this._vault = new import_sdk_core4.DataVaultService({
18719
- spaceId: session.spaceId,
18982
+ return new import_sdk_core5.DataVaultService({
18983
+ spaceId,
18720
18984
  crypto: vaultCrypto,
18721
18985
  tc: {
18722
- kv: this._kv,
18986
+ kv,
18723
18987
  ensurePublicSpace: async () => {
18724
18988
  try {
18725
18989
  await self2.ensurePublicSpace();
@@ -18731,24 +18995,21 @@ var _TinyCloudNode = class _TinyCloudNode {
18731
18995
  get publicKV() {
18732
18996
  return self2._publicKV ?? self2.tc.publicKV;
18733
18997
  },
18734
- readPublicSpace: (host, spaceId, key2) => import_sdk_core4.TinyCloud.readPublicSpace(host, spaceId, key2),
18735
- makePublicSpaceId: import_sdk_core4.TinyCloud.makePublicSpaceId,
18998
+ readPublicSpace: (host, targetSpaceId, key2) => import_sdk_core5.TinyCloud.readPublicSpace(host, targetSpaceId, key2),
18999
+ makePublicSpaceId: import_sdk_core5.TinyCloud.makePublicSpaceId,
18736
19000
  did: this.did,
18737
- address: this._address,
19001
+ address: this._address ?? "",
18738
19002
  chainId: this._chainId,
18739
19003
  hosts: [this.config.host]
18740
19004
  }
18741
19005
  });
18742
- this._vault.initialize(this._serviceContext);
18743
- this._serviceContext.registerService("vault", this._vault);
18744
- this.initializeV2Services(serviceSession);
18745
19006
  }
18746
19007
  /**
18747
19008
  * Initialize the v2 delegation system services.
18748
19009
  * @internal
18749
19010
  */
18750
19011
  initializeV2Services(serviceSession) {
18751
- this._capabilityRegistry = new import_sdk_core4.CapabilityKeyRegistry();
19012
+ this._capabilityRegistry = new import_sdk_core5.CapabilityKeyRegistry();
18752
19013
  const tcSession = this.auth?.tinyCloudSession;
18753
19014
  if (tcSession && this._address) {
18754
19015
  const sessionKey = {
@@ -18822,13 +19083,13 @@ var _TinyCloudNode = class _TinyCloudNode {
18822
19083
  }
18823
19084
  this._capabilityRegistry.registerKey(sessionKey, delegations);
18824
19085
  }
18825
- this._delegationManager = new import_sdk_core4.DelegationManager({
19086
+ this._delegationManager = new import_sdk_core5.DelegationManager({
18826
19087
  hosts: [this.config.host],
18827
19088
  session: serviceSession,
18828
- invoke: this.wasmBindings.invoke,
19089
+ invoke: this.invokeWithRuntimePermissions,
18829
19090
  fetch: globalThis.fetch.bind(globalThis)
18830
19091
  });
18831
- this._spaceService = new import_sdk_core4.SpaceService({
19092
+ this._spaceService = new import_sdk_core5.SpaceService({
18832
19093
  hosts: [this.config.host],
18833
19094
  session: serviceSession,
18834
19095
  invoke: this.wasmBindings.invoke,
@@ -18836,20 +19097,15 @@ var _TinyCloudNode = class _TinyCloudNode {
18836
19097
  capabilityRegistry: this._capabilityRegistry,
18837
19098
  userDid: this.did,
18838
19099
  createKVService: (spaceId) => {
18839
- const kvService = new import_sdk_core4.KVService({});
19100
+ return this.createSpaceScopedKVService(spaceId);
19101
+ },
19102
+ createVaultService: (spaceId) => {
19103
+ const kvService = this.createSpaceScopedKVService(spaceId);
19104
+ const vaultService = this.createVaultService(spaceId, kvService);
18840
19105
  if (this._serviceContext) {
18841
- const spaceScopedContext = new import_sdk_core4.ServiceContext({
18842
- invoke: this._serviceContext.invoke,
18843
- fetch: this._serviceContext.fetch,
18844
- hosts: this._serviceContext.hosts
18845
- });
18846
- const session = this._serviceContext.session;
18847
- if (session) {
18848
- spaceScopedContext.setSession({ ...session, spaceId });
18849
- }
18850
- kvService.initialize(spaceScopedContext);
19106
+ vaultService.initialize(this._serviceContext);
18851
19107
  }
18852
- return kvService;
19108
+ return vaultService;
18853
19109
  },
18854
19110
  // Enable space.delegations.create() via SIWE-based delegation
18855
19111
  createDelegation: async (params) => {
@@ -18906,7 +19162,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18906
19162
  * @internal
18907
19163
  */
18908
19164
  getSessionExpiry() {
18909
- const expirationMs = this.config.sessionExpirationMs ?? 60 * 60 * 1e3;
19165
+ const expirationMs = this.config.sessionExpirationMs ?? DEFAULT_SESSION_EXPIRATION_MS;
18910
19166
  return new Date(Date.now() + expirationMs);
18911
19167
  }
18912
19168
  /**
@@ -18990,7 +19246,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18990
19246
  ...prepared,
18991
19247
  signature: signature2
18992
19248
  });
18993
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
19249
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
18994
19250
  host,
18995
19251
  delegationSession.delegationHeader
18996
19252
  );
@@ -19057,12 +19313,40 @@ var _TinyCloudNode = class _TinyCloudNode {
19057
19313
  if (!this._sql) {
19058
19314
  const features = this.nodeFeatures;
19059
19315
  if (features.length > 0 && !features.includes("sql")) {
19060
- throw new import_sdk_core4.UnsupportedFeatureError("sql", this.config.host, features);
19316
+ throw new import_sdk_core5.UnsupportedFeatureError("sql", this.config.host, features);
19061
19317
  }
19062
19318
  throw new Error("Not signed in. Call signIn() first.");
19063
19319
  }
19064
19320
  return this._sql;
19065
19321
  }
19322
+ /**
19323
+ * Get an SQL service scoped to a specific space.
19324
+ *
19325
+ * Mirrors {@link SpaceService}'s per-space KV factory: clones the active
19326
+ * service context and overrides its session's spaceId so that subsequent
19327
+ * `sql/<dbName>/<action>` invocations route to that space. Useful when
19328
+ * the caller already holds a delegation covering the target space (e.g.
19329
+ * via {@link grantRuntimePermissions} or {@link useRuntimeDelegation})
19330
+ * but the SDK's per-space SQL surface isn't otherwise exposed.
19331
+ *
19332
+ * Does NOT auto-create the space.
19333
+ *
19334
+ * @param spaceId - Full space URI (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`).
19335
+ */
19336
+ sqlForSpace(spaceId) {
19337
+ if (!this._serviceContext || !this._serviceContext.session) {
19338
+ throw new Error("Not signed in. Call signIn() first.");
19339
+ }
19340
+ const sql = new import_sdk_core5.SQLService({});
19341
+ const spaceScopedContext = new import_sdk_core5.ServiceContext({
19342
+ invoke: this._serviceContext.invoke,
19343
+ fetch: this._serviceContext.fetch,
19344
+ hosts: this._serviceContext.hosts
19345
+ });
19346
+ spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
19347
+ sql.initialize(spaceScopedContext);
19348
+ return sql;
19349
+ }
19066
19350
  /**
19067
19351
  * DuckDB database operations on this user's space.
19068
19352
  */
@@ -19070,7 +19354,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19070
19354
  if (!this._duckdb) {
19071
19355
  const features = this.nodeFeatures;
19072
19356
  if (features.length > 0 && !features.includes("duckdb")) {
19073
- throw new import_sdk_core4.UnsupportedFeatureError("duckdb", this.config.host, features);
19357
+ throw new import_sdk_core5.UnsupportedFeatureError("duckdb", this.config.host, features);
19074
19358
  }
19075
19359
  throw new Error("Not signed in. Call signIn() first.");
19076
19360
  }
@@ -19086,6 +19370,33 @@ var _TinyCloudNode = class _TinyCloudNode {
19086
19370
  }
19087
19371
  return this._vault;
19088
19372
  }
19373
+ /**
19374
+ * App-facing secrets API backed by the `secrets` space vault.
19375
+ */
19376
+ get secrets() {
19377
+ if (!this._spaceService) {
19378
+ throw new Error("Not signed in. Call signIn() first.");
19379
+ }
19380
+ if (!this._secrets) {
19381
+ this._secrets = new NodeSecretsService({
19382
+ getService: () => this.getBaseSecrets(),
19383
+ getManifest: () => this.manifest,
19384
+ grantPermissions: (additional) => this.grantRuntimePermissions(additional),
19385
+ canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
19386
+ getUnlockSigner: () => this.signer ?? void 0
19387
+ });
19388
+ }
19389
+ return this._secrets;
19390
+ }
19391
+ getBaseSecrets() {
19392
+ if (!this._spaceService) {
19393
+ throw new Error("Not signed in. Call signIn() first.");
19394
+ }
19395
+ if (!this._baseSecrets) {
19396
+ this._baseSecrets = new import_sdk_core5.SecretsService(() => this.space("secrets").vault);
19397
+ }
19398
+ return this._baseSecrets;
19399
+ }
19089
19400
  /**
19090
19401
  * Hooks write stream subscription API.
19091
19402
  */
@@ -19156,6 +19467,171 @@ var _TinyCloudNode = class _TinyCloudNode {
19156
19467
  }
19157
19468
  };
19158
19469
  }
19470
+ /**
19471
+ * Check whether the current session or an approved runtime delegation covers
19472
+ * every requested permission.
19473
+ */
19474
+ hasRuntimePermissions(permissions) {
19475
+ const session = this.auth?.tinyCloudSession;
19476
+ if (!session || !Array.isArray(permissions) || permissions.length === 0) {
19477
+ return false;
19478
+ }
19479
+ const expanded = this.expandPermissionEntries(permissions);
19480
+ if (this.sessionCoversPermissionEntries(session, expanded)) {
19481
+ return true;
19482
+ }
19483
+ return this.findRuntimeGrantsForPermissionEntries(expanded, session).length > 0;
19484
+ }
19485
+ /**
19486
+ * Return installed runtime permission delegations. When `permissions` is
19487
+ * provided, only delegations currently covering those permissions are
19488
+ * returned. Base-session manifest permissions are not represented here.
19489
+ */
19490
+ getRuntimePermissionDelegations(permissions) {
19491
+ this.pruneExpiredRuntimePermissionGrants();
19492
+ if (permissions === void 0) {
19493
+ return this.runtimePermissionGrants.map((grant) => grant.delegation);
19494
+ }
19495
+ const session = this.auth?.tinyCloudSession;
19496
+ if (!session || !Array.isArray(permissions) || permissions.length === 0) {
19497
+ return [];
19498
+ }
19499
+ const expanded = this.expandPermissionEntries(permissions);
19500
+ return this.findRuntimeGrantsForPermissionEntries(expanded, session).map(
19501
+ (grant) => grant.delegation
19502
+ );
19503
+ }
19504
+ /**
19505
+ * Install a portable runtime permission delegation into this SDK instance so
19506
+ * matching service calls and downstream `delegateTo()` calls can use it.
19507
+ */
19508
+ async useRuntimeDelegation(delegation) {
19509
+ const session = this.auth?.tinyCloudSession;
19510
+ if (!session) {
19511
+ throw new import_sdk_core5.SessionExpiredError(/* @__PURE__ */ new Date(0));
19512
+ }
19513
+ if (delegation.expiry.getTime() <= Date.now()) {
19514
+ throw new import_sdk_core5.SessionExpiredError(delegation.expiry);
19515
+ }
19516
+ const expectedDids = /* @__PURE__ */ new Set([session.verificationMethod, this.sessionDid]);
19517
+ if (!expectedDids.has(delegation.delegateDID)) {
19518
+ throw new Error(
19519
+ `Runtime delegation targets ${delegation.delegateDID} but this session key is ${session.verificationMethod}.`
19520
+ );
19521
+ }
19522
+ const targetHost = delegation.host ?? this.config.host;
19523
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19524
+ targetHost,
19525
+ delegation.delegationHeader
19526
+ );
19527
+ if (!activateResult.success) {
19528
+ throw new Error(
19529
+ `Failed to activate runtime permission delegation: ${activateResult.error}`
19530
+ );
19531
+ }
19532
+ this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
19533
+ (grant) => grant.delegation.cid !== delegation.cid
19534
+ );
19535
+ this.runtimePermissionGrants.push(
19536
+ this.runtimeGrantFromDelegation(delegation, session)
19537
+ );
19538
+ }
19539
+ /**
19540
+ * Store additional permissions as narrow delegations to the current session
19541
+ * key. Future service invocations automatically use a stored delegation when
19542
+ * its `(space, service, path, action)` covers the request.
19543
+ */
19544
+ async grantRuntimePermissions(permissions, options) {
19545
+ if (!Array.isArray(permissions) || permissions.length === 0) {
19546
+ throw new Error("grantRuntimePermissions requires a non-empty permissions array");
19547
+ }
19548
+ const session = this.auth?.tinyCloudSession;
19549
+ if (!session) {
19550
+ throw new import_sdk_core5.SessionExpiredError(/* @__PURE__ */ new Date(0));
19551
+ }
19552
+ const sessionExpiry = extractSiweExpiration(session.siwe);
19553
+ if (sessionExpiry !== void 0) {
19554
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19555
+ if (sessionExpiry.getTime() <= Date.now() + marginMs) {
19556
+ throw new import_sdk_core5.SessionExpiredError(sessionExpiry);
19557
+ }
19558
+ }
19559
+ const expanded = this.expandPermissionEntries(permissions);
19560
+ if (this.sessionCoversPermissionEntries(session, expanded)) {
19561
+ return [];
19562
+ }
19563
+ const existingGrants = this.findRuntimeGrantsForPermissionEntries(expanded, session);
19564
+ if (existingGrants.length > 0) {
19565
+ return existingGrants.map((grant) => grant.delegation);
19566
+ }
19567
+ if (!this.signer) {
19568
+ throw new Error(
19569
+ "grantRuntimePermissions requires wallet mode with a signer or privateKey."
19570
+ );
19571
+ }
19572
+ const bySpace = /* @__PURE__ */ new Map();
19573
+ for (const entry of expanded) {
19574
+ const spaceId = this.resolvePermissionSpace(entry.space, session);
19575
+ const current = bySpace.get(spaceId) ?? [];
19576
+ current.push(entry);
19577
+ bySpace.set(spaceId, current);
19578
+ }
19579
+ const now = /* @__PURE__ */ new Date();
19580
+ const requestedExpiryMs = resolveExpiryMs(options?.expiry);
19581
+ let expiresAt = new Date(now.getTime() + requestedExpiryMs);
19582
+ if (sessionExpiry !== void 0 && sessionExpiry < expiresAt) {
19583
+ expiresAt = sessionExpiry;
19584
+ }
19585
+ const delegations = [];
19586
+ for (const [spaceId, entries] of bySpace) {
19587
+ const abilities = this.permissionsToAbilities(entries);
19588
+ const prepared = this.wasmBindings.prepareSession({
19589
+ abilities,
19590
+ address: this.wasmBindings.ensureEip55(session.address),
19591
+ chainId: session.chainId,
19592
+ domain: this.siweDomain,
19593
+ issuedAt: now.toISOString(),
19594
+ expirationTime: expiresAt.toISOString(),
19595
+ spaceId,
19596
+ jwk: session.jwk
19597
+ });
19598
+ const signature2 = await this.signer.signMessage(prepared.siwe);
19599
+ const delegatedSession = this.wasmBindings.completeSessionSetup({
19600
+ ...prepared,
19601
+ signature: signature2
19602
+ });
19603
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19604
+ this.config.host,
19605
+ delegatedSession.delegationHeader
19606
+ );
19607
+ if (!activateResult.success) {
19608
+ throw new Error(
19609
+ `Failed to activate runtime permission delegation: ${activateResult.error}`
19610
+ );
19611
+ }
19612
+ const delegation = this.runtimeDelegationFromSession(
19613
+ delegatedSession,
19614
+ entries,
19615
+ spaceId,
19616
+ session,
19617
+ expiresAt
19618
+ );
19619
+ this.runtimePermissionGrants.push({
19620
+ session: {
19621
+ delegationHeader: delegatedSession.delegationHeader,
19622
+ delegationCid: delegatedSession.delegationCid,
19623
+ spaceId,
19624
+ verificationMethod: session.verificationMethod,
19625
+ jwk: session.jwk
19626
+ },
19627
+ delegation,
19628
+ operations: this.permissionOperations(entries, spaceId),
19629
+ expiresAt
19630
+ });
19631
+ delegations.push(delegation);
19632
+ }
19633
+ return delegations;
19634
+ }
19159
19635
  /**
19160
19636
  * Get the DelegationManager for delegation CRUD operations.
19161
19637
  *
@@ -19224,6 +19700,12 @@ var _TinyCloudNode = class _TinyCloudNode {
19224
19700
  get spaceService() {
19225
19701
  return this.spaces;
19226
19702
  }
19703
+ /**
19704
+ * Get a Space object by short name or full URI.
19705
+ */
19706
+ space(nameOrUri) {
19707
+ return this.spaces.get(nameOrUri);
19708
+ }
19227
19709
  /**
19228
19710
  * Get the SharingService for creating and receiving v2 sharing links.
19229
19711
  *
@@ -19291,7 +19773,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19291
19773
  ];
19292
19774
  const abilities = { kv: { "": kvActions } };
19293
19775
  const now = /* @__PURE__ */ new Date();
19294
- const expiryMs = 60 * 60 * 1e3;
19776
+ const expiryMs = import_sdk_core5.EXPIRY.EPHEMERAL_MS;
19295
19777
  const expirationTime = new Date(now.getTime() + expiryMs);
19296
19778
  const prepared = this.wasmBindings.prepareSession({
19297
19779
  abilities,
@@ -19309,7 +19791,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19309
19791
  ...prepared,
19310
19792
  signature: signature2
19311
19793
  });
19312
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
19794
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19313
19795
  this.config.host,
19314
19796
  delegationSession.delegationHeader
19315
19797
  );
@@ -19336,9 +19818,9 @@ var _TinyCloudNode = class _TinyCloudNode {
19336
19818
  }]);
19337
19819
  }
19338
19820
  if (this._serviceContext) {
19339
- const publicKV = new import_sdk_core4.KVService({ prefix: "" });
19340
- const publicContext = new import_sdk_core4.ServiceContext({
19341
- invoke: this.wasmBindings.invoke,
19821
+ const publicKV = new import_sdk_core5.KVService({ prefix: "" });
19822
+ const publicContext = new import_sdk_core5.ServiceContext({
19823
+ invoke: this.invokeWithRuntimePermissions,
19342
19824
  fetch: this._serviceContext.fetch,
19343
19825
  hosts: this._serviceContext.hosts
19344
19826
  });
@@ -19426,8 +19908,9 @@ var _TinyCloudNode = class _TinyCloudNode {
19426
19908
  * Issue a delegation using the capability-chain flow.
19427
19909
  *
19428
19910
  * When every requested permission is a subset of the current
19429
- * session's recap, the delegation is signed by the session key via
19430
- * WASM no wallet prompt. When at least one is NOT derivable, a
19911
+ * session's recap, or of one installed runtime permission delegation,
19912
+ * the delegation is signed by the session key via WASM no wallet
19913
+ * prompt. When at least one is NOT derivable, a
19431
19914
  * {@link PermissionNotInManifestError} is raised (carrying the
19432
19915
  * missing entries) so the caller can trigger an escalation flow
19433
19916
  * (e.g. `TinyCloudWeb.requestPermissions`). Passing
@@ -19462,14 +19945,14 @@ var _TinyCloudNode = class _TinyCloudNode {
19462
19945
  async delegateTo(did, permissions, options) {
19463
19946
  const session = this.auth?.tinyCloudSession;
19464
19947
  if (!session) {
19465
- throw new import_sdk_core4.SessionExpiredError(/* @__PURE__ */ new Date(0));
19948
+ throw new import_sdk_core5.SessionExpiredError(/* @__PURE__ */ new Date(0));
19466
19949
  }
19467
19950
  const sessionExpiry = extractSiweExpiration(session.siwe);
19468
19951
  if (sessionExpiry !== void 0) {
19469
19952
  const now2 = Date.now();
19470
19953
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19471
19954
  if (sessionExpiry.getTime() <= now2 + marginMs) {
19472
- throw new import_sdk_core4.SessionExpiredError(sessionExpiry);
19955
+ throw new import_sdk_core5.SessionExpiredError(sessionExpiry);
19473
19956
  }
19474
19957
  }
19475
19958
  if (!Array.isArray(permissions) || permissions.length === 0) {
@@ -19477,10 +19960,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19477
19960
  "delegateTo requires a non-empty permissions array"
19478
19961
  );
19479
19962
  }
19480
- const expandedEntries = permissions.map((entry) => ({
19481
- ...entry,
19482
- actions: (0, import_sdk_core4.expandActionShortNames)(entry.service, entry.actions)
19483
- }));
19963
+ const expandedEntries = this.expandPermissionEntries(permissions);
19484
19964
  const now = /* @__PURE__ */ new Date();
19485
19965
  const expiryMs = resolveExpiryMs(options?.expiry);
19486
19966
  const expirationTime = new Date(now.getTime() + expiryMs);
@@ -19501,13 +19981,30 @@ var _TinyCloudNode = class _TinyCloudNode {
19501
19981
  );
19502
19982
  return { delegation: delegation2, prompted: true };
19503
19983
  }
19504
- const granted = (0, import_sdk_core4.parseRecapCapabilities)(
19984
+ const granted = (0, import_sdk_core5.parseRecapCapabilities)(
19505
19985
  (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
19506
19986
  session.siwe
19507
19987
  );
19508
- const { subset, missing } = (0, import_sdk_core4.isCapabilitySubset)(expandedEntries, granted);
19988
+ const { subset, missing } = (0, import_sdk_core5.isCapabilitySubset)(expandedEntries, granted);
19509
19989
  if (!subset) {
19510
- throw new import_sdk_core4.PermissionNotInManifestError(missing, granted);
19990
+ const runtimeGrant = this.findGrantForOperations(
19991
+ this.permissionEntriesToOperations(expandedEntries, session)
19992
+ );
19993
+ if (runtimeGrant) {
19994
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19995
+ if (runtimeGrant.expiresAt.getTime() <= Date.now() + marginMs) {
19996
+ throw new import_sdk_core5.SessionExpiredError(runtimeGrant.expiresAt);
19997
+ }
19998
+ const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
19999
+ const delegation2 = await this.createDelegationViaRuntimeGrant(
20000
+ did,
20001
+ expandedEntries,
20002
+ runtimeExpiration,
20003
+ runtimeGrant
20004
+ );
20005
+ return { delegation: delegation2, prompted: false };
20006
+ }
20007
+ throw new import_sdk_core5.PermissionNotInManifestError(missing, granted);
19511
20008
  }
19512
20009
  const delegation = await this.createDelegationViaWasmPath(
19513
20010
  did,
@@ -19587,7 +20084,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19587
20084
  const spaceId = [...resolvedSpaces][0];
19588
20085
  const abilities = {};
19589
20086
  for (const entry of entries) {
19590
- const shortService = import_sdk_core4.SERVICE_LONG_TO_SHORT[entry.service];
20087
+ const shortService = import_sdk_core5.SERVICE_LONG_TO_SHORT[entry.service];
19591
20088
  if (shortService === void 0) {
19592
20089
  throw new Error(
19593
20090
  `delegateTo: unknown service '${entry.service}' \u2014 no short-form mapping`
@@ -19627,7 +20124,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19627
20124
  });
19628
20125
  const primary = result.resources[0];
19629
20126
  const delegationHeader = { Authorization: result.delegation };
19630
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20127
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19631
20128
  this.config.host,
19632
20129
  delegationHeader
19633
20130
  );
@@ -19651,6 +20148,41 @@ var _TinyCloudNode = class _TinyCloudNode {
19651
20148
  host: this.config.host
19652
20149
  };
19653
20150
  }
20151
+ async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant) {
20152
+ const result = this.createDelegationWrapper({
20153
+ session: grant.session,
20154
+ delegateDID: did,
20155
+ spaceId: grant.session.spaceId,
20156
+ abilities: this.permissionsToAbilities(entries),
20157
+ expirationSecs: Math.floor(expirationTime.getTime() / 1e3)
20158
+ });
20159
+ const primary = result.resources[0];
20160
+ const delegationHeader = { Authorization: result.delegation };
20161
+ const targetHost = grant.delegation.host ?? this.config.host;
20162
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
20163
+ targetHost,
20164
+ delegationHeader
20165
+ );
20166
+ if (!activateResult.success) {
20167
+ throw new Error(
20168
+ `Failed to activate delegation with host: ${activateResult.error}`
20169
+ );
20170
+ }
20171
+ return {
20172
+ cid: result.cid,
20173
+ delegationHeader,
20174
+ spaceId: grant.session.spaceId,
20175
+ path: primary.path,
20176
+ actions: primary.actions,
20177
+ resources: result.resources,
20178
+ disableSubDelegation: false,
20179
+ expiry: result.expiry,
20180
+ delegateDID: did,
20181
+ ownerAddress: grant.delegation.ownerAddress,
20182
+ chainId: grant.delegation.chainId,
20183
+ host: targetHost
20184
+ };
20185
+ }
19654
20186
  resolvePermissionSpace(space, session) {
19655
20187
  if (space === void 0) {
19656
20188
  return this.wasmBindings.makeSpaceId(
@@ -19667,6 +20199,220 @@ var _TinyCloudNode = class _TinyCloudNode {
19667
20199
  }
19668
20200
  return this.wasmBindings.makeSpaceId(session.address, session.chainId, space);
19669
20201
  }
20202
+ expandPermissionEntries(permissions) {
20203
+ return (0, import_sdk_core5.expandPermissionEntries)(permissions);
20204
+ }
20205
+ shortServiceName(service) {
20206
+ const short = import_sdk_core5.SERVICE_LONG_TO_SHORT[service];
20207
+ if (short === void 0) {
20208
+ throw new Error(
20209
+ `unknown service '${service}' \u2014 no short-form mapping`
20210
+ );
20211
+ }
20212
+ return short;
20213
+ }
20214
+ permissionsToAbilities(entries) {
20215
+ const abilities = {};
20216
+ for (const entry of entries) {
20217
+ const service = this.shortServiceName(entry.service);
20218
+ abilities[service] ?? (abilities[service] = {});
20219
+ const existing = abilities[service][entry.path] ?? [];
20220
+ const seen = new Set(existing);
20221
+ for (const action of entry.actions) {
20222
+ if (!seen.has(action)) {
20223
+ existing.push(action);
20224
+ seen.add(action);
20225
+ }
20226
+ }
20227
+ abilities[service][entry.path] = existing;
20228
+ }
20229
+ return abilities;
20230
+ }
20231
+ permissionOperations(entries, spaceId) {
20232
+ return entries.flatMap((entry) => {
20233
+ const service = this.shortServiceName(entry.service);
20234
+ return entry.actions.map((action) => ({
20235
+ spaceId,
20236
+ service,
20237
+ path: entry.path,
20238
+ action
20239
+ }));
20240
+ });
20241
+ }
20242
+ sessionCoversPermissionEntries(session, entries) {
20243
+ try {
20244
+ const granted = (0, import_sdk_core5.parseRecapCapabilities)(
20245
+ (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
20246
+ session.siwe
20247
+ );
20248
+ return (0, import_sdk_core5.isCapabilitySubset)(entries, granted).subset;
20249
+ } catch {
20250
+ return false;
20251
+ }
20252
+ }
20253
+ permissionEntriesToOperations(entries, session) {
20254
+ return entries.flatMap((entry) => {
20255
+ const spaceId = this.resolvePermissionSpace(entry.space, session);
20256
+ const service = this.shortServiceName(entry.service);
20257
+ return entry.actions.map((action) => ({
20258
+ spaceId,
20259
+ service,
20260
+ path: entry.path,
20261
+ action
20262
+ }));
20263
+ });
20264
+ }
20265
+ findRuntimeGrantsForPermissionEntries(entries, session) {
20266
+ const grants = [];
20267
+ const operations = this.permissionEntriesToOperations(entries, session);
20268
+ if (operations.length === 0) {
20269
+ return grants;
20270
+ }
20271
+ for (const operation of operations) {
20272
+ const grant = this.findGrantForOperation(operation);
20273
+ if (!grant) {
20274
+ return [];
20275
+ }
20276
+ if (!grants.includes(grant)) {
20277
+ grants.push(grant);
20278
+ }
20279
+ }
20280
+ return grants;
20281
+ }
20282
+ runtimeDelegationFromSession(delegatedSession, entries, spaceId, session, expiresAt) {
20283
+ const resources = this.delegatedResourcesForEntries(entries, spaceId);
20284
+ const primary = resources[0];
20285
+ return {
20286
+ cid: delegatedSession.delegationCid,
20287
+ delegationHeader: delegatedSession.delegationHeader,
20288
+ spaceId,
20289
+ path: primary.path,
20290
+ actions: primary.actions,
20291
+ resources,
20292
+ disableSubDelegation: false,
20293
+ expiry: expiresAt,
20294
+ delegateDID: session.verificationMethod,
20295
+ ownerAddress: session.address,
20296
+ chainId: session.chainId,
20297
+ host: this.config.host
20298
+ };
20299
+ }
20300
+ runtimeGrantFromDelegation(delegation, session) {
20301
+ const operations = this.operationsFromDelegation(delegation);
20302
+ return {
20303
+ session: {
20304
+ delegationHeader: delegation.delegationHeader,
20305
+ delegationCid: delegation.cid,
20306
+ spaceId: delegation.spaceId,
20307
+ verificationMethod: session.verificationMethod,
20308
+ jwk: session.jwk
20309
+ },
20310
+ delegation,
20311
+ operations,
20312
+ expiresAt: delegation.expiry
20313
+ };
20314
+ }
20315
+ delegatedResourcesForEntries(entries, spaceId) {
20316
+ return entries.map((entry) => ({
20317
+ service: this.shortServiceName(entry.service),
20318
+ space: spaceId,
20319
+ path: entry.path,
20320
+ actions: [...entry.actions]
20321
+ }));
20322
+ }
20323
+ operationsFromDelegation(delegation) {
20324
+ const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
20325
+ return resources.flatMap(
20326
+ (resource) => resource.actions.map((action) => ({
20327
+ spaceId: resource.space,
20328
+ service: this.invocationServiceName(resource.service),
20329
+ path: resource.path,
20330
+ action
20331
+ }))
20332
+ );
20333
+ }
20334
+ flatDelegationResources(delegation) {
20335
+ const byService = /* @__PURE__ */ new Map();
20336
+ for (const action of delegation.actions) {
20337
+ const service = this.shortServiceName(action.split("/")[0]);
20338
+ const actions = byService.get(service) ?? [];
20339
+ actions.push(action);
20340
+ byService.set(service, actions);
20341
+ }
20342
+ return [...byService.entries()].map(([service, actions]) => ({
20343
+ service,
20344
+ space: delegation.spaceId,
20345
+ path: delegation.path,
20346
+ actions
20347
+ }));
20348
+ }
20349
+ selectInvocationSession(fallback, service, path, action) {
20350
+ const grant = this.findGrantForOperation({
20351
+ spaceId: fallback.spaceId,
20352
+ service: this.invocationServiceName(service),
20353
+ path,
20354
+ action
20355
+ });
20356
+ return grant?.session ?? fallback;
20357
+ }
20358
+ findGrantForOperations(operations) {
20359
+ if (operations.length === 0) {
20360
+ return void 0;
20361
+ }
20362
+ this.pruneExpiredRuntimePermissionGrants();
20363
+ return this.runtimePermissionGrants.find((grant) => {
20364
+ return operations.every(
20365
+ (operation) => grant.operations.some(
20366
+ (granted) => this.operationCovers(granted, operation)
20367
+ )
20368
+ );
20369
+ });
20370
+ }
20371
+ findGrantForOperation(operation) {
20372
+ return this.findGrantForOperations([operation]);
20373
+ }
20374
+ pruneExpiredRuntimePermissionGrants() {
20375
+ const now = Date.now();
20376
+ this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
20377
+ (grant) => grant.expiresAt.getTime() > now
20378
+ );
20379
+ }
20380
+ operationCovers(granted, requested) {
20381
+ return granted.spaceId === requested.spaceId && granted.service === requested.service && this.actionContains(granted.action, requested.action) && this.pathContains(granted.path, requested.path);
20382
+ }
20383
+ actionContains(grantedAction, requestedAction) {
20384
+ if (grantedAction === requestedAction) {
20385
+ return true;
20386
+ }
20387
+ if (grantedAction.endsWith("/*")) {
20388
+ const prefix = grantedAction.slice(0, -2);
20389
+ return requestedAction.startsWith(`${prefix}/`);
20390
+ }
20391
+ return false;
20392
+ }
20393
+ invocationServiceName(service) {
20394
+ return service.startsWith("tinycloud.") ? this.shortServiceName(service) : service;
20395
+ }
20396
+ pathContains(grantedPath, requestedPath) {
20397
+ if (grantedPath === "" || grantedPath === "/") {
20398
+ return true;
20399
+ }
20400
+ if (grantedPath.endsWith("/**")) {
20401
+ return requestedPath.startsWith(grantedPath.slice(0, -3));
20402
+ }
20403
+ if (grantedPath.endsWith("/*")) {
20404
+ const prefix = grantedPath.slice(0, -2);
20405
+ if (!requestedPath.startsWith(prefix)) {
20406
+ return false;
20407
+ }
20408
+ const remainder = requestedPath.slice(prefix.length);
20409
+ return !remainder.includes("/") || remainder === "/";
20410
+ }
20411
+ if (grantedPath.endsWith("/")) {
20412
+ return requestedPath.startsWith(grantedPath);
20413
+ }
20414
+ return grantedPath === requestedPath;
20415
+ }
19670
20416
  /**
19671
20417
  * Issue a delegation via the legacy wallet-signed SIWE path for a single
19672
20418
  * {@link PermissionEntry}. Shares the implementation with the public
@@ -19723,7 +20469,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19723
20469
  );
19724
20470
  return result.delegation;
19725
20471
  } catch (err) {
19726
- if (err instanceof import_sdk_core4.PermissionNotInManifestError) {
20472
+ if (err instanceof import_sdk_core5.PermissionNotInManifestError) {
19727
20473
  } else {
19728
20474
  throw err;
19729
20475
  }
@@ -19780,7 +20526,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19780
20526
  ...prepared,
19781
20527
  signature: signature2
19782
20528
  });
19783
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20529
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19784
20530
  this.config.host,
19785
20531
  delegationSession.delegationHeader
19786
20532
  );
@@ -19802,7 +20548,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19802
20548
  };
19803
20549
  const hasKvActions = params.actions.some((a) => a.startsWith("tinycloud.kv/"));
19804
20550
  if (hasKvActions && params.includePublicSpace !== false) {
19805
- const publicSpaceId = (0, import_sdk_core4.makePublicSpaceId)(
20551
+ const publicSpaceId = (0, import_sdk_core5.makePublicSpaceId)(
19806
20552
  this.wasmBindings.ensureEip55(session.address),
19807
20553
  session.chainId
19808
20554
  );
@@ -19825,7 +20571,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19825
20571
  ...publicPrepared,
19826
20572
  signature: publicSignature
19827
20573
  });
19828
- const publicActivateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20574
+ const publicActivateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19829
20575
  this.config.host,
19830
20576
  publicSession.delegationHeader
19831
20577
  );
@@ -19924,7 +20670,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19924
20670
  ...prepared,
19925
20671
  signature: signature2
19926
20672
  });
19927
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20673
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19928
20674
  targetHost,
19929
20675
  invokerSession.delegationHeader
19930
20676
  );
@@ -20013,7 +20759,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20013
20759
  ...prepared,
20014
20760
  signature: signature2
20015
20761
  });
20016
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20762
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
20017
20763
  targetHost,
20018
20764
  subDelegationSession.delegationHeader
20019
20765
  );
@@ -20055,11 +20801,11 @@ TinyCloudNode.registerNodeDefaults({
20055
20801
  });
20056
20802
 
20057
20803
  // src/index.ts
20058
- var import_sdk_core6 = require("@tinycloud/sdk-core");
20059
20804
  var import_sdk_core7 = require("@tinycloud/sdk-core");
20805
+ var import_sdk_core8 = require("@tinycloud/sdk-core");
20060
20806
 
20061
20807
  // src/storage/FileSessionStorage.ts
20062
- var import_sdk_core5 = require("@tinycloud/sdk-core");
20808
+ var import_sdk_core6 = require("@tinycloud/sdk-core");
20063
20809
  var import_fs = require("fs");
20064
20810
  var import_path = require("path");
20065
20811
  var FileSessionStorage = class {
@@ -20114,7 +20860,7 @@ var FileSessionStorage = class {
20114
20860
  try {
20115
20861
  const data = (0, import_fs.readFileSync)(filePath, "utf-8");
20116
20862
  const parsed = JSON.parse(data);
20117
- const validation = (0, import_sdk_core5.validatePersistedSessionData)(parsed);
20863
+ const validation = (0, import_sdk_core6.validatePersistedSessionData)(parsed);
20118
20864
  if (!validation.ok) {
20119
20865
  console.warn(`Invalid session data for ${address}:`, validation.error.message);
20120
20866
  (0, import_fs.unlinkSync)(filePath);
@@ -20179,7 +20925,7 @@ var FileSessionStorage = class {
20179
20925
  };
20180
20926
 
20181
20927
  // src/index.ts
20182
- var import_sdk_core8 = require("@tinycloud/sdk-core");
20928
+ var import_sdk_core9 = require("@tinycloud/sdk-core");
20183
20929
 
20184
20930
  // src/delegation.ts
20185
20931
  function serializeDelegation(delegation) {
@@ -20198,7 +20944,6 @@ function deserializeDelegation(data) {
20198
20944
  }
20199
20945
 
20200
20946
  // src/index.ts
20201
- var import_sdk_core9 = require("@tinycloud/sdk-core");
20202
20947
  var import_sdk_core10 = require("@tinycloud/sdk-core");
20203
20948
  var import_sdk_core11 = require("@tinycloud/sdk-core");
20204
20949
  var import_sdk_core12 = require("@tinycloud/sdk-core");
@@ -20208,6 +20953,7 @@ var import_sdk_core15 = require("@tinycloud/sdk-core");
20208
20953
  var import_sdk_core16 = require("@tinycloud/sdk-core");
20209
20954
  var import_sdk_core17 = require("@tinycloud/sdk-core");
20210
20955
  var import_sdk_core18 = require("@tinycloud/sdk-core");
20956
+ var import_sdk_core19 = require("@tinycloud/sdk-core");
20211
20957
  // Annotate the CommonJS export names for ESM import in node:
20212
20958
  0 && (module.exports = {
20213
20959
  ACCOUNT_REGISTRY_PATH,
@@ -20236,8 +20982,10 @@ var import_sdk_core18 = require("@tinycloud/sdk-core");
20236
20982
  PrefixedKVService,
20237
20983
  PrivateKeySigner,
20238
20984
  ProtocolMismatchError,
20985
+ SECRET_NAME_RE,
20239
20986
  SQLAction,
20240
20987
  SQLService,
20988
+ SecretsService,
20241
20989
  ServiceContext,
20242
20990
  SessionExpiredError,
20243
20991
  SharingService,
@@ -20248,11 +20996,13 @@ var import_sdk_core18 = require("@tinycloud/sdk-core");
20248
20996
  TinyCloud,
20249
20997
  TinyCloudNode,
20250
20998
  UnsupportedFeatureError,
20999
+ VAULT_PERMISSION_SERVICE,
20251
21000
  VaultHeaders,
20252
21001
  VaultPublicSpaceKVActions,
20253
21002
  VersionCheckError,
20254
21003
  WasmKeyProvider,
20255
21004
  buildSpaceUri,
21005
+ canonicalizeSecretScope,
20256
21006
  checkNodeInfo,
20257
21007
  composeManifestRequest,
20258
21008
  createCapabilityKeyRegistry,
@@ -20264,12 +21014,15 @@ var import_sdk_core18 = require("@tinycloud/sdk-core");
20264
21014
  defaultSpaceCreationHandler,
20265
21015
  deserializeDelegation,
20266
21016
  expandActionShortNames,
21017
+ expandPermissionEntries,
21018
+ expandPermissionEntry,
20267
21019
  isCapabilitySubset,
20268
21020
  loadManifest,
20269
21021
  makePublicSpaceId,
20270
21022
  parseExpiry,
20271
21023
  parseSpaceUri,
20272
21024
  resolveManifest,
21025
+ resolveSecretPath,
20273
21026
  resourceCapabilitiesToSpaceAbilitiesMap,
20274
21027
  serializeDelegation,
20275
21028
  validateManifest