@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.js CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  principalDidEquals as principalDidEquals4,
35
35
  parseCanonicalNetworkId,
36
36
  TinyCloudDebugLogger,
37
- tinyCloudDebugLogger,
37
+ tinyCloudDebugLogger as tinyCloudDebugLogger2,
38
38
  enableTinyCloudDebug,
39
39
  disableTinyCloudDebug,
40
40
  getTinyCloudDebugLogs,
@@ -250,6 +250,11 @@ import {
250
250
  resourceCapabilitiesToAbilitiesMap,
251
251
  resourceCapabilitiesToSpaceAbilitiesMap,
252
252
  resolveTinyCloudHosts,
253
+ resolveFailClosedTinyCloudHosts,
254
+ lookupOwnerRegistryVerdict,
255
+ assertSpaceCreationAllowed,
256
+ createInMemoryRegistrySequenceStore,
257
+ registryOwnerSubjectV1,
253
258
  EXPIRY,
254
259
  canonicalizeAddress,
255
260
  makePkhSpaceId,
@@ -444,6 +449,11 @@ var NodeUserAuthorization = class {
444
449
  this.tinycloudHosts = config.tinycloudHosts;
445
450
  this.tinycloudRegistryUrl = config.tinycloudRegistryUrl;
446
451
  this.tinycloudFallbackHosts = config.tinycloudFallbackHosts;
452
+ this.registryPolicy = config.registryPolicy;
453
+ this.newUserHost = config.newUserHost;
454
+ this.registryChainId = config.registryChainId;
455
+ this.registrySequenceStore = config.registrySequenceStore ?? createInMemoryRegistrySequenceStore();
456
+ this.onNodeNotFound = config.onNodeNotFound;
447
457
  this.autoDiscoverLocalNode = config.autoDiscoverLocalNode;
448
458
  this.localNodeUrl = config.localNodeUrl;
449
459
  this.localLinkName = config.localLinkName;
@@ -555,6 +565,7 @@ var NodeUserAuthorization = class {
555
565
  this._nodeFeaturesKnown = nodeFeatures !== void 0;
556
566
  this._nodeInfoIdentity = void 0;
557
567
  this.tinycloudHosts = hosts && hosts.length > 0 ? [...hosts] : void 0;
568
+ this.registryVerdict = void 0;
558
569
  this._lastActivationSkippedSpaceIds = [];
559
570
  this._lastActivationActivatedSpaceIds = [];
560
571
  if (!session) {
@@ -605,6 +616,23 @@ var NodeUserAuthorization = class {
605
616
  if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
606
617
  return;
607
618
  }
619
+ if (this.registryPolicy === "fail-closed") {
620
+ const resolved2 = await resolveFailClosedTinyCloudHosts(address, {
621
+ registryUrl: this.tinycloudRegistryUrl,
622
+ registryChainId: this.registryChainId,
623
+ newUserHost: this.newUserHost,
624
+ sequenceStore: this.registrySequenceStore,
625
+ onNodeNotFound: this.onNodeNotFound,
626
+ autoDiscoverLocalNode: this.autoDiscoverLocalNode,
627
+ localNodeUrl: this.localNodeUrl,
628
+ localLinkName: this.localLinkName,
629
+ expectedNodeDid: this.expectedNodeDid,
630
+ localNodeIdentityStore: this.localNodeIdentityStore
631
+ });
632
+ this.tinycloudHosts = resolved2.hosts;
633
+ this.registryVerdict = resolved2.verdict;
634
+ return;
635
+ }
608
636
  const subject = pkhDid(address, chainId);
609
637
  const resolved = await resolveTinyCloudHosts(subject, {
610
638
  registryUrl: this.tinycloudRegistryUrl,
@@ -617,6 +645,32 @@ var NodeUserAuthorization = class {
617
645
  });
618
646
  this.tinycloudHosts = resolved.hosts;
619
647
  }
648
+ /**
649
+ * Space-creation guard (TC-1443). Under `registryPolicy: "fail-closed"`,
650
+ * throws unless the owner's registry verdict allows a space on the primary
651
+ * host: `NodeRegistryEntryExistsError` when the owner's record does not
652
+ * list it, `RegistryUnavailableError` when the registry gives no
653
+ * verdict. Reuses this session's sign-in verdict unless it was
654
+ * `unavailable`, else looks it up now (explicit-host apps). Under the
655
+ * default policy it returns at once and performs no lookup.
656
+ */
657
+ async assertMayCreateSpace() {
658
+ if (this.registryPolicy !== "fail-closed") return;
659
+ if (this._address === void 0) {
660
+ throw new Error("Must be signed in to create a space");
661
+ }
662
+ await this.ensureTinyCloudHosts();
663
+ const subject = registryOwnerSubjectV1(this._address, this.registryChainId);
664
+ let verdict = this.registryVerdict;
665
+ if (verdict?.subject !== subject || verdict.status === "unavailable") {
666
+ verdict = await lookupOwnerRegistryVerdict(subject, {
667
+ registryUrl: this.tinycloudRegistryUrl,
668
+ sequenceStore: this.registrySequenceStore
669
+ });
670
+ this.registryVerdict = verdict;
671
+ }
672
+ assertSpaceCreationAllowed(verdict, this.primaryTinyCloudHost);
673
+ }
620
674
  requireTinyCloudHosts() {
621
675
  if (!this.tinycloudHosts || this.tinycloudHosts.length === 0) {
622
676
  throw new Error("TinyCloud hosts have not been resolved. Call signIn() first.");
@@ -1065,6 +1119,7 @@ var NodeUserAuthorization = class {
1065
1119
  if (!handler) {
1066
1120
  return;
1067
1121
  }
1122
+ await this.guardSpaceCreation(handler, creationContext);
1068
1123
  const confirmed = await handler.confirmSpaceCreation(creationContext);
1069
1124
  if (!confirmed) {
1070
1125
  return;
@@ -1105,6 +1160,7 @@ var NodeUserAuthorization = class {
1105
1160
  if (!handler) {
1106
1161
  return;
1107
1162
  }
1163
+ await this.guardSpaceCreation(handler, creationContext);
1108
1164
  const confirmed = await handler.confirmSpaceCreation(creationContext);
1109
1165
  if (!confirmed) {
1110
1166
  return;
@@ -1146,6 +1202,16 @@ var NodeUserAuthorization = class {
1146
1202
  { cause: result }
1147
1203
  );
1148
1204
  }
1205
+ /** {@link assertMayCreateSpace}, reporting a refusal to the creation handler before rethrowing it. */
1206
+ async guardSpaceCreation(handler, context) {
1207
+ try {
1208
+ await this.assertMayCreateSpace();
1209
+ } catch (error) {
1210
+ const failure = error instanceof Error ? error : new Error(String(error));
1211
+ handler.onSpaceCreationFailed?.(context, failure);
1212
+ throw failure;
1213
+ }
1214
+ }
1149
1215
  recordActivationSkippedSpaces(result, primarySpaceId) {
1150
1216
  if (result.success) {
1151
1217
  this._lastActivationSkippedSpaceIds = result.skipped ?? [];
@@ -2150,24 +2216,17 @@ function signedAuthorityFromCompactUcan(authorization) {
2150
2216
  ));
2151
2217
  continue;
2152
2218
  }
2153
- const nativeMatch = /^(tinycloud:[^/]+)\/(kv|sql|duckdb|hooks)\/(.*)$/.exec(resource);
2154
- const policyMatch = /^tinycloud:\/\/([^/]+)\/(kv|sql|duckdb|hooks)\/(.*)$/.exec(resource);
2155
- const match = nativeMatch ?? policyMatch;
2219
+ const match = /^(?:tinycloud:\/\/([^/]+)|(tinycloud:[^/]+))\/(kv|sql|duckdb|hooks)(?:\/|$)(.*)$/.exec(resource);
2156
2220
  if (!match) {
2157
2221
  throw new Error(
2158
2222
  `Validated runtime delegation has an unsupported signed resource '${resource}'.`
2159
2223
  );
2160
2224
  }
2161
- const [, space, shortService, path] = match;
2225
+ const [, policySpace, nativeSpace, shortService, path] = match;
2162
2226
  const service = SERVICE_BY_SHORT_NAME[shortService];
2163
- if (service === void 0) {
2164
- throw new Error(
2165
- `Validated runtime delegation has an unsupported signed service '${shortService}'.`
2166
- );
2167
- }
2168
2227
  permissions.push(...groupedSignedEntries(
2169
2228
  service,
2170
- space,
2229
+ nativeSpace ?? policySpace,
2171
2230
  path,
2172
2231
  abilities
2173
2232
  ));
@@ -2533,6 +2592,8 @@ import {
2533
2592
  canonicalizeAddress as canonicalizeAddress2,
2534
2593
  pkhDid as pkhDid2,
2535
2594
  resolveTinyCloudHosts as resolveTinyCloudHosts2,
2595
+ resolveFailClosedTinyCloudHosts as resolveFailClosedTinyCloudHosts2,
2596
+ createInMemoryRegistrySequenceStore as createInMemoryRegistrySequenceStore2,
2536
2597
  publishLocationRecord,
2537
2598
  principalDidEquals as principalDidEquals3,
2538
2599
  parseNetworkId as parseNetworkId2,
@@ -2553,7 +2614,8 @@ import {
2553
2614
  serviceError
2554
2615
  } from "@tinycloud/sdk-core";
2555
2616
  import {
2556
- parsePermissionHint
2617
+ parsePermissionHint,
2618
+ tinyCloudDebugLogger
2557
2619
  } from "@tinycloud/sdk-services";
2558
2620
 
2559
2621
  // src/account/AccountService.ts
@@ -3287,6 +3349,12 @@ function describeHostFailure2(result) {
3287
3349
  const text = result.error?.trim();
3288
3350
  return text ? `${result.status} - ${text}` : `${result.status}`;
3289
3351
  }
3352
+ function assertDelegationActivated(result, delegation, requireActivation) {
3353
+ const skipped = requireActivation ? (delegation.resources?.map((r) => r.space) ?? [delegation.spaceId]).filter((space) => result.skipped?.includes(space)) : [];
3354
+ if (result.success && skipped.length === 0) return;
3355
+ const detail = result.success ? `the node skipped ${[...new Set(skipped)].join(", ")} (space not hosted on the node)` : describeHostFailure2(result);
3356
+ throw Object.assign(new Error(`Failed to activate delegation with host: ${detail}`), { cause: result });
3357
+ }
3290
3358
  function ownerDelegationPermissions(params) {
3291
3359
  const hasPermissions = Object.prototype.hasOwnProperty.call(params, "permissions");
3292
3360
  const hasLegacy = Object.prototype.hasOwnProperty.call(params, "path") || Object.prototype.hasOwnProperty.call(params, "actions");
@@ -3369,7 +3437,7 @@ function ownerPermissionsToAbilities(permissions) {
3369
3437
  }
3370
3438
  return { abilities, rawAbilities };
3371
3439
  }
3372
- var TERMINAL_DELEGATION_REQUIRES_SESSION_KEY = "disableSubDelegation requires a session-key delegation";
3440
+ 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";
3373
3441
  function base64UrlEncode(bytes) {
3374
3442
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
3375
3443
  let output = "";
@@ -3683,7 +3751,9 @@ var _TinyCloudNode = class _TinyCloudNode {
3683
3751
  this.explicitHost = config.host;
3684
3752
  this.config = {
3685
3753
  ...config,
3686
- host: config.host ?? DEFAULT_HOST
3754
+ host: config.host ?? DEFAULT_HOST,
3755
+ // One store for every authorization this client creates.
3756
+ registrySequenceStore: config.registrySequenceStore ?? createInMemoryRegistrySequenceStore2()
3687
3757
  };
3688
3758
  if (this.config.replication?.enabled) {
3689
3759
  const runtime = getNodeReplicationLoaders().runtime().then(({ ReplicationRuntime }) => {
@@ -3918,7 +3988,6 @@ var _TinyCloudNode = class _TinyCloudNode {
3918
3988
  if (!this.wasmBindings.computeCid) throw new Error("computeCid is unavailable");
3919
3989
  return this.wasmBindings.computeCid(data, codec);
3920
3990
  },
3921
- // delegationManager: undefined - not needed for receive()
3922
3991
  createKVService: (config) => {
3923
3992
  const prefix = config.pathPrefix?.replace(/\/$/, "");
3924
3993
  const kvService = new KVService2({ prefix });
@@ -3926,7 +3995,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3926
3995
  invoke: config.invoke,
3927
3996
  fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
3928
3997
  hosts: config.hosts,
3929
- telemetry: this.config.telemetry
3998
+ telemetry: this.config.telemetry,
3999
+ retryPolicy: this.config.retryPolicy
3930
4000
  }));
3931
4001
  kvContext.setSession(config.session);
3932
4002
  kvService.initialize(kvContext);
@@ -3953,6 +4023,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3953
4023
  tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
3954
4024
  tinycloudRegistryUrl: config.tinycloudRegistryUrl,
3955
4025
  tinycloudFallbackHosts: config.tinycloudFallbackHosts,
4026
+ ...this.registryPolicyConfig(),
3956
4027
  autoDiscoverLocalNode: config.autoDiscoverLocalNode,
3957
4028
  localNodeUrl: config.localNodeUrl,
3958
4029
  localLinkName: config.localLinkName,
@@ -3976,7 +4047,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3976
4047
  });
3977
4048
  this.tc = new TinyCloud(this.auth, {
3978
4049
  invokeAny: this.invokeAnyWithRuntimePermissions,
3979
- telemetry: config.telemetry
4050
+ telemetry: config.telemetry,
4051
+ retryPolicy: config.retryPolicy
3980
4052
  });
3981
4053
  }
3982
4054
  shouldUseBootstrapSignInRequest(config) {
@@ -4338,7 +4410,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4338
4410
  this.auth = oldAuth;
4339
4411
  this.tc = this.auth ? new TinyCloud(this.auth, {
4340
4412
  invokeAny: this.invokeAnyWithRuntimePermissions,
4341
- telemetry: this.config.telemetry
4413
+ telemetry: this.config.telemetry,
4414
+ retryPolicy: this.config.retryPolicy
4342
4415
  }) : null;
4343
4416
  this._capabilityRegistry = new CapabilityKeyRegistry();
4344
4417
  this._keyProvider = new WasmKeyProvider({ sessionManager: this.sessionManager });
@@ -4658,6 +4731,9 @@ var _TinyCloudNode = class _TinyCloudNode {
4658
4731
  const primarySession = auth.tinyCloudSession;
4659
4732
  const defaultSpaceId = this.ownedSpaceId("default");
4660
4733
  const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === BOOTSTRAP_SESSION_REQUESTS.default;
4734
+ if (steps.some((step) => step.kind === "host")) {
4735
+ await this.assertMayCreateSpace();
4736
+ }
4661
4737
  for (const step of steps) {
4662
4738
  if (step.kind !== "session") continue;
4663
4739
  graph.assertActive();
@@ -4986,7 +5062,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4986
5062
  invokeAny: context.invokeAny,
4987
5063
  fetch: context.fetch,
4988
5064
  hosts: context.hosts,
4989
- telemetry: this.config.telemetry
5065
+ telemetry: this.config.telemetry,
5066
+ retryPolicy: this.config.retryPolicy
4990
5067
  }));
4991
5068
  scoped.setOperationAbortSignal(signal);
4992
5069
  scoped.setSession({ ...session, spaceId });
@@ -5033,6 +5110,10 @@ var _TinyCloudNode = class _TinyCloudNode {
5033
5110
  return;
5034
5111
  }
5035
5112
  if (!this.currentSessionCoversAccountRegistry()) {
5113
+ if (!_TinyCloudNode.accountRegistrySkipLogged) {
5114
+ _TinyCloudNode.accountRegistrySkipLogged = true;
5115
+ tinyCloudDebugLogger.log("registry.skip");
5116
+ }
5036
5117
  return;
5037
5118
  }
5038
5119
  const controller = new AbortController();
@@ -5048,7 +5129,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5048
5129
  invokeAny: sharedContext.invokeAny,
5049
5130
  fetch: sharedContext.fetch,
5050
5131
  hosts: sharedContext.hosts,
5051
- telemetry: this.config.telemetry
5132
+ telemetry: this.config.telemetry,
5133
+ retryPolicy: this.config.retryPolicy
5052
5134
  }));
5053
5135
  context.setOperationAbortSignal(controller.signal);
5054
5136
  const current = this.currentTinyCloudSession();
@@ -5299,6 +5381,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5299
5381
  { cause: activation }
5300
5382
  );
5301
5383
  }
5384
+ await this.assertMayCreateSpace();
5385
+ if (signal?.aborted) throw signal.reason;
5302
5386
  const created = await this.hostOwnedSpaceOnce(spaceId, signal);
5303
5387
  if (!created.success) {
5304
5388
  throw Object.assign(
@@ -5412,6 +5496,12 @@ var _TinyCloudNode = class _TinyCloudNode {
5412
5496
  * session's recap doesn't cover it and the registry has no record; the host
5413
5497
  * SIWE is idempotent server-side. Must be called after {@link signIn}.
5414
5498
  *
5499
+ * Under `registryPolicy: "fail-closed"`, hosting is refused with
5500
+ * `NodeRegistryEntryExistsError` when the owner's registry record does not
5501
+ * list the host, or `RegistryUnavailableError` when the registry gives no
5502
+ * verdict. {@link hostOwnedSpace} itself is an explicit action and is not
5503
+ * guarded.
5504
+ *
5415
5505
  * @param name - The owned space name (e.g. `"secrets"`).
5416
5506
  * @returns The hosted owned-space URI.
5417
5507
  */
@@ -5423,8 +5513,25 @@ var _TinyCloudNode = class _TinyCloudNode {
5423
5513
  if (this.hostedOwnedSpaceIds.has(spaceId) || await this.isOwnedSpaceRegistered(spaceId)) {
5424
5514
  return spaceId;
5425
5515
  }
5516
+ await this.assertMayCreateSpace();
5426
5517
  return this.hostOwnedSpace(name);
5427
5518
  }
5519
+ /**
5520
+ * Space-creation guard (TC-1443) for the automatic hosting paths: sign-in's
5521
+ * owned spaces, account bootstrap, {@link ensureOwnedSpaceHosted} and
5522
+ * {@link ensurePublicSpace}. Only `registryPolicy: "fail-closed"` consults
5523
+ * the registry ({@link NodeUserAuthorization.assertMayCreateSpace}); the
5524
+ * default policy performs no lookup.
5525
+ */
5526
+ async assertMayCreateSpace() {
5527
+ if (this.config.registryPolicy !== "fail-closed") return;
5528
+ await this.auth.assertMayCreateSpace();
5529
+ }
5530
+ /** Registry-policy settings shared by every authorization this client creates. */
5531
+ registryPolicyConfig() {
5532
+ const { registryPolicy, newUserHost, registryChainId, registrySequenceStore, onNodeNotFound } = this.config;
5533
+ return { registryPolicy, newUserHost, registryChainId, registrySequenceStore, onNodeNotFound };
5534
+ }
5428
5535
  /**
5429
5536
  * Submit the host delegation for an owned space, sharing one in-flight
5430
5537
  * request (and so one approval) between concurrent callers in this session,
@@ -5865,7 +5972,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5865
5972
  const graph = this.createServiceGraphLifetime();
5866
5973
  const core = this.auth ? new TinyCloud(this.auth, {
5867
5974
  invokeAny: graph.invokeAny,
5868
- telemetry: this.config.telemetry
5975
+ telemetry: this.config.telemetry,
5976
+ retryPolicy: this.config.retryPolicy
5869
5977
  }) : null;
5870
5978
  if (core) {
5871
5979
  core.initializeServices(graph.invoke, [input.host], graph.fetch);
@@ -5877,7 +5985,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5877
5985
  invokeAny: graph.invokeAny,
5878
5986
  fetch: graph.fetch,
5879
5987
  hosts: [input.host],
5880
- telemetry: this.config.telemetry
5988
+ telemetry: this.config.telemetry,
5989
+ retryPolicy: this.config.retryPolicy
5881
5990
  }));
5882
5991
  const kv = new KVService2({});
5883
5992
  kv.initialize(serviceContext);
@@ -5963,7 +6072,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5963
6072
  invoke: config.invoke,
5964
6073
  fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
5965
6074
  hosts: config.hosts,
5966
- telemetry: this.config.telemetry
6075
+ telemetry: this.config.telemetry,
6076
+ retryPolicy: this.config.retryPolicy
5967
6077
  }));
5968
6078
  context.setSession(config.session);
5969
6079
  service.initialize(context);
@@ -5973,7 +6083,6 @@ var _TinyCloudNode = class _TinyCloudNode {
5973
6083
  });
5974
6084
  sharingService.updateConfig({
5975
6085
  session: input.serviceSession,
5976
- delegationManager,
5977
6086
  sessionExpiry: input.sessionExpiry,
5978
6087
  createDelegationWasm: (params) => {
5979
6088
  graph.assertActive();
@@ -6004,7 +6113,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6004
6113
  invokeAny: graph.invokeAny,
6005
6114
  fetch: graph.fetch,
6006
6115
  hosts: [input.host],
6007
- telemetry: this.config.telemetry
6116
+ telemetry: this.config.telemetry,
6117
+ retryPolicy: this.config.retryPolicy
6008
6118
  }));
6009
6119
  context.setSession({ ...input.serviceSession, spaceId });
6010
6120
  scopedKv.initialize(context);
@@ -6019,7 +6129,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6019
6129
  invokeAny: graph.invokeAny,
6020
6130
  fetch: graph.fetch,
6021
6131
  hosts: [input.host],
6022
- telemetry: this.config.telemetry
6132
+ telemetry: this.config.telemetry,
6133
+ retryPolicy: this.config.retryPolicy
6023
6134
  }));
6024
6135
  context.setSession({ ...input.serviceSession, spaceId });
6025
6136
  scopedKv.initialize(context);
@@ -6102,6 +6213,21 @@ var _TinyCloudNode = class _TinyCloudNode {
6102
6213
  if (address === void 0 || chainId === void 0) {
6103
6214
  return void 0;
6104
6215
  }
6216
+ if (this.config.registryPolicy === "fail-closed") {
6217
+ const resolved2 = await resolveFailClosedTinyCloudHosts2(address, {
6218
+ registryUrl: this.config.tinycloudRegistryUrl,
6219
+ registryChainId: this.config.registryChainId,
6220
+ newUserHost: this.config.newUserHost,
6221
+ sequenceStore: this.config.registrySequenceStore,
6222
+ onNodeNotFound: this.config.onNodeNotFound,
6223
+ autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
6224
+ localNodeUrl: this.config.localNodeUrl,
6225
+ localLinkName: this.config.localLinkName,
6226
+ expectedNodeDid: this.config.expectedNodeDid,
6227
+ localNodeIdentityStore: this.config.localNodeIdentityStore
6228
+ });
6229
+ return resolved2.hosts[0];
6230
+ }
6105
6231
  const resolved = await resolveTinyCloudHosts2(pkhDid2(address, chainId), {
6106
6232
  registryUrl: this.config.tinycloudRegistryUrl,
6107
6233
  fallbackHosts: this.config.tinycloudFallbackHosts,
@@ -6294,6 +6420,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6294
6420
  tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
6295
6421
  tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
6296
6422
  tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
6423
+ ...this.registryPolicyConfig(),
6297
6424
  autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
6298
6425
  localNodeUrl: this.config.localNodeUrl,
6299
6426
  localLinkName: this.config.localLinkName,
@@ -6315,7 +6442,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6315
6442
  });
6316
6443
  this.tc = new TinyCloud(this.auth, {
6317
6444
  invokeAny: this.invokeAnyWithRuntimePermissions,
6318
- telemetry: this.config.telemetry
6445
+ telemetry: this.config.telemetry,
6446
+ retryPolicy: this.config.retryPolicy
6319
6447
  });
6320
6448
  this.config.prefix = prefix;
6321
6449
  }
@@ -6353,6 +6481,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6353
6481
  tinycloudHosts: this.explicitHost ? [this.explicitHost] : void 0,
6354
6482
  tinycloudRegistryUrl: this.config.tinycloudRegistryUrl,
6355
6483
  tinycloudFallbackHosts: this.config.tinycloudFallbackHosts,
6484
+ ...this.registryPolicyConfig(),
6356
6485
  autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
6357
6486
  localNodeUrl: this.config.localNodeUrl,
6358
6487
  localLinkName: this.config.localLinkName,
@@ -6374,7 +6503,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6374
6503
  });
6375
6504
  this.tc = new TinyCloud(this.auth, {
6376
6505
  invokeAny: this.invokeAnyWithRuntimePermissions,
6377
- telemetry: this.config.telemetry
6506
+ telemetry: this.config.telemetry,
6507
+ retryPolicy: this.config.retryPolicy
6378
6508
  });
6379
6509
  this.config.prefix = prefix;
6380
6510
  }
@@ -6398,7 +6528,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6398
6528
  invokeAny: this._serviceGraph.invokeAny,
6399
6529
  fetch: this._serviceGraph.fetch,
6400
6530
  hosts: [this.config.host],
6401
- telemetry: this.config.telemetry
6531
+ telemetry: this.config.telemetry,
6532
+ retryPolicy: this.config.retryPolicy
6402
6533
  }));
6403
6534
  this._kv = new KVService2({});
6404
6535
  this._kv.initialize(this._serviceContext);
@@ -6445,7 +6576,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6445
6576
  invokeAny: this._serviceContext.invokeAny,
6446
6577
  fetch: this._serviceContext.fetch,
6447
6578
  hosts: this._serviceContext.hosts,
6448
- telemetry: this.config.telemetry
6579
+ telemetry: this.config.telemetry,
6580
+ retryPolicy: this.config.retryPolicy
6449
6581
  }));
6450
6582
  const session = this._serviceContext.session;
6451
6583
  if (session) {
@@ -6896,7 +7028,6 @@ var _TinyCloudNode = class _TinyCloudNode {
6896
7028
  assertActive: () => graph.assertActive(),
6897
7029
  keyProvider: this._keyProvider,
6898
7030
  registry: this._capabilityRegistry,
6899
- delegationManager: this._delegationManager,
6900
7031
  sessionExpiry: this.getSessionExpiry(),
6901
7032
  createDelegationWasm: (params) => {
6902
7033
  graph.assertActive();
@@ -6913,7 +7044,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6913
7044
  invoke: config.invoke,
6914
7045
  fetch: config.fetch ?? graph.fetch,
6915
7046
  hosts: config.hosts,
6916
- telemetry: this.config.telemetry
7047
+ telemetry: this.config.telemetry,
7048
+ retryPolicy: this.config.retryPolicy
6917
7049
  }));
6918
7050
  context.setSession(config.session);
6919
7051
  service.initialize(context);
@@ -7234,7 +7366,8 @@ var _TinyCloudNode = class _TinyCloudNode {
7234
7366
  invokeAny: this._serviceContext.invokeAny,
7235
7367
  fetch: this._serviceContext.fetch,
7236
7368
  hosts: this._serviceContext.hosts,
7237
- telemetry: this.config.telemetry
7369
+ telemetry: this.config.telemetry,
7370
+ retryPolicy: this.config.retryPolicy
7238
7371
  }));
7239
7372
  spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
7240
7373
  sql.initialize(spaceScopedContext);
@@ -7437,6 +7570,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7437
7570
  }
7438
7571
  };
7439
7572
  }
7573
+ if (result.status === "aad_mismatch") return { status: "read_failed" };
7440
7574
  return { status: result.status };
7441
7575
  }
7442
7576
  if (!isSecretPayload(result.entry.value)) {
@@ -7878,16 +8012,8 @@ var _TinyCloudNode = class _TinyCloudNode {
7878
8012
  * ```typescript
7879
8013
  * const delegations = alice.delegationManager;
7880
8014
  *
7881
- * // Create a delegation
7882
- * const result = await delegations.create({
7883
- * delegateDID: bob.did,
7884
- * path: "shared/",
7885
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
7886
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
7887
- * });
7888
- *
7889
- * // List delegations
7890
- * const listResult = await delegations.list();
8015
+ * // Query account delegations
8016
+ * const page = await delegations.query();
7891
8017
  *
7892
8018
  * // Revoke a delegation
7893
8019
  * await delegations.revoke(delegationCid);
@@ -7989,7 +8115,9 @@ var _TinyCloudNode = class _TinyCloudNode {
7989
8115
  * Ensure the user's public space exists and is accessible.
7990
8116
  * Creates the space and activates a session delegation for it.
7991
8117
  * This is the trigger for lazy public space creation — call it
7992
- * before writing to spaces.get('public').kv.
8118
+ * before writing to spaces.get('public').kv. The vault calls it on unlock.
8119
+ * Under `registryPolicy: "fail-closed"` creation goes through the
8120
+ * space-creation guard.
7993
8121
  */
7994
8122
  async ensurePublicSpace() {
7995
8123
  if (!this.auth || !this.session || !this.signer) {
@@ -7999,6 +8127,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7999
8127
  if (!publicSpaceId) {
8000
8128
  throw new Error("Public space not enabled. Set enablePublicSpace: true in config.");
8001
8129
  }
8130
+ await this.assertMayCreateSpace();
8002
8131
  await this.auth.hostPublicSpace(publicSpaceId);
8003
8132
  const kvActions = [KV3.PUT, KV3.GET, KV3.DEL, KV3.LIST, KV3.METADATA];
8004
8133
  const abilities = { kv: { "": kvActions } };
@@ -8056,7 +8185,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8056
8185
  invoke: this._serviceGraph.invoke,
8057
8186
  fetch: this._serviceGraph.fetch,
8058
8187
  hosts: this._serviceContext.hosts,
8059
- telemetry: this.config.telemetry
8188
+ telemetry: this.config.telemetry,
8189
+ retryPolicy: this.config.retryPolicy
8060
8190
  }));
8061
8191
  publicContext.setSession({
8062
8192
  delegationHeader: delegationSession.delegationHeader,
@@ -8085,32 +8215,6 @@ var _TinyCloudNode = class _TinyCloudNode {
8085
8215
  // ===========================================================================
8086
8216
  // v2 Delegation Convenience Methods
8087
8217
  // ===========================================================================
8088
- /**
8089
- * Create a delegation using the v2 DelegationManager.
8090
- *
8091
- * This is a convenience method that wraps DelegationManager.create().
8092
- * For more control, use `this.delegationManager` directly.
8093
- *
8094
- * @param params - Delegation parameters
8095
- * @returns Result containing the created Delegation
8096
- *
8097
- * @example
8098
- * ```typescript
8099
- * const result = await alice.delegate({
8100
- * delegateDID: bob.did,
8101
- * path: "shared/",
8102
- * actions: ["tinycloud.kv/get", "tinycloud.kv/put"],
8103
- * expiry: new Date(Date.now() + 24 * 60 * 60 * 1000),
8104
- * });
8105
- *
8106
- * if (result.ok) {
8107
- * console.log("Delegation created:", result.data.cid);
8108
- * }
8109
- * ```
8110
- */
8111
- async delegate(params) {
8112
- return this.delegationManager.create(params);
8113
- }
8114
8218
  /**
8115
8219
  * Revoke a delegation with the owner wallet when available. Session-only
8116
8220
  * clients continue to use their delegated revocation authority.
@@ -8136,14 +8240,6 @@ var _TinyCloudNode = class _TinyCloudNode {
8136
8240
  0x55n
8137
8241
  );
8138
8242
  }
8139
- /**
8140
- * List all delegations for the current session's space.
8141
- *
8142
- * @returns Result containing an array of Delegations
8143
- */
8144
- async listDelegations() {
8145
- return this.delegationManager.list();
8146
- }
8147
8243
  /**
8148
8244
  * Check if the current session has permission for a path and action.
8149
8245
  *
@@ -8203,6 +8299,9 @@ var _TinyCloudNode = class _TinyCloudNode {
8203
8299
  "delegateTo: onPrepared cannot be combined with forceWalletSign=true; the wallet-signed path activates the delegation before it could be handed to onPrepared."
8204
8300
  );
8205
8301
  }
8302
+ if (options?.disableSubDelegation && did.startsWith("did:pkh:")) {
8303
+ throw new Error(TERMINAL_DELEGATION_REQUIRES_SESSION_KEY);
8304
+ }
8206
8305
  const session = this.currentTinyCloudSession();
8207
8306
  if (!session) {
8208
8307
  throw new SessionExpiredError(/* @__PURE__ */ new Date(0));
@@ -8268,7 +8367,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8268
8367
  plan.grant,
8269
8368
  plan.operations,
8270
8369
  onPrepared,
8271
- options?.disableSubDelegation === true
8370
+ options?.disableSubDelegation === true,
8371
+ options?.requireActivation === true
8272
8372
  );
8273
8373
  return { delegation: delegation2, prompted: false };
8274
8374
  }
@@ -8278,7 +8378,8 @@ var _TinyCloudNode = class _TinyCloudNode {
8278
8378
  effectiveExpiration,
8279
8379
  session,
8280
8380
  onPrepared,
8281
- options?.disableSubDelegation === true
8381
+ options?.disableSubDelegation === true,
8382
+ options?.requireActivation === true
8282
8383
  );
8283
8384
  return { delegation, prompted: false };
8284
8385
  }
@@ -8509,7 +8610,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8509
8610
  *
8510
8611
  * @internal
8511
8612
  */
8512
- async createDelegationViaWasmPath(did, entries, expirationTime, session, onPrepared, disableSubDelegation = false) {
8613
+ async createDelegationViaWasmPath(did, entries, expirationTime, session, onPrepared, disableSubDelegation = false, requireActivation = false) {
8513
8614
  if (entries.length === 0) {
8514
8615
  throw new Error(
8515
8616
  "createDelegationViaWasmPath requires a non-empty entries array"
@@ -8593,15 +8694,10 @@ var _TinyCloudNode = class _TinyCloudNode {
8593
8694
  this.config.host,
8594
8695
  delegationHeader
8595
8696
  );
8596
- if (!activateResult.success) {
8597
- throw Object.assign(
8598
- new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
8599
- { cause: activateResult }
8600
- );
8601
- }
8697
+ assertDelegationActivated(activateResult, delegation, requireActivation);
8602
8698
  return delegation;
8603
8699
  }
8604
- async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations, onPrepared, disableSubDelegation = false) {
8700
+ async createDelegationViaRuntimeGrant(did, entries, expirationTime, grant, requestedOperations, onPrepared, disableSubDelegation = false, requireActivation = false) {
8605
8701
  this.assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant);
8606
8702
  this.assertDelegationCaveatsPreservable(entries);
8607
8703
  const result = this.createDelegationWrapper({
@@ -8635,12 +8731,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8635
8731
  targetHost,
8636
8732
  delegationHeader
8637
8733
  );
8638
- if (!activateResult.success) {
8639
- throw Object.assign(
8640
- new Error(`Failed to activate delegation with host: ${describeHostFailure2(activateResult)}`),
8641
- { cause: activateResult }
8642
- );
8643
- }
8734
+ assertDelegationActivated(activateResult, delegation, requireActivation);
8644
8735
  return delegation;
8645
8736
  }
8646
8737
  resolvePermissionSpace(space, session) {
@@ -9587,6 +9678,8 @@ var _TinyCloudNode = class _TinyCloudNode {
9587
9678
  };
9588
9679
  }
9589
9680
  };
9681
+ /** Set once per process: the registry sync was skipped for want of account access. */
9682
+ _TinyCloudNode.accountRegistrySkipLogged = false;
9590
9683
  // ===========================================================================
9591
9684
  // Capability-chain delegation (spec: .claude/specs/capability-chain.md)
9592
9685
  // ===========================================================================
@@ -9771,7 +9864,7 @@ export {
9771
9864
  resolveSecretPath3 as resolveSecretPath,
9772
9865
  resourceCapabilitiesToSpaceAbilitiesMap2 as resourceCapabilitiesToSpaceAbilitiesMap,
9773
9866
  serializeDelegation,
9774
- tinyCloudDebugLogger,
9867
+ tinyCloudDebugLogger2 as tinyCloudDebugLogger,
9775
9868
  validateManifest
9776
9869
  };
9777
9870
  //# sourceMappingURL=core.js.map