@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/core.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, ClientSession, TinyCloudSession, Extension, Delegation, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, IDataVaultService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISharingService, CreateDelegationParams, DelegationResult, KeyProvider, ISessionManager, JWK } 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, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, 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, 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';
1
+ import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, Manifest, ClientSession, TinyCloudSession, Extension, Delegation, DelegatedResource, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, IDataVaultService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISharingService, CreateDelegationParams, DelegationResult, PermissionEntry, KeyProvider, ISessionManager, JWK } 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, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, 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, 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
3
  import { EventEmitter } from 'events';
4
4
  import { InvokeFunction } from '@tinycloud/sdk-services';
5
5
 
@@ -203,6 +203,25 @@ interface NodeUserAuthorizationConfig {
203
203
  nonce?: string;
204
204
  /** Optional SIWE configuration overrides (e.g., nonce for server-provided nonces) */
205
205
  siweConfig?: SiweConfig;
206
+ /**
207
+ * App manifest used to drive the SIWE recap at sign-in.
208
+ *
209
+ * When set, `signIn` resolves the manifest (via
210
+ * {@link resolveManifest}), unions the app's own permissions with
211
+ * every `delegations[*].permissions` list, converts to the WASM
212
+ * abilities shape, and uses that map as the session's granted
213
+ * capabilities — *instead* of `defaultActions`.
214
+ *
215
+ * This is what makes manifest-declared pre-delegations usable: the
216
+ * session key's recap covers both the app's runtime needs and the
217
+ * downstream delegation targets, so `delegateTo` can issue the
218
+ * sub-delegation via the session-key UCAN path without a wallet
219
+ * prompt.
220
+ *
221
+ * When omitted, `signIn` falls back to `defaultActions` for
222
+ * backwards compatibility.
223
+ */
224
+ manifest?: Manifest;
206
225
  }
207
226
  /**
208
227
  * Node.js implementation of IUserAuthorization.
@@ -253,6 +272,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
253
272
  private readonly nonce?;
254
273
  private readonly siweConfig?;
255
274
  private readonly wasm;
275
+ /**
276
+ * Stored manifest, if one was provided at construction time. Used by
277
+ * {@link signIn} to derive the session's granted capabilities instead
278
+ * of falling back to {@link defaultActions}.
279
+ */
280
+ private _manifest?;
256
281
  private sessionManager;
257
282
  private extensions;
258
283
  private _session?;
@@ -261,6 +286,18 @@ declare class NodeUserAuthorization implements IUserAuthorization {
261
286
  private _chainId?;
262
287
  private _nodeFeatures;
263
288
  constructor(config: NodeUserAuthorizationConfig);
289
+ /**
290
+ * Return the manifest currently driving sign-in behavior, or
291
+ * `undefined` if none is set. Used by TinyCloudWeb/TinyCloudNode
292
+ * internals to surface the manifest for requestPermissions flows
293
+ * without forcing the caller to track it separately.
294
+ */
295
+ get manifest(): Manifest | undefined;
296
+ /**
297
+ * Install or replace the stored manifest. Takes effect on the next
298
+ * `signIn()` call — the current session (if any) is not touched.
299
+ */
300
+ setManifest(manifest: Manifest | undefined): void;
264
301
  /**
265
302
  * The current active session (web-core compatible).
266
303
  */
@@ -271,6 +308,33 @@ declare class NodeUserAuthorization implements IUserAuthorization {
271
308
  */
272
309
  get tinyCloudSession(): TinyCloudSession | undefined;
273
310
  get nodeFeatures(): string[];
311
+ /**
312
+ * Compute the `abilities` map the WASM `prepareSession` call should
313
+ * see at sign-in time.
314
+ *
315
+ * When a manifest is installed, we resolve it and union together:
316
+ * - the app's own `resources` (what it needs at runtime)
317
+ * - every `additionalDelegates[*].permissions` list (what it will
318
+ * re-delegate to other DIDs post sign-in)
319
+ *
320
+ * into the short-service / path / full-URN-actions shape the WASM
321
+ * layer expects. This is the key invariant that lets
322
+ * {@link TinyCloudNode.delegateTo} issue manifest-declared
323
+ * delegations via the session key (no wallet prompt): the session's
324
+ * own recap already covers every action those delegations need.
325
+ *
326
+ * When no manifest is installed, we fall back to the
327
+ * {@link defaultActions} table so existing callers see no change.
328
+ *
329
+ * This is a pure function of `this._manifest` + `this.defaultActions`
330
+ * — the manifest resolution performs no I/O and throws a
331
+ * {@link ManifestValidationError} on structural problems (missing
332
+ * id/name, unparseable expiry, etc), which will surface at sign-in
333
+ * rather than being silently swallowed.
334
+ *
335
+ * @internal
336
+ */
337
+ private resolveSignInAbilities;
274
338
  /**
275
339
  * Build SIWE overrides from the top-level nonce and siweConfig.
276
340
  * - Top-level `nonce` is seeded first so `siweConfig.nonce` wins if both are set.
@@ -404,6 +468,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
404
468
  * - `ownerAddress`: Space owner's address for session creation
405
469
  * - `chainId`: Chain ID for session creation
406
470
  * - `host`: Optional server URL
471
+ * - `resources`: Multi-resource grant breakdown (present when the
472
+ * delegation was issued via the multi-resource WASM path, i.e. one
473
+ * UCAN covering multiple `(service, path, actions)` entries). The
474
+ * flat `path` + `actions` fields mirror the first entry for
475
+ * single-resource callers; consumers that need the full picture
476
+ * read `resources`.
407
477
  */
408
478
  interface PortableDelegation extends Omit<Delegation, "isRevoked"> {
409
479
  /** The authorization header for this delegation (structured format) */
@@ -420,6 +490,14 @@ interface PortableDelegation extends Omit<Delegation, "isRevoked"> {
420
490
  disableSubDelegation?: boolean;
421
491
  /** Companion delegation for the user's public space (auto-created when includePublicSpace is true) */
422
492
  publicDelegation?: PortableDelegation;
493
+ /**
494
+ * Full multi-resource grant breakdown. Present when the delegation
495
+ * was issued via the multi-resource WASM path; each entry describes
496
+ * one `(service, space, path, actions)` grant carried by the single
497
+ * underlying UCAN. When absent, only the flat `path` + `actions`
498
+ * fields are authoritative (legacy single-resource shape).
499
+ */
500
+ resources?: DelegatedResource[];
423
501
  }
424
502
  /**
425
503
  * Serialize a PortableDelegation for transport (e.g., over network).
@@ -549,6 +627,51 @@ interface TinyCloudNodeConfig {
549
627
  nonce?: string;
550
628
  /** Optional SIWE configuration overrides (e.g., nonce for server-provided nonces) */
551
629
  siweConfig?: SiweConfig;
630
+ /**
631
+ * App manifest driving the SIWE recap at sign-in.
632
+ *
633
+ * When set, `signIn()` resolves the manifest, unions the app's own
634
+ * permissions with every manifest-declared delegation's permissions,
635
+ * and uses that union as the session's granted capabilities — NOT
636
+ * the legacy `defaultActions` table. This is what makes
637
+ * `delegateTo(manifestDeclaredDid, permissions)` work without a
638
+ * wallet prompt: the session key's recap already covers the
639
+ * delegation target's needs at sign-in time.
640
+ *
641
+ * When omitted, `signIn()` falls back to `defaultActions` for
642
+ * backwards compatibility with callers that pre-date the manifest
643
+ * flow.
644
+ */
645
+ manifest?: Manifest;
646
+ }
647
+ /**
648
+ * Options for {@link TinyCloudNode.delegateTo}.
649
+ *
650
+ * `expiry` accepts either an ms-format duration string (e.g. `"7d"`, `"1h"`)
651
+ * or a raw number of milliseconds. When omitted, the default is 1 hour.
652
+ *
653
+ * `forceWalletSign` bypasses the derivability check and sends the
654
+ * delegation through the legacy wallet-signed SIWE path, which always
655
+ * triggers a wallet prompt. Used for testing, for explicit wallet
656
+ * confirmation flows, and by the legacy `createDelegation` fallback.
657
+ */
658
+ interface DelegateToOptions {
659
+ /** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
660
+ expiry?: string | number;
661
+ /** Force the wallet-signed SIWE path even if the caps are derivable. Default false. */
662
+ forceWalletSign?: boolean;
663
+ }
664
+ /**
665
+ * Result of {@link TinyCloudNode.delegateTo}.
666
+ *
667
+ * `prompted` indicates whether a wallet prompt was shown — `true` for the
668
+ * legacy wallet path (always), `false` for the session-key UCAN path (never).
669
+ * Callers wiring single-prompt sign-in flows use this to assert that their
670
+ * capability chain was derivable.
671
+ */
672
+ interface DelegateToResult {
673
+ delegation: PortableDelegation;
674
+ prompted: boolean;
552
675
  }
553
676
  /**
554
677
  * High-level TinyCloud API for Node.js environments.
@@ -625,6 +748,19 @@ declare class TinyCloudNode {
625
748
  * @internal
626
749
  */
627
750
  private setupAuth;
751
+ /**
752
+ * Install or replace the manifest that drives the SIWE recap at
753
+ * sign-in. Takes effect on the next `signIn()` call — the current
754
+ * session (if any) is not touched. Wire this up from a higher
755
+ * layer (e.g. TinyCloudWeb.setManifest) so the manifest is kept
756
+ * in sync across the stack.
757
+ */
758
+ setManifest(manifest: Manifest | undefined): void;
759
+ /**
760
+ * Return the manifest currently installed on the auth handler,
761
+ * or `undefined` if none is set.
762
+ */
763
+ get manifest(): Manifest | undefined;
628
764
  /**
629
765
  * Get the primary identity DID for this user.
630
766
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -749,7 +885,19 @@ declare class TinyCloudNode {
749
885
  private getSessionExpiry;
750
886
  /**
751
887
  * Wrapper for the WASM createDelegation function.
752
- * Adapts the WASM interface to what SharingService expects.
888
+ *
889
+ * The WASM call now takes a multi-resource `abilities` map
890
+ * (matching `prepareSession`'s shape) and emits ONE UCAN that
891
+ * covers every `(service, path, actions)` entry. We mirror the raw
892
+ * result back through `CreateDelegationWasmResult`, converting the
893
+ * seconds-since-epoch `expiry` to a Date and normalizing the
894
+ * `delegateDid` → `delegateDID` case.
895
+ *
896
+ * Both SharingService (single-entry) and
897
+ * {@link TinyCloudNode.delegateTo} (multi-entry) drive this through
898
+ * the same code path so there's exactly one place that touches the
899
+ * WASM boundary.
900
+ *
753
901
  * @internal
754
902
  */
755
903
  private createDelegationWrapper;
@@ -977,6 +1125,78 @@ declare class TinyCloudNode {
977
1125
  * @returns Result containing boolean permission status
978
1126
  */
979
1127
  checkPermission(path: string, action: string): Promise<DelegationResult<boolean>>;
1128
+ /**
1129
+ * Safety margin before the session's own expiry at which {@link delegateTo}
1130
+ * will refuse to issue a derived delegation. Prevents issuing sub-delegations
1131
+ * that would be invalid by the time the recipient used them. Spec: 60 seconds.
1132
+ *
1133
+ * @internal
1134
+ */
1135
+ private static readonly SESSION_EXPIRY_SAFETY_MARGIN_MS;
1136
+ /**
1137
+ * Issue a delegation using the capability-chain flow.
1138
+ *
1139
+ * When every requested permission is a subset of the current
1140
+ * session's recap, the delegation is signed by the session key via
1141
+ * WASM — no wallet prompt. When at least one is NOT derivable, a
1142
+ * {@link PermissionNotInManifestError} is raised (carrying the
1143
+ * missing entries) so the caller can trigger an escalation flow
1144
+ * (e.g. `TinyCloudWeb.requestPermissions`). Passing
1145
+ * `forceWalletSign: true` bypasses the derivability check and
1146
+ * always uses the wallet-signed SIWE path — used by the legacy
1147
+ * `createDelegation` fallback and by callers that want explicit
1148
+ * wallet confirmation.
1149
+ *
1150
+ * Multi-entry delegations are now emitted as **one** signed UCAN:
1151
+ * the underlying WASM `createDelegation` takes a full
1152
+ * `HashMap<Service, HashMap<Path, Vec<Ability>>>` abilities map
1153
+ * and produces a single attenuation carrying every
1154
+ * `(service, path, actions)` entry. The returned
1155
+ * {@link DelegateToResult.delegation} is that single blob, and
1156
+ * apps can POST it to their backend exactly like a single-entry
1157
+ * delegation (the server verifies all granted resources from one
1158
+ * UCAN).
1159
+ *
1160
+ * For single-entry requests the `PortableDelegation.path` and
1161
+ * `.actions` fields mirror the one granted entry. For
1162
+ * multi-entry requests they mirror the **first** entry (stable
1163
+ * lexicographic order from the Rust side); consumers that need
1164
+ * the full picture read `PortableDelegation.resources`.
1165
+ *
1166
+ * @throws {@link SessionExpiredError} when there is no session or
1167
+ * the current session has expired (or will within the 60s
1168
+ * safety margin).
1169
+ * @throws {@link PermissionNotInManifestError} when any requested
1170
+ * entry is not a subset of the granted session capabilities and
1171
+ * `forceWalletSign` is not set.
1172
+ */
1173
+ delegateTo(did: string, permissions: PermissionEntry[], options?: DelegateToOptions): Promise<DelegateToResult>;
1174
+ /**
1175
+ * Issue a delegation via the session-key UCAN WASM path.
1176
+ *
1177
+ * The caller has already verified every entry is derivable from
1178
+ * the current session; we build one multi-resource abilities map
1179
+ * and emit one signed UCAN covering them all.
1180
+ *
1181
+ * All entries must share the same target space (the UCAN is
1182
+ * scoped to a single space). If they don't, this throws — mixing
1183
+ * spaces in a single delegation is not supported by the underlying
1184
+ * Rust create_delegation call and the resulting UCAN would be
1185
+ * under-specified.
1186
+ *
1187
+ * @internal
1188
+ */
1189
+ private createDelegationViaWasmPath;
1190
+ /**
1191
+ * Issue a delegation via the legacy wallet-signed SIWE path for a single
1192
+ * {@link PermissionEntry}. Shares the implementation with the public
1193
+ * `createDelegation` method via {@link createDelegationWalletPath} so
1194
+ * both entry points hit exactly the same SIWE / signer / public-space
1195
+ * logic without mutual recursion.
1196
+ *
1197
+ * @internal
1198
+ */
1199
+ private createDelegationLegacyWalletPath;
980
1200
  /**
981
1201
  * Create a delegation from this user to another user.
982
1202
  *
@@ -1002,6 +1222,14 @@ declare class TinyCloudNode {
1002
1222
  /** Include a companion delegation for the user's public space (default: true) */
1003
1223
  includePublicSpace?: boolean;
1004
1224
  }): Promise<PortableDelegation>;
1225
+ /**
1226
+ * Legacy wallet-signed SIWE delegation path. Lifted from the original
1227
+ * `createDelegation` body verbatim so both the legacy public method and
1228
+ * `delegateTo({ forceWalletSign: true })` hit the same code.
1229
+ *
1230
+ * @internal
1231
+ */
1232
+ private createDelegationWalletPath;
1005
1233
  /**
1006
1234
  * Use a delegation received from another user.
1007
1235
  *
@@ -1148,4 +1376,4 @@ declare class WasmKeyProvider implements KeyProvider {
1148
1376
  */
1149
1377
  declare function createWasmKeyProvider(sessionManager: SessionManagerWithListing): WasmKeyProvider;
1150
1378
 
1151
- export { DelegatedAccess, FileSessionStorage, MemorySessionStorage, type NodeEventEmitterStrategy, NodeUserAuthorization, type NodeUserAuthorizationConfig, type PortableDelegation, type SignStrategy, TinyCloudNode, type TinyCloudNodeConfig, WasmKeyProvider, type WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation };
1379
+ export { type DelegateToOptions, type DelegateToResult, DelegatedAccess, FileSessionStorage, MemorySessionStorage, type NodeEventEmitterStrategy, NodeUserAuthorization, type NodeUserAuthorizationConfig, type PortableDelegation, type SignStrategy, TinyCloudNode, type TinyCloudNodeConfig, WasmKeyProvider, type WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation };
package/dist/core.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, ClientSession, TinyCloudSession, Extension, Delegation, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, IDataVaultService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISharingService, CreateDelegationParams, DelegationResult, KeyProvider, ISessionManager, JWK } 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, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, 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, 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';
1
+ import { ISessionStorage, PersistedSessionData, AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, IUserAuthorization, ISigner, ISpaceCreationHandler, IWasmBindings, SiweConfig, Manifest, ClientSession, TinyCloudSession, Extension, Delegation, DelegatedResource, IKVService, ISQLService, IDuckDbService, IHooksService, INotificationHandler, IENSResolver, IDataVaultService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISharingService, CreateDelegationParams, DelegationResult, PermissionEntry, KeyProvider, ISessionManager, JWK } 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, ICapabilityKeyRegistry, IDataVaultService, IDatabaseHandle, IDuckDbDatabaseHandle, IDuckDbService, IENSResolver, 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, 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
3
  import { EventEmitter } from 'events';
4
4
  import { InvokeFunction } from '@tinycloud/sdk-services';
5
5
 
@@ -203,6 +203,25 @@ interface NodeUserAuthorizationConfig {
203
203
  nonce?: string;
204
204
  /** Optional SIWE configuration overrides (e.g., nonce for server-provided nonces) */
205
205
  siweConfig?: SiweConfig;
206
+ /**
207
+ * App manifest used to drive the SIWE recap at sign-in.
208
+ *
209
+ * When set, `signIn` resolves the manifest (via
210
+ * {@link resolveManifest}), unions the app's own permissions with
211
+ * every `delegations[*].permissions` list, converts to the WASM
212
+ * abilities shape, and uses that map as the session's granted
213
+ * capabilities — *instead* of `defaultActions`.
214
+ *
215
+ * This is what makes manifest-declared pre-delegations usable: the
216
+ * session key's recap covers both the app's runtime needs and the
217
+ * downstream delegation targets, so `delegateTo` can issue the
218
+ * sub-delegation via the session-key UCAN path without a wallet
219
+ * prompt.
220
+ *
221
+ * When omitted, `signIn` falls back to `defaultActions` for
222
+ * backwards compatibility.
223
+ */
224
+ manifest?: Manifest;
206
225
  }
207
226
  /**
208
227
  * Node.js implementation of IUserAuthorization.
@@ -253,6 +272,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
253
272
  private readonly nonce?;
254
273
  private readonly siweConfig?;
255
274
  private readonly wasm;
275
+ /**
276
+ * Stored manifest, if one was provided at construction time. Used by
277
+ * {@link signIn} to derive the session's granted capabilities instead
278
+ * of falling back to {@link defaultActions}.
279
+ */
280
+ private _manifest?;
256
281
  private sessionManager;
257
282
  private extensions;
258
283
  private _session?;
@@ -261,6 +286,18 @@ declare class NodeUserAuthorization implements IUserAuthorization {
261
286
  private _chainId?;
262
287
  private _nodeFeatures;
263
288
  constructor(config: NodeUserAuthorizationConfig);
289
+ /**
290
+ * Return the manifest currently driving sign-in behavior, or
291
+ * `undefined` if none is set. Used by TinyCloudWeb/TinyCloudNode
292
+ * internals to surface the manifest for requestPermissions flows
293
+ * without forcing the caller to track it separately.
294
+ */
295
+ get manifest(): Manifest | undefined;
296
+ /**
297
+ * Install or replace the stored manifest. Takes effect on the next
298
+ * `signIn()` call — the current session (if any) is not touched.
299
+ */
300
+ setManifest(manifest: Manifest | undefined): void;
264
301
  /**
265
302
  * The current active session (web-core compatible).
266
303
  */
@@ -271,6 +308,33 @@ declare class NodeUserAuthorization implements IUserAuthorization {
271
308
  */
272
309
  get tinyCloudSession(): TinyCloudSession | undefined;
273
310
  get nodeFeatures(): string[];
311
+ /**
312
+ * Compute the `abilities` map the WASM `prepareSession` call should
313
+ * see at sign-in time.
314
+ *
315
+ * When a manifest is installed, we resolve it and union together:
316
+ * - the app's own `resources` (what it needs at runtime)
317
+ * - every `additionalDelegates[*].permissions` list (what it will
318
+ * re-delegate to other DIDs post sign-in)
319
+ *
320
+ * into the short-service / path / full-URN-actions shape the WASM
321
+ * layer expects. This is the key invariant that lets
322
+ * {@link TinyCloudNode.delegateTo} issue manifest-declared
323
+ * delegations via the session key (no wallet prompt): the session's
324
+ * own recap already covers every action those delegations need.
325
+ *
326
+ * When no manifest is installed, we fall back to the
327
+ * {@link defaultActions} table so existing callers see no change.
328
+ *
329
+ * This is a pure function of `this._manifest` + `this.defaultActions`
330
+ * — the manifest resolution performs no I/O and throws a
331
+ * {@link ManifestValidationError} on structural problems (missing
332
+ * id/name, unparseable expiry, etc), which will surface at sign-in
333
+ * rather than being silently swallowed.
334
+ *
335
+ * @internal
336
+ */
337
+ private resolveSignInAbilities;
274
338
  /**
275
339
  * Build SIWE overrides from the top-level nonce and siweConfig.
276
340
  * - Top-level `nonce` is seeded first so `siweConfig.nonce` wins if both are set.
@@ -404,6 +468,12 @@ declare class NodeUserAuthorization implements IUserAuthorization {
404
468
  * - `ownerAddress`: Space owner's address for session creation
405
469
  * - `chainId`: Chain ID for session creation
406
470
  * - `host`: Optional server URL
471
+ * - `resources`: Multi-resource grant breakdown (present when the
472
+ * delegation was issued via the multi-resource WASM path, i.e. one
473
+ * UCAN covering multiple `(service, path, actions)` entries). The
474
+ * flat `path` + `actions` fields mirror the first entry for
475
+ * single-resource callers; consumers that need the full picture
476
+ * read `resources`.
407
477
  */
408
478
  interface PortableDelegation extends Omit<Delegation, "isRevoked"> {
409
479
  /** The authorization header for this delegation (structured format) */
@@ -420,6 +490,14 @@ interface PortableDelegation extends Omit<Delegation, "isRevoked"> {
420
490
  disableSubDelegation?: boolean;
421
491
  /** Companion delegation for the user's public space (auto-created when includePublicSpace is true) */
422
492
  publicDelegation?: PortableDelegation;
493
+ /**
494
+ * Full multi-resource grant breakdown. Present when the delegation
495
+ * was issued via the multi-resource WASM path; each entry describes
496
+ * one `(service, space, path, actions)` grant carried by the single
497
+ * underlying UCAN. When absent, only the flat `path` + `actions`
498
+ * fields are authoritative (legacy single-resource shape).
499
+ */
500
+ resources?: DelegatedResource[];
423
501
  }
424
502
  /**
425
503
  * Serialize a PortableDelegation for transport (e.g., over network).
@@ -549,6 +627,51 @@ interface TinyCloudNodeConfig {
549
627
  nonce?: string;
550
628
  /** Optional SIWE configuration overrides (e.g., nonce for server-provided nonces) */
551
629
  siweConfig?: SiweConfig;
630
+ /**
631
+ * App manifest driving the SIWE recap at sign-in.
632
+ *
633
+ * When set, `signIn()` resolves the manifest, unions the app's own
634
+ * permissions with every manifest-declared delegation's permissions,
635
+ * and uses that union as the session's granted capabilities — NOT
636
+ * the legacy `defaultActions` table. This is what makes
637
+ * `delegateTo(manifestDeclaredDid, permissions)` work without a
638
+ * wallet prompt: the session key's recap already covers the
639
+ * delegation target's needs at sign-in time.
640
+ *
641
+ * When omitted, `signIn()` falls back to `defaultActions` for
642
+ * backwards compatibility with callers that pre-date the manifest
643
+ * flow.
644
+ */
645
+ manifest?: Manifest;
646
+ }
647
+ /**
648
+ * Options for {@link TinyCloudNode.delegateTo}.
649
+ *
650
+ * `expiry` accepts either an ms-format duration string (e.g. `"7d"`, `"1h"`)
651
+ * or a raw number of milliseconds. When omitted, the default is 1 hour.
652
+ *
653
+ * `forceWalletSign` bypasses the derivability check and sends the
654
+ * delegation through the legacy wallet-signed SIWE path, which always
655
+ * triggers a wallet prompt. Used for testing, for explicit wallet
656
+ * confirmation flows, and by the legacy `createDelegation` fallback.
657
+ */
658
+ interface DelegateToOptions {
659
+ /** Override expiry. ms-format string ("7d", "1h") or raw milliseconds. */
660
+ expiry?: string | number;
661
+ /** Force the wallet-signed SIWE path even if the caps are derivable. Default false. */
662
+ forceWalletSign?: boolean;
663
+ }
664
+ /**
665
+ * Result of {@link TinyCloudNode.delegateTo}.
666
+ *
667
+ * `prompted` indicates whether a wallet prompt was shown — `true` for the
668
+ * legacy wallet path (always), `false` for the session-key UCAN path (never).
669
+ * Callers wiring single-prompt sign-in flows use this to assert that their
670
+ * capability chain was derivable.
671
+ */
672
+ interface DelegateToResult {
673
+ delegation: PortableDelegation;
674
+ prompted: boolean;
552
675
  }
553
676
  /**
554
677
  * High-level TinyCloud API for Node.js environments.
@@ -625,6 +748,19 @@ declare class TinyCloudNode {
625
748
  * @internal
626
749
  */
627
750
  private setupAuth;
751
+ /**
752
+ * Install or replace the manifest that drives the SIWE recap at
753
+ * sign-in. Takes effect on the next `signIn()` call — the current
754
+ * session (if any) is not touched. Wire this up from a higher
755
+ * layer (e.g. TinyCloudWeb.setManifest) so the manifest is kept
756
+ * in sync across the stack.
757
+ */
758
+ setManifest(manifest: Manifest | undefined): void;
759
+ /**
760
+ * Return the manifest currently installed on the auth handler,
761
+ * or `undefined` if none is set.
762
+ */
763
+ get manifest(): Manifest | undefined;
628
764
  /**
629
765
  * Get the primary identity DID for this user.
630
766
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -749,7 +885,19 @@ declare class TinyCloudNode {
749
885
  private getSessionExpiry;
750
886
  /**
751
887
  * Wrapper for the WASM createDelegation function.
752
- * Adapts the WASM interface to what SharingService expects.
888
+ *
889
+ * The WASM call now takes a multi-resource `abilities` map
890
+ * (matching `prepareSession`'s shape) and emits ONE UCAN that
891
+ * covers every `(service, path, actions)` entry. We mirror the raw
892
+ * result back through `CreateDelegationWasmResult`, converting the
893
+ * seconds-since-epoch `expiry` to a Date and normalizing the
894
+ * `delegateDid` → `delegateDID` case.
895
+ *
896
+ * Both SharingService (single-entry) and
897
+ * {@link TinyCloudNode.delegateTo} (multi-entry) drive this through
898
+ * the same code path so there's exactly one place that touches the
899
+ * WASM boundary.
900
+ *
753
901
  * @internal
754
902
  */
755
903
  private createDelegationWrapper;
@@ -977,6 +1125,78 @@ declare class TinyCloudNode {
977
1125
  * @returns Result containing boolean permission status
978
1126
  */
979
1127
  checkPermission(path: string, action: string): Promise<DelegationResult<boolean>>;
1128
+ /**
1129
+ * Safety margin before the session's own expiry at which {@link delegateTo}
1130
+ * will refuse to issue a derived delegation. Prevents issuing sub-delegations
1131
+ * that would be invalid by the time the recipient used them. Spec: 60 seconds.
1132
+ *
1133
+ * @internal
1134
+ */
1135
+ private static readonly SESSION_EXPIRY_SAFETY_MARGIN_MS;
1136
+ /**
1137
+ * Issue a delegation using the capability-chain flow.
1138
+ *
1139
+ * When every requested permission is a subset of the current
1140
+ * session's recap, the delegation is signed by the session key via
1141
+ * WASM — no wallet prompt. When at least one is NOT derivable, a
1142
+ * {@link PermissionNotInManifestError} is raised (carrying the
1143
+ * missing entries) so the caller can trigger an escalation flow
1144
+ * (e.g. `TinyCloudWeb.requestPermissions`). Passing
1145
+ * `forceWalletSign: true` bypasses the derivability check and
1146
+ * always uses the wallet-signed SIWE path — used by the legacy
1147
+ * `createDelegation` fallback and by callers that want explicit
1148
+ * wallet confirmation.
1149
+ *
1150
+ * Multi-entry delegations are now emitted as **one** signed UCAN:
1151
+ * the underlying WASM `createDelegation` takes a full
1152
+ * `HashMap<Service, HashMap<Path, Vec<Ability>>>` abilities map
1153
+ * and produces a single attenuation carrying every
1154
+ * `(service, path, actions)` entry. The returned
1155
+ * {@link DelegateToResult.delegation} is that single blob, and
1156
+ * apps can POST it to their backend exactly like a single-entry
1157
+ * delegation (the server verifies all granted resources from one
1158
+ * UCAN).
1159
+ *
1160
+ * For single-entry requests the `PortableDelegation.path` and
1161
+ * `.actions` fields mirror the one granted entry. For
1162
+ * multi-entry requests they mirror the **first** entry (stable
1163
+ * lexicographic order from the Rust side); consumers that need
1164
+ * the full picture read `PortableDelegation.resources`.
1165
+ *
1166
+ * @throws {@link SessionExpiredError} when there is no session or
1167
+ * the current session has expired (or will within the 60s
1168
+ * safety margin).
1169
+ * @throws {@link PermissionNotInManifestError} when any requested
1170
+ * entry is not a subset of the granted session capabilities and
1171
+ * `forceWalletSign` is not set.
1172
+ */
1173
+ delegateTo(did: string, permissions: PermissionEntry[], options?: DelegateToOptions): Promise<DelegateToResult>;
1174
+ /**
1175
+ * Issue a delegation via the session-key UCAN WASM path.
1176
+ *
1177
+ * The caller has already verified every entry is derivable from
1178
+ * the current session; we build one multi-resource abilities map
1179
+ * and emit one signed UCAN covering them all.
1180
+ *
1181
+ * All entries must share the same target space (the UCAN is
1182
+ * scoped to a single space). If they don't, this throws — mixing
1183
+ * spaces in a single delegation is not supported by the underlying
1184
+ * Rust create_delegation call and the resulting UCAN would be
1185
+ * under-specified.
1186
+ *
1187
+ * @internal
1188
+ */
1189
+ private createDelegationViaWasmPath;
1190
+ /**
1191
+ * Issue a delegation via the legacy wallet-signed SIWE path for a single
1192
+ * {@link PermissionEntry}. Shares the implementation with the public
1193
+ * `createDelegation` method via {@link createDelegationWalletPath} so
1194
+ * both entry points hit exactly the same SIWE / signer / public-space
1195
+ * logic without mutual recursion.
1196
+ *
1197
+ * @internal
1198
+ */
1199
+ private createDelegationLegacyWalletPath;
980
1200
  /**
981
1201
  * Create a delegation from this user to another user.
982
1202
  *
@@ -1002,6 +1222,14 @@ declare class TinyCloudNode {
1002
1222
  /** Include a companion delegation for the user's public space (default: true) */
1003
1223
  includePublicSpace?: boolean;
1004
1224
  }): Promise<PortableDelegation>;
1225
+ /**
1226
+ * Legacy wallet-signed SIWE delegation path. Lifted from the original
1227
+ * `createDelegation` body verbatim so both the legacy public method and
1228
+ * `delegateTo({ forceWalletSign: true })` hit the same code.
1229
+ *
1230
+ * @internal
1231
+ */
1232
+ private createDelegationWalletPath;
1005
1233
  /**
1006
1234
  * Use a delegation received from another user.
1007
1235
  *
@@ -1148,4 +1376,4 @@ declare class WasmKeyProvider implements KeyProvider {
1148
1376
  */
1149
1377
  declare function createWasmKeyProvider(sessionManager: SessionManagerWithListing): WasmKeyProvider;
1150
1378
 
1151
- export { DelegatedAccess, FileSessionStorage, MemorySessionStorage, type NodeEventEmitterStrategy, NodeUserAuthorization, type NodeUserAuthorizationConfig, type PortableDelegation, type SignStrategy, TinyCloudNode, type TinyCloudNodeConfig, WasmKeyProvider, type WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation };
1379
+ export { type DelegateToOptions, type DelegateToResult, DelegatedAccess, FileSessionStorage, MemorySessionStorage, type NodeEventEmitterStrategy, NodeUserAuthorization, type NodeUserAuthorizationConfig, type PortableDelegation, type SignStrategy, TinyCloudNode, type TinyCloudNodeConfig, WasmKeyProvider, type WasmKeyProviderConfig, createWasmKeyProvider, defaultSignStrategy, deserializeDelegation, serializeDelegation };