@tinycloud/node-sdk 3.3.0-beta.8 → 3.3.0

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.
@@ -1,5 +1,5 @@
1
1
  import * as _tinycloud_sdk_core from '@tinycloud/sdk-core';
2
- import { AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, CapabilityPresentationEnvelopeV1, IUserAuthorization, ISigner, ISessionStorage, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, TinyCloudSession, PersistedSessionData, ClientSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, Delegation, DelegatedResource, TelemetryConfig, ServiceContext, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, StorageFullEvent, IStorageService, INotificationHandler, IENSResolver, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate } from '@tinycloud/sdk-core';
2
+ import { AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, CapabilityPresentationEnvelopeV1, IUserAuthorization, ISigner, ISessionStorage, ISpaceCreationHandler, RegistryPolicy, RegistrySequenceStore, OnNodeNotFound, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, TinyCloudSession, PersistedSessionData, ClientSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, Delegation, DelegatedResource, TelemetryConfig, ServiceContext, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, StorageFullEvent, IStorageService, INotificationHandler, IENSResolver, RetryPolicy, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate } from '@tinycloud/sdk-core';
3
3
  import { ReplicaSessionStamp } from '@tinycloud/sdk-services/kv/replication';
4
4
  import { EventEmitter } from 'events';
5
5
  import { InvokeFunction, InvokeAnyFunction, FetchFunction } from '@tinycloud/sdk-services';
@@ -181,8 +181,46 @@ interface NodeUserAuthorizationConfig {
181
181
  tinycloudHosts?: string[];
182
182
  /** TinyCloud location registry URL. Default: https://registry.tinycloud.xyz. */
183
183
  tinycloudRegistryUrl?: string | null;
184
- /** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
184
+ /**
185
+ * Fallback TinyCloud hosts. Default: hosted TinyCloud node. Used only by the
186
+ * default `registryPolicy` ("legacy-fallback"), whose silent fallback is
187
+ * deprecated and will be removed in a future major release.
188
+ */
185
189
  tinycloudFallbackHosts?: string[] | null;
190
+ /**
191
+ * How sign-in uses the location registry when no host is configured.
192
+ *
193
+ * - `"legacy-fallback"` (default, deprecated): a registry miss or failure
194
+ * silently uses `tinycloudFallbackHosts`, with a one-time warning.
195
+ * - `"fail-closed"`: sign-in acts on the registry verdict for the signer
196
+ * address. Registered owners go to their listed hosts, unregistered owners
197
+ * to `newUserHost`, and an unavailable registry is
198
+ * `RegistryUnavailableError`, never a new account. Automatic space
199
+ * creation is refused on a host the owner's record does not list
200
+ * (`NodeRegistryEntryExistsError`) or when the registry gives no verdict
201
+ * (`RegistryUnavailableError`).
202
+ */
203
+ registryPolicy?: RegistryPolicy;
204
+ /**
205
+ * `fail-closed` only: host for owners with no registry record (and only
206
+ * them). Default https://node.tinycloud.xyz. `null` refuses them with
207
+ * `NodeNotFoundError`.
208
+ */
209
+ newUserHost?: string | null;
210
+ /**
211
+ * `fail-closed` only: chain ID of the v1 registry subject, which is built
212
+ * from the signer address, never the session chain. Default 1.
213
+ */
214
+ registryChainId?: number;
215
+ /** `fail-closed` only: highest registry sequence seen per owner. Default: in-memory. */
216
+ registrySequenceStore?: RegistrySequenceStore;
217
+ /**
218
+ * `fail-closed` only: called when sign-in resolves no host
219
+ * (`NodeNotFoundError` or `RegistryUnavailableError`) to retry, use another
220
+ * host (not identity-checked; it persists with the session), or abort.
221
+ * Without it, sign-in throws the error.
222
+ */
223
+ onNodeNotFound?: OnNodeNotFound;
186
224
  /** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
187
225
  autoDiscoverLocalNode?: boolean;
188
226
  /** Local loopback node URL to probe. Omit to avoid probing loopback. */
@@ -295,6 +333,13 @@ declare class NodeUserAuthorization implements IUserAuthorization {
295
333
  private tinycloudHosts?;
296
334
  private readonly tinycloudRegistryUrl?;
297
335
  private readonly tinycloudFallbackHosts?;
336
+ private readonly registryPolicy?;
337
+ private readonly newUserHost?;
338
+ private readonly registryChainId?;
339
+ private readonly registrySequenceStore;
340
+ private readonly onNodeNotFound?;
341
+ /** Verdict from the last `fail-closed` host resolution, reused by {@link assertMayCreateSpace}. */
342
+ private registryVerdict?;
298
343
  private readonly autoDiscoverLocalNode?;
299
344
  private readonly localNodeUrl?;
300
345
  private readonly localLinkName?;
@@ -415,6 +460,16 @@ declare class NodeUserAuthorization implements IUserAuthorization {
415
460
  */
416
461
  ensureTinyCloudHosts(): Promise<void>;
417
462
  private resolveTinyCloudHostsForSignIn;
463
+ /**
464
+ * Space-creation guard (TC-1443). Under `registryPolicy: "fail-closed"`,
465
+ * throws unless the owner's registry verdict allows a space on the primary
466
+ * host: `NodeRegistryEntryExistsError` when the owner's record does not
467
+ * list it, `RegistryUnavailableError` when the registry gives no
468
+ * verdict. Reuses this session's sign-in verdict unless it was
469
+ * `unavailable`, else looks it up now (explicit-host apps). Under the
470
+ * default policy it returns at once and performs no lookup.
471
+ */
472
+ assertMayCreateSpace(): Promise<void>;
418
473
  private requireTinyCloudHosts;
419
474
  private get primaryTinyCloudHost();
420
475
  get nodeFeatures(): string[];
@@ -551,6 +606,8 @@ declare class NodeUserAuthorization implements IUserAuthorization {
551
606
  * @throws Error if space creation fails
552
607
  */
553
608
  ensureSpaceExists(): Promise<void>;
609
+ /** {@link assertMayCreateSpace}, reporting a refusal to the creation handler before rethrowing it. */
610
+ private guardSpaceCreation;
554
611
  private recordActivationSkippedSpaces;
555
612
  createBootstrapSession(options: CreateBootstrapSessionOptions): Promise<TinyCloudSession>;
556
613
  private persistedData;
@@ -1175,8 +1232,35 @@ interface TinyCloudNodeConfig {
1175
1232
  host?: string;
1176
1233
  /** TinyCloud location registry URL. Default: https://registry.tinycloud.xyz. */
1177
1234
  tinycloudRegistryUrl?: string | null;
1178
- /** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
1235
+ /**
1236
+ * Fallback TinyCloud hosts. Default: hosted TinyCloud node. Used only by the
1237
+ * default `registryPolicy` ("legacy-fallback"), whose silent fallback is
1238
+ * deprecated and will be removed in a future major release.
1239
+ */
1179
1240
  tinycloudFallbackHosts?: string[] | null;
1241
+ /**
1242
+ * How sign-in uses the location registry when no `host` is configured.
1243
+ * Default `"legacy-fallback"` (deprecated): a registry miss or failure
1244
+ * silently uses `tinycloudFallbackHosts`, with a one-time warning.
1245
+ * `"fail-closed"`: routing acts on the registry verdict for the signer
1246
+ * address, an unavailable registry is `RegistryUnavailableError` (never a
1247
+ * new account), record hosts are used only if HTTPS or loopback, and
1248
+ * automatic space creation (sign-in, account bootstrap, owned-space
1249
+ * hosting, the public space the vault creates) is refused on a host the
1250
+ * owner's registry record does not list (`NodeRegistryEntryExistsError`)
1251
+ * or when the registry gives no verdict. An explicit `hostOwnedSpace()`
1252
+ * call is not guarded. `newUserHost` governs routing only: a pinned host
1253
+ * may still create spaces for an unregistered owner.
1254
+ */
1255
+ registryPolicy?: RegistryPolicy;
1256
+ /** `fail-closed` only: host for owners with no registry record. Default https://node.tinycloud.xyz; `null` refuses them with `NodeNotFoundError`. */
1257
+ newUserHost?: string | null;
1258
+ /** `fail-closed` only: chain ID of the v1 registry subject built from the signer address (never the session chain). Default 1. */
1259
+ registryChainId?: number;
1260
+ /** `fail-closed` only: highest registry sequence seen per owner. Default: in-memory for this client. */
1261
+ registrySequenceStore?: RegistrySequenceStore;
1262
+ /** `fail-closed` only: retry, use another host (not identity-checked; it persists with the session), or abort when sign-in resolves no host. Without it, sign-in throws. */
1263
+ onNodeNotFound?: OnNodeNotFound;
1180
1264
  /** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
1181
1265
  autoDiscoverLocalNode?: boolean;
1182
1266
  /** Local loopback node URL to probe. Omit to avoid probing loopback. */
@@ -1240,6 +1324,8 @@ interface TinyCloudNodeConfig {
1240
1324
  autoBootstrapAccount?: boolean;
1241
1325
  /** Default-off service telemetry. */
1242
1326
  telemetry?: TelemetryConfig;
1327
+ /** Retry of node busy/timeout answers; `{ maxAttempts: 1 }` disables it. See {@link RetryPolicy}. */
1328
+ retryPolicy?: Partial<RetryPolicy>;
1243
1329
  /**
1244
1330
  * Optional read-through replica configuration; disabled unless explicitly enabled.
1245
1331
  * Node profile mutations require `profileDir` and a caller-supplied `profileGuard` holding
@@ -1287,9 +1373,16 @@ interface DelegateToOptions {
1287
1373
  * Mark the delegation terminal: the node refuses any delegation that cites
1288
1374
  * it as a parent (`terminal-parent-cannot-redelegate`). The delegate can
1289
1375
  * still use it directly. Only session-key UCAN delegations can carry the
1290
- * marker, so this throws with `forceWalletSign`. Default false.
1376
+ * marker, so this throws with `forceWalletSign`, and with a `did:pkh`
1377
+ * recipient (use its session-key DID). Default false.
1291
1378
  */
1292
1379
  disableSubDelegation?: boolean;
1380
+ /**
1381
+ * Throw when the node answers 200 but skips a space the delegation targets (a space it does not
1382
+ * host): it registers the delegation without attaching it, which otherwise looks like success.
1383
+ * Off by default because grants to a not-yet-hosted space (e.g. secrets) are valid. Default false.
1384
+ */
1385
+ requireActivation?: boolean;
1293
1386
  }
1294
1387
  /**
1295
1388
  * Result of {@link TinyCloudNode.delegateTo}.
@@ -1811,6 +1904,8 @@ declare class TinyCloudNode {
1811
1904
  private registerPrimarySessionGrant;
1812
1905
  private writeManifestRegistryRecords;
1813
1906
  private createAccountRegistryServices;
1907
+ /** Set once per process: the registry sync was skipped for want of account access. */
1908
+ private static accountRegistrySkipLogged;
1814
1909
  private scheduleAccountRegistrySync;
1815
1910
  private enqueueAccountRegistryOperation;
1816
1911
  /**
@@ -1903,10 +1998,26 @@ declare class TinyCloudNode {
1903
1998
  * session's recap doesn't cover it and the registry has no record; the host
1904
1999
  * SIWE is idempotent server-side. Must be called after {@link signIn}.
1905
2000
  *
2001
+ * Under `registryPolicy: "fail-closed"`, hosting is refused with
2002
+ * `NodeRegistryEntryExistsError` when the owner's registry record does not
2003
+ * list the host, or `RegistryUnavailableError` when the registry gives no
2004
+ * verdict. {@link hostOwnedSpace} itself is an explicit action and is not
2005
+ * guarded.
2006
+ *
1906
2007
  * @param name - The owned space name (e.g. `"secrets"`).
1907
2008
  * @returns The hosted owned-space URI.
1908
2009
  */
1909
2010
  ensureOwnedSpaceHosted(name: string): Promise<string>;
2011
+ /**
2012
+ * Space-creation guard (TC-1443) for the automatic hosting paths: sign-in's
2013
+ * owned spaces, account bootstrap, {@link ensureOwnedSpaceHosted} and
2014
+ * {@link ensurePublicSpace}. Only `registryPolicy: "fail-closed"` consults
2015
+ * the registry ({@link NodeUserAuthorization.assertMayCreateSpace}); the
2016
+ * default policy performs no lookup.
2017
+ */
2018
+ private assertMayCreateSpace;
2019
+ /** Registry-policy settings shared by every authorization this client creates. */
2020
+ private registryPolicyConfig;
1910
2021
  /**
1911
2022
  * Submit the host delegation for an owned space, sharing one in-flight
1912
2023
  * request (and so one approval) between concurrent callers in this session,
@@ -2366,16 +2477,8 @@ declare class TinyCloudNode {
2366
2477
  * ```typescript
2367
2478
  * const delegations = alice.delegationManager;
2368
2479
  *
2369
- * // Create a delegation
2370
- * const result = await delegations.create({
2371
- * delegateDID: bob.did,
2372
- * path: "shared/",
2373
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
2374
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
2375
- * });
2376
- *
2377
- * // List delegations
2378
- * const listResult = await delegations.list();
2480
+ * // Query account delegations
2481
+ * const page = await delegations.query();
2379
2482
  *
2380
2483
  * // Revoke a delegation
2381
2484
  * await delegations.revoke(delegationCid);
@@ -2456,7 +2559,9 @@ declare class TinyCloudNode {
2456
2559
  * Ensure the user's public space exists and is accessible.
2457
2560
  * Creates the space and activates a session delegation for it.
2458
2561
  * This is the trigger for lazy public space creation — call it
2459
- * before writing to spaces.get('public').kv.
2562
+ * before writing to spaces.get('public').kv. The vault calls it on unlock.
2563
+ * Under `registryPolicy: "fail-closed"` creation goes through the
2564
+ * space-creation guard.
2460
2565
  */
2461
2566
  ensurePublicSpace(): Promise<void>;
2462
2567
  /**
@@ -2464,30 +2569,6 @@ declare class TinyCloudNode {
2464
2569
  * Writes require authentication (owner/delegate).
2465
2570
  */
2466
2571
  get publicKV(): IKVService;
2467
- /**
2468
- * Create a delegation using the v2 DelegationManager.
2469
- *
2470
- * This is a convenience method that wraps DelegationManager.create().
2471
- * For more control, use `this.delegationManager` directly.
2472
- *
2473
- * @param params - Delegation parameters
2474
- * @returns Result containing the created Delegation
2475
- *
2476
- * @example
2477
- * ```typescript
2478
- * const result = await alice.delegate({
2479
- * delegateDID: bob.did,
2480
- * path: "shared/",
2481
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
2482
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000),
2483
- * });
2484
- *
2485
- * if (result.ok) {
2486
- * console.log("Delegation created:", result.data.cid);
2487
- * }
2488
- * ```
2489
- */
2490
- delegate(params: CreateDelegationParams): Promise<DelegationResult<Delegation>>;
2491
2572
  /**
2492
2573
  * Revoke a delegation with the owner wallet when available. Session-only
2493
2574
  * clients continue to use their delegated revocation authority.
@@ -2500,12 +2581,6 @@ declare class TinyCloudNode {
2500
2581
  getDelegationStatus(cid: string): Promise<DelegationResult<DelegationStatus>>;
2501
2582
  /** Compute the canonical CID of a compact UCAN or DAG-CBOR delegation authorization. */
2502
2583
  computeDelegationCid(authorization: string): string;
2503
- /**
2504
- * List all delegations for the current session's space.
2505
- *
2506
- * @returns Result containing an array of Delegations
2507
- */
2508
- listDelegations(): Promise<DelegationResult<Delegation[]>>;
2509
2584
  /**
2510
2585
  * Check if the current session has permission for a path and action.
2511
2586
  *
@@ -2746,7 +2821,9 @@ declare class TinyCloudNode {
2746
2821
  * Prevent the recipient from creating sub-delegations (default: false).
2747
2822
  * The delegation carries the node's terminal marker, so the node refuses
2748
2823
  * its children. Needs capabilities the current session holds; throws
2749
- * rather than fall back to a wallet-signed delegation.
2824
+ * rather than fall back to a wallet-signed delegation, and throws for a
2825
+ * `did:pkh` recipient (a wallet-mode `useDelegation` of it is refused);
2826
+ * grant the recipient's session-key DID instead.
2750
2827
  */
2751
2828
  disableSubDelegation?: boolean;
2752
2829
  /** Expiration time in milliseconds from now (default: 1 hour) */
@@ -1,5 +1,5 @@
1
1
  import * as _tinycloud_sdk_core from '@tinycloud/sdk-core';
2
- import { AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, CapabilityPresentationEnvelopeV1, IUserAuthorization, ISigner, ISessionStorage, ISpaceCreationHandler, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, TinyCloudSession, PersistedSessionData, ClientSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, Delegation, DelegatedResource, TelemetryConfig, ServiceContext, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, StorageFullEvent, IStorageService, INotificationHandler, IENSResolver, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, CreateDelegationParams, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate } from '@tinycloud/sdk-core';
2
+ import { AutoSignStrategy, AutoRejectStrategy, CallbackStrategy, CapabilityPresentationEnvelopeV1, IUserAuthorization, ISigner, ISessionStorage, ISpaceCreationHandler, RegistryPolicy, RegistrySequenceStore, OnNodeNotFound, LocalNodeIdentityStore, IWasmBindings, ISessionManager, SiweConfig, Manifest, ComposedManifestRequest, ReplicationOptions, TinyCloudSession, PersistedSessionData, ClientSession, PermissionEntry, Extension, SignRequest, SpaceHostResult, SignInOptions, Delegation, DelegatedResource, TelemetryConfig, ServiceContext, IKVService, ISQLService, IDuckDbService, IHooksService, CreateOwnerDelegationParams as CreateOwnerDelegationParams$1, OwnerDelegationReceipt as OwnerDelegationReceipt$1, StorageFullEvent, IStorageService, INotificationHandler, IENSResolver, RetryPolicy, KVReplicaStorage, AccountService, InvokeAnyFunction as InvokeAnyFunction$1, UnifiedPolicyCapability, RegisterPolicyV3Input, RegisterPolicyV3Receipt, CanonicalJson, ShareDeliveryAuthorizationV3Receipt, IDataVaultService, IEncryptionService, NetworkDescriptor, ISecretsService, ICapabilityKeyRegistry, DelegationManager, ISpaceService, ISpace, ISharingService, DelegationResult, DelegationRevocationReceipt, DelegationStatus, ServiceSession, ReplicationControl, ResolvedDelegate } from '@tinycloud/sdk-core';
3
3
  import { ReplicaSessionStamp } from '@tinycloud/sdk-services/kv/replication';
4
4
  import { EventEmitter } from 'events';
5
5
  import { InvokeFunction, InvokeAnyFunction, FetchFunction } from '@tinycloud/sdk-services';
@@ -181,8 +181,46 @@ interface NodeUserAuthorizationConfig {
181
181
  tinycloudHosts?: string[];
182
182
  /** TinyCloud location registry URL. Default: https://registry.tinycloud.xyz. */
183
183
  tinycloudRegistryUrl?: string | null;
184
- /** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
184
+ /**
185
+ * Fallback TinyCloud hosts. Default: hosted TinyCloud node. Used only by the
186
+ * default `registryPolicy` ("legacy-fallback"), whose silent fallback is
187
+ * deprecated and will be removed in a future major release.
188
+ */
185
189
  tinycloudFallbackHosts?: string[] | null;
190
+ /**
191
+ * How sign-in uses the location registry when no host is configured.
192
+ *
193
+ * - `"legacy-fallback"` (default, deprecated): a registry miss or failure
194
+ * silently uses `tinycloudFallbackHosts`, with a one-time warning.
195
+ * - `"fail-closed"`: sign-in acts on the registry verdict for the signer
196
+ * address. Registered owners go to their listed hosts, unregistered owners
197
+ * to `newUserHost`, and an unavailable registry is
198
+ * `RegistryUnavailableError`, never a new account. Automatic space
199
+ * creation is refused on a host the owner's record does not list
200
+ * (`NodeRegistryEntryExistsError`) or when the registry gives no verdict
201
+ * (`RegistryUnavailableError`).
202
+ */
203
+ registryPolicy?: RegistryPolicy;
204
+ /**
205
+ * `fail-closed` only: host for owners with no registry record (and only
206
+ * them). Default https://node.tinycloud.xyz. `null` refuses them with
207
+ * `NodeNotFoundError`.
208
+ */
209
+ newUserHost?: string | null;
210
+ /**
211
+ * `fail-closed` only: chain ID of the v1 registry subject, which is built
212
+ * from the signer address, never the session chain. Default 1.
213
+ */
214
+ registryChainId?: number;
215
+ /** `fail-closed` only: highest registry sequence seen per owner. Default: in-memory. */
216
+ registrySequenceStore?: RegistrySequenceStore;
217
+ /**
218
+ * `fail-closed` only: called when sign-in resolves no host
219
+ * (`NodeNotFoundError` or `RegistryUnavailableError`) to retry, use another
220
+ * host (not identity-checked; it persists with the session), or abort.
221
+ * Without it, sign-in throws the error.
222
+ */
223
+ onNodeNotFound?: OnNodeNotFound;
186
224
  /** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
187
225
  autoDiscoverLocalNode?: boolean;
188
226
  /** Local loopback node URL to probe. Omit to avoid probing loopback. */
@@ -295,6 +333,13 @@ declare class NodeUserAuthorization implements IUserAuthorization {
295
333
  private tinycloudHosts?;
296
334
  private readonly tinycloudRegistryUrl?;
297
335
  private readonly tinycloudFallbackHosts?;
336
+ private readonly registryPolicy?;
337
+ private readonly newUserHost?;
338
+ private readonly registryChainId?;
339
+ private readonly registrySequenceStore;
340
+ private readonly onNodeNotFound?;
341
+ /** Verdict from the last `fail-closed` host resolution, reused by {@link assertMayCreateSpace}. */
342
+ private registryVerdict?;
298
343
  private readonly autoDiscoverLocalNode?;
299
344
  private readonly localNodeUrl?;
300
345
  private readonly localLinkName?;
@@ -415,6 +460,16 @@ declare class NodeUserAuthorization implements IUserAuthorization {
415
460
  */
416
461
  ensureTinyCloudHosts(): Promise<void>;
417
462
  private resolveTinyCloudHostsForSignIn;
463
+ /**
464
+ * Space-creation guard (TC-1443). Under `registryPolicy: "fail-closed"`,
465
+ * throws unless the owner's registry verdict allows a space on the primary
466
+ * host: `NodeRegistryEntryExistsError` when the owner's record does not
467
+ * list it, `RegistryUnavailableError` when the registry gives no
468
+ * verdict. Reuses this session's sign-in verdict unless it was
469
+ * `unavailable`, else looks it up now (explicit-host apps). Under the
470
+ * default policy it returns at once and performs no lookup.
471
+ */
472
+ assertMayCreateSpace(): Promise<void>;
418
473
  private requireTinyCloudHosts;
419
474
  private get primaryTinyCloudHost();
420
475
  get nodeFeatures(): string[];
@@ -551,6 +606,8 @@ declare class NodeUserAuthorization implements IUserAuthorization {
551
606
  * @throws Error if space creation fails
552
607
  */
553
608
  ensureSpaceExists(): Promise<void>;
609
+ /** {@link assertMayCreateSpace}, reporting a refusal to the creation handler before rethrowing it. */
610
+ private guardSpaceCreation;
554
611
  private recordActivationSkippedSpaces;
555
612
  createBootstrapSession(options: CreateBootstrapSessionOptions): Promise<TinyCloudSession>;
556
613
  private persistedData;
@@ -1175,8 +1232,35 @@ interface TinyCloudNodeConfig {
1175
1232
  host?: string;
1176
1233
  /** TinyCloud location registry URL. Default: https://registry.tinycloud.xyz. */
1177
1234
  tinycloudRegistryUrl?: string | null;
1178
- /** Fallback TinyCloud hosts. Default: hosted TinyCloud node. */
1235
+ /**
1236
+ * Fallback TinyCloud hosts. Default: hosted TinyCloud node. Used only by the
1237
+ * default `registryPolicy` ("legacy-fallback"), whose silent fallback is
1238
+ * deprecated and will be removed in a future major release.
1239
+ */
1179
1240
  tinycloudFallbackHosts?: string[] | null;
1241
+ /**
1242
+ * How sign-in uses the location registry when no `host` is configured.
1243
+ * Default `"legacy-fallback"` (deprecated): a registry miss or failure
1244
+ * silently uses `tinycloudFallbackHosts`, with a one-time warning.
1245
+ * `"fail-closed"`: routing acts on the registry verdict for the signer
1246
+ * address, an unavailable registry is `RegistryUnavailableError` (never a
1247
+ * new account), record hosts are used only if HTTPS or loopback, and
1248
+ * automatic space creation (sign-in, account bootstrap, owned-space
1249
+ * hosting, the public space the vault creates) is refused on a host the
1250
+ * owner's registry record does not list (`NodeRegistryEntryExistsError`)
1251
+ * or when the registry gives no verdict. An explicit `hostOwnedSpace()`
1252
+ * call is not guarded. `newUserHost` governs routing only: a pinned host
1253
+ * may still create spaces for an unregistered owner.
1254
+ */
1255
+ registryPolicy?: RegistryPolicy;
1256
+ /** `fail-closed` only: host for owners with no registry record. Default https://node.tinycloud.xyz; `null` refuses them with `NodeNotFoundError`. */
1257
+ newUserHost?: string | null;
1258
+ /** `fail-closed` only: chain ID of the v1 registry subject built from the signer address (never the session chain). Default 1. */
1259
+ registryChainId?: number;
1260
+ /** `fail-closed` only: highest registry sequence seen per owner. Default: in-memory for this client. */
1261
+ registrySequenceStore?: RegistrySequenceStore;
1262
+ /** `fail-closed` only: retry, use another host (not identity-checked; it persists with the session), or abort when sign-in resolves no host. Without it, sign-in throws. */
1263
+ onNodeNotFound?: OnNodeNotFound;
1180
1264
  /** Probe configured/registered local nodes before registry/fallback resolution. Default: true. */
1181
1265
  autoDiscoverLocalNode?: boolean;
1182
1266
  /** Local loopback node URL to probe. Omit to avoid probing loopback. */
@@ -1240,6 +1324,8 @@ interface TinyCloudNodeConfig {
1240
1324
  autoBootstrapAccount?: boolean;
1241
1325
  /** Default-off service telemetry. */
1242
1326
  telemetry?: TelemetryConfig;
1327
+ /** Retry of node busy/timeout answers; `{ maxAttempts: 1 }` disables it. See {@link RetryPolicy}. */
1328
+ retryPolicy?: Partial<RetryPolicy>;
1243
1329
  /**
1244
1330
  * Optional read-through replica configuration; disabled unless explicitly enabled.
1245
1331
  * Node profile mutations require `profileDir` and a caller-supplied `profileGuard` holding
@@ -1287,9 +1373,16 @@ interface DelegateToOptions {
1287
1373
  * Mark the delegation terminal: the node refuses any delegation that cites
1288
1374
  * it as a parent (`terminal-parent-cannot-redelegate`). The delegate can
1289
1375
  * still use it directly. Only session-key UCAN delegations can carry the
1290
- * marker, so this throws with `forceWalletSign`. Default false.
1376
+ * marker, so this throws with `forceWalletSign`, and with a `did:pkh`
1377
+ * recipient (use its session-key DID). Default false.
1291
1378
  */
1292
1379
  disableSubDelegation?: boolean;
1380
+ /**
1381
+ * Throw when the node answers 200 but skips a space the delegation targets (a space it does not
1382
+ * host): it registers the delegation without attaching it, which otherwise looks like success.
1383
+ * Off by default because grants to a not-yet-hosted space (e.g. secrets) are valid. Default false.
1384
+ */
1385
+ requireActivation?: boolean;
1293
1386
  }
1294
1387
  /**
1295
1388
  * Result of {@link TinyCloudNode.delegateTo}.
@@ -1811,6 +1904,8 @@ declare class TinyCloudNode {
1811
1904
  private registerPrimarySessionGrant;
1812
1905
  private writeManifestRegistryRecords;
1813
1906
  private createAccountRegistryServices;
1907
+ /** Set once per process: the registry sync was skipped for want of account access. */
1908
+ private static accountRegistrySkipLogged;
1814
1909
  private scheduleAccountRegistrySync;
1815
1910
  private enqueueAccountRegistryOperation;
1816
1911
  /**
@@ -1903,10 +1998,26 @@ declare class TinyCloudNode {
1903
1998
  * session's recap doesn't cover it and the registry has no record; the host
1904
1999
  * SIWE is idempotent server-side. Must be called after {@link signIn}.
1905
2000
  *
2001
+ * Under `registryPolicy: "fail-closed"`, hosting is refused with
2002
+ * `NodeRegistryEntryExistsError` when the owner's registry record does not
2003
+ * list the host, or `RegistryUnavailableError` when the registry gives no
2004
+ * verdict. {@link hostOwnedSpace} itself is an explicit action and is not
2005
+ * guarded.
2006
+ *
1906
2007
  * @param name - The owned space name (e.g. `"secrets"`).
1907
2008
  * @returns The hosted owned-space URI.
1908
2009
  */
1909
2010
  ensureOwnedSpaceHosted(name: string): Promise<string>;
2011
+ /**
2012
+ * Space-creation guard (TC-1443) for the automatic hosting paths: sign-in's
2013
+ * owned spaces, account bootstrap, {@link ensureOwnedSpaceHosted} and
2014
+ * {@link ensurePublicSpace}. Only `registryPolicy: "fail-closed"` consults
2015
+ * the registry ({@link NodeUserAuthorization.assertMayCreateSpace}); the
2016
+ * default policy performs no lookup.
2017
+ */
2018
+ private assertMayCreateSpace;
2019
+ /** Registry-policy settings shared by every authorization this client creates. */
2020
+ private registryPolicyConfig;
1910
2021
  /**
1911
2022
  * Submit the host delegation for an owned space, sharing one in-flight
1912
2023
  * request (and so one approval) between concurrent callers in this session,
@@ -2366,16 +2477,8 @@ declare class TinyCloudNode {
2366
2477
  * ```typescript
2367
2478
  * const delegations = alice.delegationManager;
2368
2479
  *
2369
- * // Create a delegation
2370
- * const result = await delegations.create({
2371
- * delegateDID: bob.did,
2372
- * path: "shared/",
2373
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
2374
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
2375
- * });
2376
- *
2377
- * // List delegations
2378
- * const listResult = await delegations.list();
2480
+ * // Query account delegations
2481
+ * const page = await delegations.query();
2379
2482
  *
2380
2483
  * // Revoke a delegation
2381
2484
  * await delegations.revoke(delegationCid);
@@ -2456,7 +2559,9 @@ declare class TinyCloudNode {
2456
2559
  * Ensure the user's public space exists and is accessible.
2457
2560
  * Creates the space and activates a session delegation for it.
2458
2561
  * This is the trigger for lazy public space creation — call it
2459
- * before writing to spaces.get('public').kv.
2562
+ * before writing to spaces.get('public').kv. The vault calls it on unlock.
2563
+ * Under `registryPolicy: "fail-closed"` creation goes through the
2564
+ * space-creation guard.
2460
2565
  */
2461
2566
  ensurePublicSpace(): Promise<void>;
2462
2567
  /**
@@ -2464,30 +2569,6 @@ declare class TinyCloudNode {
2464
2569
  * Writes require authentication (owner/delegate).
2465
2570
  */
2466
2571
  get publicKV(): IKVService;
2467
- /**
2468
- * Create a delegation using the v2 DelegationManager.
2469
- *
2470
- * This is a convenience method that wraps DelegationManager.create().
2471
- * For more control, use `this.delegationManager` directly.
2472
- *
2473
- * @param params - Delegation parameters
2474
- * @returns Result containing the created Delegation
2475
- *
2476
- * @example
2477
- * ```typescript
2478
- * const result = await alice.delegate({
2479
- * delegateDID: bob.did,
2480
- * path: "shared/",
2481
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
2482
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000),
2483
- * });
2484
- *
2485
- * if (result.ok) {
2486
- * console.log("Delegation created:", result.data.cid);
2487
- * }
2488
- * ```
2489
- */
2490
- delegate(params: CreateDelegationParams): Promise<DelegationResult<Delegation>>;
2491
2572
  /**
2492
2573
  * Revoke a delegation with the owner wallet when available. Session-only
2493
2574
  * clients continue to use their delegated revocation authority.
@@ -2500,12 +2581,6 @@ declare class TinyCloudNode {
2500
2581
  getDelegationStatus(cid: string): Promise<DelegationResult<DelegationStatus>>;
2501
2582
  /** Compute the canonical CID of a compact UCAN or DAG-CBOR delegation authorization. */
2502
2583
  computeDelegationCid(authorization: string): string;
2503
- /**
2504
- * List all delegations for the current session's space.
2505
- *
2506
- * @returns Result containing an array of Delegations
2507
- */
2508
- listDelegations(): Promise<DelegationResult<Delegation[]>>;
2509
2584
  /**
2510
2585
  * Check if the current session has permission for a path and action.
2511
2586
  *
@@ -2746,7 +2821,9 @@ declare class TinyCloudNode {
2746
2821
  * Prevent the recipient from creating sub-delegations (default: false).
2747
2822
  * The delegation carries the node's terminal marker, so the node refuses
2748
2823
  * its children. Needs capabilities the current session holds; throws
2749
- * rather than fall back to a wallet-signed delegation.
2824
+ * rather than fall back to a wallet-signed delegation, and throws for a
2825
+ * `did:pkh` recipient (a wallet-mode `useDelegation` of it is refused);
2826
+ * grant the recipient's session-key DID instead.
2750
2827
  */
2751
2828
  disableSubDelegation?: boolean;
2752
2829
  /** Expiration time in milliseconds from now (default: 1 hour) */
@@ -1,7 +1,7 @@
1
1
  import { ReplicationOptions, PermissionEntry, TinyCloudSession, KVReplicaStorage, ServiceContext, IWasmBindings, WasmRecapEntry } from '@tinycloud/sdk-core';
2
2
  import { ReplicaConsentAnchor, AuthorityRefusal, ReplicationAuthority } from '@tinycloud/sdk-services';
3
3
  import { ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-CcNh20QX.cjs';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-DeV-L_14.cjs';
5
5
 
6
6
  /** Constructor-time validation; the space-dependent secrets check runs at sign-in and open. */
7
7
  declare function assertValidReplicationConfig(replication: (ReplicationOptions & {
@@ -1,7 +1,7 @@
1
1
  import { ReplicationOptions, PermissionEntry, TinyCloudSession, KVReplicaStorage, ServiceContext, IWasmBindings, WasmRecapEntry } from '@tinycloud/sdk-core';
2
2
  import { ReplicaConsentAnchor, AuthorityRefusal, ReplicationAuthority } from '@tinycloud/sdk-services';
3
3
  import { ReplicaSessionStamp, ReplicaDenyInput } from '@tinycloud/sdk-services/kv/replication';
4
- import { T as TinyCloudNode } from './TinyCloudNode-CcNh20QX.js';
4
+ import { T as TinyCloudNode } from './TinyCloudNode-DeV-L_14.js';
5
5
 
6
6
  /** Constructor-time validation; the space-dependent secrets check runs at sign-in and open. */
7
7
  declare function assertValidReplicationConfig(replication: (ReplicationOptions & {