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

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,4 +1,4 @@
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, PermissionEntry, KeyProvider, ISessionManager, JWK } 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
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';
@@ -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,22 @@ 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;
552
646
  }
553
647
  /**
554
648
  * Options for {@link TinyCloudNode.delegateTo}.
@@ -654,6 +748,19 @@ declare class TinyCloudNode {
654
748
  * @internal
655
749
  */
656
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;
657
764
  /**
658
765
  * Get the primary identity DID for this user.
659
766
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -778,7 +885,19 @@ declare class TinyCloudNode {
778
885
  private getSessionExpiry;
779
886
  /**
780
887
  * Wrapper for the WASM createDelegation function.
781
- * 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
+ *
782
901
  * @internal
783
902
  */
784
903
  private createDelegationWrapper;
@@ -1017,33 +1136,53 @@ declare class TinyCloudNode {
1017
1136
  /**
1018
1137
  * Issue a delegation using the capability-chain flow.
1019
1138
  *
1020
- * When the requested permissions are a subset of the current session's
1021
- * recap, the delegation is signed by the session key via WASM — no wallet
1022
- * prompt. When they are not, a {@link PermissionNotInManifestError} is
1023
- * raised so the caller can trigger an escalation flow (e.g.
1024
- * `TinyCloudWeb.requestPermissions`). Passing `forceWalletSign: true`
1025
- * bypasses the derivability check and always uses the wallet-signed SIWE
1026
- * path used by the legacy `createDelegation` fallback and by callers
1027
- * that want explicit wallet confirmation.
1028
- *
1029
- * Current limitation: exactly one {@link PermissionEntry} per call. For
1030
- * multi-resource delegation, call `delegateTo` multiple times. This keeps
1031
- * each delegation a single `(spaceId, path)` grant, which matches the
1032
- * underlying `PortableDelegation` shape.
1033
- *
1034
- * @throws {@link SessionExpiredError} when there is no session or the
1035
- * current session has expired (or will within the 60s safety margin).
1036
- * @throws {@link PermissionNotInManifestError} when the requested entries
1037
- * are not a subset of the granted session capabilities and
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
1038
1171
  * `forceWalletSign` is not set.
1039
1172
  */
1040
1173
  delegateTo(did: string, permissions: PermissionEntry[], options?: DelegateToOptions): Promise<DelegateToResult>;
1041
1174
  /**
1042
1175
  * Issue a delegation via the session-key UCAN WASM path.
1043
1176
  *
1044
- * The caller has already verified the request is derivable from the
1045
- * current session; we just need to shape the inputs for
1046
- * {@link createDelegationWrapper}.
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.
1047
1186
  *
1048
1187
  * @internal
1049
1188
  */
package/dist/core.d.ts CHANGED
@@ -1,4 +1,4 @@
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, PermissionEntry, KeyProvider, ISessionManager, JWK } 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
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';
@@ -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,22 @@ 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;
552
646
  }
553
647
  /**
554
648
  * Options for {@link TinyCloudNode.delegateTo}.
@@ -654,6 +748,19 @@ declare class TinyCloudNode {
654
748
  * @internal
655
749
  */
656
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;
657
764
  /**
658
765
  * Get the primary identity DID for this user.
659
766
  * - If wallet connected and signed in: returns PKH DID (did:pkh:eip155:{chainId}:{address})
@@ -778,7 +885,19 @@ declare class TinyCloudNode {
778
885
  private getSessionExpiry;
779
886
  /**
780
887
  * Wrapper for the WASM createDelegation function.
781
- * 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
+ *
782
901
  * @internal
783
902
  */
784
903
  private createDelegationWrapper;
@@ -1017,33 +1136,53 @@ declare class TinyCloudNode {
1017
1136
  /**
1018
1137
  * Issue a delegation using the capability-chain flow.
1019
1138
  *
1020
- * When the requested permissions are a subset of the current session's
1021
- * recap, the delegation is signed by the session key via WASM — no wallet
1022
- * prompt. When they are not, a {@link PermissionNotInManifestError} is
1023
- * raised so the caller can trigger an escalation flow (e.g.
1024
- * `TinyCloudWeb.requestPermissions`). Passing `forceWalletSign: true`
1025
- * bypasses the derivability check and always uses the wallet-signed SIWE
1026
- * path used by the legacy `createDelegation` fallback and by callers
1027
- * that want explicit wallet confirmation.
1028
- *
1029
- * Current limitation: exactly one {@link PermissionEntry} per call. For
1030
- * multi-resource delegation, call `delegateTo` multiple times. This keeps
1031
- * each delegation a single `(spaceId, path)` grant, which matches the
1032
- * underlying `PortableDelegation` shape.
1033
- *
1034
- * @throws {@link SessionExpiredError} when there is no session or the
1035
- * current session has expired (or will within the 60s safety margin).
1036
- * @throws {@link PermissionNotInManifestError} when the requested entries
1037
- * are not a subset of the granted session capabilities and
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
1038
1171
  * `forceWalletSign` is not set.
1039
1172
  */
1040
1173
  delegateTo(did: string, permissions: PermissionEntry[], options?: DelegateToOptions): Promise<DelegateToResult>;
1041
1174
  /**
1042
1175
  * Issue a delegation via the session-key UCAN WASM path.
1043
1176
  *
1044
- * The caller has already verified the request is derivable from the
1045
- * current session; we just need to shape the inputs for
1046
- * {@link createDelegationWrapper}.
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.
1047
1186
  *
1048
1187
  * @internal
1049
1188
  */