@tinycloud/node-sdk 2.1.0-beta.0 → 2.1.0-beta.2

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.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ISigner, Bytes, IWasmBindings, ISessionManager } from '@tinycloud/sdk-core';
2
- export { AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, ClientSession, ColumnInfo, CreateDelegationParams, DataVaultConfig, DataVaultService, DatabaseHandle, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, HookEvent, HookServiceName, HookStreamEvent, HookSubscription, HookWebhookListOptions, HookWebhookRecord, HookWebhookRegistration, HookWebhookScope, HookWebhookUnregisterOptions, HooksService, HooksServiceConfig, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IHooksService, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IngestOptions, InvokeFunction, JWK, KVResponse, KVService, KVServiceConfig, KeyInfo, KeyProvider, KeyType, PersistedSessionData, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, ServiceContext, ServiceContextConfig, ServiceSession, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, SubscribeOptions, TableInfo, TinyCloud, TinyCloudConfig, TinyCloudSession, UnsupportedFeatureError, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, buildSpaceUri, checkNodeInfo, createCapabilityKeyRegistry, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, makePublicSpaceId, parseSpaceUri } from '@tinycloud/sdk-core';
3
- export { DelegatedAccess, FileSessionStorage, MemorySessionStorage, NodeEventEmitterStrategy, NodeUserAuthorization, NodeUserAuthorizationConfig, PortableDelegation, SignStrategy, TinyCloudNode, TinyCloudNodeConfig, WasmKeyProvider, WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation } from './core.cjs';
4
- import { invoke, invokeAny, prepareSession, completeSessionSetup, ensureEip55, makeSpaceId, createDelegation, generateHostSIWEMessage, siweToDelegationHeaders, protocolVersion, vault_encrypt, vault_decrypt, vault_derive_key, vault_x25519_from_seed, vault_x25519_dh, vault_random_bytes, vault_sha256 } from '@tinycloud/node-sdk-wasm';
2
+ export { AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, ClientSession, ColumnInfo, CreateDelegationParams, DataVaultConfig, DataVaultService, DatabaseHandle, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, HookEvent, HookServiceName, HookStreamEvent, HookSubscription, HookWebhookListOptions, HookWebhookRecord, HookWebhookRegistration, HookWebhookScope, HookWebhookUnregisterOptions, HooksService, HooksServiceConfig, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IHooksService, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IngestOptions, InvokeFunction, JWK, KVResponse, KVService, KVServiceConfig, KeyInfo, KeyProvider, KeyType, Manifest, ManifestDefaults, ManifestDelegation, ManifestValidationError, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, ResolvedCapabilities, ResolvedDelegate, ResourceCapability, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, ServiceContext, ServiceContextConfig, ServiceSession, SessionExpiredError, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, SubscribeOptions, TableInfo, TinyCloud, TinyCloudConfig, TinyCloudSession, UnsupportedFeatureError, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, buildSpaceUri, checkNodeInfo, createCapabilityKeyRegistry, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, expandActionShortNames, isCapabilitySubset, loadManifest, makePublicSpaceId, parseExpiry, parseSpaceUri, resolveManifest, validateManifest } from '@tinycloud/sdk-core';
3
+ export { DelegateToOptions, DelegateToResult, DelegatedAccess, FileSessionStorage, MemorySessionStorage, NodeEventEmitterStrategy, NodeUserAuthorization, NodeUserAuthorizationConfig, PortableDelegation, SignStrategy, TinyCloudNode, TinyCloudNodeConfig, WasmKeyProvider, WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation } from './core.cjs';
4
+ import { invoke, invokeAny, prepareSession, completeSessionSetup, ensureEip55, makeSpaceId, createDelegation, parseRecapFromSiwe, generateHostSIWEMessage, siweToDelegationHeaders, protocolVersion, vault_encrypt, vault_decrypt, vault_derive_key, vault_x25519_from_seed, vault_x25519_dh, vault_random_bytes, vault_sha256 } from '@tinycloud/node-sdk-wasm';
5
5
  import 'events';
6
6
  import '@tinycloud/sdk-services';
7
7
 
@@ -76,6 +76,7 @@ declare class NodeWasmBindings implements IWasmBindings {
76
76
  ensureEip55: typeof ensureEip55;
77
77
  makeSpaceId: typeof makeSpaceId;
78
78
  createDelegation: typeof createDelegation;
79
+ parseRecapFromSiwe: typeof parseRecapFromSiwe;
79
80
  generateHostSIWEMessage: typeof generateHostSIWEMessage;
80
81
  siweToDelegationHeaders: typeof siweToDelegationHeaders;
81
82
  protocolVersion: typeof protocolVersion;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ISigner, Bytes, IWasmBindings, ISessionManager } from '@tinycloud/sdk-core';
2
- export { AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, ClientSession, ColumnInfo, CreateDelegationParams, DataVaultConfig, DataVaultService, DatabaseHandle, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, HookEvent, HookServiceName, HookStreamEvent, HookSubscription, HookWebhookListOptions, HookWebhookRecord, HookWebhookRegistration, HookWebhookScope, HookWebhookUnregisterOptions, HooksService, HooksServiceConfig, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IHooksService, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IngestOptions, InvokeFunction, JWK, KVResponse, KVService, KVServiceConfig, KeyInfo, KeyProvider, KeyType, PersistedSessionData, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, ServiceContext, ServiceContextConfig, ServiceSession, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, SubscribeOptions, TableInfo, TinyCloud, TinyCloudConfig, TinyCloudSession, UnsupportedFeatureError, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, buildSpaceUri, checkNodeInfo, createCapabilityKeyRegistry, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, makePublicSpaceId, parseSpaceUri } from '@tinycloud/sdk-core';
3
- export { DelegatedAccess, FileSessionStorage, MemorySessionStorage, NodeEventEmitterStrategy, NodeUserAuthorization, NodeUserAuthorizationConfig, PortableDelegation, SignStrategy, TinyCloudNode, TinyCloudNodeConfig, WasmKeyProvider, WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation } from './core.js';
4
- import { invoke, invokeAny, prepareSession, completeSessionSetup, ensureEip55, makeSpaceId, createDelegation, generateHostSIWEMessage, siweToDelegationHeaders, protocolVersion, vault_encrypt, vault_decrypt, vault_derive_key, vault_x25519_from_seed, vault_x25519_dh, vault_random_bytes, vault_sha256 } from '@tinycloud/node-sdk-wasm';
2
+ export { AutoApproveSpaceCreationHandler, AutoRejectStrategy, AutoSignStrategy, BatchOptions, BatchResponse, CallbackStrategy, CapabilityEntry, CapabilityKeyRegistry, CapabilityKeyRegistryErrorCode, CapabilityKeyRegistryErrorCodes, ClientSession, ColumnInfo, CreateDelegationParams, DataVaultConfig, DataVaultService, DatabaseHandle, Delegation, DelegationChain, DelegationChainV2, DelegationDirection, DelegationError, DelegationErrorCode, DelegationErrorCodes, DelegationFilters, DelegationManager, DelegationManagerConfig, DelegationRecord, DelegationResult, DuckDbAction, DuckDbActionType, DuckDbBatchOptions, DuckDbBatchResponse, DuckDbDatabaseHandle, DuckDbExecuteOptions, DuckDbExecuteResponse, DuckDbOptions, DuckDbQueryOptions, DuckDbQueryResponse, DuckDbService, DuckDbServiceConfig, DuckDbStatement, DuckDbValue, EncodedShareData, ExecuteOptions, ExecuteResponse, Extension, FetchFunction, GenerateShareParams, HookEvent, HookServiceName, HookStreamEvent, HookSubscription, HookWebhookListOptions, HookWebhookRecord, HookWebhookRegistration, HookWebhookScope, HookWebhookUnregisterOptions, HooksService, HooksServiceConfig, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, IHooksService, IKVService, INotificationHandler, IPrefixedKVService, ISQLService, ISessionManager, ISessionStorage, ISharingService, ISigner, ISpace, ISpaceCreationHandler, ISpaceScopedDelegations, ISpaceScopedSharing, ISpaceService, IUserAuthorization, IWasmBindings, IngestOptions, InvokeFunction, JWK, KVResponse, KVService, KVServiceConfig, KeyInfo, KeyProvider, KeyType, Manifest, ManifestDefaults, ManifestDelegation, ManifestValidationError, PermissionEntry, PermissionNotInManifestError, PersistedSessionData, PrefixedKVService, ProtocolMismatchError, QueryOptions, QueryResponse, ReceiveOptions, ResolvedCapabilities, ResolvedDelegate, ResourceCapability, SQLAction, SQLActionType, SQLService, SQLServiceConfig, SchemaInfo, ServiceContext, ServiceContextConfig, ServiceSession, SessionExpiredError, ShareAccess, ShareLink, ShareLinkData, ShareSchema, SharingService, SharingServiceConfig, SignCallback, SignRequest, SignResponse, SilentNotificationHandler, Space, SpaceConfig, SpaceCreationContext, SpaceErrorCode, SpaceErrorCodes, SpaceInfo, SpaceOwnership, SpaceService, SpaceServiceConfig, SqlStatement, SqlValue, StoredDelegationChain, SubscribeOptions, TableInfo, TinyCloud, TinyCloudConfig, TinyCloudSession, UnsupportedFeatureError, VaultCrypto, VaultEntry, VaultError, VaultGetOptions, VaultGrantOptions, VaultHeaders, VaultListOptions, VaultPublicSpaceKVActions, VaultPutOptions, VersionCheckError, ViewInfo, WasmVaultFunctions, buildSpaceUri, checkNodeInfo, createCapabilityKeyRegistry, createSharingService, createSpaceService, createVaultCrypto, defaultSpaceCreationHandler, expandActionShortNames, isCapabilitySubset, loadManifest, makePublicSpaceId, parseExpiry, parseSpaceUri, resolveManifest, validateManifest } from '@tinycloud/sdk-core';
3
+ export { DelegateToOptions, DelegateToResult, DelegatedAccess, FileSessionStorage, MemorySessionStorage, NodeEventEmitterStrategy, NodeUserAuthorization, NodeUserAuthorizationConfig, PortableDelegation, SignStrategy, TinyCloudNode, TinyCloudNodeConfig, WasmKeyProvider, WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation } from './core.js';
4
+ import { invoke, invokeAny, prepareSession, completeSessionSetup, ensureEip55, makeSpaceId, createDelegation, parseRecapFromSiwe, generateHostSIWEMessage, siweToDelegationHeaders, protocolVersion, vault_encrypt, vault_decrypt, vault_derive_key, vault_x25519_from_seed, vault_x25519_dh, vault_random_bytes, vault_sha256 } from '@tinycloud/node-sdk-wasm';
5
5
  import 'events';
6
6
  import '@tinycloud/sdk-services';
7
7
 
@@ -76,6 +76,7 @@ declare class NodeWasmBindings implements IWasmBindings {
76
76
  ensureEip55: typeof ensureEip55;
77
77
  makeSpaceId: typeof makeSpaceId;
78
78
  createDelegation: typeof createDelegation;
79
+ parseRecapFromSiwe: typeof parseRecapFromSiwe;
79
80
  generateHostSIWEMessage: typeof generateHostSIWEMessage;
80
81
  siweToDelegationHeaders: typeof siweToDelegationHeaders;
81
82
  protocolVersion: typeof protocolVersion;
package/dist/index.js CHANGED
@@ -17036,6 +17036,7 @@ import {
17036
17036
  ensureEip55,
17037
17037
  makeSpaceId,
17038
17038
  createDelegation,
17039
+ parseRecapFromSiwe,
17039
17040
  generateHostSIWEMessage,
17040
17041
  siweToDelegationHeaders,
17041
17042
  protocolVersion,
@@ -17058,6 +17059,7 @@ var _NodeWasmBindings = class _NodeWasmBindings {
17058
17059
  this.ensureEip55 = ensureEip55;
17059
17060
  this.makeSpaceId = makeSpaceId;
17060
17061
  this.createDelegation = createDelegation;
17062
+ this.parseRecapFromSiwe = parseRecapFromSiwe;
17061
17063
  this.generateHostSIWEMessage = generateHostSIWEMessage;
17062
17064
  this.siweToDelegationHeaders = siweToDelegationHeaders;
17063
17065
  this.protocolVersion = protocolVersion;
@@ -17165,7 +17167,13 @@ import {
17165
17167
  CapabilityKeyRegistry,
17166
17168
  SharingService,
17167
17169
  UnsupportedFeatureError,
17168
- makePublicSpaceId
17170
+ makePublicSpaceId,
17171
+ PermissionNotInManifestError,
17172
+ SessionExpiredError,
17173
+ expandActionShortNames,
17174
+ isCapabilitySubset,
17175
+ parseRecapCapabilities,
17176
+ SERVICE_LONG_TO_SHORT
17169
17177
  } from "@tinycloud/sdk-core";
17170
17178
 
17171
17179
  // src/authorization/NodeUserAuthorization.ts
@@ -17174,7 +17182,9 @@ import {
17174
17182
  submitHostDelegation,
17175
17183
  activateSessionWithHost,
17176
17184
  checkNodeInfo,
17177
- AutoApproveSpaceCreationHandler
17185
+ AutoApproveSpaceCreationHandler,
17186
+ manifestAbilitiesUnion,
17187
+ resolveManifest
17178
17188
  } from "@tinycloud/sdk-core";
17179
17189
 
17180
17190
  // src/authorization/strategies.ts
@@ -17314,8 +17324,25 @@ var NodeUserAuthorization = class {
17314
17324
  this.enablePublicSpace = config.enablePublicSpace ?? true;
17315
17325
  this.nonce = config.nonce;
17316
17326
  this.siweConfig = config.siweConfig;
17327
+ this._manifest = config.manifest;
17317
17328
  this.sessionManager = this.wasm.createSessionManager();
17318
17329
  }
17330
+ /**
17331
+ * Return the manifest currently driving sign-in behavior, or
17332
+ * `undefined` if none is set. Used by TinyCloudWeb/TinyCloudNode
17333
+ * internals to surface the manifest for requestPermissions flows
17334
+ * without forcing the caller to track it separately.
17335
+ */
17336
+ get manifest() {
17337
+ return this._manifest;
17338
+ }
17339
+ /**
17340
+ * Install or replace the stored manifest. Takes effect on the next
17341
+ * `signIn()` call — the current session (if any) is not touched.
17342
+ */
17343
+ setManifest(manifest) {
17344
+ this._manifest = manifest;
17345
+ }
17319
17346
  /**
17320
17347
  * The current active session (web-core compatible).
17321
17348
  */
@@ -17332,6 +17359,39 @@ var NodeUserAuthorization = class {
17332
17359
  get nodeFeatures() {
17333
17360
  return this._nodeFeatures;
17334
17361
  }
17362
+ /**
17363
+ * Compute the `abilities` map the WASM `prepareSession` call should
17364
+ * see at sign-in time.
17365
+ *
17366
+ * When a manifest is installed, we resolve it and union together:
17367
+ * - the app's own `resources` (what it needs at runtime)
17368
+ * - every `additionalDelegates[*].permissions` list (what it will
17369
+ * re-delegate to other DIDs post sign-in)
17370
+ *
17371
+ * into the short-service / path / full-URN-actions shape the WASM
17372
+ * layer expects. This is the key invariant that lets
17373
+ * {@link TinyCloudNode.delegateTo} issue manifest-declared
17374
+ * delegations via the session key (no wallet prompt): the session's
17375
+ * own recap already covers every action those delegations need.
17376
+ *
17377
+ * When no manifest is installed, we fall back to the
17378
+ * {@link defaultActions} table so existing callers see no change.
17379
+ *
17380
+ * This is a pure function of `this._manifest` + `this.defaultActions`
17381
+ * — the manifest resolution performs no I/O and throws a
17382
+ * {@link ManifestValidationError} on structural problems (missing
17383
+ * id/name, unparseable expiry, etc), which will surface at sign-in
17384
+ * rather than being silently swallowed.
17385
+ *
17386
+ * @internal
17387
+ */
17388
+ resolveSignInAbilities() {
17389
+ if (this._manifest === void 0) {
17390
+ return this.defaultActions;
17391
+ }
17392
+ const resolved = resolveManifest(this._manifest);
17393
+ return manifestAbilitiesUnion(resolved);
17394
+ }
17335
17395
  /**
17336
17396
  * Build SIWE overrides from the top-level nonce and siweConfig.
17337
17397
  * - Top-level `nonce` is seeded first so `siweConfig.nonce` wins if both are set.
@@ -17535,7 +17595,7 @@ var NodeUserAuthorization = class {
17535
17595
  const now = /* @__PURE__ */ new Date();
17536
17596
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
17537
17597
  const prepared = this.wasm.prepareSession({
17538
- abilities: this.defaultActions,
17598
+ abilities: this.resolveSignInAbilities(),
17539
17599
  address,
17540
17600
  chainId,
17541
17601
  domain: this.domain,
@@ -17678,7 +17738,7 @@ var NodeUserAuthorization = class {
17678
17738
  const now = /* @__PURE__ */ new Date();
17679
17739
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
17680
17740
  const prepared = this.wasm.prepareSession({
17681
- abilities: this.defaultActions,
17741
+ abilities: this.resolveSignInAbilities(),
17682
17742
  address,
17683
17743
  chainId,
17684
17744
  domain: this.domain,
@@ -18004,9 +18064,72 @@ function createWasmKeyProvider(sessionManager) {
18004
18064
  return new WasmKeyProvider({ sessionManager });
18005
18065
  }
18006
18066
 
18067
+ // src/delegateToHelpers.ts
18068
+ import {
18069
+ parseExpiry,
18070
+ SiweMessage
18071
+ } from "@tinycloud/sdk-core";
18072
+ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
18073
+ const byService = /* @__PURE__ */ new Map();
18074
+ for (const a of actions) {
18075
+ const slashIdx = a.indexOf("/");
18076
+ if (slashIdx === -1) {
18077
+ continue;
18078
+ }
18079
+ const service = a.slice(0, slashIdx);
18080
+ if (!service.startsWith("tinycloud.")) {
18081
+ continue;
18082
+ }
18083
+ const list = byService.get(service);
18084
+ if (list === void 0) {
18085
+ byService.set(service, [a]);
18086
+ } else {
18087
+ list.push(a);
18088
+ }
18089
+ }
18090
+ const space = spaceIdOverride ?? "default";
18091
+ const entries = [];
18092
+ for (const [service, actionList] of byService) {
18093
+ entries.push({
18094
+ service,
18095
+ space,
18096
+ path,
18097
+ actions: actionList
18098
+ });
18099
+ }
18100
+ return entries;
18101
+ }
18102
+ function resolveExpiryMs(expiry) {
18103
+ if (expiry === void 0) {
18104
+ return 60 * 60 * 1e3;
18105
+ }
18106
+ if (typeof expiry === "number") {
18107
+ if (!Number.isFinite(expiry) || expiry <= 0) {
18108
+ throw new Error(
18109
+ `delegateTo expiry must be a positive finite number (got ${expiry})`
18110
+ );
18111
+ }
18112
+ return expiry;
18113
+ }
18114
+ return parseExpiry(expiry);
18115
+ }
18116
+ function extractSiweExpiration(siwe) {
18117
+ const parsed = new SiweMessage(siwe);
18118
+ if (parsed.expirationTime === void 0 || parsed.expirationTime === null) {
18119
+ return void 0;
18120
+ }
18121
+ const d = new Date(parsed.expirationTime);
18122
+ if (Number.isNaN(d.getTime())) {
18123
+ throw new Error(
18124
+ `Session SIWE has unparseable expirationTime: ${parsed.expirationTime}`
18125
+ );
18126
+ }
18127
+ return d;
18128
+ }
18129
+
18007
18130
  // src/TinyCloudNode.ts
18008
18131
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
18009
- var TinyCloudNode = class _TinyCloudNode {
18132
+ var _TinyCloudNode = class _TinyCloudNode {
18010
18133
  /**
18011
18134
  * Create a new TinyCloudNode instance.
18012
18135
  *
@@ -18130,12 +18253,35 @@ var TinyCloudNode = class _TinyCloudNode {
18130
18253
  enablePublicSpace: config.enablePublicSpace ?? true,
18131
18254
  spaceCreationHandler: config.spaceCreationHandler,
18132
18255
  nonce: config.nonce,
18133
- siweConfig: config.siweConfig
18256
+ siweConfig: config.siweConfig,
18257
+ manifest: config.manifest
18134
18258
  });
18135
18259
  this.tc = new TinyCloud(this.auth, {
18136
18260
  invokeAny: this.wasmBindings.invokeAny
18137
18261
  });
18138
18262
  }
18263
+ /**
18264
+ * Install or replace the manifest that drives the SIWE recap at
18265
+ * sign-in. Takes effect on the next `signIn()` call — the current
18266
+ * session (if any) is not touched. Wire this up from a higher
18267
+ * layer (e.g. TinyCloudWeb.setManifest) so the manifest is kept
18268
+ * in sync across the stack.
18269
+ */
18270
+ setManifest(manifest) {
18271
+ if (!this.auth) {
18272
+ throw new Error(
18273
+ "setManifest requires wallet mode. Provide a signer or privateKey in the TinyCloudNode config."
18274
+ );
18275
+ }
18276
+ this.auth.setManifest(manifest);
18277
+ }
18278
+ /**
18279
+ * Return the manifest currently installed on the auth handler,
18280
+ * or `undefined` if none is set.
18281
+ */
18282
+ get manifest() {
18283
+ return this.auth?.manifest;
18284
+ }
18139
18285
  /**
18140
18286
  * Get the primary identity DID for this user.
18141
18287
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -18642,7 +18788,19 @@ var TinyCloudNode = class _TinyCloudNode {
18642
18788
  }
18643
18789
  /**
18644
18790
  * Wrapper for the WASM createDelegation function.
18645
- * Adapts the WASM interface to what SharingService expects.
18791
+ *
18792
+ * The WASM call now takes a multi-resource `abilities` map
18793
+ * (matching `prepareSession`'s shape) and emits ONE UCAN that
18794
+ * covers every `(service, path, actions)` entry. We mirror the raw
18795
+ * result back through `CreateDelegationWasmResult`, converting the
18796
+ * seconds-since-epoch `expiry` to a Date and normalizing the
18797
+ * `delegateDid` → `delegateDID` case.
18798
+ *
18799
+ * Both SharingService (single-entry) and
18800
+ * {@link TinyCloudNode.delegateTo} (multi-entry) drive this through
18801
+ * the same code path so there's exactly one place that touches the
18802
+ * WASM boundary.
18803
+ *
18646
18804
  * @internal
18647
18805
  */
18648
18806
  createDelegationWrapper(params) {
@@ -18657,18 +18815,19 @@ var TinyCloudNode = class _TinyCloudNode {
18657
18815
  wasmSession,
18658
18816
  params.delegateDID,
18659
18817
  params.spaceId,
18660
- params.path,
18661
- params.actions,
18818
+ params.abilities,
18662
18819
  params.expirationSecs,
18663
18820
  params.notBeforeSecs
18664
18821
  );
18665
18822
  return {
18666
18823
  delegation: result.delegation,
18667
18824
  cid: result.cid,
18668
- delegateDID: result.delegateDid,
18669
- path: result.path,
18670
- actions: result.actions,
18671
- expiry: new Date(result.expiry * 1e3)
18825
+ // Rust serde `rename_all = "camelCase"` emits `delegateDid`
18826
+ // (lowercase d); the TypeScript interface uses `delegateDID`
18827
+ // (historical, matches Delegation.delegateDID). Normalize here.
18828
+ delegateDID: result.delegateDid ?? result.delegateDID,
18829
+ expiry: new Date(result.expiry * 1e3),
18830
+ resources: result.resources
18672
18831
  };
18673
18832
  }
18674
18833
  /**
@@ -19140,6 +19299,209 @@ var TinyCloudNode = class _TinyCloudNode {
19140
19299
  async checkPermission(path, action) {
19141
19300
  return this.delegationManager.checkPermission(path, action);
19142
19301
  }
19302
+ /**
19303
+ * Issue a delegation using the capability-chain flow.
19304
+ *
19305
+ * When every requested permission is a subset of the current
19306
+ * session's recap, the delegation is signed by the session key via
19307
+ * WASM — no wallet prompt. When at least one is NOT derivable, a
19308
+ * {@link PermissionNotInManifestError} is raised (carrying the
19309
+ * missing entries) so the caller can trigger an escalation flow
19310
+ * (e.g. `TinyCloudWeb.requestPermissions`). Passing
19311
+ * `forceWalletSign: true` bypasses the derivability check and
19312
+ * always uses the wallet-signed SIWE path — used by the legacy
19313
+ * `createDelegation` fallback and by callers that want explicit
19314
+ * wallet confirmation.
19315
+ *
19316
+ * Multi-entry delegations are now emitted as **one** signed UCAN:
19317
+ * the underlying WASM `createDelegation` takes a full
19318
+ * `HashMap<Service, HashMap<Path, Vec<Ability>>>` abilities map
19319
+ * and produces a single attenuation carrying every
19320
+ * `(service, path, actions)` entry. The returned
19321
+ * {@link DelegateToResult.delegation} is that single blob, and
19322
+ * apps can POST it to their backend exactly like a single-entry
19323
+ * delegation (the server verifies all granted resources from one
19324
+ * UCAN).
19325
+ *
19326
+ * For single-entry requests the `PortableDelegation.path` and
19327
+ * `.actions` fields mirror the one granted entry. For
19328
+ * multi-entry requests they mirror the **first** entry (stable
19329
+ * lexicographic order from the Rust side); consumers that need
19330
+ * the full picture read `PortableDelegation.resources`.
19331
+ *
19332
+ * @throws {@link SessionExpiredError} when there is no session or
19333
+ * the current session has expired (or will within the 60s
19334
+ * safety margin).
19335
+ * @throws {@link PermissionNotInManifestError} when any requested
19336
+ * entry is not a subset of the granted session capabilities and
19337
+ * `forceWalletSign` is not set.
19338
+ */
19339
+ async delegateTo(did, permissions, options) {
19340
+ const session = this.auth?.tinyCloudSession;
19341
+ if (!session) {
19342
+ throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
19343
+ }
19344
+ const sessionExpiry = extractSiweExpiration(session.siwe);
19345
+ if (sessionExpiry !== void 0) {
19346
+ const now2 = Date.now();
19347
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
19348
+ if (sessionExpiry.getTime() <= now2 + marginMs) {
19349
+ throw new SessionExpiredError(sessionExpiry);
19350
+ }
19351
+ }
19352
+ if (!Array.isArray(permissions) || permissions.length === 0) {
19353
+ throw new Error(
19354
+ "delegateTo requires a non-empty permissions array"
19355
+ );
19356
+ }
19357
+ const expandedEntries = permissions.map((entry) => ({
19358
+ ...entry,
19359
+ actions: expandActionShortNames(entry.service, entry.actions)
19360
+ }));
19361
+ const now = /* @__PURE__ */ new Date();
19362
+ const expiryMs = resolveExpiryMs(options?.expiry);
19363
+ const expirationTime = new Date(now.getTime() + expiryMs);
19364
+ let effectiveExpiration = expirationTime;
19365
+ if (sessionExpiry !== void 0 && sessionExpiry < expirationTime) {
19366
+ effectiveExpiration = sessionExpiry;
19367
+ }
19368
+ if (options?.forceWalletSign) {
19369
+ if (expandedEntries.length > 1) {
19370
+ throw new Error(
19371
+ "delegateTo with forceWalletSign=true supports at most one PermissionEntry. Multi-entry requests must go through the session-key UCAN path (drop forceWalletSign) or the legacy createDelegation method."
19372
+ );
19373
+ }
19374
+ const delegation2 = await this.createDelegationLegacyWalletPath(
19375
+ did,
19376
+ expandedEntries[0],
19377
+ effectiveExpiration
19378
+ );
19379
+ return { delegation: delegation2, prompted: true };
19380
+ }
19381
+ const granted = parseRecapCapabilities(
19382
+ (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
19383
+ session.siwe
19384
+ );
19385
+ const { subset, missing } = isCapabilitySubset(expandedEntries, granted);
19386
+ if (!subset) {
19387
+ throw new PermissionNotInManifestError(missing, granted);
19388
+ }
19389
+ const delegation = await this.createDelegationViaWasmPath(
19390
+ did,
19391
+ expandedEntries,
19392
+ effectiveExpiration,
19393
+ session
19394
+ );
19395
+ return { delegation, prompted: false };
19396
+ }
19397
+ /**
19398
+ * Issue a delegation via the session-key UCAN WASM path.
19399
+ *
19400
+ * The caller has already verified every entry is derivable from
19401
+ * the current session; we build one multi-resource abilities map
19402
+ * and emit one signed UCAN covering them all.
19403
+ *
19404
+ * All entries must share the same target space (the UCAN is
19405
+ * scoped to a single space). If they don't, this throws — mixing
19406
+ * spaces in a single delegation is not supported by the underlying
19407
+ * Rust create_delegation call and the resulting UCAN would be
19408
+ * under-specified.
19409
+ *
19410
+ * @internal
19411
+ */
19412
+ async createDelegationViaWasmPath(did, entries, expirationTime, session) {
19413
+ if (entries.length === 0) {
19414
+ throw new Error(
19415
+ "createDelegationViaWasmPath requires a non-empty entries array"
19416
+ );
19417
+ }
19418
+ const resolvedSpaces = /* @__PURE__ */ new Set();
19419
+ for (const entry of entries) {
19420
+ const spaceId2 = entry.space === "default" ? session.spaceId : entry.space;
19421
+ resolvedSpaces.add(spaceId2);
19422
+ }
19423
+ if (resolvedSpaces.size !== 1) {
19424
+ throw new Error(
19425
+ `delegateTo: all permission entries must target the same space, got ${resolvedSpaces.size}: ${JSON.stringify([...resolvedSpaces])}`
19426
+ );
19427
+ }
19428
+ const spaceId = [...resolvedSpaces][0];
19429
+ const abilities = {};
19430
+ for (const entry of entries) {
19431
+ const shortService = SERVICE_LONG_TO_SHORT[entry.service];
19432
+ if (shortService === void 0) {
19433
+ throw new Error(
19434
+ `delegateTo: unknown service '${entry.service}' \u2014 no short-form mapping`
19435
+ );
19436
+ }
19437
+ if (abilities[shortService] === void 0) {
19438
+ abilities[shortService] = {};
19439
+ }
19440
+ const pathsMap = abilities[shortService];
19441
+ const existing = pathsMap[entry.path];
19442
+ if (existing === void 0) {
19443
+ pathsMap[entry.path] = [...entry.actions];
19444
+ } else {
19445
+ const seen = new Set(existing);
19446
+ for (const action of entry.actions) {
19447
+ if (!seen.has(action)) {
19448
+ existing.push(action);
19449
+ seen.add(action);
19450
+ }
19451
+ }
19452
+ }
19453
+ }
19454
+ const serviceSession = {
19455
+ delegationHeader: session.delegationHeader,
19456
+ delegationCid: session.delegationCid,
19457
+ jwk: session.jwk,
19458
+ spaceId,
19459
+ verificationMethod: session.verificationMethod
19460
+ };
19461
+ const expirationSecs = Math.floor(expirationTime.getTime() / 1e3);
19462
+ const result = this.createDelegationWrapper({
19463
+ session: serviceSession,
19464
+ delegateDID: did,
19465
+ spaceId,
19466
+ abilities,
19467
+ expirationSecs
19468
+ });
19469
+ const primary = result.resources[0];
19470
+ return {
19471
+ cid: result.cid,
19472
+ delegationHeader: { Authorization: `Bearer ${result.delegation}` },
19473
+ spaceId,
19474
+ path: primary.path,
19475
+ actions: primary.actions,
19476
+ resources: result.resources,
19477
+ disableSubDelegation: false,
19478
+ expiry: result.expiry,
19479
+ delegateDID: did,
19480
+ ownerAddress: session.address,
19481
+ chainId: session.chainId,
19482
+ host: this.config.host
19483
+ };
19484
+ }
19485
+ /**
19486
+ * Issue a delegation via the legacy wallet-signed SIWE path for a single
19487
+ * {@link PermissionEntry}. Shares the implementation with the public
19488
+ * `createDelegation` method via {@link createDelegationWalletPath} so
19489
+ * both entry points hit exactly the same SIWE / signer / public-space
19490
+ * logic without mutual recursion.
19491
+ *
19492
+ * @internal
19493
+ */
19494
+ async createDelegationLegacyWalletPath(delegateDID, entry, expirationTime) {
19495
+ const spaceIdOverride = entry.space === "default" ? void 0 : entry.space;
19496
+ return this.createDelegationWalletPath({
19497
+ path: entry.path,
19498
+ actions: entry.actions,
19499
+ delegateDID,
19500
+ includePublicSpace: true,
19501
+ expiryMs: Math.max(0, expirationTime.getTime() - Date.now()),
19502
+ spaceIdOverride
19503
+ });
19504
+ }
19143
19505
  /**
19144
19506
  * Create a delegation from this user to another user.
19145
19507
  *
@@ -19150,6 +19512,49 @@ var TinyCloudNode = class _TinyCloudNode {
19150
19512
  * @returns A portable delegation that can be sent to the recipient
19151
19513
  */
19152
19514
  async createDelegation(params) {
19515
+ if (!this.signer) {
19516
+ throw new Error("Cannot createDelegation() in session-only mode. Requires wallet mode.");
19517
+ }
19518
+ if (!this.auth?.tinyCloudSession) {
19519
+ throw new Error("Not signed in. Call signIn() first.");
19520
+ }
19521
+ let resolvedDelegateDID = params.delegateDID;
19522
+ if (resolvedDelegateDID.endsWith(".eth") && this.config.ensResolver) {
19523
+ const address = await this.config.ensResolver.resolveAddress(resolvedDelegateDID);
19524
+ if (!address) throw new Error(`Could not resolve ENS name: ${resolvedDelegateDID}`);
19525
+ resolvedDelegateDID = `did:pkh:eip155:1:${address}`;
19526
+ }
19527
+ const entries = legacyParamsToPermissionEntries(
19528
+ params.actions,
19529
+ params.path,
19530
+ params.spaceIdOverride
19531
+ );
19532
+ try {
19533
+ const result = await this.delegateTo(
19534
+ resolvedDelegateDID,
19535
+ entries,
19536
+ params.expiryMs !== void 0 ? { expiry: params.expiryMs } : void 0
19537
+ );
19538
+ return result.delegation;
19539
+ } catch (err) {
19540
+ if (err instanceof PermissionNotInManifestError) {
19541
+ } else {
19542
+ throw err;
19543
+ }
19544
+ }
19545
+ return this.createDelegationWalletPath({
19546
+ ...params,
19547
+ delegateDID: resolvedDelegateDID
19548
+ });
19549
+ }
19550
+ /**
19551
+ * Legacy wallet-signed SIWE delegation path. Lifted from the original
19552
+ * `createDelegation` body verbatim so both the legacy public method and
19553
+ * `delegateTo({ forceWalletSign: true })` hit the same code.
19554
+ *
19555
+ * @internal
19556
+ */
19557
+ async createDelegationWalletPath(params) {
19153
19558
  if (!this.signer) {
19154
19559
  throw new Error("Cannot createDelegation() in session-only mode. Requires wallet mode.");
19155
19560
  }
@@ -19157,11 +19562,6 @@ var TinyCloudNode = class _TinyCloudNode {
19157
19562
  if (!session) {
19158
19563
  throw new Error("Not signed in. Call signIn() first.");
19159
19564
  }
19160
- if (params.delegateDID.endsWith(".eth") && this.config.ensResolver) {
19161
- const address = await this.config.ensResolver.resolveAddress(params.delegateDID);
19162
- if (!address) throw new Error(`Could not resolve ENS name: ${params.delegateDID}`);
19163
- params = { ...params, delegateDID: `did:pkh:eip155:1:${address}` };
19164
- }
19165
19565
  const abilities = {};
19166
19566
  const kvActions = params.actions.filter((a) => a.startsWith("tinycloud.kv/"));
19167
19567
  const sqlActions = params.actions.filter((a) => a.startsWith("tinycloud.sql/"));
@@ -19449,6 +19849,18 @@ var TinyCloudNode = class _TinyCloudNode {
19449
19849
  };
19450
19850
  }
19451
19851
  };
19852
+ // ===========================================================================
19853
+ // Capability-chain delegation (spec: .claude/specs/capability-chain.md)
19854
+ // ===========================================================================
19855
+ /**
19856
+ * Safety margin before the session's own expiry at which {@link delegateTo}
19857
+ * will refuse to issue a derived delegation. Prevents issuing sub-delegations
19858
+ * that would be invalid by the time the recipient used them. Spec: 60 seconds.
19859
+ *
19860
+ * @internal
19861
+ */
19862
+ _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS = 6e4;
19863
+ var TinyCloudNode = _TinyCloudNode;
19452
19864
 
19453
19865
  // src/nodeDefaults.ts
19454
19866
  TinyCloudNode.registerNodeDefaults({
@@ -19584,6 +19996,19 @@ var FileSessionStorage = class {
19584
19996
  }
19585
19997
  };
19586
19998
 
19999
+ // src/index.ts
20000
+ import {
20001
+ PermissionNotInManifestError as PermissionNotInManifestError2,
20002
+ SessionExpiredError as SessionExpiredError2,
20003
+ ManifestValidationError,
20004
+ resolveManifest as resolveManifest2,
20005
+ validateManifest,
20006
+ loadManifest,
20007
+ isCapabilitySubset as isCapabilitySubset2,
20008
+ expandActionShortNames as expandActionShortNames2,
20009
+ parseExpiry as parseExpiry2
20010
+ } from "@tinycloud/sdk-core";
20011
+
19587
20012
  // src/delegation.ts
19588
20013
  function serializeDelegation(delegation) {
19589
20014
  return JSON.stringify({
@@ -19657,15 +20082,18 @@ export {
19657
20082
  FileSessionStorage,
19658
20083
  HooksService3 as HooksService,
19659
20084
  KVService3 as KVService,
20085
+ ManifestValidationError,
19660
20086
  MemorySessionStorage,
19661
20087
  NodeUserAuthorization,
19662
20088
  NodeWasmBindings,
20089
+ PermissionNotInManifestError2 as PermissionNotInManifestError,
19663
20090
  PrefixedKVService,
19664
20091
  PrivateKeySigner,
19665
20092
  ProtocolMismatchError,
19666
20093
  SQLAction,
19667
20094
  SQLService3 as SQLService,
19668
20095
  ServiceContext3 as ServiceContext,
20096
+ SessionExpiredError2 as SessionExpiredError,
19669
20097
  SharingService2 as SharingService,
19670
20098
  SilentNotificationHandler2 as SilentNotificationHandler,
19671
20099
  Space,
@@ -19688,9 +20116,15 @@ export {
19688
20116
  defaultSignStrategy,
19689
20117
  defaultSpaceCreationHandler,
19690
20118
  deserializeDelegation,
20119
+ expandActionShortNames2 as expandActionShortNames,
20120
+ isCapabilitySubset2 as isCapabilitySubset,
20121
+ loadManifest,
19691
20122
  makePublicSpaceId2 as makePublicSpaceId,
20123
+ parseExpiry2 as parseExpiry,
19692
20124
  parseSpaceUri,
19693
- serializeDelegation
20125
+ resolveManifest2 as resolveManifest,
20126
+ serializeDelegation,
20127
+ validateManifest
19694
20128
  };
19695
20129
  /*! Bundled license information:
19696
20130