@tinycloud/node-sdk 2.2.0-beta.6 → 2.2.0-beta.8

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,70 @@ 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
+ SQLAction: () => import_sdk_core11.SQLAction,
17055
+ SQLService: () => import_sdk_core11.SQLService,
17056
+ SecretsService: () => import_sdk_core13.SecretsService,
17057
+ ServiceContext: () => import_sdk_core19.ServiceContext,
17058
+ SessionExpiredError: () => import_sdk_core9.SessionExpiredError,
17059
+ SharingService: () => import_sdk_core15.SharingService,
17060
+ SilentNotificationHandler: () => import_sdk_core8.SilentNotificationHandler,
17061
+ Space: () => import_sdk_core17.Space,
17062
+ SpaceErrorCodes: () => import_sdk_core17.SpaceErrorCodes,
17063
+ SpaceService: () => import_sdk_core17.SpaceService,
17064
+ TinyCloud: () => import_sdk_core7.TinyCloud,
17064
17065
  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,
17066
+ UnsupportedFeatureError: () => import_sdk_core18.UnsupportedFeatureError,
17067
+ VaultHeaders: () => import_sdk_core13.VaultHeaders,
17068
+ VaultPublicSpaceKVActions: () => import_sdk_core13.VaultPublicSpaceKVActions,
17069
+ VersionCheckError: () => import_sdk_core18.VersionCheckError,
17069
17070
  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,
17071
+ buildSpaceUri: () => import_sdk_core17.buildSpaceUri,
17072
+ checkNodeInfo: () => import_sdk_core18.checkNodeInfo,
17073
+ composeManifestRequest: () => import_sdk_core9.composeManifestRequest,
17074
+ createCapabilityKeyRegistry: () => import_sdk_core16.createCapabilityKeyRegistry,
17075
+ createSharingService: () => import_sdk_core15.createSharingService,
17076
+ createSpaceService: () => import_sdk_core17.createSpaceService,
17077
+ createVaultCrypto: () => import_sdk_core13.createVaultCrypto,
17077
17078
  createWasmKeyProvider: () => createWasmKeyProvider,
17078
17079
  defaultSignStrategy: () => defaultSignStrategy,
17079
- defaultSpaceCreationHandler: () => import_sdk_core7.defaultSpaceCreationHandler,
17080
+ defaultSpaceCreationHandler: () => import_sdk_core8.defaultSpaceCreationHandler,
17080
17081
  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,
17082
+ expandActionShortNames: () => import_sdk_core9.expandActionShortNames,
17083
+ isCapabilitySubset: () => import_sdk_core9.isCapabilitySubset,
17084
+ loadManifest: () => import_sdk_core9.loadManifest,
17085
+ makePublicSpaceId: () => import_sdk_core17.makePublicSpaceId,
17086
+ parseExpiry: () => import_sdk_core9.parseExpiry,
17087
+ parseSpaceUri: () => import_sdk_core17.parseSpaceUri,
17088
+ resolveManifest: () => import_sdk_core9.resolveManifest,
17089
+ resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core9.resourceCapabilitiesToSpaceAbilitiesMap,
17089
17090
  serializeDelegation: () => serializeDelegation,
17090
- validateManifest: () => import_sdk_core8.validateManifest
17091
+ validateManifest: () => import_sdk_core9.validateManifest
17091
17092
  });
17092
17093
  module.exports = __toCommonJS(index_exports);
17093
17094
 
@@ -17191,7 +17192,7 @@ var PrivateKeySigner = class {
17191
17192
  };
17192
17193
 
17193
17194
  // src/TinyCloudNode.ts
17194
- var import_sdk_core4 = require("@tinycloud/sdk-core");
17195
+ var import_sdk_core5 = require("@tinycloud/sdk-core");
17195
17196
 
17196
17197
  // src/authorization/NodeUserAuthorization.ts
17197
17198
  var import_sdk_core = require("@tinycloud/sdk-core");
@@ -18237,6 +18238,148 @@ function extractSiweExpiration(siwe) {
18237
18238
  return d;
18238
18239
  }
18239
18240
 
18241
+ // src/NodeSecretsService.ts
18242
+ var import_sdk_core4 = require("@tinycloud/sdk-core");
18243
+ var SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;
18244
+ var SECRET_PREFIX = "secrets/";
18245
+ var SECRETS_SPACE = "secrets";
18246
+ function ok() {
18247
+ return { ok: true, data: void 0 };
18248
+ }
18249
+ function secretsError(code, message, cause) {
18250
+ return {
18251
+ ok: false,
18252
+ error: {
18253
+ code,
18254
+ service: "secrets",
18255
+ message,
18256
+ ...cause ? { cause } : {}
18257
+ }
18258
+ };
18259
+ }
18260
+ function actionUrn(action) {
18261
+ return `tinycloud.kv/${action}`;
18262
+ }
18263
+ function secretResourcePath(base2, name) {
18264
+ return `${base2}/${SECRET_PREFIX}${name}`;
18265
+ }
18266
+ function secretPermissionEntries(name, action) {
18267
+ return [
18268
+ {
18269
+ service: "tinycloud.kv",
18270
+ space: SECRETS_SPACE,
18271
+ path: secretResourcePath("keys", name),
18272
+ actions: [action],
18273
+ skipPrefix: true
18274
+ },
18275
+ {
18276
+ service: "tinycloud.kv",
18277
+ space: SECRETS_SPACE,
18278
+ path: secretResourcePath("vault", name),
18279
+ actions: [action],
18280
+ skipPrefix: true
18281
+ }
18282
+ ];
18283
+ }
18284
+ function isSecretsSpace(space) {
18285
+ return space === SECRETS_SPACE || space.endsWith(`:${SECRETS_SPACE}`);
18286
+ }
18287
+ var NodeSecretsService = class {
18288
+ constructor(config) {
18289
+ this.config = config;
18290
+ this.shouldRestoreUnlock = false;
18291
+ }
18292
+ get vault() {
18293
+ return this.service.vault;
18294
+ }
18295
+ get isUnlocked() {
18296
+ return this.service.isUnlocked;
18297
+ }
18298
+ async unlock(signer) {
18299
+ const effectiveSigner = signer ?? this.config.getUnlockSigner?.();
18300
+ if (effectiveSigner !== void 0) {
18301
+ this.unlockSigner = effectiveSigner;
18302
+ }
18303
+ const result = await this.service.unlock(effectiveSigner);
18304
+ if (result.ok) {
18305
+ this.shouldRestoreUnlock = true;
18306
+ }
18307
+ return result;
18308
+ }
18309
+ lock() {
18310
+ this.shouldRestoreUnlock = false;
18311
+ this.service.lock();
18312
+ }
18313
+ get(name) {
18314
+ return this.service.get(name);
18315
+ }
18316
+ async put(name, value) {
18317
+ const permission = await this.ensureMutationPermission(name, "put");
18318
+ if (!permission.ok) return permission;
18319
+ return this.service.put(name, value);
18320
+ }
18321
+ async delete(name) {
18322
+ const permission = await this.ensureMutationPermission(name, "del");
18323
+ if (!permission.ok) return permission;
18324
+ return this.service.delete(name);
18325
+ }
18326
+ list() {
18327
+ return this.service.list();
18328
+ }
18329
+ get service() {
18330
+ return this.config.getService();
18331
+ }
18332
+ async ensureMutationPermission(name, action) {
18333
+ if (!SECRET_NAME_RE.test(name)) {
18334
+ return secretsError(
18335
+ import_sdk_core4.ErrorCodes.INVALID_INPUT,
18336
+ `Invalid secret name ${JSON.stringify(name)}. Secret names must match ${SECRET_NAME_RE.source}.`
18337
+ );
18338
+ }
18339
+ if (this.hasMutationPermission(name, action)) {
18340
+ return ok();
18341
+ }
18342
+ if (!this.config.canEscalate()) {
18343
+ return secretsError(
18344
+ import_sdk_core4.ErrorCodes.PERMISSION_DENIED,
18345
+ `Cannot autosign ${actionUrn(action)} for ${name}; TinyCloudNode needs wallet mode with a signer or privateKey.`
18346
+ );
18347
+ }
18348
+ try {
18349
+ await this.config.grantPermissions(secretPermissionEntries(name, action));
18350
+ return this.restoreUnlockAfterEscalation();
18351
+ } catch (error) {
18352
+ return secretsError(
18353
+ import_sdk_core4.ErrorCodes.PERMISSION_DENIED,
18354
+ error instanceof Error ? error.message : `Autosign escalation for ${actionUrn(action)} on ${name} failed.`,
18355
+ error instanceof Error ? error : void 0
18356
+ );
18357
+ }
18358
+ }
18359
+ async restoreUnlockAfterEscalation() {
18360
+ if (!this.shouldRestoreUnlock) {
18361
+ return ok();
18362
+ }
18363
+ return this.service.unlock(this.unlockSigner);
18364
+ }
18365
+ hasMutationPermission(name, action) {
18366
+ const manifest = this.config.getManifest();
18367
+ if (manifest === void 0) {
18368
+ return false;
18369
+ }
18370
+ const manifests = Array.isArray(manifest) ? manifest : [manifest];
18371
+ const requiredAction = actionUrn(action);
18372
+ return manifests.some((entry) => {
18373
+ const resolved = (0, import_sdk_core4.resolveManifest)(entry);
18374
+ return ["keys", "vault"].every(
18375
+ (base2) => resolved.resources.some(
18376
+ (resource) => resource.service === "tinycloud.kv" && isSecretsSpace(resource.space) && resource.path === secretResourcePath(base2, name) && resource.actions.includes(requiredAction)
18377
+ )
18378
+ );
18379
+ });
18380
+ }
18381
+ };
18382
+
18240
18383
  // src/TinyCloudNode.ts
18241
18384
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
18242
18385
  var _TinyCloudNode = class _TinyCloudNode {
@@ -18268,6 +18411,30 @@ var _TinyCloudNode = class _TinyCloudNode {
18268
18411
  this.auth = null;
18269
18412
  this.tc = null;
18270
18413
  this._chainId = 1;
18414
+ this.runtimePermissionGrants = [];
18415
+ this.invokeWithRuntimePermissions = (session, service, path, action, facts) => {
18416
+ return this.wasmBindings.invoke(
18417
+ this.selectInvocationSession(session, service, path, action),
18418
+ service,
18419
+ path,
18420
+ action,
18421
+ facts
18422
+ );
18423
+ };
18424
+ this.invokeAnyWithRuntimePermissions = (session, entries, facts) => {
18425
+ if (!this.wasmBindings.invokeAny) {
18426
+ throw new Error("WASM binding does not support invokeAny");
18427
+ }
18428
+ const grant = this.findGrantForOperations(
18429
+ entries.map((entry) => ({
18430
+ spaceId: entry.spaceId,
18431
+ service: this.invocationServiceName(entry.service),
18432
+ path: entry.path,
18433
+ action: entry.action
18434
+ }))
18435
+ );
18436
+ return this.wasmBindings.invokeAny(grant?.session ?? session, entries, facts);
18437
+ };
18271
18438
  this.explicitHost = config.host;
18272
18439
  this.config = {
18273
18440
  ...config,
@@ -18295,23 +18462,23 @@ var _TinyCloudNode = class _TinyCloudNode {
18295
18462
  throw new Error("Failed to get session key JWK");
18296
18463
  }
18297
18464
  this.sessionKeyJwk = JSON.parse(jwkStr);
18298
- this._capabilityRegistry = new import_sdk_core4.CapabilityKeyRegistry();
18465
+ this._capabilityRegistry = new import_sdk_core5.CapabilityKeyRegistry();
18299
18466
  this._keyProvider = new WasmKeyProvider({
18300
18467
  sessionManager: this.sessionManager
18301
18468
  });
18302
- this.notificationHandler = config.notificationHandler ?? new import_sdk_core4.SilentNotificationHandler();
18303
- this._sharingService = new import_sdk_core4.SharingService({
18469
+ this.notificationHandler = config.notificationHandler ?? new import_sdk_core5.SilentNotificationHandler();
18470
+ this._sharingService = new import_sdk_core5.SharingService({
18304
18471
  hosts: [this.config.host],
18305
18472
  // session: undefined - not needed for receive()
18306
- invoke: this.wasmBindings.invoke,
18473
+ invoke: this.invokeWithRuntimePermissions,
18307
18474
  fetch: globalThis.fetch.bind(globalThis),
18308
18475
  keyProvider: this._keyProvider,
18309
18476
  registry: this._capabilityRegistry,
18310
18477
  // delegationManager: undefined - not needed for receive()
18311
18478
  createKVService: (config2) => {
18312
18479
  const prefix = config2.pathPrefix?.replace(/\/$/, "");
18313
- const kvService = new import_sdk_core4.KVService({ prefix });
18314
- const kvContext = new import_sdk_core4.ServiceContext({
18480
+ const kvService = new import_sdk_core5.KVService({ prefix });
18481
+ const kvContext = new import_sdk_core5.ServiceContext({
18315
18482
  invoke: config2.invoke,
18316
18483
  fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
18317
18484
  hosts: config2.hosts
@@ -18370,8 +18537,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18370
18537
  capabilityRequest: config.capabilityRequest,
18371
18538
  includeAccountRegistryPermissions: config.includeAccountRegistryPermissions
18372
18539
  });
18373
- this.tc = new import_sdk_core4.TinyCloud(this.auth, {
18374
- invokeAny: this.wasmBindings.invokeAny
18540
+ this.tc = new import_sdk_core5.TinyCloud(this.auth, {
18541
+ invokeAny: this.invokeAnyWithRuntimePermissions
18375
18542
  });
18376
18543
  }
18377
18544
  syncResolvedHostFromAuth() {
@@ -18491,7 +18658,12 @@ var _TinyCloudNode = class _TinyCloudNode {
18491
18658
  this._sql = void 0;
18492
18659
  this._duckdb = void 0;
18493
18660
  this._hooks = void 0;
18661
+ this._vault = void 0;
18662
+ this._baseSecrets = void 0;
18663
+ this._secrets = void 0;
18664
+ this._spaceService = void 0;
18494
18665
  this._serviceContext = void 0;
18666
+ this.runtimePermissionGrants = [];
18495
18667
  await this.tc.signIn(options);
18496
18668
  this.syncResolvedHostFromAuth();
18497
18669
  this.initializeServices();
@@ -18512,7 +18684,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18512
18684
  if (!this.auth || !this.signer) {
18513
18685
  throw new Error("Manifest registry write requires wallet mode");
18514
18686
  }
18515
- const accountSpaceId = this.ownedSpaceId(import_sdk_core4.ACCOUNT_REGISTRY_SPACE);
18687
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core5.ACCOUNT_REGISTRY_SPACE);
18516
18688
  await this.ensureOwnedSpaceHosted(accountSpaceId);
18517
18689
  const accountKV = this.spaces.get(accountSpaceId).kv;
18518
18690
  for (const record of request.registryRecords) {
@@ -18540,7 +18712,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18540
18712
  if (!host) {
18541
18713
  throw new Error("Owned space hosting requires a TinyCloud host");
18542
18714
  }
18543
- const activation = await (0, import_sdk_core4.activateSessionWithHost)(host, session.delegationHeader);
18715
+ const activation = await (0, import_sdk_core5.activateSessionWithHost)(host, session.delegationHeader);
18544
18716
  if (activation.success && !activation.skipped?.includes(spaceId)) {
18545
18717
  return;
18546
18718
  }
@@ -18554,7 +18726,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18554
18726
  throw new Error(`Failed to create owned space: ${spaceId}`);
18555
18727
  }
18556
18728
  await new Promise((resolve) => setTimeout(resolve, 100));
18557
- const retry = await (0, import_sdk_core4.activateSessionWithHost)(host, session.delegationHeader);
18729
+ const retry = await (0, import_sdk_core5.activateSessionWithHost)(host, session.delegationHeader);
18558
18730
  if (!retry.success || retry.skipped?.includes(spaceId)) {
18559
18731
  throw new Error(
18560
18732
  `Failed to activate session after creating owned space ${spaceId}: ${retry.error ?? "space was skipped"}`
@@ -18576,29 +18748,34 @@ var _TinyCloudNode = class _TinyCloudNode {
18576
18748
  this._sql = void 0;
18577
18749
  this._duckdb = void 0;
18578
18750
  this._hooks = void 0;
18751
+ this._vault = void 0;
18752
+ this._baseSecrets = void 0;
18753
+ this._secrets = void 0;
18754
+ this._spaceService = void 0;
18579
18755
  this._serviceContext = void 0;
18756
+ this.runtimePermissionGrants = [];
18580
18757
  if (sessionData.address) {
18581
18758
  this._address = sessionData.address;
18582
18759
  }
18583
18760
  if (sessionData.chainId) {
18584
18761
  this._chainId = sessionData.chainId;
18585
18762
  }
18586
- this._serviceContext = new import_sdk_core4.ServiceContext({
18587
- invoke: this.wasmBindings.invoke,
18588
- invokeAny: this.wasmBindings.invokeAny,
18763
+ this._serviceContext = new import_sdk_core5.ServiceContext({
18764
+ invoke: this.invokeWithRuntimePermissions,
18765
+ invokeAny: this.invokeAnyWithRuntimePermissions,
18589
18766
  fetch: globalThis.fetch.bind(globalThis),
18590
18767
  hosts: [this.config.host]
18591
18768
  });
18592
- this._kv = new import_sdk_core4.KVService({});
18769
+ this._kv = new import_sdk_core5.KVService({});
18593
18770
  this._kv.initialize(this._serviceContext);
18594
18771
  this._serviceContext.registerService("kv", this._kv);
18595
- this._sql = new import_sdk_core4.SQLService({});
18772
+ this._sql = new import_sdk_core5.SQLService({});
18596
18773
  this._sql.initialize(this._serviceContext);
18597
18774
  this._serviceContext.registerService("sql", this._sql);
18598
- this._duckdb = new import_sdk_core4.DuckDbService({});
18775
+ this._duckdb = new import_sdk_core5.DuckDbService({});
18599
18776
  this._duckdb.initialize(this._serviceContext);
18600
18777
  this._serviceContext.registerService("duckdb", this._duckdb);
18601
- this._hooks = new import_sdk_core4.HooksService({});
18778
+ this._hooks = new import_sdk_core5.HooksService({});
18602
18779
  this._hooks.initialize(this._serviceContext);
18603
18780
  this._serviceContext.registerService("hooks", this._hooks);
18604
18781
  const serviceSession = {
@@ -18609,41 +18786,7 @@ var _TinyCloudNode = class _TinyCloudNode {
18609
18786
  jwk: sessionData.jwk
18610
18787
  };
18611
18788
  this._serviceContext.setSession(serviceSession);
18612
- const wasm = this.wasmBindings;
18613
- const vaultCrypto = (0, import_sdk_core4.createVaultCrypto)({
18614
- vault_encrypt: wasm.vault_encrypt,
18615
- vault_decrypt: wasm.vault_decrypt,
18616
- vault_derive_key: wasm.vault_derive_key,
18617
- vault_x25519_from_seed: wasm.vault_x25519_from_seed,
18618
- vault_x25519_dh: wasm.vault_x25519_dh,
18619
- vault_random_bytes: wasm.vault_random_bytes,
18620
- vault_sha256: wasm.vault_sha256
18621
- });
18622
- const self2 = this;
18623
- this._vault = new import_sdk_core4.DataVaultService({
18624
- spaceId: sessionData.spaceId,
18625
- crypto: vaultCrypto,
18626
- tc: {
18627
- kv: this._kv,
18628
- ensurePublicSpace: async () => {
18629
- try {
18630
- await self2.ensurePublicSpace();
18631
- return { ok: true, data: void 0 };
18632
- } catch (error) {
18633
- return { ok: false, error: { code: "STORAGE_ERROR", message: error instanceof Error ? error.message : String(error), service: "vault" } };
18634
- }
18635
- },
18636
- get publicKV() {
18637
- return self2._publicKV ?? self2.tc.publicKV;
18638
- },
18639
- readPublicSpace: (host, spaceId, key2) => import_sdk_core4.TinyCloud.readPublicSpace(host, spaceId, key2),
18640
- makePublicSpaceId: import_sdk_core4.TinyCloud.makePublicSpaceId,
18641
- did: this.did,
18642
- address: sessionData.address ?? this._address ?? "",
18643
- chainId: sessionData.chainId ?? this._chainId,
18644
- hosts: [this.config.host]
18645
- }
18646
- });
18789
+ this._vault = this.createVaultService(sessionData.spaceId, this._kv);
18647
18790
  this._vault.initialize(this._serviceContext);
18648
18791
  this._serviceContext.registerService("vault", this._vault);
18649
18792
  this.initializeV2Services(serviceSession);
@@ -18704,8 +18847,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18704
18847
  capabilityRequest: this.config.capabilityRequest,
18705
18848
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
18706
18849
  });
18707
- this.tc = new import_sdk_core4.TinyCloud(this.auth, {
18708
- invokeAny: this.wasmBindings.invokeAny
18850
+ this.tc = new import_sdk_core5.TinyCloud(this.auth, {
18851
+ invokeAny: this.invokeAnyWithRuntimePermissions
18709
18852
  });
18710
18853
  this.config.prefix = prefix;
18711
18854
  }
@@ -18748,8 +18891,8 @@ var _TinyCloudNode = class _TinyCloudNode {
18748
18891
  capabilityRequest: this.config.capabilityRequest,
18749
18892
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
18750
18893
  });
18751
- this.tc = new import_sdk_core4.TinyCloud(this.auth, {
18752
- invokeAny: this.wasmBindings.invokeAny
18894
+ this.tc = new import_sdk_core5.TinyCloud(this.auth, {
18895
+ invokeAny: this.invokeAnyWithRuntimePermissions
18753
18896
  });
18754
18897
  this.config.prefix = prefix;
18755
18898
  }
@@ -18762,28 +18905,28 @@ var _TinyCloudNode = class _TinyCloudNode {
18762
18905
  if (!session) {
18763
18906
  return;
18764
18907
  }
18765
- this.tc.initializeServices(this.wasmBindings.invoke, [this.config.host]);
18766
- this._serviceContext = new import_sdk_core4.ServiceContext({
18767
- invoke: this.wasmBindings.invoke,
18768
- invokeAny: this.wasmBindings.invokeAny,
18908
+ this.tc.initializeServices(this.invokeWithRuntimePermissions, [this.config.host]);
18909
+ this._serviceContext = new import_sdk_core5.ServiceContext({
18910
+ invoke: this.invokeWithRuntimePermissions,
18911
+ invokeAny: this.invokeAnyWithRuntimePermissions,
18769
18912
  fetch: globalThis.fetch.bind(globalThis),
18770
18913
  hosts: [this.config.host]
18771
18914
  });
18772
- this._kv = new import_sdk_core4.KVService({});
18915
+ this._kv = new import_sdk_core5.KVService({});
18773
18916
  this._kv.initialize(this._serviceContext);
18774
18917
  this._serviceContext.registerService("kv", this._kv);
18775
18918
  const features = this.nodeFeatures;
18776
18919
  if (features.length === 0 || features.includes("sql")) {
18777
- this._sql = new import_sdk_core4.SQLService({});
18920
+ this._sql = new import_sdk_core5.SQLService({});
18778
18921
  this._sql.initialize(this._serviceContext);
18779
18922
  this._serviceContext.registerService("sql", this._sql);
18780
18923
  }
18781
18924
  if (features.length === 0 || features.includes("duckdb")) {
18782
- this._duckdb = new import_sdk_core4.DuckDbService({});
18925
+ this._duckdb = new import_sdk_core5.DuckDbService({});
18783
18926
  this._duckdb.initialize(this._serviceContext);
18784
18927
  this._serviceContext.registerService("duckdb", this._duckdb);
18785
18928
  }
18786
- this._hooks = new import_sdk_core4.HooksService({});
18929
+ this._hooks = new import_sdk_core5.HooksService({});
18787
18930
  this._hooks.initialize(this._serviceContext);
18788
18931
  this._serviceContext.registerService("hooks", this._hooks);
18789
18932
  const serviceSession = {
@@ -18795,8 +18938,30 @@ var _TinyCloudNode = class _TinyCloudNode {
18795
18938
  };
18796
18939
  this._serviceContext.setSession(serviceSession);
18797
18940
  this.tc.serviceContext.setSession(serviceSession);
18941
+ this._vault = this.createVaultService(session.spaceId, this._kv);
18942
+ this._vault.initialize(this._serviceContext);
18943
+ this._serviceContext.registerService("vault", this._vault);
18944
+ this.initializeV2Services(serviceSession);
18945
+ }
18946
+ createSpaceScopedKVService(spaceId) {
18947
+ const kvService = new import_sdk_core5.KVService({});
18948
+ if (this._serviceContext) {
18949
+ const spaceScopedContext = new import_sdk_core5.ServiceContext({
18950
+ invoke: this._serviceContext.invoke,
18951
+ fetch: this._serviceContext.fetch,
18952
+ hosts: this._serviceContext.hosts
18953
+ });
18954
+ const session = this._serviceContext.session;
18955
+ if (session) {
18956
+ spaceScopedContext.setSession({ ...session, spaceId });
18957
+ }
18958
+ kvService.initialize(spaceScopedContext);
18959
+ }
18960
+ return kvService;
18961
+ }
18962
+ createVaultService(spaceId, kv) {
18798
18963
  const wasm = this.wasmBindings;
18799
- const vaultCrypto = (0, import_sdk_core4.createVaultCrypto)({
18964
+ const vaultCrypto = (0, import_sdk_core5.createVaultCrypto)({
18800
18965
  vault_encrypt: wasm.vault_encrypt,
18801
18966
  vault_decrypt: wasm.vault_decrypt,
18802
18967
  vault_derive_key: wasm.vault_derive_key,
@@ -18806,11 +18971,11 @@ var _TinyCloudNode = class _TinyCloudNode {
18806
18971
  vault_sha256: wasm.vault_sha256
18807
18972
  });
18808
18973
  const self2 = this;
18809
- this._vault = new import_sdk_core4.DataVaultService({
18810
- spaceId: session.spaceId,
18974
+ return new import_sdk_core5.DataVaultService({
18975
+ spaceId,
18811
18976
  crypto: vaultCrypto,
18812
18977
  tc: {
18813
- kv: this._kv,
18978
+ kv,
18814
18979
  ensurePublicSpace: async () => {
18815
18980
  try {
18816
18981
  await self2.ensurePublicSpace();
@@ -18822,24 +18987,21 @@ var _TinyCloudNode = class _TinyCloudNode {
18822
18987
  get publicKV() {
18823
18988
  return self2._publicKV ?? self2.tc.publicKV;
18824
18989
  },
18825
- readPublicSpace: (host, spaceId, key2) => import_sdk_core4.TinyCloud.readPublicSpace(host, spaceId, key2),
18826
- makePublicSpaceId: import_sdk_core4.TinyCloud.makePublicSpaceId,
18990
+ readPublicSpace: (host, targetSpaceId, key2) => import_sdk_core5.TinyCloud.readPublicSpace(host, targetSpaceId, key2),
18991
+ makePublicSpaceId: import_sdk_core5.TinyCloud.makePublicSpaceId,
18827
18992
  did: this.did,
18828
- address: this._address,
18993
+ address: this._address ?? "",
18829
18994
  chainId: this._chainId,
18830
18995
  hosts: [this.config.host]
18831
18996
  }
18832
18997
  });
18833
- this._vault.initialize(this._serviceContext);
18834
- this._serviceContext.registerService("vault", this._vault);
18835
- this.initializeV2Services(serviceSession);
18836
18998
  }
18837
18999
  /**
18838
19000
  * Initialize the v2 delegation system services.
18839
19001
  * @internal
18840
19002
  */
18841
19003
  initializeV2Services(serviceSession) {
18842
- this._capabilityRegistry = new import_sdk_core4.CapabilityKeyRegistry();
19004
+ this._capabilityRegistry = new import_sdk_core5.CapabilityKeyRegistry();
18843
19005
  const tcSession = this.auth?.tinyCloudSession;
18844
19006
  if (tcSession && this._address) {
18845
19007
  const sessionKey = {
@@ -18913,13 +19075,13 @@ var _TinyCloudNode = class _TinyCloudNode {
18913
19075
  }
18914
19076
  this._capabilityRegistry.registerKey(sessionKey, delegations);
18915
19077
  }
18916
- this._delegationManager = new import_sdk_core4.DelegationManager({
19078
+ this._delegationManager = new import_sdk_core5.DelegationManager({
18917
19079
  hosts: [this.config.host],
18918
19080
  session: serviceSession,
18919
- invoke: this.wasmBindings.invoke,
19081
+ invoke: this.invokeWithRuntimePermissions,
18920
19082
  fetch: globalThis.fetch.bind(globalThis)
18921
19083
  });
18922
- this._spaceService = new import_sdk_core4.SpaceService({
19084
+ this._spaceService = new import_sdk_core5.SpaceService({
18923
19085
  hosts: [this.config.host],
18924
19086
  session: serviceSession,
18925
19087
  invoke: this.wasmBindings.invoke,
@@ -18927,20 +19089,15 @@ var _TinyCloudNode = class _TinyCloudNode {
18927
19089
  capabilityRegistry: this._capabilityRegistry,
18928
19090
  userDid: this.did,
18929
19091
  createKVService: (spaceId) => {
18930
- const kvService = new import_sdk_core4.KVService({});
19092
+ return this.createSpaceScopedKVService(spaceId);
19093
+ },
19094
+ createVaultService: (spaceId) => {
19095
+ const kvService = this.createSpaceScopedKVService(spaceId);
19096
+ const vaultService = this.createVaultService(spaceId, kvService);
18931
19097
  if (this._serviceContext) {
18932
- const spaceScopedContext = new import_sdk_core4.ServiceContext({
18933
- invoke: this._serviceContext.invoke,
18934
- fetch: this._serviceContext.fetch,
18935
- hosts: this._serviceContext.hosts
18936
- });
18937
- const session = this._serviceContext.session;
18938
- if (session) {
18939
- spaceScopedContext.setSession({ ...session, spaceId });
18940
- }
18941
- kvService.initialize(spaceScopedContext);
19098
+ vaultService.initialize(this._serviceContext);
18942
19099
  }
18943
- return kvService;
19100
+ return vaultService;
18944
19101
  },
18945
19102
  // Enable space.delegations.create() via SIWE-based delegation
18946
19103
  createDelegation: async (params) => {
@@ -19081,7 +19238,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19081
19238
  ...prepared,
19082
19239
  signature: signature2
19083
19240
  });
19084
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
19241
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19085
19242
  host,
19086
19243
  delegationSession.delegationHeader
19087
19244
  );
@@ -19148,7 +19305,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19148
19305
  if (!this._sql) {
19149
19306
  const features = this.nodeFeatures;
19150
19307
  if (features.length > 0 && !features.includes("sql")) {
19151
- throw new import_sdk_core4.UnsupportedFeatureError("sql", this.config.host, features);
19308
+ throw new import_sdk_core5.UnsupportedFeatureError("sql", this.config.host, features);
19152
19309
  }
19153
19310
  throw new Error("Not signed in. Call signIn() first.");
19154
19311
  }
@@ -19161,7 +19318,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19161
19318
  if (!this._duckdb) {
19162
19319
  const features = this.nodeFeatures;
19163
19320
  if (features.length > 0 && !features.includes("duckdb")) {
19164
- throw new import_sdk_core4.UnsupportedFeatureError("duckdb", this.config.host, features);
19321
+ throw new import_sdk_core5.UnsupportedFeatureError("duckdb", this.config.host, features);
19165
19322
  }
19166
19323
  throw new Error("Not signed in. Call signIn() first.");
19167
19324
  }
@@ -19177,6 +19334,33 @@ var _TinyCloudNode = class _TinyCloudNode {
19177
19334
  }
19178
19335
  return this._vault;
19179
19336
  }
19337
+ /**
19338
+ * App-facing secrets API backed by the `secrets` space vault.
19339
+ */
19340
+ get secrets() {
19341
+ if (!this._spaceService) {
19342
+ throw new Error("Not signed in. Call signIn() first.");
19343
+ }
19344
+ if (!this._secrets) {
19345
+ this._secrets = new NodeSecretsService({
19346
+ getService: () => this.getBaseSecrets(),
19347
+ getManifest: () => this.manifest,
19348
+ grantPermissions: (additional) => this.grantRuntimePermissions(additional),
19349
+ canEscalate: () => this.signer !== void 0 && this.tc !== void 0,
19350
+ getUnlockSigner: () => this.signer ?? void 0
19351
+ });
19352
+ }
19353
+ return this._secrets;
19354
+ }
19355
+ getBaseSecrets() {
19356
+ if (!this._spaceService) {
19357
+ throw new Error("Not signed in. Call signIn() first.");
19358
+ }
19359
+ if (!this._baseSecrets) {
19360
+ this._baseSecrets = new import_sdk_core5.SecretsService(() => this.space("secrets").vault);
19361
+ }
19362
+ return this._baseSecrets;
19363
+ }
19180
19364
  /**
19181
19365
  * Hooks write stream subscription API.
19182
19366
  */
@@ -19247,6 +19431,171 @@ var _TinyCloudNode = class _TinyCloudNode {
19247
19431
  }
19248
19432
  };
19249
19433
  }
19434
+ /**
19435
+ * Check whether the current session or an approved runtime delegation covers
19436
+ * every requested permission.
19437
+ */
19438
+ hasRuntimePermissions(permissions) {
19439
+ const session = this.auth?.tinyCloudSession;
19440
+ if (!session || !Array.isArray(permissions) || permissions.length === 0) {
19441
+ return false;
19442
+ }
19443
+ const expanded = this.expandPermissionEntries(permissions);
19444
+ if (this.sessionCoversPermissionEntries(session, expanded)) {
19445
+ return true;
19446
+ }
19447
+ return this.findRuntimeGrantsForPermissionEntries(expanded, session).length > 0;
19448
+ }
19449
+ /**
19450
+ * Return installed runtime permission delegations. When `permissions` is
19451
+ * provided, only delegations currently covering those permissions are
19452
+ * returned. Base-session manifest permissions are not represented here.
19453
+ */
19454
+ getRuntimePermissionDelegations(permissions) {
19455
+ this.pruneExpiredRuntimePermissionGrants();
19456
+ if (permissions === void 0) {
19457
+ return this.runtimePermissionGrants.map((grant) => grant.delegation);
19458
+ }
19459
+ const session = this.auth?.tinyCloudSession;
19460
+ if (!session || !Array.isArray(permissions) || permissions.length === 0) {
19461
+ return [];
19462
+ }
19463
+ const expanded = this.expandPermissionEntries(permissions);
19464
+ return this.findRuntimeGrantsForPermissionEntries(expanded, session).map(
19465
+ (grant) => grant.delegation
19466
+ );
19467
+ }
19468
+ /**
19469
+ * Install a portable runtime permission delegation into this SDK instance so
19470
+ * matching service calls and downstream `delegateTo()` calls can use it.
19471
+ */
19472
+ async useRuntimeDelegation(delegation) {
19473
+ const session = this.auth?.tinyCloudSession;
19474
+ if (!session) {
19475
+ throw new import_sdk_core5.SessionExpiredError(/* @__PURE__ */ new Date(0));
19476
+ }
19477
+ if (delegation.expiry.getTime() <= Date.now()) {
19478
+ throw new import_sdk_core5.SessionExpiredError(delegation.expiry);
19479
+ }
19480
+ const expectedDids = /* @__PURE__ */ new Set([session.verificationMethod, this.sessionDid]);
19481
+ if (!expectedDids.has(delegation.delegateDID)) {
19482
+ throw new Error(
19483
+ `Runtime delegation targets ${delegation.delegateDID} but this session key is ${session.verificationMethod}.`
19484
+ );
19485
+ }
19486
+ const targetHost = delegation.host ?? this.config.host;
19487
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19488
+ targetHost,
19489
+ delegation.delegationHeader
19490
+ );
19491
+ if (!activateResult.success) {
19492
+ throw new Error(
19493
+ `Failed to activate runtime permission delegation: ${activateResult.error}`
19494
+ );
19495
+ }
19496
+ this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
19497
+ (grant) => grant.delegation.cid !== delegation.cid
19498
+ );
19499
+ this.runtimePermissionGrants.push(
19500
+ this.runtimeGrantFromDelegation(delegation, session)
19501
+ );
19502
+ }
19503
+ /**
19504
+ * Store additional permissions as narrow delegations to the current session
19505
+ * key. Future service invocations automatically use a stored delegation when
19506
+ * its `(space, service, path, action)` covers the request.
19507
+ */
19508
+ async grantRuntimePermissions(permissions, options) {
19509
+ if (!Array.isArray(permissions) || permissions.length === 0) {
19510
+ throw new Error("grantRuntimePermissions requires a non-empty permissions array");
19511
+ }
19512
+ const session = this.auth?.tinyCloudSession;
19513
+ if (!session) {
19514
+ throw new import_sdk_core5.SessionExpiredError(/* @__PURE__ */ new Date(0));
19515
+ }
19516
+ const sessionExpiry = extractSiweExpiration(session.siwe);
19517
+ if (sessionExpiry !== void 0) {
19518
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19519
+ if (sessionExpiry.getTime() <= Date.now() + marginMs) {
19520
+ throw new import_sdk_core5.SessionExpiredError(sessionExpiry);
19521
+ }
19522
+ }
19523
+ const expanded = this.expandPermissionEntries(permissions);
19524
+ if (this.sessionCoversPermissionEntries(session, expanded)) {
19525
+ return [];
19526
+ }
19527
+ const existingGrants = this.findRuntimeGrantsForPermissionEntries(expanded, session);
19528
+ if (existingGrants.length > 0) {
19529
+ return existingGrants.map((grant) => grant.delegation);
19530
+ }
19531
+ if (!this.signer) {
19532
+ throw new Error(
19533
+ "grantRuntimePermissions requires wallet mode with a signer or privateKey."
19534
+ );
19535
+ }
19536
+ const bySpace = /* @__PURE__ */ new Map();
19537
+ for (const entry of expanded) {
19538
+ const spaceId = this.resolvePermissionSpace(entry.space, session);
19539
+ const current = bySpace.get(spaceId) ?? [];
19540
+ current.push(entry);
19541
+ bySpace.set(spaceId, current);
19542
+ }
19543
+ const now = /* @__PURE__ */ new Date();
19544
+ const requestedExpiryMs = resolveExpiryMs(options?.expiry);
19545
+ let expiresAt = new Date(now.getTime() + requestedExpiryMs);
19546
+ if (sessionExpiry !== void 0 && sessionExpiry < expiresAt) {
19547
+ expiresAt = sessionExpiry;
19548
+ }
19549
+ const delegations = [];
19550
+ for (const [spaceId, entries] of bySpace) {
19551
+ const abilities = this.permissionsToAbilities(entries);
19552
+ const prepared = this.wasmBindings.prepareSession({
19553
+ abilities,
19554
+ address: this.wasmBindings.ensureEip55(session.address),
19555
+ chainId: session.chainId,
19556
+ domain: this.siweDomain,
19557
+ issuedAt: now.toISOString(),
19558
+ expirationTime: expiresAt.toISOString(),
19559
+ spaceId,
19560
+ jwk: session.jwk
19561
+ });
19562
+ const signature2 = await this.signer.signMessage(prepared.siwe);
19563
+ const delegatedSession = this.wasmBindings.completeSessionSetup({
19564
+ ...prepared,
19565
+ signature: signature2
19566
+ });
19567
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19568
+ this.config.host,
19569
+ delegatedSession.delegationHeader
19570
+ );
19571
+ if (!activateResult.success) {
19572
+ throw new Error(
19573
+ `Failed to activate runtime permission delegation: ${activateResult.error}`
19574
+ );
19575
+ }
19576
+ const delegation = this.runtimeDelegationFromSession(
19577
+ delegatedSession,
19578
+ entries,
19579
+ spaceId,
19580
+ session,
19581
+ expiresAt
19582
+ );
19583
+ this.runtimePermissionGrants.push({
19584
+ session: {
19585
+ delegationHeader: delegatedSession.delegationHeader,
19586
+ delegationCid: delegatedSession.delegationCid,
19587
+ spaceId,
19588
+ verificationMethod: session.verificationMethod,
19589
+ jwk: session.jwk
19590
+ },
19591
+ delegation,
19592
+ operations: this.permissionOperations(entries, spaceId),
19593
+ expiresAt
19594
+ });
19595
+ delegations.push(delegation);
19596
+ }
19597
+ return delegations;
19598
+ }
19250
19599
  /**
19251
19600
  * Get the DelegationManager for delegation CRUD operations.
19252
19601
  *
@@ -19315,6 +19664,12 @@ var _TinyCloudNode = class _TinyCloudNode {
19315
19664
  get spaceService() {
19316
19665
  return this.spaces;
19317
19666
  }
19667
+ /**
19668
+ * Get a Space object by short name or full URI.
19669
+ */
19670
+ space(nameOrUri) {
19671
+ return this.spaces.get(nameOrUri);
19672
+ }
19318
19673
  /**
19319
19674
  * Get the SharingService for creating and receiving v2 sharing links.
19320
19675
  *
@@ -19400,7 +19755,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19400
19755
  ...prepared,
19401
19756
  signature: signature2
19402
19757
  });
19403
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
19758
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19404
19759
  this.config.host,
19405
19760
  delegationSession.delegationHeader
19406
19761
  );
@@ -19427,9 +19782,9 @@ var _TinyCloudNode = class _TinyCloudNode {
19427
19782
  }]);
19428
19783
  }
19429
19784
  if (this._serviceContext) {
19430
- const publicKV = new import_sdk_core4.KVService({ prefix: "" });
19431
- const publicContext = new import_sdk_core4.ServiceContext({
19432
- invoke: this.wasmBindings.invoke,
19785
+ const publicKV = new import_sdk_core5.KVService({ prefix: "" });
19786
+ const publicContext = new import_sdk_core5.ServiceContext({
19787
+ invoke: this.invokeWithRuntimePermissions,
19433
19788
  fetch: this._serviceContext.fetch,
19434
19789
  hosts: this._serviceContext.hosts
19435
19790
  });
@@ -19517,8 +19872,9 @@ var _TinyCloudNode = class _TinyCloudNode {
19517
19872
  * Issue a delegation using the capability-chain flow.
19518
19873
  *
19519
19874
  * When every requested permission is a subset of the current
19520
- * session's recap, the delegation is signed by the session key via
19521
- * WASM no wallet prompt. When at least one is NOT derivable, a
19875
+ * session's recap, or of one installed runtime permission delegation,
19876
+ * the delegation is signed by the session key via WASM no wallet
19877
+ * prompt. When at least one is NOT derivable, a
19522
19878
  * {@link PermissionNotInManifestError} is raised (carrying the
19523
19879
  * missing entries) so the caller can trigger an escalation flow
19524
19880
  * (e.g. `TinyCloudWeb.requestPermissions`). Passing
@@ -19553,14 +19909,14 @@ var _TinyCloudNode = class _TinyCloudNode {
19553
19909
  async delegateTo(did, permissions, options) {
19554
19910
  const session = this.auth?.tinyCloudSession;
19555
19911
  if (!session) {
19556
- throw new import_sdk_core4.SessionExpiredError(/* @__PURE__ */ new Date(0));
19912
+ throw new import_sdk_core5.SessionExpiredError(/* @__PURE__ */ new Date(0));
19557
19913
  }
19558
19914
  const sessionExpiry = extractSiweExpiration(session.siwe);
19559
19915
  if (sessionExpiry !== void 0) {
19560
19916
  const now2 = Date.now();
19561
19917
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19562
19918
  if (sessionExpiry.getTime() <= now2 + marginMs) {
19563
- throw new import_sdk_core4.SessionExpiredError(sessionExpiry);
19919
+ throw new import_sdk_core5.SessionExpiredError(sessionExpiry);
19564
19920
  }
19565
19921
  }
19566
19922
  if (!Array.isArray(permissions) || permissions.length === 0) {
@@ -19570,7 +19926,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19570
19926
  }
19571
19927
  const expandedEntries = permissions.map((entry) => ({
19572
19928
  ...entry,
19573
- actions: (0, import_sdk_core4.expandActionShortNames)(entry.service, entry.actions)
19929
+ actions: (0, import_sdk_core5.expandActionShortNames)(entry.service, entry.actions)
19574
19930
  }));
19575
19931
  const now = /* @__PURE__ */ new Date();
19576
19932
  const expiryMs = resolveExpiryMs(options?.expiry);
@@ -19592,13 +19948,30 @@ var _TinyCloudNode = class _TinyCloudNode {
19592
19948
  );
19593
19949
  return { delegation: delegation2, prompted: true };
19594
19950
  }
19595
- const granted = (0, import_sdk_core4.parseRecapCapabilities)(
19951
+ const granted = (0, import_sdk_core5.parseRecapCapabilities)(
19596
19952
  (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
19597
19953
  session.siwe
19598
19954
  );
19599
- const { subset, missing } = (0, import_sdk_core4.isCapabilitySubset)(expandedEntries, granted);
19955
+ const { subset, missing } = (0, import_sdk_core5.isCapabilitySubset)(expandedEntries, granted);
19600
19956
  if (!subset) {
19601
- throw new import_sdk_core4.PermissionNotInManifestError(missing, granted);
19957
+ const runtimeGrant = this.findGrantForOperations(
19958
+ this.permissionEntriesToOperations(expandedEntries, session)
19959
+ );
19960
+ if (runtimeGrant) {
19961
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19962
+ if (runtimeGrant.expiresAt.getTime() <= Date.now() + marginMs) {
19963
+ throw new import_sdk_core5.SessionExpiredError(runtimeGrant.expiresAt);
19964
+ }
19965
+ const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
19966
+ const delegation2 = await this.createDelegationViaRuntimeGrant(
19967
+ did,
19968
+ expandedEntries,
19969
+ runtimeExpiration,
19970
+ runtimeGrant
19971
+ );
19972
+ return { delegation: delegation2, prompted: false };
19973
+ }
19974
+ throw new import_sdk_core5.PermissionNotInManifestError(missing, granted);
19602
19975
  }
19603
19976
  const delegation = await this.createDelegationViaWasmPath(
19604
19977
  did,
@@ -19678,7 +20051,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19678
20051
  const spaceId = [...resolvedSpaces][0];
19679
20052
  const abilities = {};
19680
20053
  for (const entry of entries) {
19681
- const shortService = import_sdk_core4.SERVICE_LONG_TO_SHORT[entry.service];
20054
+ const shortService = import_sdk_core5.SERVICE_LONG_TO_SHORT[entry.service];
19682
20055
  if (shortService === void 0) {
19683
20056
  throw new Error(
19684
20057
  `delegateTo: unknown service '${entry.service}' \u2014 no short-form mapping`
@@ -19718,7 +20091,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19718
20091
  });
19719
20092
  const primary = result.resources[0];
19720
20093
  const delegationHeader = { Authorization: result.delegation };
19721
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20094
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19722
20095
  this.config.host,
19723
20096
  delegationHeader
19724
20097
  );
@@ -19742,6 +20115,41 @@ var _TinyCloudNode = class _TinyCloudNode {
19742
20115
  host: this.config.host
19743
20116
  };
19744
20117
  }
20118
+ async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant) {
20119
+ const result = this.createDelegationWrapper({
20120
+ session: grant.session,
20121
+ delegateDID: did,
20122
+ spaceId: grant.session.spaceId,
20123
+ abilities: this.permissionsToAbilities(entries),
20124
+ expirationSecs: Math.floor(expirationTime.getTime() / 1e3)
20125
+ });
20126
+ const primary = result.resources[0];
20127
+ const delegationHeader = { Authorization: result.delegation };
20128
+ const targetHost = grant.delegation.host ?? this.config.host;
20129
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
20130
+ targetHost,
20131
+ delegationHeader
20132
+ );
20133
+ if (!activateResult.success) {
20134
+ throw new Error(
20135
+ `Failed to activate delegation with host: ${activateResult.error}`
20136
+ );
20137
+ }
20138
+ return {
20139
+ cid: result.cid,
20140
+ delegationHeader,
20141
+ spaceId: grant.session.spaceId,
20142
+ path: primary.path,
20143
+ actions: primary.actions,
20144
+ resources: result.resources,
20145
+ disableSubDelegation: false,
20146
+ expiry: result.expiry,
20147
+ delegateDID: did,
20148
+ ownerAddress: grant.delegation.ownerAddress,
20149
+ chainId: grant.delegation.chainId,
20150
+ host: targetHost
20151
+ };
20152
+ }
19745
20153
  resolvePermissionSpace(space, session) {
19746
20154
  if (space === void 0) {
19747
20155
  return this.wasmBindings.makeSpaceId(
@@ -19758,6 +20166,223 @@ var _TinyCloudNode = class _TinyCloudNode {
19758
20166
  }
19759
20167
  return this.wasmBindings.makeSpaceId(session.address, session.chainId, space);
19760
20168
  }
20169
+ expandPermissionEntries(permissions) {
20170
+ return permissions.map((entry) => ({
20171
+ ...entry,
20172
+ actions: (0, import_sdk_core5.expandActionShortNames)(entry.service, entry.actions)
20173
+ }));
20174
+ }
20175
+ shortServiceName(service) {
20176
+ const short = import_sdk_core5.SERVICE_LONG_TO_SHORT[service];
20177
+ if (short === void 0) {
20178
+ throw new Error(
20179
+ `unknown service '${service}' \u2014 no short-form mapping`
20180
+ );
20181
+ }
20182
+ return short;
20183
+ }
20184
+ permissionsToAbilities(entries) {
20185
+ const abilities = {};
20186
+ for (const entry of entries) {
20187
+ const service = this.shortServiceName(entry.service);
20188
+ abilities[service] ?? (abilities[service] = {});
20189
+ const existing = abilities[service][entry.path] ?? [];
20190
+ const seen = new Set(existing);
20191
+ for (const action of entry.actions) {
20192
+ if (!seen.has(action)) {
20193
+ existing.push(action);
20194
+ seen.add(action);
20195
+ }
20196
+ }
20197
+ abilities[service][entry.path] = existing;
20198
+ }
20199
+ return abilities;
20200
+ }
20201
+ permissionOperations(entries, spaceId) {
20202
+ return entries.flatMap((entry) => {
20203
+ const service = this.shortServiceName(entry.service);
20204
+ return entry.actions.map((action) => ({
20205
+ spaceId,
20206
+ service,
20207
+ path: entry.path,
20208
+ action
20209
+ }));
20210
+ });
20211
+ }
20212
+ sessionCoversPermissionEntries(session, entries) {
20213
+ try {
20214
+ const granted = (0, import_sdk_core5.parseRecapCapabilities)(
20215
+ (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
20216
+ session.siwe
20217
+ );
20218
+ return (0, import_sdk_core5.isCapabilitySubset)(entries, granted).subset;
20219
+ } catch {
20220
+ return false;
20221
+ }
20222
+ }
20223
+ permissionEntriesToOperations(entries, session) {
20224
+ return entries.flatMap((entry) => {
20225
+ const spaceId = this.resolvePermissionSpace(entry.space, session);
20226
+ const service = this.shortServiceName(entry.service);
20227
+ return entry.actions.map((action) => ({
20228
+ spaceId,
20229
+ service,
20230
+ path: entry.path,
20231
+ action
20232
+ }));
20233
+ });
20234
+ }
20235
+ findRuntimeGrantsForPermissionEntries(entries, session) {
20236
+ const grants = [];
20237
+ const operations = this.permissionEntriesToOperations(entries, session);
20238
+ if (operations.length === 0) {
20239
+ return grants;
20240
+ }
20241
+ for (const operation of operations) {
20242
+ const grant = this.findGrantForOperation(operation);
20243
+ if (!grant) {
20244
+ return [];
20245
+ }
20246
+ if (!grants.includes(grant)) {
20247
+ grants.push(grant);
20248
+ }
20249
+ }
20250
+ return grants;
20251
+ }
20252
+ runtimeDelegationFromSession(delegatedSession, entries, spaceId, session, expiresAt) {
20253
+ const resources = this.delegatedResourcesForEntries(entries, spaceId);
20254
+ const primary = resources[0];
20255
+ return {
20256
+ cid: delegatedSession.delegationCid,
20257
+ delegationHeader: delegatedSession.delegationHeader,
20258
+ spaceId,
20259
+ path: primary.path,
20260
+ actions: primary.actions,
20261
+ resources,
20262
+ disableSubDelegation: false,
20263
+ expiry: expiresAt,
20264
+ delegateDID: session.verificationMethod,
20265
+ ownerAddress: session.address,
20266
+ chainId: session.chainId,
20267
+ host: this.config.host
20268
+ };
20269
+ }
20270
+ runtimeGrantFromDelegation(delegation, session) {
20271
+ const operations = this.operationsFromDelegation(delegation);
20272
+ return {
20273
+ session: {
20274
+ delegationHeader: delegation.delegationHeader,
20275
+ delegationCid: delegation.cid,
20276
+ spaceId: delegation.spaceId,
20277
+ verificationMethod: session.verificationMethod,
20278
+ jwk: session.jwk
20279
+ },
20280
+ delegation,
20281
+ operations,
20282
+ expiresAt: delegation.expiry
20283
+ };
20284
+ }
20285
+ delegatedResourcesForEntries(entries, spaceId) {
20286
+ return entries.map((entry) => ({
20287
+ service: this.shortServiceName(entry.service),
20288
+ space: spaceId,
20289
+ path: entry.path,
20290
+ actions: [...entry.actions]
20291
+ }));
20292
+ }
20293
+ operationsFromDelegation(delegation) {
20294
+ const resources = delegation.resources !== void 0 && delegation.resources.length > 0 ? delegation.resources : this.flatDelegationResources(delegation);
20295
+ return resources.flatMap(
20296
+ (resource) => resource.actions.map((action) => ({
20297
+ spaceId: resource.space,
20298
+ service: this.invocationServiceName(resource.service),
20299
+ path: resource.path,
20300
+ action
20301
+ }))
20302
+ );
20303
+ }
20304
+ flatDelegationResources(delegation) {
20305
+ const byService = /* @__PURE__ */ new Map();
20306
+ for (const action of delegation.actions) {
20307
+ const service = this.shortServiceName(action.split("/")[0]);
20308
+ const actions = byService.get(service) ?? [];
20309
+ actions.push(action);
20310
+ byService.set(service, actions);
20311
+ }
20312
+ return [...byService.entries()].map(([service, actions]) => ({
20313
+ service,
20314
+ space: delegation.spaceId,
20315
+ path: delegation.path,
20316
+ actions
20317
+ }));
20318
+ }
20319
+ selectInvocationSession(fallback, service, path, action) {
20320
+ const grant = this.findGrantForOperation({
20321
+ spaceId: fallback.spaceId,
20322
+ service: this.invocationServiceName(service),
20323
+ path,
20324
+ action
20325
+ });
20326
+ return grant?.session ?? fallback;
20327
+ }
20328
+ findGrantForOperations(operations) {
20329
+ if (operations.length === 0) {
20330
+ return void 0;
20331
+ }
20332
+ this.pruneExpiredRuntimePermissionGrants();
20333
+ return this.runtimePermissionGrants.find((grant) => {
20334
+ return operations.every(
20335
+ (operation) => grant.operations.some(
20336
+ (granted) => this.operationCovers(granted, operation)
20337
+ )
20338
+ );
20339
+ });
20340
+ }
20341
+ findGrantForOperation(operation) {
20342
+ return this.findGrantForOperations([operation]);
20343
+ }
20344
+ pruneExpiredRuntimePermissionGrants() {
20345
+ const now = Date.now();
20346
+ this.runtimePermissionGrants = this.runtimePermissionGrants.filter(
20347
+ (grant) => grant.expiresAt.getTime() > now
20348
+ );
20349
+ }
20350
+ operationCovers(granted, requested) {
20351
+ return granted.spaceId === requested.spaceId && granted.service === requested.service && this.actionContains(granted.action, requested.action) && this.pathContains(granted.path, requested.path);
20352
+ }
20353
+ actionContains(grantedAction, requestedAction) {
20354
+ if (grantedAction === requestedAction) {
20355
+ return true;
20356
+ }
20357
+ if (grantedAction.endsWith("/*")) {
20358
+ const prefix = grantedAction.slice(0, -2);
20359
+ return requestedAction.startsWith(`${prefix}/`);
20360
+ }
20361
+ return false;
20362
+ }
20363
+ invocationServiceName(service) {
20364
+ return service.startsWith("tinycloud.") ? this.shortServiceName(service) : service;
20365
+ }
20366
+ pathContains(grantedPath, requestedPath) {
20367
+ if (grantedPath === "" || grantedPath === "/") {
20368
+ return true;
20369
+ }
20370
+ if (grantedPath.endsWith("/**")) {
20371
+ return requestedPath.startsWith(grantedPath.slice(0, -3));
20372
+ }
20373
+ if (grantedPath.endsWith("/*")) {
20374
+ const prefix = grantedPath.slice(0, -2);
20375
+ if (!requestedPath.startsWith(prefix)) {
20376
+ return false;
20377
+ }
20378
+ const remainder = requestedPath.slice(prefix.length);
20379
+ return !remainder.includes("/") || remainder === "/";
20380
+ }
20381
+ if (grantedPath.endsWith("/")) {
20382
+ return requestedPath.startsWith(grantedPath);
20383
+ }
20384
+ return grantedPath === requestedPath;
20385
+ }
19761
20386
  /**
19762
20387
  * Issue a delegation via the legacy wallet-signed SIWE path for a single
19763
20388
  * {@link PermissionEntry}. Shares the implementation with the public
@@ -19814,7 +20439,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19814
20439
  );
19815
20440
  return result.delegation;
19816
20441
  } catch (err) {
19817
- if (err instanceof import_sdk_core4.PermissionNotInManifestError) {
20442
+ if (err instanceof import_sdk_core5.PermissionNotInManifestError) {
19818
20443
  } else {
19819
20444
  throw err;
19820
20445
  }
@@ -19871,7 +20496,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19871
20496
  ...prepared,
19872
20497
  signature: signature2
19873
20498
  });
19874
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20499
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19875
20500
  this.config.host,
19876
20501
  delegationSession.delegationHeader
19877
20502
  );
@@ -19893,7 +20518,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19893
20518
  };
19894
20519
  const hasKvActions = params.actions.some((a) => a.startsWith("tinycloud.kv/"));
19895
20520
  if (hasKvActions && params.includePublicSpace !== false) {
19896
- const publicSpaceId = (0, import_sdk_core4.makePublicSpaceId)(
20521
+ const publicSpaceId = (0, import_sdk_core5.makePublicSpaceId)(
19897
20522
  this.wasmBindings.ensureEip55(session.address),
19898
20523
  session.chainId
19899
20524
  );
@@ -19916,7 +20541,7 @@ var _TinyCloudNode = class _TinyCloudNode {
19916
20541
  ...publicPrepared,
19917
20542
  signature: publicSignature
19918
20543
  });
19919
- const publicActivateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20544
+ const publicActivateResult = await (0, import_sdk_core5.activateSessionWithHost)(
19920
20545
  this.config.host,
19921
20546
  publicSession.delegationHeader
19922
20547
  );
@@ -20015,7 +20640,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20015
20640
  ...prepared,
20016
20641
  signature: signature2
20017
20642
  });
20018
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20643
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
20019
20644
  targetHost,
20020
20645
  invokerSession.delegationHeader
20021
20646
  );
@@ -20104,7 +20729,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20104
20729
  ...prepared,
20105
20730
  signature: signature2
20106
20731
  });
20107
- const activateResult = await (0, import_sdk_core4.activateSessionWithHost)(
20732
+ const activateResult = await (0, import_sdk_core5.activateSessionWithHost)(
20108
20733
  targetHost,
20109
20734
  subDelegationSession.delegationHeader
20110
20735
  );
@@ -20146,11 +20771,11 @@ TinyCloudNode.registerNodeDefaults({
20146
20771
  });
20147
20772
 
20148
20773
  // src/index.ts
20149
- var import_sdk_core6 = require("@tinycloud/sdk-core");
20150
20774
  var import_sdk_core7 = require("@tinycloud/sdk-core");
20775
+ var import_sdk_core8 = require("@tinycloud/sdk-core");
20151
20776
 
20152
20777
  // src/storage/FileSessionStorage.ts
20153
- var import_sdk_core5 = require("@tinycloud/sdk-core");
20778
+ var import_sdk_core6 = require("@tinycloud/sdk-core");
20154
20779
  var import_fs = require("fs");
20155
20780
  var import_path = require("path");
20156
20781
  var FileSessionStorage = class {
@@ -20205,7 +20830,7 @@ var FileSessionStorage = class {
20205
20830
  try {
20206
20831
  const data = (0, import_fs.readFileSync)(filePath, "utf-8");
20207
20832
  const parsed = JSON.parse(data);
20208
- const validation = (0, import_sdk_core5.validatePersistedSessionData)(parsed);
20833
+ const validation = (0, import_sdk_core6.validatePersistedSessionData)(parsed);
20209
20834
  if (!validation.ok) {
20210
20835
  console.warn(`Invalid session data for ${address}:`, validation.error.message);
20211
20836
  (0, import_fs.unlinkSync)(filePath);
@@ -20270,7 +20895,7 @@ var FileSessionStorage = class {
20270
20895
  };
20271
20896
 
20272
20897
  // src/index.ts
20273
- var import_sdk_core8 = require("@tinycloud/sdk-core");
20898
+ var import_sdk_core9 = require("@tinycloud/sdk-core");
20274
20899
 
20275
20900
  // src/delegation.ts
20276
20901
  function serializeDelegation(delegation) {
@@ -20289,7 +20914,6 @@ function deserializeDelegation(data) {
20289
20914
  }
20290
20915
 
20291
20916
  // src/index.ts
20292
- var import_sdk_core9 = require("@tinycloud/sdk-core");
20293
20917
  var import_sdk_core10 = require("@tinycloud/sdk-core");
20294
20918
  var import_sdk_core11 = require("@tinycloud/sdk-core");
20295
20919
  var import_sdk_core12 = require("@tinycloud/sdk-core");
@@ -20299,6 +20923,7 @@ var import_sdk_core15 = require("@tinycloud/sdk-core");
20299
20923
  var import_sdk_core16 = require("@tinycloud/sdk-core");
20300
20924
  var import_sdk_core17 = require("@tinycloud/sdk-core");
20301
20925
  var import_sdk_core18 = require("@tinycloud/sdk-core");
20926
+ var import_sdk_core19 = require("@tinycloud/sdk-core");
20302
20927
  // Annotate the CommonJS export names for ESM import in node:
20303
20928
  0 && (module.exports = {
20304
20929
  ACCOUNT_REGISTRY_PATH,
@@ -20329,6 +20954,7 @@ var import_sdk_core18 = require("@tinycloud/sdk-core");
20329
20954
  ProtocolMismatchError,
20330
20955
  SQLAction,
20331
20956
  SQLService,
20957
+ SecretsService,
20332
20958
  ServiceContext,
20333
20959
  SessionExpiredError,
20334
20960
  SharingService,