@tinycloud/node-sdk 2.0.4 → 2.1.0-beta.1

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.js CHANGED
@@ -17030,11 +17030,13 @@ var require_utils2 = __commonJS({
17030
17030
  // src/NodeWasmBindings.ts
17031
17031
  import {
17032
17032
  invoke,
17033
+ invokeAny,
17033
17034
  prepareSession,
17034
17035
  completeSessionSetup,
17035
17036
  ensureEip55,
17036
17037
  makeSpaceId,
17037
17038
  createDelegation,
17039
+ parseRecapFromSiwe,
17038
17040
  generateHostSIWEMessage,
17039
17041
  siweToDelegationHeaders,
17040
17042
  protocolVersion,
@@ -17051,11 +17053,13 @@ import {
17051
17053
  var _NodeWasmBindings = class _NodeWasmBindings {
17052
17054
  constructor() {
17053
17055
  this.invoke = invoke;
17056
+ this.invokeAny = invokeAny;
17054
17057
  this.prepareSession = prepareSession;
17055
17058
  this.completeSessionSetup = completeSessionSetup;
17056
17059
  this.ensureEip55 = ensureEip55;
17057
17060
  this.makeSpaceId = makeSpaceId;
17058
17061
  this.createDelegation = createDelegation;
17062
+ this.parseRecapFromSiwe = parseRecapFromSiwe;
17059
17063
  this.generateHostSIWEMessage = generateHostSIWEMessage;
17060
17064
  this.siweToDelegationHeaders = siweToDelegationHeaders;
17061
17065
  this.protocolVersion = protocolVersion;
@@ -17153,6 +17157,7 @@ import {
17153
17157
  KVService as KVService2,
17154
17158
  SQLService as SQLService2,
17155
17159
  DuckDbService as DuckDbService2,
17160
+ HooksService as HooksService2,
17156
17161
  DataVaultService,
17157
17162
  createVaultCrypto,
17158
17163
  ServiceContext as ServiceContext2,
@@ -17162,7 +17167,12 @@ import {
17162
17167
  CapabilityKeyRegistry,
17163
17168
  SharingService,
17164
17169
  UnsupportedFeatureError,
17165
- makePublicSpaceId
17170
+ makePublicSpaceId,
17171
+ PermissionNotInManifestError,
17172
+ SessionExpiredError,
17173
+ expandActionShortNames,
17174
+ isCapabilitySubset,
17175
+ parseRecapCapabilities
17166
17176
  } from "@tinycloud/sdk-core";
17167
17177
 
17168
17178
  // src/authorization/NodeUserAuthorization.ts
@@ -17292,12 +17302,22 @@ var NodeUserAuthorization = class {
17292
17302
  },
17293
17303
  capabilities: {
17294
17304
  "": ["tinycloud.capabilities/read"]
17305
+ },
17306
+ hooks: {
17307
+ "": [
17308
+ "tinycloud.hooks/subscribe",
17309
+ "tinycloud.hooks/register",
17310
+ "tinycloud.hooks/list",
17311
+ "tinycloud.hooks/unregister"
17312
+ ]
17295
17313
  }
17296
17314
  };
17297
17315
  this.sessionExpirationMs = config.sessionExpirationMs ?? 60 * 60 * 1e3;
17298
17316
  this.autoCreateSpace = config.autoCreateSpace ?? false;
17299
17317
  this.spaceCreationHandler = config.spaceCreationHandler;
17300
- this.tinycloudHosts = config.tinycloudHosts ?? ["https://node.tinycloud.xyz"];
17318
+ this.tinycloudHosts = config.tinycloudHosts ?? [
17319
+ "https://node.tinycloud.xyz"
17320
+ ];
17301
17321
  this.enablePublicSpace = config.enablePublicSpace ?? true;
17302
17322
  this.nonce = config.nonce;
17303
17323
  this.siweConfig = config.siweConfig;
@@ -17437,7 +17457,10 @@ var NodeUserAuthorization = class {
17437
17457
  throw err;
17438
17458
  }
17439
17459
  } catch (error) {
17440
- handler.onSpaceCreationFailed?.(creationContext, error instanceof Error ? error : new Error(String(error)));
17460
+ handler.onSpaceCreationFailed?.(
17461
+ creationContext,
17462
+ error instanceof Error ? error : new Error(String(error))
17463
+ );
17441
17464
  throw error;
17442
17465
  }
17443
17466
  await new Promise((resolve) => setTimeout(resolve, 100));
@@ -17471,7 +17494,10 @@ var NodeUserAuthorization = class {
17471
17494
  throw err;
17472
17495
  }
17473
17496
  } catch (error) {
17474
- handler.onSpaceCreationFailed?.(creationContext, error instanceof Error ? error : new Error(String(error)));
17497
+ handler.onSpaceCreationFailed?.(
17498
+ creationContext,
17499
+ error instanceof Error ? error : new Error(String(error))
17500
+ );
17475
17501
  throw error;
17476
17502
  }
17477
17503
  await new Promise((resolve) => setTimeout(resolve, 100));
@@ -17580,7 +17606,10 @@ var NodeUserAuthorization = class {
17580
17606
  this._tinyCloudSession = tinyCloudSession;
17581
17607
  this._address = address;
17582
17608
  this._chainId = chainId;
17583
- const nodeInfo = await checkNodeInfo(this.tinycloudHosts[0], this.wasm.protocolVersion());
17609
+ const nodeInfo = await checkNodeInfo(
17610
+ this.tinycloudHosts[0],
17611
+ this.wasm.protocolVersion()
17612
+ );
17584
17613
  this._nodeFeatures = nodeInfo.features;
17585
17614
  for (const ext of this.extensions) {
17586
17615
  if (ext.afterSignIn) {
@@ -17740,7 +17769,10 @@ var NodeUserAuthorization = class {
17740
17769
  this._tinyCloudSession = tinyCloudSession;
17741
17770
  this._address = address;
17742
17771
  this._chainId = chainId;
17743
- const nodeInfo = await checkNodeInfo(this.tinycloudHosts[0], this.wasm.protocolVersion());
17772
+ const nodeInfo = await checkNodeInfo(
17773
+ this.tinycloudHosts[0],
17774
+ this.wasm.protocolVersion()
17775
+ );
17744
17776
  this._nodeFeatures = nodeInfo.features;
17745
17777
  for (const ext of this.extensions) {
17746
17778
  if (ext.afterSignIn) {
@@ -17791,7 +17823,9 @@ var NodeUserAuthorization = class {
17791
17823
  );
17792
17824
  }
17793
17825
  default:
17794
- throw new Error(`Unknown sign strategy: ${this.signStrategy.type}`);
17826
+ throw new Error(
17827
+ `Unknown sign strategy: ${this.signStrategy.type}`
17828
+ );
17795
17829
  }
17796
17830
  }
17797
17831
  /**
@@ -17821,6 +17855,7 @@ var NodeUserAuthorization = class {
17821
17855
  // src/DelegatedAccess.ts
17822
17856
  import {
17823
17857
  KVService,
17858
+ HooksService,
17824
17859
  SQLService,
17825
17860
  DuckDbService,
17826
17861
  ServiceContext
@@ -17845,6 +17880,9 @@ var DelegatedAccess = class {
17845
17880
  this._duckdb = new DuckDbService({});
17846
17881
  this._duckdb.initialize(this._serviceContext);
17847
17882
  this._serviceContext.registerService("duckdb", this._duckdb);
17883
+ this._hooks = new HooksService({});
17884
+ this._hooks.initialize(this._serviceContext);
17885
+ this._serviceContext.registerService("hooks", this._hooks);
17848
17886
  const serviceSession = {
17849
17887
  delegationHeader: session.delegationHeader,
17850
17888
  delegationCid: session.delegationCid,
@@ -17890,6 +17928,12 @@ var DelegatedAccess = class {
17890
17928
  get duckdb() {
17891
17929
  return this._duckdb;
17892
17930
  }
17931
+ /**
17932
+ * Hooks write-stream subscriptions on the delegated space.
17933
+ */
17934
+ get hooks() {
17935
+ return this._hooks;
17936
+ }
17893
17937
  };
17894
17938
 
17895
17939
  // src/keys/WasmKeyProvider.ts
@@ -17967,9 +18011,72 @@ function createWasmKeyProvider(sessionManager) {
17967
18011
  return new WasmKeyProvider({ sessionManager });
17968
18012
  }
17969
18013
 
18014
+ // src/delegateToHelpers.ts
18015
+ import {
18016
+ parseExpiry,
18017
+ SiweMessage
18018
+ } from "@tinycloud/sdk-core";
18019
+ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
18020
+ const byService = /* @__PURE__ */ new Map();
18021
+ for (const a of actions) {
18022
+ const slashIdx = a.indexOf("/");
18023
+ if (slashIdx === -1) {
18024
+ continue;
18025
+ }
18026
+ const service = a.slice(0, slashIdx);
18027
+ if (!service.startsWith("tinycloud.")) {
18028
+ continue;
18029
+ }
18030
+ const list = byService.get(service);
18031
+ if (list === void 0) {
18032
+ byService.set(service, [a]);
18033
+ } else {
18034
+ list.push(a);
18035
+ }
18036
+ }
18037
+ const space = spaceIdOverride ?? "default";
18038
+ const entries = [];
18039
+ for (const [service, actionList] of byService) {
18040
+ entries.push({
18041
+ service,
18042
+ space,
18043
+ path,
18044
+ actions: actionList
18045
+ });
18046
+ }
18047
+ return entries;
18048
+ }
18049
+ function resolveExpiryMs(expiry) {
18050
+ if (expiry === void 0) {
18051
+ return 60 * 60 * 1e3;
18052
+ }
18053
+ if (typeof expiry === "number") {
18054
+ if (!Number.isFinite(expiry) || expiry <= 0) {
18055
+ throw new Error(
18056
+ `delegateTo expiry must be a positive finite number (got ${expiry})`
18057
+ );
18058
+ }
18059
+ return expiry;
18060
+ }
18061
+ return parseExpiry(expiry);
18062
+ }
18063
+ function extractSiweExpiration(siwe) {
18064
+ const parsed = new SiweMessage(siwe);
18065
+ if (parsed.expirationTime === void 0 || parsed.expirationTime === null) {
18066
+ return void 0;
18067
+ }
18068
+ const d = new Date(parsed.expirationTime);
18069
+ if (Number.isNaN(d.getTime())) {
18070
+ throw new Error(
18071
+ `Session SIWE has unparseable expirationTime: ${parsed.expirationTime}`
18072
+ );
18073
+ }
18074
+ return d;
18075
+ }
18076
+
17970
18077
  // src/TinyCloudNode.ts
17971
18078
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
17972
- var TinyCloudNode = class _TinyCloudNode {
18079
+ var _TinyCloudNode = class _TinyCloudNode {
17973
18080
  /**
17974
18081
  * Create a new TinyCloudNode instance.
17975
18082
  *
@@ -18095,7 +18202,9 @@ var TinyCloudNode = class _TinyCloudNode {
18095
18202
  nonce: config.nonce,
18096
18203
  siweConfig: config.siweConfig
18097
18204
  });
18098
- this.tc = new TinyCloud(this.auth);
18205
+ this.tc = new TinyCloud(this.auth, {
18206
+ invokeAny: this.wasmBindings.invokeAny
18207
+ });
18099
18208
  }
18100
18209
  /**
18101
18210
  * Get the primary identity DID for this user.
@@ -18164,6 +18273,7 @@ var TinyCloudNode = class _TinyCloudNode {
18164
18273
  this._kv = void 0;
18165
18274
  this._sql = void 0;
18166
18275
  this._duckdb = void 0;
18276
+ this._hooks = void 0;
18167
18277
  this._serviceContext = void 0;
18168
18278
  await this.tc.signIn();
18169
18279
  this.initializeServices();
@@ -18183,6 +18293,7 @@ var TinyCloudNode = class _TinyCloudNode {
18183
18293
  this._kv = void 0;
18184
18294
  this._sql = void 0;
18185
18295
  this._duckdb = void 0;
18296
+ this._hooks = void 0;
18186
18297
  this._serviceContext = void 0;
18187
18298
  if (sessionData.address) {
18188
18299
  this._address = sessionData.address;
@@ -18192,6 +18303,7 @@ var TinyCloudNode = class _TinyCloudNode {
18192
18303
  }
18193
18304
  this._serviceContext = new ServiceContext2({
18194
18305
  invoke: this.wasmBindings.invoke,
18306
+ invokeAny: this.wasmBindings.invokeAny,
18195
18307
  fetch: globalThis.fetch.bind(globalThis),
18196
18308
  hosts: [this.config.host]
18197
18309
  });
@@ -18204,6 +18316,9 @@ var TinyCloudNode = class _TinyCloudNode {
18204
18316
  this._duckdb = new DuckDbService2({});
18205
18317
  this._duckdb.initialize(this._serviceContext);
18206
18318
  this._serviceContext.registerService("duckdb", this._duckdb);
18319
+ this._hooks = new HooksService2({});
18320
+ this._hooks.initialize(this._serviceContext);
18321
+ this._serviceContext.registerService("hooks", this._hooks);
18207
18322
  const serviceSession = {
18208
18323
  delegationHeader: sessionData.delegationHeader,
18209
18324
  delegationCid: sessionData.delegationCid,
@@ -18303,7 +18418,9 @@ var TinyCloudNode = class _TinyCloudNode {
18303
18418
  nonce: this.config.nonce,
18304
18419
  siweConfig: this.config.siweConfig
18305
18420
  });
18306
- this.tc = new TinyCloud(this.auth);
18421
+ this.tc = new TinyCloud(this.auth, {
18422
+ invokeAny: this.wasmBindings.invokeAny
18423
+ });
18307
18424
  this.config.prefix = prefix;
18308
18425
  }
18309
18426
  /**
@@ -18341,7 +18458,9 @@ var TinyCloudNode = class _TinyCloudNode {
18341
18458
  nonce: this.config.nonce,
18342
18459
  siweConfig: this.config.siweConfig
18343
18460
  });
18344
- this.tc = new TinyCloud(this.auth);
18461
+ this.tc = new TinyCloud(this.auth, {
18462
+ invokeAny: this.wasmBindings.invokeAny
18463
+ });
18345
18464
  this.config.prefix = prefix;
18346
18465
  }
18347
18466
  /**
@@ -18356,6 +18475,7 @@ var TinyCloudNode = class _TinyCloudNode {
18356
18475
  this.tc.initializeServices(this.wasmBindings.invoke, [this.config.host]);
18357
18476
  this._serviceContext = new ServiceContext2({
18358
18477
  invoke: this.wasmBindings.invoke,
18478
+ invokeAny: this.wasmBindings.invokeAny,
18359
18479
  fetch: globalThis.fetch.bind(globalThis),
18360
18480
  hosts: [this.config.host]
18361
18481
  });
@@ -18373,6 +18493,9 @@ var TinyCloudNode = class _TinyCloudNode {
18373
18493
  this._duckdb.initialize(this._serviceContext);
18374
18494
  this._serviceContext.registerService("duckdb", this._duckdb);
18375
18495
  }
18496
+ this._hooks = new HooksService2({});
18497
+ this._hooks.initialize(this._serviceContext);
18498
+ this._serviceContext.registerService("hooks", this._hooks);
18376
18499
  const serviceSession = {
18377
18500
  delegationHeader: session.delegationHeader,
18378
18501
  delegationCid: session.delegationCid,
@@ -18751,6 +18874,15 @@ var TinyCloudNode = class _TinyCloudNode {
18751
18874
  }
18752
18875
  return this._vault;
18753
18876
  }
18877
+ /**
18878
+ * Hooks write stream subscription API.
18879
+ */
18880
+ get hooks() {
18881
+ if (!this._hooks) {
18882
+ throw new Error("Not signed in. Call signIn() first.");
18883
+ }
18884
+ return this._hooks;
18885
+ }
18754
18886
  // ===========================================================================
18755
18887
  // v2 Service Accessors
18756
18888
  // ===========================================================================
@@ -19078,6 +19210,150 @@ var TinyCloudNode = class _TinyCloudNode {
19078
19210
  async checkPermission(path, action) {
19079
19211
  return this.delegationManager.checkPermission(path, action);
19080
19212
  }
19213
+ /**
19214
+ * Issue a delegation using the capability-chain flow.
19215
+ *
19216
+ * When the requested permissions are a subset of the current session's
19217
+ * recap, the delegation is signed by the session key via WASM — no wallet
19218
+ * prompt. When they are not, a {@link PermissionNotInManifestError} is
19219
+ * raised so the caller can trigger an escalation flow (e.g.
19220
+ * `TinyCloudWeb.requestPermissions`). Passing `forceWalletSign: true`
19221
+ * bypasses the derivability check and always uses the wallet-signed SIWE
19222
+ * path — used by the legacy `createDelegation` fallback and by callers
19223
+ * that want explicit wallet confirmation.
19224
+ *
19225
+ * Current limitation: exactly one {@link PermissionEntry} per call. For
19226
+ * multi-resource delegation, call `delegateTo` multiple times. This keeps
19227
+ * each delegation a single `(spaceId, path)` grant, which matches the
19228
+ * underlying `PortableDelegation` shape.
19229
+ *
19230
+ * @throws {@link SessionExpiredError} when there is no session or the
19231
+ * current session has expired (or will within the 60s safety margin).
19232
+ * @throws {@link PermissionNotInManifestError} when the requested entries
19233
+ * are not a subset of the granted session capabilities and
19234
+ * `forceWalletSign` is not set.
19235
+ */
19236
+ async delegateTo(did, permissions, options) {
19237
+ const session = this.auth?.tinyCloudSession;
19238
+ if (!session) {
19239
+ throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
19240
+ }
19241
+ const sessionExpiry = extractSiweExpiration(session.siwe);
19242
+ if (sessionExpiry !== void 0) {
19243
+ const now2 = Date.now();
19244
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19245
+ if (sessionExpiry.getTime() <= now2 + marginMs) {
19246
+ throw new SessionExpiredError(sessionExpiry);
19247
+ }
19248
+ }
19249
+ if (!Array.isArray(permissions) || permissions.length === 0) {
19250
+ throw new Error(
19251
+ "delegateTo requires a non-empty permissions array"
19252
+ );
19253
+ }
19254
+ if (permissions.length > 1) {
19255
+ throw new Error(
19256
+ "delegateTo currently supports one permission entry per call. Call delegateTo multiple times for multi-resource delegation."
19257
+ );
19258
+ }
19259
+ const entry = permissions[0];
19260
+ const expandedEntry = {
19261
+ ...entry,
19262
+ actions: expandActionShortNames(entry.service, entry.actions)
19263
+ };
19264
+ const now = /* @__PURE__ */ new Date();
19265
+ const expiryMs = resolveExpiryMs(options?.expiry);
19266
+ const expirationTime = new Date(now.getTime() + expiryMs);
19267
+ let effectiveExpiration = expirationTime;
19268
+ if (sessionExpiry !== void 0 && sessionExpiry < expirationTime) {
19269
+ effectiveExpiration = sessionExpiry;
19270
+ }
19271
+ if (options?.forceWalletSign) {
19272
+ const delegation2 = await this.createDelegationLegacyWalletPath(
19273
+ did,
19274
+ expandedEntry,
19275
+ effectiveExpiration
19276
+ );
19277
+ return { delegation: delegation2, prompted: true };
19278
+ }
19279
+ const granted = parseRecapCapabilities(
19280
+ (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
19281
+ session.siwe
19282
+ );
19283
+ const requested = [expandedEntry];
19284
+ const { subset, missing } = isCapabilitySubset(requested, granted);
19285
+ if (!subset) {
19286
+ throw new PermissionNotInManifestError(missing, granted);
19287
+ }
19288
+ const delegation = await this.createDelegationViaWasmPath(
19289
+ did,
19290
+ expandedEntry,
19291
+ effectiveExpiration,
19292
+ session
19293
+ );
19294
+ return { delegation, prompted: false };
19295
+ }
19296
+ /**
19297
+ * Issue a delegation via the session-key UCAN WASM path.
19298
+ *
19299
+ * The caller has already verified the request is derivable from the
19300
+ * current session; we just need to shape the inputs for
19301
+ * {@link createDelegationWrapper}.
19302
+ *
19303
+ * @internal
19304
+ */
19305
+ async createDelegationViaWasmPath(did, entry, expirationTime, session) {
19306
+ const spaceId = entry.space === "default" ? session.spaceId : entry.space;
19307
+ const serviceSession = {
19308
+ delegationHeader: session.delegationHeader,
19309
+ delegationCid: session.delegationCid,
19310
+ jwk: session.jwk,
19311
+ spaceId,
19312
+ verificationMethod: session.verificationMethod
19313
+ };
19314
+ const expirationSecs = Math.floor(expirationTime.getTime() / 1e3);
19315
+ const result = this.createDelegationWrapper({
19316
+ session: serviceSession,
19317
+ delegateDID: did,
19318
+ spaceId,
19319
+ path: entry.path,
19320
+ actions: entry.actions,
19321
+ expirationSecs
19322
+ });
19323
+ return {
19324
+ cid: result.cid,
19325
+ delegationHeader: { Authorization: `Bearer ${result.delegation}` },
19326
+ spaceId,
19327
+ path: entry.path,
19328
+ actions: entry.actions,
19329
+ disableSubDelegation: false,
19330
+ expiry: result.expiry,
19331
+ delegateDID: did,
19332
+ ownerAddress: session.address,
19333
+ chainId: session.chainId,
19334
+ host: this.config.host
19335
+ };
19336
+ }
19337
+ /**
19338
+ * Issue a delegation via the legacy wallet-signed SIWE path for a single
19339
+ * {@link PermissionEntry}. Shares the implementation with the public
19340
+ * `createDelegation` method via {@link createDelegationWalletPath} so
19341
+ * both entry points hit exactly the same SIWE / signer / public-space
19342
+ * logic without mutual recursion.
19343
+ *
19344
+ * @internal
19345
+ */
19346
+ async createDelegationLegacyWalletPath(delegateDID, entry, expirationTime) {
19347
+ const spaceIdOverride = entry.space === "default" ? void 0 : entry.space;
19348
+ return this.createDelegationWalletPath({
19349
+ path: entry.path,
19350
+ actions: entry.actions,
19351
+ delegateDID,
19352
+ includePublicSpace: true,
19353
+ expiryMs: Math.max(0, expirationTime.getTime() - Date.now()),
19354
+ spaceIdOverride
19355
+ });
19356
+ }
19081
19357
  /**
19082
19358
  * Create a delegation from this user to another user.
19083
19359
  *
@@ -19088,6 +19364,51 @@ var TinyCloudNode = class _TinyCloudNode {
19088
19364
  * @returns A portable delegation that can be sent to the recipient
19089
19365
  */
19090
19366
  async createDelegation(params) {
19367
+ if (!this.signer) {
19368
+ throw new Error("Cannot createDelegation() in session-only mode. Requires wallet mode.");
19369
+ }
19370
+ if (!this.auth?.tinyCloudSession) {
19371
+ throw new Error("Not signed in. Call signIn() first.");
19372
+ }
19373
+ let resolvedDelegateDID = params.delegateDID;
19374
+ if (resolvedDelegateDID.endsWith(".eth") && this.config.ensResolver) {
19375
+ const address = await this.config.ensResolver.resolveAddress(resolvedDelegateDID);
19376
+ if (!address) throw new Error(`Could not resolve ENS name: ${resolvedDelegateDID}`);
19377
+ resolvedDelegateDID = `did:pkh:eip155:1:${address}`;
19378
+ }
19379
+ const entries = legacyParamsToPermissionEntries(
19380
+ params.actions,
19381
+ params.path,
19382
+ params.spaceIdOverride
19383
+ );
19384
+ if (entries.length === 1) {
19385
+ try {
19386
+ const result = await this.delegateTo(
19387
+ resolvedDelegateDID,
19388
+ [entries[0]],
19389
+ params.expiryMs !== void 0 ? { expiry: params.expiryMs } : void 0
19390
+ );
19391
+ return result.delegation;
19392
+ } catch (err) {
19393
+ if (err instanceof PermissionNotInManifestError) {
19394
+ } else {
19395
+ throw err;
19396
+ }
19397
+ }
19398
+ }
19399
+ return this.createDelegationWalletPath({
19400
+ ...params,
19401
+ delegateDID: resolvedDelegateDID
19402
+ });
19403
+ }
19404
+ /**
19405
+ * Legacy wallet-signed SIWE delegation path. Lifted from the original
19406
+ * `createDelegation` body verbatim so both the legacy public method and
19407
+ * `delegateTo({ forceWalletSign: true })` hit the same code.
19408
+ *
19409
+ * @internal
19410
+ */
19411
+ async createDelegationWalletPath(params) {
19091
19412
  if (!this.signer) {
19092
19413
  throw new Error("Cannot createDelegation() in session-only mode. Requires wallet mode.");
19093
19414
  }
@@ -19095,11 +19416,6 @@ var TinyCloudNode = class _TinyCloudNode {
19095
19416
  if (!session) {
19096
19417
  throw new Error("Not signed in. Call signIn() first.");
19097
19418
  }
19098
- if (params.delegateDID.endsWith(".eth") && this.config.ensResolver) {
19099
- const address = await this.config.ensResolver.resolveAddress(params.delegateDID);
19100
- if (!address) throw new Error(`Could not resolve ENS name: ${params.delegateDID}`);
19101
- params = { ...params, delegateDID: `did:pkh:eip155:1:${address}` };
19102
- }
19103
19419
  const abilities = {};
19104
19420
  const kvActions = params.actions.filter((a) => a.startsWith("tinycloud.kv/"));
19105
19421
  const sqlActions = params.actions.filter((a) => a.startsWith("tinycloud.sql/"));
@@ -19387,6 +19703,18 @@ var TinyCloudNode = class _TinyCloudNode {
19387
19703
  };
19388
19704
  }
19389
19705
  };
19706
+ // ===========================================================================
19707
+ // Capability-chain delegation (spec: .claude/specs/capability-chain.md)
19708
+ // ===========================================================================
19709
+ /**
19710
+ * Safety margin before the session's own expiry at which {@link delegateTo}
19711
+ * will refuse to issue a derived delegation. Prevents issuing sub-delegations
19712
+ * that would be invalid by the time the recipient used them. Spec: 60 seconds.
19713
+ *
19714
+ * @internal
19715
+ */
19716
+ _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS = 6e4;
19717
+ var TinyCloudNode = _TinyCloudNode;
19390
19718
 
19391
19719
  // src/nodeDefaults.ts
19392
19720
  TinyCloudNode.registerNodeDefaults({
@@ -19522,6 +19850,19 @@ var FileSessionStorage = class {
19522
19850
  }
19523
19851
  };
19524
19852
 
19853
+ // src/index.ts
19854
+ import {
19855
+ PermissionNotInManifestError as PermissionNotInManifestError2,
19856
+ SessionExpiredError as SessionExpiredError2,
19857
+ ManifestValidationError,
19858
+ resolveManifest,
19859
+ validateManifest,
19860
+ loadManifest,
19861
+ isCapabilitySubset as isCapabilitySubset2,
19862
+ expandActionShortNames as expandActionShortNames2,
19863
+ parseExpiry as parseExpiry2
19864
+ } from "@tinycloud/sdk-core";
19865
+
19525
19866
  // src/delegation.ts
19526
19867
  function serializeDelegation(delegation) {
19527
19868
  return JSON.stringify({
@@ -19541,8 +19882,18 @@ function deserializeDelegation(data) {
19541
19882
  // src/index.ts
19542
19883
  import { KVService as KVService3, PrefixedKVService } from "@tinycloud/sdk-core";
19543
19884
  import { SQLService as SQLService3, SQLAction, DatabaseHandle } from "@tinycloud/sdk-core";
19544
- import { DuckDbService as DuckDbService3, DuckDbDatabaseHandle, DuckDbAction } from "@tinycloud/sdk-core";
19545
- import { DataVaultService as DataVaultService2, VaultHeaders, VaultPublicSpaceKVActions, createVaultCrypto as createVaultCrypto2 } from "@tinycloud/sdk-core";
19885
+ import {
19886
+ DuckDbService as DuckDbService3,
19887
+ DuckDbDatabaseHandle,
19888
+ DuckDbAction
19889
+ } from "@tinycloud/sdk-core";
19890
+ import {
19891
+ DataVaultService as DataVaultService2,
19892
+ VaultHeaders,
19893
+ VaultPublicSpaceKVActions,
19894
+ createVaultCrypto as createVaultCrypto2
19895
+ } from "@tinycloud/sdk-core";
19896
+ import { HooksService as HooksService3 } from "@tinycloud/sdk-core";
19546
19897
  import {
19547
19898
  DelegationManager as DelegationManager2,
19548
19899
  SharingService as SharingService2,
@@ -19583,16 +19934,20 @@ export {
19583
19934
  DuckDbDatabaseHandle,
19584
19935
  DuckDbService3 as DuckDbService,
19585
19936
  FileSessionStorage,
19937
+ HooksService3 as HooksService,
19586
19938
  KVService3 as KVService,
19939
+ ManifestValidationError,
19587
19940
  MemorySessionStorage,
19588
19941
  NodeUserAuthorization,
19589
19942
  NodeWasmBindings,
19943
+ PermissionNotInManifestError2 as PermissionNotInManifestError,
19590
19944
  PrefixedKVService,
19591
19945
  PrivateKeySigner,
19592
19946
  ProtocolMismatchError,
19593
19947
  SQLAction,
19594
19948
  SQLService3 as SQLService,
19595
19949
  ServiceContext3 as ServiceContext,
19950
+ SessionExpiredError2 as SessionExpiredError,
19596
19951
  SharingService2 as SharingService,
19597
19952
  SilentNotificationHandler2 as SilentNotificationHandler,
19598
19953
  Space,
@@ -19615,9 +19970,15 @@ export {
19615
19970
  defaultSignStrategy,
19616
19971
  defaultSpaceCreationHandler,
19617
19972
  deserializeDelegation,
19973
+ expandActionShortNames2 as expandActionShortNames,
19974
+ isCapabilitySubset2 as isCapabilitySubset,
19975
+ loadManifest,
19618
19976
  makePublicSpaceId2 as makePublicSpaceId,
19977
+ parseExpiry2 as parseExpiry,
19619
19978
  parseSpaceUri,
19620
- serializeDelegation
19979
+ resolveManifest,
19980
+ serializeDelegation,
19981
+ validateManifest
19621
19982
  };
19622
19983
  /*! Bundled license information:
19623
19984