@tinycloud/node-sdk 3.3.0-beta.9 → 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.
package/dist/core.cjs CHANGED
@@ -517,6 +517,11 @@ var NodeUserAuthorization = class {
517
517
  this.tinycloudHosts = config.tinycloudHosts;
518
518
  this.tinycloudRegistryUrl = config.tinycloudRegistryUrl;
519
519
  this.tinycloudFallbackHosts = config.tinycloudFallbackHosts;
520
+ this.registryPolicy = config.registryPolicy;
521
+ this.newUserHost = config.newUserHost;
522
+ this.registryChainId = config.registryChainId;
523
+ this.registrySequenceStore = config.registrySequenceStore ?? (0, import_sdk_core4.createInMemoryRegistrySequenceStore)();
524
+ this.onNodeNotFound = config.onNodeNotFound;
520
525
  this.autoDiscoverLocalNode = config.autoDiscoverLocalNode;
521
526
  this.localNodeUrl = config.localNodeUrl;
522
527
  this.localLinkName = config.localLinkName;
@@ -628,6 +633,7 @@ var NodeUserAuthorization = class {
628
633
  this._nodeFeaturesKnown = nodeFeatures !== void 0;
629
634
  this._nodeInfoIdentity = void 0;
630
635
  this.tinycloudHosts = hosts && hosts.length > 0 ? [...hosts] : void 0;
636
+ this.registryVerdict = void 0;
631
637
  this._lastActivationSkippedSpaceIds = [];
632
638
  this._lastActivationActivatedSpaceIds = [];
633
639
  if (!session) {
@@ -678,6 +684,23 @@ var NodeUserAuthorization = class {
678
684
  if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
679
685
  return;
680
686
  }
687
+ if (this.registryPolicy === "fail-closed") {
688
+ const resolved2 = await (0, import_sdk_core4.resolveFailClosedTinyCloudHosts)(address, {
689
+ registryUrl: this.tinycloudRegistryUrl,
690
+ registryChainId: this.registryChainId,
691
+ newUserHost: this.newUserHost,
692
+ sequenceStore: this.registrySequenceStore,
693
+ onNodeNotFound: this.onNodeNotFound,
694
+ autoDiscoverLocalNode: this.autoDiscoverLocalNode,
695
+ localNodeUrl: this.localNodeUrl,
696
+ localLinkName: this.localLinkName,
697
+ expectedNodeDid: this.expectedNodeDid,
698
+ localNodeIdentityStore: this.localNodeIdentityStore
699
+ });
700
+ this.tinycloudHosts = resolved2.hosts;
701
+ this.registryVerdict = resolved2.verdict;
702
+ return;
703
+ }
681
704
  const subject = (0, import_sdk_core4.pkhDid)(address, chainId);
682
705
  const resolved = await (0, import_sdk_core4.resolveTinyCloudHosts)(subject, {
683
706
  registryUrl: this.tinycloudRegistryUrl,
@@ -690,6 +713,32 @@ var NodeUserAuthorization = class {
690
713
  });
691
714
  this.tinycloudHosts = resolved.hosts;
692
715
  }
716
+ /**
717
+ * Space-creation guard (TC-1443). Under `registryPolicy: "fail-closed"`,
718
+ * throws unless the owner's registry verdict allows a space on the primary
719
+ * host: `NodeRegistryEntryExistsError` when the owner's record does not
720
+ * list it, `RegistryUnavailableError` when the registry gives no
721
+ * verdict. Reuses this session's sign-in verdict unless it was
722
+ * `unavailable`, else looks it up now (explicit-host apps). Under the
723
+ * default policy it returns at once and performs no lookup.
724
+ */
725
+ async assertMayCreateSpace() {
726
+ if (this.registryPolicy !== "fail-closed") return;
727
+ if (this._address === void 0) {
728
+ throw new Error("Must be signed in to create a space");
729
+ }
730
+ await this.ensureTinyCloudHosts();
731
+ const subject = (0, import_sdk_core4.registryOwnerSubjectV1)(this._address, this.registryChainId);
732
+ let verdict = this.registryVerdict;
733
+ if (verdict?.subject !== subject || verdict.status === "unavailable") {
734
+ verdict = await (0, import_sdk_core4.lookupOwnerRegistryVerdict)(subject, {
735
+ registryUrl: this.tinycloudRegistryUrl,
736
+ sequenceStore: this.registrySequenceStore
737
+ });
738
+ this.registryVerdict = verdict;
739
+ }
740
+ (0, import_sdk_core4.assertSpaceCreationAllowed)(verdict, this.primaryTinyCloudHost);
741
+ }
693
742
  requireTinyCloudHosts() {
694
743
  if (!this.tinycloudHosts || this.tinycloudHosts.length === 0) {
695
744
  throw new Error("TinyCloud hosts have not been resolved. Call signIn() first.");
@@ -1138,6 +1187,7 @@ var NodeUserAuthorization = class {
1138
1187
  if (!handler) {
1139
1188
  return;
1140
1189
  }
1190
+ await this.guardSpaceCreation(handler, creationContext);
1141
1191
  const confirmed = await handler.confirmSpaceCreation(creationContext);
1142
1192
  if (!confirmed) {
1143
1193
  return;
@@ -1178,6 +1228,7 @@ var NodeUserAuthorization = class {
1178
1228
  if (!handler) {
1179
1229
  return;
1180
1230
  }
1231
+ await this.guardSpaceCreation(handler, creationContext);
1181
1232
  const confirmed = await handler.confirmSpaceCreation(creationContext);
1182
1233
  if (!confirmed) {
1183
1234
  return;
@@ -1219,6 +1270,16 @@ var NodeUserAuthorization = class {
1219
1270
  { cause: result }
1220
1271
  );
1221
1272
  }
1273
+ /** {@link assertMayCreateSpace}, reporting a refusal to the creation handler before rethrowing it. */
1274
+ async guardSpaceCreation(handler, context) {
1275
+ try {
1276
+ await this.assertMayCreateSpace();
1277
+ } catch (error) {
1278
+ const failure = error instanceof Error ? error : new Error(String(error));
1279
+ handler.onSpaceCreationFailed?.(context, failure);
1280
+ throw failure;
1281
+ }
1282
+ }
1222
1283
  recordActivationSkippedSpaces(result, primarySpaceId) {
1223
1284
  if (result.success) {
1224
1285
  this._lastActivationSkippedSpaceIds = result.skipped ?? [];
@@ -2219,24 +2280,17 @@ function signedAuthorityFromCompactUcan(authorization) {
2219
2280
  ));
2220
2281
  continue;
2221
2282
  }
2222
- const nativeMatch = /^(tinycloud:[^/]+)\/(kv|sql|duckdb|hooks)\/(.*)$/.exec(resource);
2223
- const policyMatch = /^tinycloud:\/\/([^/]+)\/(kv|sql|duckdb|hooks)\/(.*)$/.exec(resource);
2224
- const match = nativeMatch ?? policyMatch;
2283
+ const match = /^(?:tinycloud:\/\/([^/]+)|(tinycloud:[^/]+))\/(kv|sql|duckdb|hooks)(?:\/|$)(.*)$/.exec(resource);
2225
2284
  if (!match) {
2226
2285
  throw new Error(
2227
2286
  `Validated runtime delegation has an unsupported signed resource '${resource}'.`
2228
2287
  );
2229
2288
  }
2230
- const [, space, shortService, path] = match;
2289
+ const [, policySpace, nativeSpace, shortService, path] = match;
2231
2290
  const service = SERVICE_BY_SHORT_NAME[shortService];
2232
- if (service === void 0) {
2233
- throw new Error(
2234
- `Validated runtime delegation has an unsupported signed service '${shortService}'.`
2235
- );
2236
- }
2237
2291
  permissions.push(...groupedSignedEntries(
2238
2292
  service,
2239
- space,
2293
+ nativeSpace ?? policySpace,
2240
2294
  path,
2241
2295
  abilities
2242
2296
  ));
@@ -3265,6 +3319,12 @@ function describeHostFailure2(result) {
3265
3319
  const text = result.error?.trim();
3266
3320
  return text ? `${result.status} - ${text}` : `${result.status}`;
3267
3321
  }
3322
+ function assertDelegationActivated(result, delegation, requireActivation) {
3323
+ const skipped = requireActivation ? (delegation.resources?.map((r) => r.space) ?? [delegation.spaceId]).filter((space) => result.skipped?.includes(space)) : [];
3324
+ if (result.success && skipped.length === 0) return;
3325
+ const detail = result.success ? `the node skipped ${[...new Set(skipped)].join(", ")} (space not hosted on the node)` : describeHostFailure2(result);
3326
+ throw Object.assign(new Error(`Failed to activate delegation with host: ${detail}`), { cause: result });
3327
+ }
3268
3328
  function ownerDelegationPermissions(params) {
3269
3329
  const hasPermissions = Object.prototype.hasOwnProperty.call(params, "permissions");
3270
3330
  const hasLegacy = Object.prototype.hasOwnProperty.call(params, "path") || Object.prototype.hasOwnProperty.call(params, "actions");
@@ -3347,7 +3407,7 @@ function ownerPermissionsToAbilities(permissions) {
3347
3407
  }
3348
3408
  return { abilities, rawAbilities };
3349
3409
  }
3350
- var TERMINAL_DELEGATION_REQUIRES_SESSION_KEY = "disableSubDelegation requires a session-key delegation";
3410
+ var TERMINAL_DELEGATION_REQUIRES_SESSION_KEY = "disableSubDelegation requires a session-key delegation to a did:key (not did:pkh); use the session-key DID or drop the flag";
3351
3411
  function base64UrlEncode(bytes) {
3352
3412
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
3353
3413
  let output = "";
@@ -3661,7 +3721,9 @@ var _TinyCloudNode = class _TinyCloudNode {
3661
3721
  this.explicitHost = config.host;
3662
3722
  this.config = {
3663
3723
  ...config,
3664
- host: config.host ?? DEFAULT_HOST
3724
+ host: config.host ?? DEFAULT_HOST,
3725
+ // One store for every authorization this client creates.
3726
+ registrySequenceStore: config.registrySequenceStore ?? (0, import_sdk_core10.createInMemoryRegistrySequenceStore)()
3665
3727
  };
3666
3728
  if (this.config.replication?.enabled) {
3667
3729
  const runtime = getNodeReplicationLoaders().runtime().then(({ ReplicationRuntime }) => {
@@ -3896,7 +3958,6 @@ var _TinyCloudNode = class _TinyCloudNode {
3896
3958
  if (!this.wasmBindings.computeCid) throw new Error("computeCid is unavailable");
3897
3959
  return this.wasmBindings.computeCid(data, codec);
3898
3960
  },
3899
- // delegationManager: undefined - not needed for receive()
3900
3961
  createKVService: (config) => {
3901
3962
  const prefix = config.pathPrefix?.replace(/\/$/, "");
3902
3963
  const kvService = new import_sdk_core10.KVService({ prefix });
@@ -3904,7 +3965,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3904
3965
  invoke: config.invoke,
3905
3966
  fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
3906
3967
  hosts: config.hosts,
3907
- telemetry: this.config.telemetry
3968
+ telemetry: this.config.telemetry,
3969
+ retryPolicy: this.config.retryPolicy
3908
3970
  }));
3909
3971
  kvContext.setSession(config.session);
3910
3972
  kvService.initialize(kvContext);
@@ -3931,6 +3993,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3931
3993
  tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
3932
3994
  tinycloudRegistryUrl: config.tinycloudRegistryUrl,
3933
3995
  tinycloudFallbackHosts: config.tinycloudFallbackHosts,
3996
+ ...this.registryPolicyConfig(),
3934
3997
  autoDiscoverLocalNode: config.autoDiscoverLocalNode,
3935
3998
  localNodeUrl: config.localNodeUrl,
3936
3999
  localLinkName: config.localLinkName,
@@ -3954,7 +4017,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3954
4017
  });
3955
4018
  this.tc = new import_sdk_core10.TinyCloud(this.auth, {
3956
4019
  invokeAny: this.invokeAnyWithRuntimePermissions,
3957
- telemetry: config.telemetry
4020
+ telemetry: config.telemetry,
4021
+ retryPolicy: config.retryPolicy
3958
4022
  });
3959
4023
  }
3960
4024
  shouldUseBootstrapSignInRequest(config) {
@@ -4316,7 +4380,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4316
4380
  this.auth = oldAuth;
4317
4381
  this.tc = this.auth ? new import_sdk_core10.TinyCloud(this.auth, {
4318
4382
  invokeAny: this.invokeAnyWithRuntimePermissions,
4319
- telemetry: this.config.telemetry
4383
+ telemetry: this.config.telemetry,
4384
+ retryPolicy: this.config.retryPolicy
4320
4385
  }) : null;
4321
4386
  this._capabilityRegistry = new import_sdk_core10.CapabilityKeyRegistry();
4322
4387
  this._keyProvider = new WasmKeyProvider({ sessionManager: this.sessionManager });
@@ -4636,6 +4701,9 @@ var _TinyCloudNode = class _TinyCloudNode {
4636
4701
  const primarySession = auth.tinyCloudSession;
4637
4702
  const defaultSpaceId = this.ownedSpaceId("default");
4638
4703
  const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core10.BOOTSTRAP_SESSION_REQUESTS.default;
4704
+ if (steps.some((step) => step.kind === "host")) {
4705
+ await this.assertMayCreateSpace();
4706
+ }
4639
4707
  for (const step of steps) {
4640
4708
  if (step.kind !== "session") continue;
4641
4709
  graph.assertActive();
@@ -4964,7 +5032,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4964
5032
  invokeAny: context.invokeAny,
4965
5033
  fetch: context.fetch,
4966
5034
  hosts: context.hosts,
4967
- telemetry: this.config.telemetry
5035
+ telemetry: this.config.telemetry,
5036
+ retryPolicy: this.config.retryPolicy
4968
5037
  }));
4969
5038
  scoped.setOperationAbortSignal(signal);
4970
5039
  scoped.setSession({ ...session, spaceId });
@@ -5011,6 +5080,10 @@ var _TinyCloudNode = class _TinyCloudNode {
5011
5080
  return;
5012
5081
  }
5013
5082
  if (!this.currentSessionCoversAccountRegistry()) {
5083
+ if (!_TinyCloudNode.accountRegistrySkipLogged) {
5084
+ _TinyCloudNode.accountRegistrySkipLogged = true;
5085
+ import_sdk_services2.tinyCloudDebugLogger.log("registry.skip");
5086
+ }
5014
5087
  return;
5015
5088
  }
5016
5089
  const controller = new AbortController();
@@ -5026,7 +5099,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5026
5099
  invokeAny: sharedContext.invokeAny,
5027
5100
  fetch: sharedContext.fetch,
5028
5101
  hosts: sharedContext.hosts,
5029
- telemetry: this.config.telemetry
5102
+ telemetry: this.config.telemetry,
5103
+ retryPolicy: this.config.retryPolicy
5030
5104
  }));
5031
5105
  context.setOperationAbortSignal(controller.signal);
5032
5106
  const current = this.currentTinyCloudSession();
@@ -5277,6 +5351,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5277
5351
  { cause: activation }
5278
5352
  );
5279
5353
  }
5354
+ await this.assertMayCreateSpace();
5355
+ if (signal?.aborted) throw signal.reason;
5280
5356
  const created = await this.hostOwnedSpaceOnce(spaceId, signal);
5281
5357
  if (!created.success) {
5282
5358
  throw Object.assign(
@@ -5390,6 +5466,12 @@ var _TinyCloudNode = class _TinyCloudNode {
5390
5466
  * session's recap doesn't cover it and the registry has no record; the host
5391
5467
  * SIWE is idempotent server-side. Must be called after {@link signIn}.
5392
5468
  *
5469
+ * Under `registryPolicy: "fail-closed"`, hosting is refused with
5470
+ * `NodeRegistryEntryExistsError` when the owner's registry record does not
5471
+ * list the host, or `RegistryUnavailableError` when the registry gives no
5472
+ * verdict. {@link hostOwnedSpace} itself is an explicit action and is not
5473
+ * guarded.
5474
+ *
5393
5475
  * @param name - The owned space name (e.g. `"secrets"`).
5394
5476
  * @returns The hosted owned-space URI.
5395
5477
  */
@@ -5401,8 +5483,25 @@ var _TinyCloudNode = class _TinyCloudNode {
5401
5483
  if (this.hostedOwnedSpaceIds.has(spaceId) || await this.isOwnedSpaceRegistered(spaceId)) {
5402
5484
  return spaceId;
5403
5485
  }
5486
+ await this.assertMayCreateSpace();
5404
5487
  return this.hostOwnedSpace(name);
5405
5488
  }
5489
+ /**
5490
+ * Space-creation guard (TC-1443) for the automatic hosting paths: sign-in's
5491
+ * owned spaces, account bootstrap, {@link ensureOwnedSpaceHosted} and
5492
+ * {@link ensurePublicSpace}. Only `registryPolicy: "fail-closed"` consults
5493
+ * the registry ({@link NodeUserAuthorization.assertMayCreateSpace}); the
5494
+ * default policy performs no lookup.
5495
+ */
5496
+ async assertMayCreateSpace() {
5497
+ if (this.config.registryPolicy !== "fail-closed") return;
5498
+ await this.auth.assertMayCreateSpace();
5499
+ }
5500
+ /** Registry-policy settings shared by every authorization this client creates. */
5501
+ registryPolicyConfig() {
5502
+ const { registryPolicy, newUserHost, registryChainId, registrySequenceStore, onNodeNotFound } = this.config;
5503
+ return { registryPolicy, newUserHost, registryChainId, registrySequenceStore, onNodeNotFound };
5504
+ }
5406
5505
  /**
5407
5506
  * Submit the host delegation for an owned space, sharing one in-flight
5408
5507
  * request (and so one approval) between concurrent callers in this session,
@@ -5843,7 +5942,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5843
5942
  const graph = this.createServiceGraphLifetime();
5844
5943
  const core = this.auth ? new import_sdk_core10.TinyCloud(this.auth, {
5845
5944
  invokeAny: graph.invokeAny,
5846
- telemetry: this.config.telemetry
5945
+ telemetry: this.config.telemetry,
5946
+ retryPolicy: this.config.retryPolicy
5847
5947
  }) : null;
5848
5948
  if (core) {
5849
5949
  core.initializeServices(graph.invoke, [input.host], graph.fetch);
@@ -5855,7 +5955,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5855
5955
  invokeAny: graph.invokeAny,
5856
5956
  fetch: graph.fetch,
5857
5957
  hosts: [input.host],
5858
- telemetry: this.config.telemetry
5958
+ telemetry: this.config.telemetry,
5959
+ retryPolicy: this.config.retryPolicy
5859
5960
  }));
5860
5961
  const kv = new import_sdk_core10.KVService({});
5861
5962
  kv.initialize(serviceContext);
@@ -5941,7 +6042,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5941
6042
  invoke: config.invoke,
5942
6043
  fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
5943
6044
  hosts: config.hosts,
5944
- telemetry: this.config.telemetry
6045
+ telemetry: this.config.telemetry,
6046
+ retryPolicy: this.config.retryPolicy
5945
6047
  }));
5946
6048
  context.setSession(config.session);
5947
6049
  service.initialize(context);
@@ -5951,7 +6053,6 @@ var _TinyCloudNode = class _TinyCloudNode {
5951
6053
  });
5952
6054
  sharingService.updateConfig({
5953
6055
  session: input.serviceSession,
5954
- delegationManager,
5955
6056
  sessionExpiry: input.sessionExpiry,
5956
6057
  createDelegationWasm: (params) => {
5957
6058
  graph.assertActive();
@@ -5982,7 +6083,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5982
6083
  invokeAny: graph.invokeAny,
5983
6084
  fetch: graph.fetch,
5984
6085
  hosts: [input.host],
5985
- telemetry: this.config.telemetry
6086
+ telemetry: this.config.telemetry,
6087
+ retryPolicy: this.config.retryPolicy
5986
6088
  }));
5987
6089
  context.setSession({ ...input.serviceSession, spaceId });
5988
6090
  scopedKv.initialize(context);
@@ -5997,7 +6099,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5997
6099
  invokeAny: graph.invokeAny,
5998
6100
  fetch: graph.fetch,
5999
6101
  hosts: [input.host],
6000
- telemetry: this.config.telemetry
6102
+ telemetry: this.config.telemetry,
6103
+ retryPolicy: this.config.retryPolicy
6001
6104
  }));
6002
6105
  context.setSession({ ...input.serviceSession, spaceId });
6003
6106
  scopedKv.initialize(context);
@@ -6080,6 +6183,21 @@ var _TinyCloudNode = class _TinyCloudNode {
6080
6183
  if (address === void 0 || chainId === void 0) {
6081
6184
  return void 0;
6082
6185
  }
6186
+ if (this.config.registryPolicy === "fail-closed") {
6187
+ const resolved2 = await (0, import_sdk_core10.resolveFailClosedTinyCloudHosts)(address, {
6188
+ registryUrl: this.config.tinycloudRegistryUrl,
6189
+ registryChainId: this.config.registryChainId,
6190
+ newUserHost: this.config.newUserHost,
6191
+ sequenceStore: this.config.registrySequenceStore,
6192
+ onNodeNotFound: this.config.onNodeNotFound,
6193
+ autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
6194
+ localNodeUrl: this.config.localNodeUrl,
6195
+ localLinkName: this.config.localLinkName,
6196
+ expectedNodeDid: this.config.expectedNodeDid,
6197
+ localNodeIdentityStore: this.config.localNodeIdentityStore
6198
+ });
6199
+ return resolved2.hosts[0];
6200
+ }
6083
6201
  const resolved = await (0, import_sdk_core10.resolveTinyCloudHosts)((0, import_sdk_core10.pkhDid)(address, chainId), {
6084
6202
  registryUrl: this.config.tinycloudRegistryUrl,
6085
6203
  fallbackHosts: this.config.tinycloudFallbackHosts,
@@ -6272,6 +6390,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6272
6390
  tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
6273
6391
  tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
6274
6392
  tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
6393
+ ...this.registryPolicyConfig(),
6275
6394
  autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
6276
6395
  localNodeUrl: this.config.localNodeUrl,
6277
6396
  localLinkName: this.config.localLinkName,
@@ -6293,7 +6412,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6293
6412
  });
6294
6413
  this.tc = new import_sdk_core10.TinyCloud(this.auth, {
6295
6414
  invokeAny: this.invokeAnyWithRuntimePermissions,
6296
- telemetry: this.config.telemetry
6415
+ telemetry: this.config.telemetry,
6416
+ retryPolicy: this.config.retryPolicy
6297
6417
  });
6298
6418
  this.config.prefix = prefix;
6299
6419
  }
@@ -6331,6 +6451,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6331
6451
  tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
6332
6452
  tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
6333
6453
  tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
6454
+ ...this.registryPolicyConfig(),
6334
6455
  autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
6335
6456
  localNodeUrl: this.config.localNodeUrl,
6336
6457
  localLinkName: this.config.localLinkName,
@@ -6352,7 +6473,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6352
6473
  });
6353
6474
  this.tc = new import_sdk_core10.TinyCloud(this.auth, {
6354
6475
  invokeAny: this.invokeAnyWithRuntimePermissions,
6355
- telemetry: this.config.telemetry
6476
+ telemetry: this.config.telemetry,
6477
+ retryPolicy: this.config.retryPolicy
6356
6478
  });
6357
6479
  this.config.prefix = prefix;
6358
6480
  }
@@ -6376,7 +6498,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6376
6498
  invokeAny: this._serviceGraph.invokeAny,
6377
6499
  fetch: this._serviceGraph.fetch,
6378
6500
  hosts: [this.config.host],
6379
- telemetry: this.config.telemetry
6501
+ telemetry: this.config.telemetry,
6502
+ retryPolicy: this.config.retryPolicy
6380
6503
  }));
6381
6504
  this._kv = new import_sdk_core10.KVService({});
6382
6505
  this._kv.initialize(this._serviceContext);
@@ -6423,7 +6546,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6423
6546
  invokeAny: this._serviceContext.invokeAny,
6424
6547
  fetch: this._serviceContext.fetch,
6425
6548
  hosts: this._serviceContext.hosts,
6426
- telemetry: this.config.telemetry
6549
+ telemetry: this.config.telemetry,
6550
+ retryPolicy: this.config.retryPolicy
6427
6551
  }));
6428
6552
  const session = this._serviceContext.session;
6429
6553
  if (session) {
@@ -6874,7 +6998,6 @@ var _TinyCloudNode = class _TinyCloudNode {
6874
6998
  assertActive: () => graph.assertActive(),
6875
6999
  keyProvider: this._keyProvider,
6876
7000
  registry: this._capabilityRegistry,
6877
- delegationManager: this._delegationManager,
6878
7001
  sessionExpiry: this.getSessionExpiry(),
6879
7002
  createDelegationWasm: (params) => {
6880
7003
  graph.assertActive();
@@ -6891,7 +7014,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6891
7014
  invoke: config.invoke,
6892
7015
  fetch: config.fetch ?? graph.fetch,
6893
7016
  hosts: config.hosts,
6894
- telemetry: this.config.telemetry
7017
+ telemetry: this.config.telemetry,
7018
+ retryPolicy: this.config.retryPolicy
6895
7019
  }));
6896
7020
  context.setSession(config.session);
6897
7021
  service.initialize(context);
@@ -7212,7 +7336,8 @@ var _TinyCloudNode = class _TinyCloudNode {
7212
7336
  invokeAny: this._serviceContext.invokeAny,
7213
7337
  fetch: this._serviceContext.fetch,
7214
7338
  hosts: this._serviceContext.hosts,
7215
- telemetry: this.config.telemetry
7339
+ telemetry: this.config.telemetry,
7340
+ retryPolicy: this.config.retryPolicy
7216
7341
  }));
7217
7342
  spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
7218
7343
  sql.initialize(spaceScopedContext);
@@ -7415,6 +7540,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7415
7540
  }
7416
7541
  };
7417
7542
  }
7543
+ if (result.status === "aad_mismatch") return { status: "read_failed" };
7418
7544
  return { status: result.status };
7419
7545
  }
7420
7546
  if (!isSecretPayload(result.entry.value)) {
@@ -7856,16 +7982,8 @@ var _TinyCloudNode = class _TinyCloudNode {
7856
7982
  * ```typescript
7857
7983
  * const delegations = alice.delegationManager;
7858
7984
  *
7859
- * // Create a delegation
7860
- * const result = await delegations.create({
7861
- * delegateDID: bob.did,
7862
- * path: "shared/",
7863
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
7864
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
7865
- * });
7866
- *
7867
- * // List delegations
7868
- * const listResult = await delegations.list();
7985
+ * // Query account delegations
7986
+ * const page = await delegations.query();
7869
7987
  *
7870
7988
  * // Revoke a delegation
7871
7989
  * await delegations.revoke(delegationCid);
@@ -7967,7 +8085,9 @@ var _TinyCloudNode = class _TinyCloudNode {
7967
8085
  * Ensure the user's public space exists and is accessible.
7968
8086
  * Creates the space and activates a session delegation for it.
7969
8087
  * This is the trigger for lazy public space creation — call it
7970
- * before writing to spaces.get('public').kv.
8088
+ * before writing to spaces.get('public').kv. The vault calls it on unlock.
8089
+ * Under `registryPolicy: "fail-closed"` creation goes through the
8090
+ * space-creation guard.
7971
8091
  */
7972
8092
  async ensurePublicSpace() {
7973
8093
  if (!this.auth || !this.session || !this.signer) {
@@ -7977,6 +8097,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7977
8097
  if (!publicSpaceId) {
7978
8098
  throw new Error("Public space not enabled. Set enablePublicSpace: true in config.");
7979
8099
  }
8100
+ await this.assertMayCreateSpace();
7980
8101
  await this.auth.hostPublicSpace(publicSpaceId);
7981
8102
  const kvActions = [import_sdk_core10.KV.PUT, import_sdk_core10.KV.GET, import_sdk_core10.KV.DEL, import_sdk_core10.KV.LIST, import_sdk_core10.KV.METADATA];
7982
8103
  const abilities = { kv: { "": kvActions } };
@@ -8034,7 +8155,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8034
8155
  invoke: this._serviceGraph.invoke,
8035
8156
  fetch: this._serviceGraph.fetch,
8036
8157
  hosts: this._serviceContext.hosts,
8037
- telemetry: this.config.telemetry
8158
+ telemetry: this.config.telemetry,
8159
+ retryPolicy: this.config.retryPolicy
8038
8160
  }));
8039
8161
  publicContext.setSession({
8040
8162
  delegationHeader: delegationSession.delegationHeader,
@@ -8063,32 +8185,6 @@ var _TinyCloudNode = class _TinyCloudNode {
8063
8185
  // ===========================================================================
8064
8186
  // v2 Delegation Convenience Methods
8065
8187
  // ===========================================================================
8066
- /**
8067
- * Create a delegation using the v2 DelegationManager.
8068
- *
8069
- * This is a convenience method that wraps DelegationManager.create().
8070
- * For more control, use `this.delegationManager` directly.
8071
- *
8072
- * @param params - Delegation parameters
8073
- * @returns Result containing the created Delegation
8074
- *
8075
- * @example
8076
- * ```typescript
8077
- * const result = await alice.delegate({
8078
- * delegateDID: bob.did,
8079
- * path: "shared/",
8080
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
8081
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000),
8082
- * });
8083
- *
8084
- * if (result.ok) {
8085
- * console.log("Delegation created:", result.data.cid);
8086
- * }
8087
- * ```
8088
- */
8089
- async delegate(params) {
8090
- return this.delegationManager.create(params);
8091
- }
8092
8188
  /**
8093
8189
  * Revoke a delegation with the owner wallet when available. Session-only
8094
8190
  * clients continue to use their delegated revocation authority.
@@ -8114,14 +8210,6 @@ var _TinyCloudNode = class _TinyCloudNode {
8114
8210
  0x55n
8115
8211
  );
8116
8212
  }
8117
- /**
8118
- * List all delegations for the current session's space.
8119
- *
8120
- * @returns Result containing an array of Delegations
8121
- */
8122
- async listDelegations() {
8123
- return this.delegationManager.list();
8124
- }
8125
8213
  /**
8126
8214
  * Check if the current session has permission for a path and action.
8127
8215
  *
@@ -8181,6 +8269,9 @@ var _TinyCloudNode = class _TinyCloudNode {
8181
8269
  "delegateTo: onPrepared cannot be combined with forceWalletSign=true; the wallet-signed path activates the delegation before it could be handed to onPrepared."
8182
8270
  );
8183
8271
  }
8272
+ if (options?.disableSubDelegation && did.startsWith("did:pkh:")) {
8273
+ throw new Error(TERMINAL_DELEGATION_REQUIRES_SESSION_KEY);
8274
+ }
8184
8275
  const session = this.currentTinyCloudSession();
8185
8276
  if (!session) {
8186
8277
  throw new import_sdk_core10.SessionExpiredError(/* @__PURE__ */ new Date(0));
@@ -8246,7 +8337,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8246
8337
  plan.grant,
8247
8338
  plan.operations,
8248
8339
  onPrepared,
8249
- options?.disableSubDelegation === true
8340
+ options?.disableSubDelegation === true,
8341
+ options?.requireActivation === true
8250
8342
  );
8251
8343
  return { delegation: delegation2, prompted: false };
8252
8344
  }
@@ -8256,7 +8348,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8256
8348
  effectiveExpiration,
8257
8349
  session,
8258
8350
  onPrepared,
8259
- options?.disableSubDelegation === true
8351
+ options?.disableSubDelegation === true,
8352
+ options?.requireActivation === true
8260
8353
  );
8261
8354
  return { delegation, prompted: false };
8262
8355
  }
@@ -8487,7 +8580,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8487
8580
  *
8488
8581
  * @internal
8489
8582
  */
8490
- async createDelegationViaWasmPath(did, entries, expirationTime, session, onPrepared, disableSubDelegation = false) {
8583
+ async createDelegationViaWasmPath(did, entries, expirationTime, session, onPrepared, disableSubDelegation = false, requireActivation = false) {
8491
8584
  if (entries.length === 0) {
8492
8585
  throw new Error(
8493
8586
  "createDelegationViaWasmPath requires a non-empty entries array"
@@ -8571,15 +8664,10 @@ var _TinyCloudNode = class _TinyCloudNode {
8571
8664
  this.config.host,
8572
8665
  delegationHeader
8573
8666
  );
8574
- if (!activateResult.success) {
8575
- throw Object.assign(
8576
- new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
8577
- { cause: activateResult }
8578
- );
8579
- }
8667
+ assertDelegationActivated(activateResult, delegation, requireActivation);
8580
8668
  return delegation;
8581
8669
  }
8582
- async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations, onPrepared, disableSubDelegation = false) {
8670
+ async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations, onPrepared, disableSubDelegation = false, requireActivation = false) {
8583
8671
  this.assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant);
8584
8672
  this.assertDelegationCaveatsPreservable(entries);
8585
8673
  const result = this.createDelegationWrapper({
@@ -8613,12 +8701,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8613
8701
  targetHost,
8614
8702
  delegationHeader
8615
8703
  );
8616
- if (!activateResult.success) {
8617
- throw Object.assign(
8618
- new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
8619
- { cause: activateResult }
8620
- );
8621
- }
8704
+ assertDelegationActivated(activateResult, delegation, requireActivation);
8622
8705
  return delegation;
8623
8706
  }
8624
8707
  resolvePermissionSpace(space, session) {
@@ -9565,6 +9648,8 @@ var _TinyCloudNode = class _TinyCloudNode {
9565
9648
  };
9566
9649
  }
9567
9650
  };
9651
+ /** Set once per process: the registry sync was skipped for want of account access. */
9652
+ _TinyCloudNode.accountRegistrySkipLogged = false;
9568
9653
  // ===========================================================================
9569
9654
  // Capability-chain delegation (spec: .claude/specs/capability-chain.md)
9570
9655
  // ===========================================================================