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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.cjs CHANGED
@@ -30,109 +30,124 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/core.ts
31
31
  var core_exports = {};
32
32
  __export(core_exports, {
33
- ACCOUNT_REGISTRY_PATH: () => import_sdk_core12.ACCOUNT_REGISTRY_PATH,
34
- ACCOUNT_REGISTRY_SPACE: () => import_sdk_core12.ACCOUNT_REGISTRY_SPACE,
35
- AccountService: () => import_sdk_core5.AccountService,
36
- AutoApproveSpaceCreationHandler: () => import_sdk_core11.AutoApproveSpaceCreationHandler,
37
- CapabilityKeyRegistry: () => import_sdk_core18.CapabilityKeyRegistry,
38
- CapabilityKeyRegistryErrorCodes: () => import_sdk_core18.CapabilityKeyRegistryErrorCodes,
39
- CaveatedDelegationUnsupportedError: () => import_sdk_core12.CaveatedDelegationUnsupportedError,
40
- DEFAULT_MANIFEST_SPACE: () => import_sdk_core12.DEFAULT_MANIFEST_SPACE,
41
- DEFAULT_MANIFEST_VERSION: () => import_sdk_core12.DEFAULT_MANIFEST_VERSION,
42
- DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => import_sdk_core13.DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
43
- DataVaultService: () => import_sdk_core16.DataVaultService,
44
- DatabaseHandle: () => import_sdk_core14.DatabaseHandle,
33
+ ACCOUNT_REGISTRY_PATH: () => import_sdk_core13.ACCOUNT_REGISTRY_PATH,
34
+ ACCOUNT_REGISTRY_SPACE: () => import_sdk_core13.ACCOUNT_REGISTRY_SPACE,
35
+ AccountService: () => import_sdk_core6.AccountService,
36
+ AutoApproveSpaceCreationHandler: () => import_sdk_core12.AutoApproveSpaceCreationHandler,
37
+ CapabilityKeyRegistry: () => import_sdk_core19.CapabilityKeyRegistry,
38
+ CapabilityKeyRegistryErrorCodes: () => import_sdk_core19.CapabilityKeyRegistryErrorCodes,
39
+ CaveatedDelegationUnsupportedError: () => import_sdk_core13.CaveatedDelegationUnsupportedError,
40
+ DEFAULT_MANIFEST_SPACE: () => import_sdk_core13.DEFAULT_MANIFEST_SPACE,
41
+ DEFAULT_MANIFEST_VERSION: () => import_sdk_core13.DEFAULT_MANIFEST_VERSION,
42
+ DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => import_sdk_core14.DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
43
+ DataVaultService: () => import_sdk_core17.DataVaultService,
44
+ DatabaseHandle: () => import_sdk_core15.DatabaseHandle,
45
45
  DelegatedAccess: () => DelegatedAccess,
46
- DelegationErrorCodes: () => import_sdk_core17.DelegationErrorCodes,
47
- DelegationManager: () => import_sdk_core17.DelegationManager,
48
- DuckDbAction: () => import_sdk_core15.DuckDbAction,
49
- DuckDbDatabaseHandle: () => import_sdk_core15.DuckDbDatabaseHandle,
50
- DuckDbService: () => import_sdk_core15.DuckDbService,
46
+ DelegationErrorCodes: () => import_sdk_core18.DelegationErrorCodes,
47
+ DelegationManager: () => import_sdk_core18.DelegationManager,
48
+ DuckDbAction: () => import_sdk_core16.DuckDbAction,
49
+ DuckDbDatabaseHandle: () => import_sdk_core16.DuckDbDatabaseHandle,
50
+ DuckDbService: () => import_sdk_core16.DuckDbService,
51
51
  FileSessionStorage: () => FileSessionStorage,
52
- IdentityParseError: () => import_sdk_core11.IdentityParseError,
52
+ IdentityParseError: () => import_sdk_core12.IdentityParseError,
53
53
  InvalidRestoredSessionError: () => InvalidRestoredSessionError,
54
- KVService: () => import_sdk_core13.KVService,
55
- ManifestValidationError: () => import_sdk_core12.ManifestValidationError,
54
+ KVService: () => import_sdk_core14.KVService,
55
+ ManifestValidationError: () => import_sdk_core13.ManifestValidationError,
56
56
  MemorySessionStorage: () => MemorySessionStorage,
57
57
  NodeUserAuthorization: () => NodeUserAuthorization,
58
- PermissionNotInManifestError: () => import_sdk_core12.PermissionNotInManifestError,
59
- PrefixedKVService: () => import_sdk_core13.PrefixedKVService,
60
- ProtocolMismatchError: () => import_sdk_core20.ProtocolMismatchError,
61
- SECRET_NAME_RE: () => import_sdk_core16.SECRET_NAME_RE,
62
- SQLAction: () => import_sdk_core14.SQLAction,
63
- SQLService: () => import_sdk_core14.SQLService,
64
- SecretsService: () => import_sdk_core16.SecretsService,
65
- ServiceContext: () => import_sdk_core21.ServiceContext,
66
- SessionExpiredError: () => import_sdk_core12.SessionExpiredError,
67
- SharingService: () => import_sdk_core17.SharingService,
68
- SilentNotificationHandler: () => import_sdk_core11.SilentNotificationHandler,
69
- Space: () => import_sdk_core19.Space,
70
- SpaceErrorCodes: () => import_sdk_core19.SpaceErrorCodes,
71
- SpaceService: () => import_sdk_core19.SpaceService,
72
- TinyCloud: () => import_sdk_core10.TinyCloud,
73
- TinyCloudDebugLogger: () => import_sdk_core11.TinyCloudDebugLogger,
58
+ PermissionNotInManifestError: () => import_sdk_core13.PermissionNotInManifestError,
59
+ PrefixedKVService: () => import_sdk_core14.PrefixedKVService,
60
+ ProtocolMismatchError: () => import_sdk_core21.ProtocolMismatchError,
61
+ SECRET_NAME_RE: () => import_sdk_core17.SECRET_NAME_RE,
62
+ SQLAction: () => import_sdk_core15.SQLAction,
63
+ SQLService: () => import_sdk_core15.SQLService,
64
+ SecretsService: () => import_sdk_core17.SecretsService,
65
+ ServiceContext: () => import_sdk_core22.ServiceContext,
66
+ SessionExpiredError: () => import_sdk_core13.SessionExpiredError,
67
+ SharingService: () => import_sdk_core18.SharingService,
68
+ SilentNotificationHandler: () => import_sdk_core12.SilentNotificationHandler,
69
+ Space: () => import_sdk_core20.Space,
70
+ SpaceErrorCodes: () => import_sdk_core20.SpaceErrorCodes,
71
+ SpaceService: () => import_sdk_core20.SpaceService,
72
+ TinyCloud: () => import_sdk_core11.TinyCloud,
73
+ TinyCloudDebugLogger: () => import_sdk_core12.TinyCloudDebugLogger,
74
74
  TinyCloudNode: () => TinyCloudNode,
75
- UnsupportedFeatureError: () => import_sdk_core20.UnsupportedFeatureError,
75
+ UnsupportedFeatureError: () => import_sdk_core21.UnsupportedFeatureError,
76
76
  UnsupportedSessionRestoreError: () => UnsupportedSessionRestoreError,
77
- VAULT_PERMISSION_SERVICE: () => import_sdk_core12.VAULT_PERMISSION_SERVICE,
78
- VaultHeaders: () => import_sdk_core16.VaultHeaders,
79
- VaultPublicSpaceKVActions: () => import_sdk_core16.VaultPublicSpaceKVActions,
80
- VersionCheckError: () => import_sdk_core20.VersionCheckError,
77
+ VAULT_PERMISSION_SERVICE: () => import_sdk_core13.VAULT_PERMISSION_SERVICE,
78
+ VaultHeaders: () => import_sdk_core17.VaultHeaders,
79
+ VaultPublicSpaceKVActions: () => import_sdk_core17.VaultPublicSpaceKVActions,
80
+ VersionCheckError: () => import_sdk_core21.VersionCheckError,
81
81
  WasmKeyProvider: () => WasmKeyProvider,
82
82
  activateCompactRuntimeDelegation: () => activateCompactRuntimeDelegation,
83
- addressStorageKey: () => import_sdk_core11.addressStorageKey,
84
- buildSpaceUri: () => import_sdk_core19.buildSpaceUri,
85
- canonicalizeAddress: () => import_sdk_core11.canonicalizeAddress,
86
- canonicalizeDid: () => import_sdk_core11.canonicalizeDid,
87
- canonicalizeDidUrl: () => import_sdk_core11.canonicalizeDidUrl,
88
- canonicalizeNetworkId: () => import_sdk_core11.canonicalizeNetworkId,
89
- canonicalizeSecretScope: () => import_sdk_core16.canonicalizeSecretScope,
90
- checkNodeInfo: () => import_sdk_core20.checkNodeInfo,
91
- clearTinyCloudDebugLogs: () => import_sdk_core11.clearTinyCloudDebugLogs,
92
- composeManifestRequest: () => import_sdk_core12.composeManifestRequest,
93
- createCapabilityKeyRegistry: () => import_sdk_core18.createCapabilityKeyRegistry,
94
- createOpenKeyCallbackSigningStrategy: () => import_sdk_core2.createOpenKeyCallbackSigningStrategy,
95
- createSharingService: () => import_sdk_core17.createSharingService,
96
- createSpaceService: () => import_sdk_core19.createSpaceService,
97
- createVaultCrypto: () => import_sdk_core16.createVaultCrypto,
83
+ addressStorageKey: () => import_sdk_core12.addressStorageKey,
84
+ buildSpaceUri: () => import_sdk_core20.buildSpaceUri,
85
+ canonicalizeAddress: () => import_sdk_core12.canonicalizeAddress,
86
+ canonicalizeDid: () => import_sdk_core12.canonicalizeDid,
87
+ canonicalizeDidUrl: () => import_sdk_core12.canonicalizeDidUrl,
88
+ canonicalizeNetworkId: () => import_sdk_core12.canonicalizeNetworkId,
89
+ canonicalizeSecretScope: () => import_sdk_core17.canonicalizeSecretScope,
90
+ checkNodeInfo: () => import_sdk_core21.checkNodeInfo,
91
+ clearTinyCloudDebugLogs: () => import_sdk_core12.clearTinyCloudDebugLogs,
92
+ composeManifestRequest: () => import_sdk_core13.composeManifestRequest,
93
+ createCapabilityKeyRegistry: () => import_sdk_core19.createCapabilityKeyRegistry,
94
+ createOpenKeyCallbackSigningStrategy: () => import_sdk_core3.createOpenKeyCallbackSigningStrategy,
95
+ createSharingService: () => import_sdk_core18.createSharingService,
96
+ createSpaceService: () => import_sdk_core20.createSpaceService,
97
+ createVaultCrypto: () => import_sdk_core17.createVaultCrypto,
98
98
  createWasmKeyProvider: () => createWasmKeyProvider,
99
99
  defaultSignStrategy: () => defaultSignStrategy,
100
- defaultSpaceCreationHandler: () => import_sdk_core11.defaultSpaceCreationHandler,
100
+ defaultSpaceCreationHandler: () => import_sdk_core12.defaultSpaceCreationHandler,
101
101
  deserializeDelegation: () => deserializeDelegation,
102
- didCacheKey: () => import_sdk_core11.didCacheKey,
103
- didEquals: () => import_sdk_core11.didEquals,
104
- disableTinyCloudDebug: () => import_sdk_core11.disableTinyCloudDebug,
105
- enableTinyCloudDebug: () => import_sdk_core11.enableTinyCloudDebug,
106
- expandActionShortNames: () => import_sdk_core12.expandActionShortNames,
107
- expandPermissionEntries: () => import_sdk_core12.expandPermissionEntries,
108
- expandPermissionEntry: () => import_sdk_core12.expandPermissionEntry,
109
- getTinyCloudDebugLogs: () => import_sdk_core11.getTinyCloudDebugLogs,
110
- installTinyCloudDebugGlobals: () => import_sdk_core11.installTinyCloudDebugGlobals,
111
- isCapabilitySubset: () => import_sdk_core12.isCapabilitySubset,
112
- isEvmAddress: () => import_sdk_core11.isEvmAddress,
113
- loadManifest: () => import_sdk_core12.loadManifest,
114
- makePkhSpaceId: () => import_sdk_core11.makePkhSpaceId,
115
- makePublicSpaceId: () => import_sdk_core19.makePublicSpaceId,
116
- parseCanonicalNetworkId: () => import_sdk_core11.parseCanonicalNetworkId,
117
- parseExpiry: () => import_sdk_core12.parseExpiry,
118
- parsePkhDid: () => import_sdk_core11.parsePkhDid,
119
- parseSecretCatalogKey: () => import_sdk_core16.parseSecretCatalogKey,
120
- parseSpaceUri: () => import_sdk_core19.parseSpaceUri,
121
- pkhDid: () => import_sdk_core11.pkhDid,
122
- principalDid: () => import_sdk_core11.principalDid,
123
- principalDidEquals: () => import_sdk_core11.principalDidEquals,
124
- resolveManifest: () => import_sdk_core12.resolveManifest,
125
- resolveSecretListPrefix: () => import_sdk_core16.resolveSecretListPrefix,
126
- resolveSecretPath: () => import_sdk_core16.resolveSecretPath,
127
- resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core12.resourceCapabilitiesToSpaceAbilitiesMap,
102
+ didCacheKey: () => import_sdk_core12.didCacheKey,
103
+ didEquals: () => import_sdk_core12.didEquals,
104
+ disableTinyCloudDebug: () => import_sdk_core12.disableTinyCloudDebug,
105
+ enableTinyCloudDebug: () => import_sdk_core12.enableTinyCloudDebug,
106
+ expandActionShortNames: () => import_sdk_core13.expandActionShortNames,
107
+ expandPermissionEntries: () => import_sdk_core13.expandPermissionEntries,
108
+ expandPermissionEntry: () => import_sdk_core13.expandPermissionEntry,
109
+ getTinyCloudDebugLogs: () => import_sdk_core12.getTinyCloudDebugLogs,
110
+ installTinyCloudDebugGlobals: () => import_sdk_core12.installTinyCloudDebugGlobals,
111
+ isCapabilitySubset: () => import_sdk_core13.isCapabilitySubset,
112
+ isEvmAddress: () => import_sdk_core12.isEvmAddress,
113
+ loadManifest: () => import_sdk_core13.loadManifest,
114
+ makePkhSpaceId: () => import_sdk_core12.makePkhSpaceId,
115
+ makePublicSpaceId: () => import_sdk_core20.makePublicSpaceId,
116
+ parseCanonicalNetworkId: () => import_sdk_core12.parseCanonicalNetworkId,
117
+ parseExpiry: () => import_sdk_core13.parseExpiry,
118
+ parsePkhDid: () => import_sdk_core12.parsePkhDid,
119
+ parseSecretCatalogKey: () => import_sdk_core17.parseSecretCatalogKey,
120
+ parseSpaceUri: () => import_sdk_core20.parseSpaceUri,
121
+ pkhDid: () => import_sdk_core12.pkhDid,
122
+ principalDid: () => import_sdk_core12.principalDid,
123
+ principalDidEquals: () => import_sdk_core12.principalDidEquals,
124
+ registerReplicationLoaders: () => registerReplicationLoaders,
125
+ resolveManifest: () => import_sdk_core13.resolveManifest,
126
+ resolveSecretListPrefix: () => import_sdk_core17.resolveSecretListPrefix,
127
+ resolveSecretPath: () => import_sdk_core17.resolveSecretPath,
128
+ resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core13.resourceCapabilitiesToSpaceAbilitiesMap,
128
129
  serializeDelegation: () => serializeDelegation,
129
- tinyCloudDebugLogger: () => import_sdk_core11.tinyCloudDebugLogger,
130
- validateManifest: () => import_sdk_core12.validateManifest
130
+ tinyCloudDebugLogger: () => import_sdk_core12.tinyCloudDebugLogger,
131
+ validateManifest: () => import_sdk_core13.validateManifest
131
132
  });
132
133
  module.exports = __toCommonJS(core_exports);
133
- var import_sdk_core10 = require("@tinycloud/sdk-core");
134
134
  var import_sdk_core11 = require("@tinycloud/sdk-core");
135
135
 
136
+ // src/replication/module-registry.ts
137
+ var nodeLoaders;
138
+ function registerReplicationLoaders(loaders) {
139
+ nodeLoaders = loaders;
140
+ }
141
+ function getNodeReplicationLoaders() {
142
+ if (nodeLoaders === void 0) {
143
+ throw new Error("Replication requires registering replication controller loaders.");
144
+ }
145
+ return nodeLoaders;
146
+ }
147
+
148
+ // src/core.ts
149
+ var import_sdk_core12 = require("@tinycloud/sdk-core");
150
+
136
151
  // src/storage/MemorySessionStorage.ts
137
152
  var MemorySessionStorage = class {
138
153
  constructor() {
@@ -327,15 +342,51 @@ var FileSessionStorage = class {
327
342
  // src/authorization/NodeUserAuthorization.ts
328
343
  var import_node_crypto = require("crypto");
329
344
  var import_siwe = require("siwe");
330
- var import_sdk_core3 = require("@tinycloud/sdk-core");
345
+ var import_sdk_core4 = require("@tinycloud/sdk-core");
331
346
 
332
- // src/authorization/strategies.ts
347
+ // src/replication/authority-sign-in.ts
333
348
  var import_sdk_core2 = require("@tinycloud/sdk-core");
349
+ var import_sdk_services = require("@tinycloud/sdk-services");
350
+ var KV_GET = import_sdk_core2.KV.GET;
351
+ var KV_SYNC = import_sdk_core2.KV.SYNC;
352
+ var KV_SERVICE = "tinycloud.kv";
353
+ function hasUnrestrictedGetCoverage(entries, spaceId, prefix) {
354
+ const requiredPaths = (0, import_sdk_core2.grantPathsForSelector)(prefix);
355
+ return (0, import_sdk_core2.isCapabilitySubset)(
356
+ requiredPaths.map((path) => ({ service: KV_SERVICE, space: spaceId, path, actions: [KV_GET] })),
357
+ [...entries]
358
+ ).subset;
359
+ }
360
+ function augmentSignInEntriesWithReplication(input) {
361
+ const out = [];
362
+ const replication = input.replication;
363
+ if (replication === void 0) return out;
364
+ for (const prefix of replication.prefixes) {
365
+ if ((0, import_sdk_services.requiresSecretsOptIn)(input.primarySpaceId, prefix) && replication.allowSecrets !== true) {
366
+ continue;
367
+ }
368
+ if (!hasUnrestrictedGetCoverage(input.entries, input.primarySpaceId, prefix)) {
369
+ continue;
370
+ }
371
+ for (const path of (0, import_sdk_core2.grantPathsForSelector)(prefix)) {
372
+ out.push({
373
+ service: KV_SERVICE,
374
+ space: input.primarySpaceId,
375
+ path,
376
+ actions: [KV_GET, KV_SYNC]
377
+ });
378
+ }
379
+ }
380
+ return out;
381
+ }
382
+
383
+ // src/authorization/strategies.ts
384
+ var import_sdk_core3 = require("@tinycloud/sdk-core");
334
385
  var defaultSignStrategy = { type: "auto-sign" };
335
386
 
336
387
  // src/authorization/NodeUserAuthorization.ts
337
- var DECRYPT_ACTION = import_sdk_core3.ENCRYPTION.DECRYPT;
338
- var NETWORK_CREATE_ACTION = import_sdk_core3.ENCRYPTION.NETWORK_CREATE;
388
+ var DECRYPT_ACTION = import_sdk_core4.ENCRYPTION.DECRYPT;
389
+ var NETWORK_CREATE_ACTION = import_sdk_core4.ENCRYPTION.NETWORK_CREATE;
339
390
  function describeHostFailure(result) {
340
391
  const text = result.error?.trim();
341
392
  return text ? `${result.status} - ${text}` : `${result.status}`;
@@ -363,7 +414,7 @@ function canonicalOpenKeyManifestSha256Hex(value) {
363
414
  }
364
415
  function didPrincipalMatches(actual, expected) {
365
416
  try {
366
- return (0, import_sdk_core3.principalDidEquals)(actual, expected);
417
+ return (0, import_sdk_core4.principalDidEquals)(actual, expected);
367
418
  } catch {
368
419
  return actual === expected;
369
420
  }
@@ -404,30 +455,30 @@ var NodeUserAuthorization = class {
404
455
  this.spacePrefix = config.spacePrefix ?? "default";
405
456
  this.defaultActions = config.defaultActions ?? {
406
457
  kv: {
407
- "": [import_sdk_core3.KV.PUT, import_sdk_core3.KV.GET, import_sdk_core3.KV.DEL, import_sdk_core3.KV.LIST, import_sdk_core3.KV.METADATA]
458
+ "": [import_sdk_core4.KV.PUT, import_sdk_core4.KV.GET, import_sdk_core4.KV.DEL, import_sdk_core4.KV.LIST, import_sdk_core4.KV.METADATA]
408
459
  },
409
460
  sql: {
410
- "": [import_sdk_core3.SQL.READ, import_sdk_core3.SQL.WRITE, import_sdk_core3.SQL.SCHEMA, import_sdk_core3.SQL.ADMIN, import_sdk_core3.SQL.EXPORT]
461
+ "": [import_sdk_core4.SQL.READ, import_sdk_core4.SQL.WRITE, import_sdk_core4.SQL.SCHEMA, import_sdk_core4.SQL.ADMIN, import_sdk_core4.SQL.EXPORT]
411
462
  },
412
463
  duckdb: {
413
464
  "": [
414
- import_sdk_core3.DUCKDB.READ,
415
- import_sdk_core3.DUCKDB.WRITE,
416
- import_sdk_core3.DUCKDB.ADMIN,
417
- import_sdk_core3.DUCKDB.DESCRIBE,
418
- import_sdk_core3.DUCKDB.EXPORT,
419
- import_sdk_core3.DUCKDB.IMPORT,
420
- import_sdk_core3.DUCKDB.EXECUTE
465
+ import_sdk_core4.DUCKDB.READ,
466
+ import_sdk_core4.DUCKDB.WRITE,
467
+ import_sdk_core4.DUCKDB.ADMIN,
468
+ import_sdk_core4.DUCKDB.DESCRIBE,
469
+ import_sdk_core4.DUCKDB.EXPORT,
470
+ import_sdk_core4.DUCKDB.IMPORT,
471
+ import_sdk_core4.DUCKDB.EXECUTE
421
472
  ]
422
473
  },
423
474
  capabilities: {
424
- "": [import_sdk_core3.CAPABILITIES.READ]
475
+ "": [import_sdk_core4.CAPABILITIES.READ]
425
476
  },
426
477
  hooks: {
427
- "": [import_sdk_core3.HOOKS.SUBSCRIBE, import_sdk_core3.HOOKS.REGISTER, import_sdk_core3.HOOKS.LIST, import_sdk_core3.HOOKS.UNREGISTER]
478
+ "": [import_sdk_core4.HOOKS.SUBSCRIBE, import_sdk_core4.HOOKS.REGISTER, import_sdk_core4.HOOKS.LIST, import_sdk_core4.HOOKS.UNREGISTER]
428
479
  }
429
480
  };
430
- this.sessionExpirationMs = config.sessionExpirationMs ?? import_sdk_core3.EXPIRY.SESSION_MS;
481
+ this.sessionExpirationMs = config.sessionExpirationMs ?? import_sdk_core4.EXPIRY.SESSION_MS;
431
482
  this.autoCreateSpace = config.autoCreateSpace ?? false;
432
483
  this.spaceCreationHandler = config.spaceCreationHandler;
433
484
  this.tinycloudHosts = config.tinycloudHosts;
@@ -442,6 +493,7 @@ var NodeUserAuthorization = class {
442
493
  this.nonce = config.nonce;
443
494
  this.siweConfig = config.siweConfig;
444
495
  this.includeAccountRegistryPermissions = config.includeAccountRegistryPermissions ?? true;
496
+ this.replication = config.replication?.enabled === true ? config.replication : void 0;
445
497
  this._manifest = config.manifest;
446
498
  this._capabilityRequest = config.capabilityRequest;
447
499
  this.sessionManager = config.sessionManager ?? this.wasm.createSessionManager();
@@ -506,7 +558,7 @@ var NodeUserAuthorization = class {
506
558
  * {@link ensureTinyCloudHosts}.
507
559
  */
508
560
  setRestoredTinyCloudSession(session, hosts) {
509
- const address = (0, import_sdk_core3.canonicalizeAddress)(session.address);
561
+ const address = (0, import_sdk_core4.canonicalizeAddress)(session.address);
510
562
  this._tinyCloudSession = { ...session, address };
511
563
  this._address = address;
512
564
  this._chainId = session.chainId;
@@ -567,8 +619,8 @@ var NodeUserAuthorization = class {
567
619
  if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
568
620
  return;
569
621
  }
570
- const subject = (0, import_sdk_core3.pkhDid)(address, chainId);
571
- const resolved = await (0, import_sdk_core3.resolveTinyCloudHosts)(subject, {
622
+ const subject = (0, import_sdk_core4.pkhDid)(address, chainId);
623
+ const resolved = await (0, import_sdk_core4.resolveTinyCloudHosts)(subject, {
572
624
  registryUrl: this.tinycloudRegistryUrl,
573
625
  fallbackHosts: this.tinycloudFallbackHosts,
574
626
  autoDiscoverLocalNode: this.autoDiscoverLocalNode,
@@ -636,7 +688,7 @@ var NodeUserAuthorization = class {
636
688
  if (this._manifest === void 0) {
637
689
  return void 0;
638
690
  }
639
- this._capabilityRequest = (0, import_sdk_core3.composeManifestRequest)(
691
+ this._capabilityRequest = (0, import_sdk_core4.composeManifestRequest)(
640
692
  Array.isArray(this._manifest) ? this._manifest : [this._manifest],
641
693
  {
642
694
  includeAccountRegistryPermissions: this.includeAccountRegistryPermissions
@@ -648,50 +700,173 @@ var NodeUserAuthorization = class {
648
700
  if (space.startsWith("tinycloud:")) {
649
701
  return space;
650
702
  }
651
- return (0, import_sdk_core3.makePkhSpaceId)(address, chainId, space);
703
+ return (0, import_sdk_core4.makePkhSpaceId)(address, chainId, space);
704
+ }
705
+ /**
706
+ * The plain-session primary abilities: `defaultActions` (the shared table)
707
+ * unless the primary space IS the account space, where account-registry
708
+ * permissions merge into a private clone so the shared table is never
709
+ * mutated. Shared between `resolveSignInCapabilities` and
710
+ * `signInPermissionInputs` so sign-in and `replicationSignInEntries`
711
+ * can't disagree (§4.6).
712
+ */
713
+ primaryActionsForSignIn() {
714
+ const primaryActions = this.includeAccountRegistryPermissions && this.spacePrefix === import_sdk_core4.ACCOUNT_REGISTRY_SPACE ? cloneAbilitiesMap(this.defaultActions) : this.defaultActions;
715
+ if (this.includeAccountRegistryPermissions && this.spacePrefix === import_sdk_core4.ACCOUNT_REGISTRY_SPACE) {
716
+ const accountAbilities = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(
717
+ import_sdk_core4.ACCOUNT_MANIFEST_PERMISSIONS
718
+ );
719
+ for (const [service, paths] of Object.entries(accountAbilities)) {
720
+ const existingPaths = primaryActions[service] ?? (primaryActions[service] = {});
721
+ for (const [path, actions] of Object.entries(paths)) {
722
+ const existingActions = existingPaths[path] ?? (existingPaths[path] = []);
723
+ for (const action of actions) {
724
+ if (!existingActions.includes(action)) existingActions.push(action);
725
+ }
726
+ }
727
+ }
728
+ }
729
+ return primaryActions;
730
+ }
731
+ /**
732
+ * The abilities a `spacePrefix: "secrets"` plain session actually requests
733
+ * for its primary space: the vault-secrets subtree only — the
734
+ * `defaultActions` root `get` is REPLACED, not merged (sign-in installs
735
+ * this map under the primary space id). Shared between
736
+ * `resolveSignInCapabilities` and `signInPermissionInputs` so the
737
+ * replication augmentation measures coverage against the effective
738
+ * pre-replication request, never the uninstalled `primaryActions` (§4.1).
739
+ */
740
+ secretsPrimaryAbilities() {
741
+ return {
742
+ kv: {
743
+ "vault/secrets/": [
744
+ import_sdk_core4.KV.GET,
745
+ import_sdk_core4.KV.PUT,
746
+ import_sdk_core4.KV.DEL,
747
+ import_sdk_core4.KV.LIST,
748
+ import_sdk_core4.KV.METADATA
749
+ ]
750
+ }
751
+ };
752
+ }
753
+ /**
754
+ * The effective sign-in request as `PermissionEntry`s plus the resolved
755
+ * primary space id — the inputs to the replication augmentation (§4.1).
756
+ * `resolveSignInCapabilities` merges the augmented entries into its
757
+ * abilities; `replicationSignInEntries()` returns them verbatim, so the
758
+ * entries the SIWE recap carries and the restore check sees are the same.
759
+ */
760
+ signInPermissionInputs(address, chainId) {
761
+ const request = this.getCapabilityRequest();
762
+ if (request === void 0) {
763
+ const primarySpaceId2 = (0, import_sdk_core4.makePkhSpaceId)(address, chainId, this.spacePrefix);
764
+ const effectivePrimary = this.spacePrefix === "secrets" ? this.secretsPrimaryAbilities() : this.primaryActionsForSignIn();
765
+ const kvPaths = effectivePrimary["kv"] ?? {};
766
+ return {
767
+ primarySpaceId: primarySpaceId2,
768
+ entries: Object.entries(kvPaths).map(([path, actions]) => ({
769
+ service: "tinycloud.kv",
770
+ space: primarySpaceId2,
771
+ path,
772
+ actions: [...actions]
773
+ }))
774
+ };
775
+ }
776
+ const spaceResources = request.resources.filter(
777
+ (entry) => entry.service !== import_sdk_core4.ENCRYPTION_PERMISSION_SERVICE
778
+ );
779
+ const primarySpaceName = spaceResources.find((entry) => entry.space !== "account")?.space ?? import_sdk_core4.DEFAULT_MANIFEST_SPACE;
780
+ const primarySpaceId = this.resolveSpaceName(
781
+ primarySpaceName,
782
+ address,
783
+ chainId
784
+ );
785
+ return {
786
+ primarySpaceId,
787
+ entries: spaceResources.map((entry) => ({
788
+ service: entry.service,
789
+ space: this.resolveSpaceName(entry.space, address, chainId),
790
+ path: entry.path,
791
+ actions: [...entry.actions]
792
+ }))
793
+ };
794
+ }
795
+ /**
796
+ * Merge replication augmentation entries into a space's abilities map
797
+ * without mutating shared tables (`defaultActions` may back the base map):
798
+ * the primary entry in `spaceAbilities` is replaced with a copy whose `kv`
799
+ * paths gain `get`/`sync`. Returns the merged map for `abilities`.
800
+ */
801
+ mergeReplicationEntries(spaceAbilities, primarySpaceId, abilities, entries) {
802
+ var _a;
803
+ if (entries.length === 0) {
804
+ return abilities;
805
+ }
806
+ const base = spaceAbilities[primarySpaceId] ?? abilities;
807
+ const kv = {};
808
+ for (const [path, actions] of Object.entries(base["kv"] ?? {})) {
809
+ kv[path] = [...actions];
810
+ }
811
+ for (const entry of entries) {
812
+ const list = kv[_a = entry.path] ?? (kv[_a] = []);
813
+ for (const action of entry.actions) {
814
+ if (!list.includes(action)) list.push(action);
815
+ }
816
+ }
817
+ const merged = { ...base, kv };
818
+ spaceAbilities[primarySpaceId] = merged;
819
+ return merged;
820
+ }
821
+ /**
822
+ * The replication entries this authorization's sign-in request carries
823
+ * for the signed-in or restored address (TC-858 §4.1/§4.6): the output of
824
+ * the same augmentation `resolveSignInCapabilities` runs — one
825
+ * `{tinycloud.kv, primarySpace, prefix, [get, sync]}` per configured
826
+ * prefix that already has an unrestricted covering `get` and passes the
827
+ * secrets opt-in gate. Empty when replication is off or no address is
828
+ * known. Pure.
829
+ */
830
+ replicationSignInEntries() {
831
+ if (this.replication === void 0) return [];
832
+ const address = this._address ?? this._tinyCloudSession?.address;
833
+ const chainId = this._chainId ?? this._tinyCloudSession?.chainId;
834
+ if (address === void 0 || chainId === void 0) return [];
835
+ const { entries, primarySpaceId } = this.signInPermissionInputs(address, chainId);
836
+ return augmentSignInEntriesWithReplication({
837
+ entries,
838
+ primarySpaceId,
839
+ replication: this.replication
840
+ });
652
841
  }
653
842
  defaultEncryptionNetworkId(address, chainId) {
654
- return `urn:tinycloud:encryption:${(0, import_sdk_core3.pkhDid)(address, chainId)}:default`;
843
+ return `urn:tinycloud:encryption:${(0, import_sdk_core4.pkhDid)(address, chainId)}:default`;
655
844
  }
656
845
  resolveSignInCapabilities(address, chainId) {
657
846
  const request = this.getCapabilityRequest();
658
847
  if (request === void 0) {
659
848
  const defaultNetworkId = this.defaultEncryptionNetworkId(address, chainId);
660
- const primarySpaceId2 = (0, import_sdk_core3.makePkhSpaceId)(address, chainId, this.spacePrefix);
661
- const secretsSpaceId = (0, import_sdk_core3.makePkhSpaceId)(address, chainId, "secrets");
662
- const primaryActions = this.includeAccountRegistryPermissions && this.spacePrefix === import_sdk_core3.ACCOUNT_REGISTRY_SPACE ? cloneAbilitiesMap(this.defaultActions) : this.defaultActions;
849
+ const primarySpaceId2 = (0, import_sdk_core4.makePkhSpaceId)(address, chainId, this.spacePrefix);
850
+ const secretsSpaceId = (0, import_sdk_core4.makePkhSpaceId)(address, chainId, "secrets");
851
+ const primaryActions = this.primaryActionsForSignIn();
663
852
  const spaceAbilities2 = {
664
853
  [primarySpaceId2]: primaryActions,
665
- [secretsSpaceId]: {
666
- kv: {
667
- "vault/secrets/": [
668
- import_sdk_core3.KV.GET,
669
- import_sdk_core3.KV.PUT,
670
- import_sdk_core3.KV.DEL,
671
- import_sdk_core3.KV.LIST,
672
- import_sdk_core3.KV.METADATA
673
- ]
674
- }
675
- }
854
+ [secretsSpaceId]: this.secretsPrimaryAbilities()
676
855
  };
677
- if (this.includeAccountRegistryPermissions && this.spacePrefix !== import_sdk_core3.ACCOUNT_REGISTRY_SPACE) {
678
- spaceAbilities2[(0, import_sdk_core3.makePkhSpaceId)(address, chainId, import_sdk_core3.ACCOUNT_REGISTRY_SPACE)] = (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)(import_sdk_core3.ACCOUNT_MANIFEST_PERMISSIONS);
679
- } else if (this.includeAccountRegistryPermissions) {
680
- const accountAbilities = (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)(
681
- import_sdk_core3.ACCOUNT_MANIFEST_PERMISSIONS
682
- );
683
- for (const [service, paths] of Object.entries(accountAbilities)) {
684
- const existingPaths = primaryActions[service] ?? (primaryActions[service] = {});
685
- for (const [path, actions] of Object.entries(paths)) {
686
- const existingActions = existingPaths[path] ?? (existingPaths[path] = []);
687
- for (const action of actions) {
688
- if (!existingActions.includes(action)) existingActions.push(action);
689
- }
690
- }
691
- }
692
- }
856
+ if (this.includeAccountRegistryPermissions && this.spacePrefix !== import_sdk_core4.ACCOUNT_REGISTRY_SPACE) {
857
+ spaceAbilities2[(0, import_sdk_core4.makePkhSpaceId)(address, chainId, import_sdk_core4.ACCOUNT_REGISTRY_SPACE)] = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(import_sdk_core4.ACCOUNT_MANIFEST_PERMISSIONS);
858
+ }
859
+ const mergedPrimary = this.mergeReplicationEntries(
860
+ spaceAbilities2,
861
+ primarySpaceId2,
862
+ primaryActions,
863
+ augmentSignInEntriesWithReplication({
864
+ ...this.signInPermissionInputs(address, chainId),
865
+ replication: this.replication
866
+ })
867
+ );
693
868
  return {
694
- abilities: primaryActions,
869
+ abilities: mergedPrimary,
695
870
  spaceId: primarySpaceId2,
696
871
  spaceAbilities: spaceAbilities2,
697
872
  rawAbilities: {
@@ -700,35 +875,44 @@ var NodeUserAuthorization = class {
700
875
  };
701
876
  }
702
877
  const rawAbilities = {};
703
- const currentDid = (0, import_sdk_core3.pkhDid)(address, chainId);
878
+ const currentDid = (0, import_sdk_core4.pkhDid)(address, chainId);
704
879
  const spaceResources = request.resources.filter((entry) => {
705
- if (entry.service !== import_sdk_core3.ENCRYPTION_PERMISSION_SERVICE) {
880
+ if (entry.service !== import_sdk_core4.ENCRYPTION_PERMISSION_SERVICE) {
706
881
  return true;
707
882
  }
708
883
  for (const action of entry.actions) {
709
884
  addRawAbility(rawAbilities, entry.path, action);
710
885
  }
711
886
  if (entry.actions.includes(DECRYPT_ACTION)) {
712
- const parsed = (0, import_sdk_core3.parseNetworkId)(entry.path);
887
+ const parsed = (0, import_sdk_core4.parseNetworkId)(entry.path);
713
888
  if (didPrincipalMatches(parsed.ownerDid, currentDid)) {
714
889
  addRawAbility(rawAbilities, entry.path, NETWORK_CREATE_ACTION);
715
890
  }
716
891
  }
717
892
  return false;
718
893
  });
719
- const primarySpaceName = spaceResources.find((entry) => entry.space !== "account")?.space ?? import_sdk_core3.DEFAULT_MANIFEST_SPACE;
894
+ const primarySpaceName = spaceResources.find((entry) => entry.space !== "account")?.space ?? import_sdk_core4.DEFAULT_MANIFEST_SPACE;
720
895
  const primarySpaceId = this.resolveSpaceName(
721
896
  primarySpaceName,
722
897
  address,
723
898
  chainId
724
899
  );
725
- const bySpace = (0, import_sdk_core3.resourceCapabilitiesToSpaceAbilitiesMap)(spaceResources);
900
+ const bySpace = (0, import_sdk_core4.resourceCapabilitiesToSpaceAbilitiesMap)(spaceResources);
726
901
  const spaceAbilities = {};
727
902
  for (const [space, abilities] of Object.entries(bySpace)) {
728
903
  spaceAbilities[this.resolveSpaceName(space, address, chainId)] = abilities;
729
904
  }
905
+ const mergedPrimaryAbilities = this.mergeReplicationEntries(
906
+ spaceAbilities,
907
+ primarySpaceId,
908
+ spaceAbilities[primarySpaceId] ?? (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)([]),
909
+ augmentSignInEntriesWithReplication({
910
+ ...this.signInPermissionInputs(address, chainId),
911
+ replication: this.replication
912
+ })
913
+ );
730
914
  return {
731
- abilities: spaceAbilities[primarySpaceId] ?? (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)([]),
915
+ abilities: mergedPrimaryAbilities,
732
916
  spaceId: primarySpaceId,
733
917
  spaceAbilities,
734
918
  rawAbilities: Object.keys(rawAbilities).length > 0 ? rawAbilities : void 0
@@ -786,14 +970,14 @@ var NodeUserAuthorization = class {
786
970
  * Create the space on the TinyCloud server (host delegation).
787
971
  * This registers the user as the owner of the space.
788
972
  */
789
- async hostSpace(targetSpaceId, purpose) {
973
+ async hostSpace(targetSpaceId, purpose, signal) {
790
974
  if (!this._tinyCloudSession || !this._address || !this._chainId) {
791
975
  throw new Error("Must be signed in to host space");
792
976
  }
793
977
  await this.ensureTinyCloudHosts();
794
978
  const host = this.primaryTinyCloudHost;
795
979
  const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
796
- const peerId = await (0, import_sdk_core3.fetchPeerId)(host, spaceId);
980
+ const peerId = await (0, import_sdk_core4.fetchPeerId)(host, spaceId, signal);
797
981
  const siwe = this.wasm.generateHostSIWEMessage({
798
982
  address: this._address,
799
983
  chainId: this._chainId,
@@ -802,9 +986,28 @@ var NodeUserAuthorization = class {
802
986
  spaceId,
803
987
  peerId
804
988
  });
805
- const signature = await this.signMessage(siwe, purpose);
989
+ if (signal?.aborted) throw signal.reason;
990
+ const signing = this.signMessage(siwe, purpose);
991
+ let signature;
992
+ if (!signal) {
993
+ signature = await signing;
994
+ } else {
995
+ let rejectOnAbort;
996
+ const aborted = new Promise((_resolve, reject2) => {
997
+ rejectOnAbort = reject2;
998
+ });
999
+ const onAbort = () => rejectOnAbort(signal.reason);
1000
+ signal.addEventListener("abort", onAbort, { once: true });
1001
+ if (signal.aborted) onAbort();
1002
+ try {
1003
+ signature = await Promise.race([signing, aborted]);
1004
+ } finally {
1005
+ signal.removeEventListener("abort", onAbort);
1006
+ }
1007
+ }
1008
+ if (signal?.aborted) throw signal.reason;
806
1009
  const headers = this.wasm.siweToDelegationHeaders({ siwe, signature });
807
- return (0, import_sdk_core3.submitHostDelegation)(host, headers);
1010
+ return (0, import_sdk_core4.submitHostDelegation)(host, headers, signal);
808
1011
  }
809
1012
  /**
810
1013
  * Create a specific space on the server via host delegation.
@@ -825,8 +1028,8 @@ var NodeUserAuthorization = class {
825
1028
  * keeps its HTTP status (e.g. a typed 401/403) instead of collapsing to
826
1029
  * `false`.
827
1030
  */
828
- async hostOwnedSpaceResult(spaceId, purpose) {
829
- return this.hostSpace(spaceId, purpose);
1031
+ async hostOwnedSpaceResult(spaceId, purpose, signal) {
1032
+ return this.hostSpace(spaceId, purpose, signal);
830
1033
  }
831
1034
  /**
832
1035
  * Ensure the user's space exists on the TinyCloud server.
@@ -843,12 +1046,12 @@ var NodeUserAuthorization = class {
843
1046
  await this.ensureTinyCloudHosts();
844
1047
  const host = this.primaryTinyCloudHost;
845
1048
  const primarySpaceId = this._tinyCloudSession.spaceId;
846
- const result = await (0, import_sdk_core3.activateSessionWithHost)(
1049
+ const result = await (0, import_sdk_core4.activateSessionWithHost)(
847
1050
  host,
848
1051
  this._tinyCloudSession.delegationHeader
849
1052
  );
850
1053
  this.recordActivationSkippedSpaces(result, primarySpaceId);
851
- const handler = this.spaceCreationHandler ?? (this.autoCreateSpace ? new import_sdk_core3.AutoApproveSpaceCreationHandler() : void 0);
1054
+ const handler = this.spaceCreationHandler ?? (this.autoCreateSpace ? new import_sdk_core4.AutoApproveSpaceCreationHandler() : void 0);
852
1055
  const creationContext = {
853
1056
  spaceId: primarySpaceId,
854
1057
  address: this._address,
@@ -884,7 +1087,7 @@ var NodeUserAuthorization = class {
884
1087
  throw error;
885
1088
  }
886
1089
  await new Promise((resolve) => setTimeout(resolve, 100));
887
- const retryResult = await (0, import_sdk_core3.activateSessionWithHost)(
1090
+ const retryResult = await (0, import_sdk_core4.activateSessionWithHost)(
888
1091
  host,
889
1092
  this._tinyCloudSession.delegationHeader
890
1093
  );
@@ -924,7 +1127,7 @@ var NodeUserAuthorization = class {
924
1127
  throw error;
925
1128
  }
926
1129
  await new Promise((resolve) => setTimeout(resolve, 100));
927
- const retryResult = await (0, import_sdk_core3.activateSessionWithHost)(
1130
+ const retryResult = await (0, import_sdk_core4.activateSessionWithHost)(
928
1131
  host,
929
1132
  this._tinyCloudSession.delegationHeader
930
1133
  );
@@ -966,7 +1169,7 @@ var NodeUserAuthorization = class {
966
1169
  const jwk = JSON.parse(jwkString);
967
1170
  const now = /* @__PURE__ */ new Date();
968
1171
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
969
- const abilities = (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)(
1172
+ const abilities = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(
970
1173
  options.capabilityRequest.resources
971
1174
  );
972
1175
  const prepared = this.wasm.prepareSession({
@@ -1017,7 +1220,7 @@ var NodeUserAuthorization = class {
1017
1220
  * @param options - Optional per-call SIWE overrides for this sign-in only
1018
1221
  */
1019
1222
  async signIn(options) {
1020
- this._address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
1223
+ this._address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
1021
1224
  this._chainId = await this.signer.getChainId();
1022
1225
  const address = this._address;
1023
1226
  const chainId = this._chainId;
@@ -1066,7 +1269,7 @@ var NodeUserAuthorization = class {
1066
1269
  siwe: prepared.siwe,
1067
1270
  signature
1068
1271
  };
1069
- const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core3.makePkhSpaceId)(address, chainId, "public") } : void 0;
1272
+ const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core4.makePkhSpaceId)(address, chainId, "public") } : void 0;
1070
1273
  const tinyCloudSession = {
1071
1274
  address,
1072
1275
  chainId,
@@ -1104,7 +1307,7 @@ var NodeUserAuthorization = class {
1104
1307
  this._address = address;
1105
1308
  this._chainId = chainId;
1106
1309
  const infoHost = this.primaryTinyCloudHost;
1107
- const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
1310
+ const nodeInfo = await (0, import_sdk_core4.checkNodeInfo)(
1108
1311
  infoHost,
1109
1312
  this.wasm.protocolVersion()
1110
1313
  );
@@ -1144,7 +1347,7 @@ var NodeUserAuthorization = class {
1144
1347
  */
1145
1348
  async signMessage(message, purpose) {
1146
1349
  if (!this._address) {
1147
- this._address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
1350
+ this._address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
1148
1351
  }
1149
1352
  if (!this._chainId) {
1150
1353
  this._chainId = await this.signer.getChainId();
@@ -1172,7 +1375,7 @@ var NodeUserAuthorization = class {
1172
1375
  * ```
1173
1376
  */
1174
1377
  async prepareSessionForSigning() {
1175
- const address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
1378
+ const address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
1176
1379
  const chainId = await this.signer.getChainId();
1177
1380
  const keyId = `session-${Date.now()}`;
1178
1381
  this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
@@ -1223,7 +1426,7 @@ var NodeUserAuthorization = class {
1223
1426
  ...prepared,
1224
1427
  signature
1225
1428
  });
1226
- const address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
1429
+ const address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
1227
1430
  const chainId = await this.signer.getChainId();
1228
1431
  await this.resolveTinyCloudHostsForSignIn(address, chainId);
1229
1432
  const clientSession = {
@@ -1234,7 +1437,7 @@ var NodeUserAuthorization = class {
1234
1437
  siwe: prepared.siwe,
1235
1438
  signature
1236
1439
  };
1237
- const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core3.makePkhSpaceId)(address, chainId, "public") } : void 0;
1440
+ const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core4.makePkhSpaceId)(address, chainId, "public") } : void 0;
1238
1441
  const tinyCloudSession = {
1239
1442
  address,
1240
1443
  chainId,
@@ -1276,7 +1479,7 @@ var NodeUserAuthorization = class {
1276
1479
  this._address = address;
1277
1480
  this._chainId = chainId;
1278
1481
  const infoHost = this.primaryTinyCloudHost;
1279
- const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
1482
+ const nodeInfo = await (0, import_sdk_core4.checkNodeInfo)(
1280
1483
  infoHost,
1281
1484
  this.wasm.protocolVersion()
1282
1485
  );
@@ -1332,7 +1535,7 @@ var NodeUserAuthorization = class {
1332
1535
  }
1333
1536
  this.tinycloudHosts = [overrideHost];
1334
1537
  }
1335
- const signingAddress = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
1538
+ const signingAddress = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
1336
1539
  const signingChainId = await this.signer.getChainId();
1337
1540
  await this.resolveTinyCloudHostsForSignIn(signingAddress, signingChainId);
1338
1541
  const { prepared, keyId, jwk } = await this.prepareSessionForSigning();
@@ -1437,8 +1640,8 @@ var NodeUserAuthorization = class {
1437
1640
  "signInWithOpenKeyResult requires prepared.siwe (the SDK-generated SIWE the sign-in was proposed with)"
1438
1641
  );
1439
1642
  }
1440
- const expectedAddress = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
1441
- if ((0, import_sdk_core3.canonicalizeAddress)(result.address) !== expectedAddress) {
1643
+ const expectedAddress = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
1644
+ if ((0, import_sdk_core4.canonicalizeAddress)(result.address) !== expectedAddress) {
1442
1645
  throw new Error(
1443
1646
  `OpenKey returned signature from ${result.address} but expected ${expectedAddress}`
1444
1647
  );
@@ -1463,15 +1666,15 @@ var NodeUserAuthorization = class {
1463
1666
  `OpenKey signature verification failed${type ? `: ${type}` : ""}${details}`
1464
1667
  );
1465
1668
  }
1466
- if ((0, import_sdk_core3.canonicalizeAddress)(parsedSignedSiwe.address) !== expectedAddress) {
1669
+ if ((0, import_sdk_core4.canonicalizeAddress)(parsedSignedSiwe.address) !== expectedAddress) {
1467
1670
  throw new Error(
1468
1671
  `OpenKey signedMessage.address (${parsedSignedSiwe.address}) does not match local signer address (${expectedAddress})`
1469
1672
  );
1470
1673
  }
1471
1674
  const originalHasRecap = /(?:^|\n)-\s+urn:recap:/i.test(prepared.siwe);
1472
- const originalFields = (0, import_sdk_core3.extractImmutableSiweFields)(prepared.siwe);
1473
- const signedFields = (0, import_sdk_core3.extractImmutableSiweFields)(result.signedMessage);
1474
- const changedFields = (0, import_sdk_core3.diffImmutableSiweFields)(originalFields, signedFields, {
1675
+ const originalFields = (0, import_sdk_core4.extractImmutableSiweFields)(prepared.siwe);
1676
+ const signedFields = (0, import_sdk_core4.extractImmutableSiweFields)(result.signedMessage);
1677
+ const changedFields = (0, import_sdk_core4.diffImmutableSiweFields)(originalFields, signedFields, {
1475
1678
  originalHasRecap
1476
1679
  });
1477
1680
  if (changedFields.length > 0) {
@@ -1482,20 +1685,20 @@ var NodeUserAuthorization = class {
1482
1685
  let originalCaps;
1483
1686
  let signedCaps;
1484
1687
  try {
1485
- originalCaps = (0, import_sdk_core3.extractRecapAttenuations)(prepared.siwe);
1688
+ originalCaps = (0, import_sdk_core4.extractRecapAttenuations)(prepared.siwe);
1486
1689
  } catch (err) {
1487
1690
  throw new Error(
1488
1691
  `Failed to decode prepared SIWE recap: ${err.message}`
1489
1692
  );
1490
1693
  }
1491
1694
  try {
1492
- signedCaps = (0, import_sdk_core3.extractRecapAttenuations)(result.signedMessage);
1695
+ signedCaps = (0, import_sdk_core4.extractRecapAttenuations)(result.signedMessage);
1493
1696
  } catch (err) {
1494
1697
  throw new Error(
1495
1698
  `Failed to decode OpenKey signedMessage recap: ${err.message}`
1496
1699
  );
1497
1700
  }
1498
- const unauthorized = (0, import_sdk_core3.unauthorizedRecapCapabilities)(signedCaps, originalCaps);
1701
+ const unauthorized = (0, import_sdk_core4.unauthorizedRecapCapabilities)(signedCaps, originalCaps);
1499
1702
  if (unauthorized.length > 0) {
1500
1703
  const previewLimit = 5;
1501
1704
  const preview = unauthorized.slice(0, previewLimit).map((u) => `${u.resource}::${u.action}`).join(", ");
@@ -1512,7 +1715,7 @@ var NodeUserAuthorization = class {
1512
1715
  const grantedPairs = /* @__PURE__ */ new Set();
1513
1716
  const grantedFourPartIndex = /* @__PURE__ */ new Map();
1514
1717
  for (const [resource, actions] of Object.entries(signedCaps)) {
1515
- const { space, path } = (0, import_sdk_core3.parseCanonicalRecapResource)(resource);
1718
+ const { space, path } = (0, import_sdk_core4.parseCanonicalRecapResource)(resource);
1516
1719
  for (const action of Object.keys(actions)) {
1517
1720
  grantedPairs.add(`${resource}\0${action}`);
1518
1721
  const slashIdx = action.indexOf("/");
@@ -1753,7 +1956,7 @@ var NodeUserAuthorization = class {
1753
1956
  };
1754
1957
 
1755
1958
  // src/delegation.ts
1756
- var import_sdk_core4 = require("@tinycloud/sdk-core");
1959
+ var import_sdk_core5 = require("@tinycloud/sdk-core");
1757
1960
  var RuntimeDelegationRejectedError = class extends Error {
1758
1961
  constructor(reason, message) {
1759
1962
  super(message);
@@ -1761,6 +1964,18 @@ var RuntimeDelegationRejectedError = class extends Error {
1761
1964
  this.reason = reason;
1762
1965
  }
1763
1966
  };
1967
+ function activationRejectionReason(error) {
1968
+ if (typeof error !== "object" || error === null) return "activation_rejected";
1969
+ if ("code" in error && error.code === "ACTIVATION_TRANSPORT_FAILED") {
1970
+ return "activation_unavailable";
1971
+ }
1972
+ const cause = "cause" in error ? error.cause : void 0;
1973
+ const status = typeof cause === "object" && cause !== null && "status" in cause ? cause.status : void 0;
1974
+ if (typeof status !== "number") return "activation_rejected";
1975
+ if (status === 408 || status === 429 || status >= 500) return "activation_unavailable";
1976
+ if (status === 401) return "activation_unauthenticated";
1977
+ return "activation_rejected";
1978
+ }
1764
1979
  function reject(reason, message) {
1765
1980
  throw new RuntimeDelegationRejectedError(reason, message);
1766
1981
  }
@@ -1781,7 +1996,7 @@ function normalizedHost(host) {
1781
1996
  }
1782
1997
  function didPrincipalsMatch(left, right) {
1783
1998
  try {
1784
- return (0, import_sdk_core4.principalDidEquals)(left, right);
1999
+ return (0, import_sdk_core5.principalDidEquals)(left, right);
1785
2000
  } catch {
1786
2001
  return left === right;
1787
2002
  }
@@ -1796,7 +2011,7 @@ function compactUcanPayload(authorization) {
1796
2011
  }
1797
2012
  try {
1798
2013
  const payload = JSON.parse(
1799
- new TextDecoder("utf-8", { fatal: true }).decode((0, import_sdk_core4.decodeBase64Url)(parts[1]))
2014
+ new TextDecoder("utf-8", { fatal: true }).decode((0, import_sdk_core5.decodeBase64Url)(parts[1]))
1800
2015
  );
1801
2016
  if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
1802
2017
  throw new Error("payload is not an object");
@@ -1824,7 +2039,7 @@ function canonicalPermissionEntries(permissions) {
1824
2039
  ...permission,
1825
2040
  actions: [...permission.actions].sort()
1826
2041
  })).sort(
1827
- (left, right) => left.service.localeCompare(right.service) || (left.space ?? "").localeCompare(right.space ?? "") || left.path.localeCompare(right.path) || left.actions.join("\0").localeCompare(right.actions.join("\0")) || (0, import_sdk_core4.canonicalizeRecapCaveats)(left.caveats).localeCompare((0, import_sdk_core4.canonicalizeRecapCaveats)(right.caveats))
2042
+ (left, right) => left.service.localeCompare(right.service) || (left.space ?? "").localeCompare(right.space ?? "") || left.path.localeCompare(right.path) || left.actions.join("\0").localeCompare(right.actions.join("\0")) || (0, import_sdk_core5.canonicalizeRecapCaveats)(left.caveats).localeCompare((0, import_sdk_core5.canonicalizeRecapCaveats)(right.caveats))
1828
2043
  );
1829
2044
  }
1830
2045
  function signedCaveats(value) {
@@ -1834,13 +2049,13 @@ function signedCaveats(value) {
1834
2049
  throw new Error("Validated runtime delegation has malformed signed ReCap caveats.");
1835
2050
  }
1836
2051
  const cloned = JSON.parse(JSON.stringify(value));
1837
- return (0, import_sdk_core4.canonicalizeRecapCaveats)(cloned) === (0, import_sdk_core4.canonicalizeRecapCaveats)(void 0) ? void 0 : cloned;
2052
+ return (0, import_sdk_core5.canonicalizeRecapCaveats)(cloned) === (0, import_sdk_core5.canonicalizeRecapCaveats)(void 0) ? void 0 : cloned;
1838
2053
  }
1839
2054
  function groupedSignedEntries(service, space, path, abilities) {
1840
2055
  const groups = /* @__PURE__ */ new Map();
1841
2056
  for (const [action, rawCaveats] of Object.entries(abilities)) {
1842
2057
  const caveats = signedCaveats(rawCaveats);
1843
- const identity = (0, import_sdk_core4.canonicalizeRecapCaveats)(caveats);
2058
+ const identity = (0, import_sdk_core5.canonicalizeRecapCaveats)(caveats);
1844
2059
  const group = groups.get(identity) ?? { actions: [], caveats };
1845
2060
  group.actions.push(action);
1846
2061
  groups.set(identity, group);
@@ -1999,7 +2214,7 @@ function signedAuthorityFromSessionGrant(node, delegation, authorization, cid) {
1999
2214
  reject("authority_invalid", "Runtime delegation has signed authority outside its space.");
2000
2215
  }
2001
2216
  const caveats = signedCaveats(entry.caveats ?? []);
2002
- const key = JSON.stringify([service, raw ? "" : entry.space, entry.path, (0, import_sdk_core4.canonicalizeRecapCaveats)(caveats)]);
2217
+ const key = JSON.stringify([service, raw ? "" : entry.space, entry.path, (0, import_sdk_core5.canonicalizeRecapCaveats)(caveats)]);
2003
2218
  const group = groups.get(key) ?? {
2004
2219
  service,
2005
2220
  ...raw ? {} : { space: entry.space },
@@ -2023,7 +2238,7 @@ function signedAuthorityFromSessionGrant(node, delegation, authorization, cid) {
2023
2238
  function canonicalResourcesFromPortableDelegation(delegation) {
2024
2239
  if (delegation.resources !== void 0 && delegation.resources.length > 0) {
2025
2240
  return delegation.resources.map((resource) => ({ ...resource, actions: [...resource.actions].sort() })).sort(
2026
- (left, right) => left.service.localeCompare(right.service) || left.space.localeCompare(right.space) || left.path.localeCompare(right.path) || left.actions.join("\0").localeCompare(right.actions.join("\0")) || (0, import_sdk_core4.canonicalizeRecapCaveats)(left.caveats).localeCompare((0, import_sdk_core4.canonicalizeRecapCaveats)(right.caveats))
2241
+ (left, right) => left.service.localeCompare(right.service) || left.space.localeCompare(right.space) || left.path.localeCompare(right.path) || left.actions.join("\0").localeCompare(right.actions.join("\0")) || (0, import_sdk_core5.canonicalizeRecapCaveats)(left.caveats).localeCompare((0, import_sdk_core5.canonicalizeRecapCaveats)(right.caveats))
2027
2242
  );
2028
2243
  }
2029
2244
  const byService = /* @__PURE__ */ new Map();
@@ -2047,7 +2262,7 @@ function canonicalResourcesFromPortableDelegation(delegation) {
2047
2262
  function resourcesMatch(actual, expected) {
2048
2263
  const comparable = (resource) => ({
2049
2264
  ...resource,
2050
- caveats: (0, import_sdk_core4.canonicalizeRecapCaveats)(resource.caveats)
2265
+ caveats: (0, import_sdk_core5.canonicalizeRecapCaveats)(resource.caveats)
2051
2266
  });
2052
2267
  return JSON.stringify(actual.map(comparable)) === JSON.stringify(expected.map(comparable));
2053
2268
  }
@@ -2139,13 +2354,16 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
2139
2354
  ...compact ? {} : { siweProof: delegation.siweProof }
2140
2355
  };
2141
2356
  try {
2142
- if (node.isSessionOnly === true && typeof node.did === "string" && (0, import_sdk_core4.principalDidEquals)(node.did, node.sessionDid) && typeof node.useDelegation === "function") {
2357
+ if (node.isSessionOnly === true && typeof node.did === "string" && (0, import_sdk_core5.principalDidEquals)(node.did, node.sessionDid) && typeof node.useDelegation === "function") {
2143
2358
  await node.useDelegation(installedCandidate);
2144
2359
  } else {
2145
2360
  await node.useRuntimeDelegation(installedCandidate);
2146
2361
  }
2147
2362
  } catch (error) {
2148
- reject("activation_rejected", error instanceof Error ? error.message : String(error));
2363
+ reject(
2364
+ activationRejectionReason(error),
2365
+ error instanceof Error ? error.message : String(error)
2366
+ );
2149
2367
  }
2150
2368
  const installed = node.getRuntimePermissionDelegations().find((candidate) => candidate.cid === cid);
2151
2369
  if (!installed) {
@@ -2218,21 +2436,52 @@ function deserializeDelegation(data) {
2218
2436
  };
2219
2437
  }
2220
2438
 
2439
+ // src/replication/config.ts
2440
+ var import_sdk_services2 = require("@tinycloud/sdk-services");
2441
+ function assertValidReplicationConfig(replication) {
2442
+ if (replication === void 0 || replication.enabled !== true) return;
2443
+ if (replication.storage === void 0 || replication.storage === null) {
2444
+ throw new TypeError("replication.enabled requires replication.storage");
2445
+ }
2446
+ if (!Array.isArray(replication.prefixes) || replication.prefixes.length === 0) {
2447
+ throw new TypeError("replication.prefixes must be a non-empty array");
2448
+ }
2449
+ for (const prefix of replication.prefixes) {
2450
+ if (typeof prefix !== "string" || prefix === "") {
2451
+ throw new TypeError("replication.prefixes must not contain an empty prefix");
2452
+ }
2453
+ }
2454
+ for (const [index, prefix] of replication.prefixes.entries()) {
2455
+ for (const other of replication.prefixes.slice(index + 1)) {
2456
+ if ((0, import_sdk_services2.kvPrefixCovers)(prefix, other) || (0, import_sdk_services2.kvPrefixCovers)(other, prefix)) {
2457
+ throw new TypeError(
2458
+ `replication.prefixes must not overlap: ${JSON.stringify(prefix)} and ${JSON.stringify(other)}`
2459
+ );
2460
+ }
2461
+ }
2462
+ if (prefix.split("/", 1)[0] === "vault" && replication.allowSecrets !== true) {
2463
+ throw new TypeError(
2464
+ `replication prefix ${JSON.stringify(prefix)} overlaps the vault namespace; pass allowSecrets to opt in`
2465
+ );
2466
+ }
2467
+ }
2468
+ }
2469
+
2221
2470
  // src/TinyCloudNode.ts
2222
- var import_sdk_core9 = require("@tinycloud/sdk-core");
2223
- var import_sdk_services = require("@tinycloud/sdk-services");
2471
+ var import_sdk_core10 = require("@tinycloud/sdk-core");
2472
+ var import_sdk_services3 = require("@tinycloud/sdk-services");
2224
2473
 
2225
2474
  // src/account/AccountService.ts
2226
- var import_sdk_core5 = require("@tinycloud/sdk-core");
2475
+ var import_sdk_core6 = require("@tinycloud/sdk-core");
2227
2476
 
2228
2477
  // src/DelegatedAccess.ts
2229
- var import_sdk_core6 = require("@tinycloud/sdk-core");
2478
+ var import_sdk_core7 = require("@tinycloud/sdk-core");
2230
2479
  var DelegatedAccess = class {
2231
2480
  constructor(session, delegation, host, invoke, invokeAny, telemetry) {
2232
2481
  this.session = session;
2233
2482
  this._delegation = delegation;
2234
2483
  this.host = host;
2235
- this._serviceContext = new import_sdk_core6.ServiceContext({
2484
+ this._serviceContext = new import_sdk_core7.ServiceContext({
2236
2485
  invoke,
2237
2486
  invokeAny,
2238
2487
  fetch: globalThis.fetch.bind(globalThis),
@@ -2240,16 +2489,16 @@ var DelegatedAccess = class {
2240
2489
  telemetry
2241
2490
  });
2242
2491
  const prefix = this._delegation.path.replace(/\/$/, "");
2243
- this._kv = new import_sdk_core6.KVService({ prefix });
2492
+ this._kv = new import_sdk_core7.KVService({ prefix });
2244
2493
  this._kv.initialize(this._serviceContext);
2245
2494
  this._serviceContext.registerService("kv", this._kv);
2246
- this._sql = new import_sdk_core6.SQLService({});
2495
+ this._sql = new import_sdk_core7.SQLService({});
2247
2496
  this._sql.initialize(this._serviceContext);
2248
2497
  this._serviceContext.registerService("sql", this._sql);
2249
- this._duckdb = new import_sdk_core6.DuckDbService({});
2498
+ this._duckdb = new import_sdk_core7.DuckDbService({});
2250
2499
  this._duckdb.initialize(this._serviceContext);
2251
2500
  this._serviceContext.registerService("duckdb", this._duckdb);
2252
- this._hooks = new import_sdk_core6.HooksService({});
2501
+ this._hooks = new import_sdk_core7.HooksService({});
2253
2502
  this._hooks.initialize(this._serviceContext);
2254
2503
  this._serviceContext.registerService("hooks", this._hooks);
2255
2504
  const serviceSession = {
@@ -2399,7 +2648,7 @@ function createWasmKeyProvider(sessionManager) {
2399
2648
  }
2400
2649
 
2401
2650
  // src/delegateToHelpers.ts
2402
- var import_sdk_core7 = require("@tinycloud/sdk-core");
2651
+ var import_sdk_core8 = require("@tinycloud/sdk-core");
2403
2652
  function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
2404
2653
  const byService = /* @__PURE__ */ new Map();
2405
2654
  for (const a of actions) {
@@ -2430,7 +2679,7 @@ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
2430
2679
  }
2431
2680
  return entries;
2432
2681
  }
2433
- var DEFAULT_DELEGATION_EXPIRY_MS = import_sdk_core7.EXPIRY.SESSION_MS;
2682
+ var DEFAULT_DELEGATION_EXPIRY_MS = import_sdk_core8.EXPIRY.SESSION_MS;
2434
2683
  function resolveExpiryMs(expiry) {
2435
2684
  if (expiry === void 0) {
2436
2685
  return DEFAULT_DELEGATION_EXPIRY_MS;
@@ -2443,10 +2692,10 @@ function resolveExpiryMs(expiry) {
2443
2692
  }
2444
2693
  return expiry;
2445
2694
  }
2446
- return (0, import_sdk_core7.parseExpiry)(expiry);
2695
+ return (0, import_sdk_core8.parseExpiry)(expiry);
2447
2696
  }
2448
2697
  function extractSiweExpiration(siwe) {
2449
- const parsed = new import_sdk_core7.SiweMessage(siwe);
2698
+ const parsed = new import_sdk_core8.SiweMessage(siwe);
2450
2699
  if (parsed.expirationTime === void 0 || parsed.expirationTime === null) {
2451
2700
  return void 0;
2452
2701
  }
@@ -2460,7 +2709,7 @@ function extractSiweExpiration(siwe) {
2460
2709
  }
2461
2710
 
2462
2711
  // src/NodeSecretsService.ts
2463
- var import_sdk_core8 = require("@tinycloud/sdk-core");
2712
+ var import_sdk_core9 = require("@tinycloud/sdk-core");
2464
2713
  var SECRETS_SPACE = "secrets";
2465
2714
  function ok() {
2466
2715
  return { ok: true, data: void 0 };
@@ -2493,7 +2742,7 @@ function secretActionName(action) {
2493
2742
  }
2494
2743
  function secretPermissionEntries(name, options, action, space, encryptionNetworkId) {
2495
2744
  const entries = [];
2496
- const path = action === "list" ? (0, import_sdk_core8.resolveSecretListPrefix)(options) : (0, import_sdk_core8.resolveSecretPath)(name, options).permissionPaths.vault;
2745
+ const path = action === "list" ? (0, import_sdk_core9.resolveSecretListPrefix)(options) : (0, import_sdk_core9.resolveSecretPath)(name, options).permissionPaths.vault;
2497
2746
  entries.push({
2498
2747
  service: "tinycloud.kv",
2499
2748
  space,
@@ -2590,7 +2839,7 @@ var NodeSecretsService = class {
2590
2839
  );
2591
2840
  } catch (error) {
2592
2841
  return secretsError(
2593
- import_sdk_core8.ErrorCodes.INVALID_INPUT,
2842
+ import_sdk_core9.ErrorCodes.INVALID_INPUT,
2594
2843
  error instanceof Error ? error.message : String(error),
2595
2844
  error instanceof Error ? error : void 0
2596
2845
  );
@@ -2600,7 +2849,7 @@ var NodeSecretsService = class {
2600
2849
  }
2601
2850
  if (!this.config.canEscalate()) {
2602
2851
  return secretsError(
2603
- import_sdk_core8.ErrorCodes.PERMISSION_DENIED,
2852
+ import_sdk_core9.ErrorCodes.PERMISSION_DENIED,
2604
2853
  `Cannot autosign ${displayActionUrn(action)} for ${target}; TinyCloudNode needs wallet mode with a signer or privateKey.`
2605
2854
  );
2606
2855
  }
@@ -2609,7 +2858,7 @@ var NodeSecretsService = class {
2609
2858
  return this.restoreUnlockAfterEscalation();
2610
2859
  } catch (error) {
2611
2860
  return secretsError(
2612
- import_sdk_core8.ErrorCodes.PERMISSION_DENIED,
2861
+ import_sdk_core9.ErrorCodes.PERMISSION_DENIED,
2613
2862
  error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${target} failed.`,
2614
2863
  error instanceof Error ? error : void 0
2615
2864
  );
@@ -2630,10 +2879,10 @@ var NodeSecretsService = class {
2630
2879
  return false;
2631
2880
  }
2632
2881
  const manifests = Array.isArray(manifest) ? manifest : [manifest];
2633
- const requestedEntries = (0, import_sdk_core8.expandPermissionEntries)(permissionEntries);
2882
+ const requestedEntries = (0, import_sdk_core9.expandPermissionEntries)(permissionEntries);
2634
2883
  return requestedEntries.every(
2635
2884
  (entry) => manifests.some((candidate) => {
2636
- const resolved = (0, import_sdk_core8.resolveManifest)(candidate);
2885
+ const resolved = (0, import_sdk_core9.resolveManifest)(candidate);
2637
2886
  return resolved.resources.some(
2638
2887
  (resource) => resource.service === entry.service && spaceMatches(
2639
2888
  resource.space,
@@ -2649,8 +2898,8 @@ var NodeSecretsService = class {
2649
2898
  // src/TinyCloudNode.ts
2650
2899
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
2651
2900
  var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
2652
- var NETWORK_CREATE_ACTION2 = import_sdk_core9.ENCRYPTION.NETWORK_CREATE;
2653
- var DECRYPT_ACTION2 = import_sdk_core9.ENCRYPTION.DECRYPT;
2901
+ var NETWORK_CREATE_ACTION2 = import_sdk_core10.ENCRYPTION.NETWORK_CREATE;
2902
+ var DECRYPT_ACTION2 = import_sdk_core10.ENCRYPTION.DECRYPT;
2654
2903
  var BOOTSTRAP_COMPLETION_MARKER_KEY = "system/bootstrap/complete";
2655
2904
  var BOOTSTRAP_COMPLETION_MARKER_VERSION = 1;
2656
2905
  var ACCEPTED_MARKER_VERSIONS = [BOOTSTRAP_COMPLETION_MARKER_VERSION];
@@ -2659,24 +2908,24 @@ function isSecretPayload(value) {
2659
2908
  return typeof value === "object" && value !== null && "value" in value && typeof value.value === "string" && "createdAt" in value && typeof value.createdAt === "string" && "updatedAt" in value && typeof value.updatedAt === "string";
2660
2909
  }
2661
2910
  var ROOT_DELEGATION_ACTIONS = [
2662
- import_sdk_core9.KV.PUT,
2663
- import_sdk_core9.KV.GET,
2664
- import_sdk_core9.KV.DEL,
2665
- import_sdk_core9.KV.LIST,
2666
- import_sdk_core9.KV.METADATA,
2667
- import_sdk_core9.SQL.READ,
2668
- import_sdk_core9.SQL.WRITE,
2669
- import_sdk_core9.SQL.ADMIN,
2670
- import_sdk_core9.SQL.ALL,
2671
- import_sdk_core9.DUCKDB.READ,
2672
- import_sdk_core9.DUCKDB.WRITE,
2673
- import_sdk_core9.DUCKDB.ADMIN,
2674
- import_sdk_core9.DUCKDB.DESCRIBE,
2675
- import_sdk_core9.DUCKDB.EXPORT,
2676
- import_sdk_core9.DUCKDB.IMPORT,
2677
- import_sdk_core9.DUCKDB.ALL
2911
+ import_sdk_core10.KV.PUT,
2912
+ import_sdk_core10.KV.GET,
2913
+ import_sdk_core10.KV.DEL,
2914
+ import_sdk_core10.KV.LIST,
2915
+ import_sdk_core10.KV.METADATA,
2916
+ import_sdk_core10.SQL.READ,
2917
+ import_sdk_core10.SQL.WRITE,
2918
+ import_sdk_core10.SQL.ADMIN,
2919
+ import_sdk_core10.SQL.ALL,
2920
+ import_sdk_core10.DUCKDB.READ,
2921
+ import_sdk_core10.DUCKDB.WRITE,
2922
+ import_sdk_core10.DUCKDB.ADMIN,
2923
+ import_sdk_core10.DUCKDB.DESCRIBE,
2924
+ import_sdk_core10.DUCKDB.EXPORT,
2925
+ import_sdk_core10.DUCKDB.IMPORT,
2926
+ import_sdk_core10.DUCKDB.ALL
2678
2927
  ];
2679
- var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core9.EXPIRY.SESSION_MS;
2928
+ var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core10.EXPIRY.SESSION_MS;
2680
2929
  function unifiedRootAttenuation(capabilities) {
2681
2930
  const attenuation = {};
2682
2931
  for (const capability of capabilities) {
@@ -2722,7 +2971,7 @@ function isInteractiveSigner(config) {
2722
2971
  }
2723
2972
  function didPrincipalMatches2(actual, expected) {
2724
2973
  try {
2725
- return (0, import_sdk_core9.principalDidEquals)(actual, expected);
2974
+ return (0, import_sdk_core10.principalDidEquals)(actual, expected);
2726
2975
  } catch {
2727
2976
  return actual === expected;
2728
2977
  }
@@ -2933,7 +3182,7 @@ function ownerDelegationPermissions(params) {
2933
3182
  }
2934
3183
  const slash = action.indexOf("/");
2935
3184
  const service = slash === -1 ? "" : action.slice(0, slash);
2936
- if (import_sdk_core9.SERVICE_LONG_TO_SHORT[service] === void 0) {
3185
+ if (import_sdk_core10.SERVICE_LONG_TO_SHORT[service] === void 0) {
2937
3186
  throw new Error("Owner delegation capabilities are unsupported");
2938
3187
  }
2939
3188
  const actions = byService.get(service) ?? [];
@@ -2949,7 +3198,7 @@ function ownerDelegationPermissions(params) {
2949
3198
  }
2950
3199
  const resources = /* @__PURE__ */ new Set();
2951
3200
  for (const permission of permissions) {
2952
- if (typeof permission.service !== "string" || import_sdk_core9.SERVICE_LONG_TO_SHORT[permission.service] === void 0 || typeof permission.path !== "string" || permission.path.length === 0 || permission.path.trim() !== permission.path || /[\u0000-\u001f\u007f\\*]/.test(permission.path) || !Array.isArray(permission.actions) || permission.actions.length === 0 || permission.actions.length > 32) {
3201
+ if (typeof permission.service !== "string" || import_sdk_core10.SERVICE_LONG_TO_SHORT[permission.service] === void 0 || typeof permission.path !== "string" || permission.path.length === 0 || permission.path.trim() !== permission.path || /[\u0000-\u001f\u007f\\*]/.test(permission.path) || !Array.isArray(permission.actions) || permission.actions.length === 0 || permission.actions.length > 32) {
2953
3202
  throw new Error("Owner delegation requires bounded capabilities");
2954
3203
  }
2955
3204
  const resourceKey = `${permission.service}\0${permission.path}`;
@@ -2964,9 +3213,9 @@ function ownerDelegationPermissions(params) {
2964
3213
  }
2965
3214
  actions.add(action);
2966
3215
  }
2967
- if (permission.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE) {
3216
+ if (permission.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE) {
2968
3217
  try {
2969
- (0, import_sdk_core9.parseNetworkId)(permission.path);
3218
+ (0, import_sdk_core10.parseNetworkId)(permission.path);
2970
3219
  } catch {
2971
3220
  throw new Error("Owner delegation encryption permission requires a canonical network URN");
2972
3221
  }
@@ -2978,11 +3227,11 @@ function ownerPermissionsToAbilities(permissions) {
2978
3227
  const abilities = {};
2979
3228
  const rawAbilities = {};
2980
3229
  for (const permission of permissions) {
2981
- if (permission.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE) {
3230
+ if (permission.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE) {
2982
3231
  rawAbilities[permission.path] = [...permission.actions];
2983
3232
  continue;
2984
3233
  }
2985
- const shortService = import_sdk_core9.SERVICE_LONG_TO_SHORT[permission.service];
3234
+ const shortService = import_sdk_core10.SERVICE_LONG_TO_SHORT[permission.service];
2986
3235
  abilities[shortService] ?? (abilities[shortService] = {});
2987
3236
  abilities[shortService][permission.path] = [...permission.actions];
2988
3237
  }
@@ -3114,6 +3363,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3114
3363
  this.confirmedHostedSpaceIds = /* @__PURE__ */ new Set();
3115
3364
  /** Serializes account-registry writes for the active node instance. */
3116
3365
  this.accountRegistryTail = Promise.resolve();
3366
+ /** Bounds best-effort registry work on the sign-in critical path. */
3367
+ this.accountRegistryDeadlineMs = 4e3;
3117
3368
  /**
3118
3369
  * True when the last signIn() detected an interactive signer and skipped
3119
3370
  * client-side bootstrap. Apps can read this to know whether bootstrap was
@@ -3185,18 +3436,53 @@ var _TinyCloudNode = class _TinyCloudNode {
3185
3436
  if (!granted?.caveats?.length) {
3186
3437
  return entry;
3187
3438
  }
3188
- if (entry.caveats !== void 0 && !(0, import_sdk_core9.recapCaveatsEqual)(entry.caveats, granted.caveats)) {
3439
+ if (entry.caveats !== void 0 && !(0, import_sdk_core10.recapCaveatsEqual)(entry.caveats, granted.caveats)) {
3189
3440
  throw new Error("Invocation caveats do not match signed ReCap authority.");
3190
3441
  }
3191
3442
  return { ...entry, caveats: cloneRecapCaveats(granted.caveats) };
3192
3443
  });
3193
3444
  return this.wasmBindings.invokeAny(invocationSession, caveatPreservingEntries, facts);
3194
3445
  };
3446
+ assertValidReplicationConfig(config.replication);
3195
3447
  this.explicitHost = config.host;
3196
3448
  this.config = {
3197
3449
  ...config,
3198
3450
  host: config.host ?? DEFAULT_HOST
3199
3451
  };
3452
+ if (this.config.replication?.enabled) {
3453
+ const runtime = getNodeReplicationLoaders().runtime().then(({ ReplicationRuntime }) => {
3454
+ const instance = new ReplicationRuntime(this.config.replication);
3455
+ this.replicationRuntimeInstance = instance;
3456
+ return instance;
3457
+ });
3458
+ this.replicationRuntime = runtime;
3459
+ this.replicationControl = {
3460
+ status: async () => {
3461
+ const status = await runtime.then((ready) => ready.control.status());
3462
+ const scopeError = this.replicationScopeError;
3463
+ if (!scopeError) return status;
3464
+ return this.config.replication.prefixes.map((prefix) => ({
3465
+ prefix,
3466
+ state: "unavailable",
3467
+ lastError: {
3468
+ at: (/* @__PURE__ */ new Date()).toISOString(),
3469
+ code: "SESSION_SCOPE_MISMATCH",
3470
+ message: scopeError
3471
+ },
3472
+ pending: { inFlight: 0, committed: 0, ambiguous: 0 },
3473
+ pinned: [],
3474
+ lagMs: null
3475
+ }));
3476
+ },
3477
+ sync: async (input) => (await runtime).control.sync(input),
3478
+ purge: (input) => {
3479
+ const instance = this.replicationRuntimeInstance;
3480
+ return instance ? instance.control.purge(input) : runtime.then((ready) => ready.control.purge(input));
3481
+ },
3482
+ clearPending: async () => (await runtime).control.clearPending(),
3483
+ close: async () => (await runtime).control.close()
3484
+ };
3485
+ }
3200
3486
  if (config.wasmBindings) {
3201
3487
  this.wasmBindings = config.wasmBindings;
3202
3488
  } else if (_TinyCloudNode.nodeDefaults) {
@@ -3220,13 +3506,13 @@ var _TinyCloudNode = class _TinyCloudNode {
3220
3506
  }
3221
3507
  this.sessionKeyJwk = JSON.parse(jwkStr);
3222
3508
  this._serviceGraph = this.createServiceGraphLifetime();
3223
- this._capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
3509
+ this._capabilityRegistry = new import_sdk_core10.CapabilityKeyRegistry();
3224
3510
  this._keyProvider = new WasmKeyProvider({
3225
3511
  sessionManager: this.sessionManager
3226
3512
  });
3227
- this.notificationHandler = config.notificationHandler ?? new import_sdk_core9.SilentNotificationHandler();
3513
+ this.notificationHandler = config.notificationHandler ?? new import_sdk_core10.SilentNotificationHandler();
3228
3514
  const receiveOnlyGraph = this._serviceGraph;
3229
- this._sharingService = new import_sdk_core9.SharingService({
3515
+ this._sharingService = new import_sdk_core10.SharingService({
3230
3516
  hosts: [this.config.host],
3231
3517
  // session: undefined - not needed for receive()
3232
3518
  invoke: receiveOnlyGraph.invoke,
@@ -3242,8 +3528,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3242
3528
  // delegationManager: undefined - not needed for receive()
3243
3529
  createKVService: (config2) => {
3244
3530
  const prefix = config2.pathPrefix?.replace(/\/$/, "");
3245
- const kvService = new import_sdk_core9.KVService({ prefix });
3246
- const kvContext = receiveOnlyGraph.track(new import_sdk_core9.ServiceContext({
3531
+ const kvService = new import_sdk_core10.KVService({ prefix });
3532
+ const kvContext = receiveOnlyGraph.track(new import_sdk_core10.ServiceContext({
3247
3533
  invoke: config2.invoke,
3248
3534
  fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
3249
3535
  hosts: config2.hosts,
@@ -3316,10 +3602,17 @@ var _TinyCloudNode = class _TinyCloudNode {
3316
3602
  nonce: config.nonce,
3317
3603
  siweConfig: config.siweConfig,
3318
3604
  manifest: useBootstrapSignInRequest ? void 0 : config.manifest,
3319
- capabilityRequest: useBootstrapSignInRequest ? config.includeAccountRegistryPermissions === false ? import_sdk_core9.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
3320
- includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : config.includeAccountRegistryPermissions
3605
+ capabilityRequest: useBootstrapSignInRequest ? config.includeAccountRegistryPermissions === false ? import_sdk_core10.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core10.BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
3606
+ includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : config.includeAccountRegistryPermissions,
3607
+ // Sign-in needs only the entry inputs (prefixes + secrets opt-in);
3608
+ // storage and scheduling never leave TinyCloudNode.
3609
+ replication: config.replication?.enabled === true ? {
3610
+ enabled: true,
3611
+ prefixes: config.replication.prefixes,
3612
+ allowSecrets: config.replication.allowSecrets === true
3613
+ } : void 0
3321
3614
  });
3322
- this.tc = new import_sdk_core9.TinyCloud(this.auth, {
3615
+ this.tc = new import_sdk_core10.TinyCloud(this.auth, {
3323
3616
  invokeAny: this.invokeAnyWithRuntimePermissions,
3324
3617
  telemetry: config.telemetry
3325
3618
  });
@@ -3399,7 +3692,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3399
3692
  /** Publish the active owner Node as a session-signed registry record. */
3400
3693
  async publishActiveNodeLocation(registryUrl, fetchFn = globalThis.fetch.bind(globalThis)) {
3401
3694
  const node = await this.activeNodeIdentity();
3402
- return (0, import_sdk_core9.publishLocationRecord)({
3695
+ return (0, import_sdk_core10.publishLocationRecord)({
3403
3696
  registryUrl,
3404
3697
  subject: this.credentialHolderDid,
3405
3698
  nodeOrigin: node.origin,
@@ -3416,7 +3709,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3416
3709
  */
3417
3710
  get did() {
3418
3711
  if (this._address) {
3419
- return (0, import_sdk_core9.pkhDid)(this._address, this._chainId);
3712
+ return (0, import_sdk_core10.pkhDid)(this._address, this._chainId);
3420
3713
  }
3421
3714
  return this.sessionManager.getDID(this.sessionKeyId);
3422
3715
  }
@@ -3453,7 +3746,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3453
3746
  /** Normalize signed capabilities without collapsing nested encryption into raw authority. */
3454
3747
  projectSignedRecapCapabilities(siwe) {
3455
3748
  const projected = this.parseRecapWithCaveats(siwe).map((entry) => {
3456
- const normalized = (0, import_sdk_core9.parseRecapCapabilities)(() => [entry], siwe)[0];
3749
+ const normalized = (0, import_sdk_core10.parseRecapCapabilities)(() => [entry], siwe)[0];
3457
3750
  if (normalized.service !== "tinycloud.encryption") return normalized;
3458
3751
  if (!this.isEncryptionNetworkOperation("encryption", entry.path, entry.space)) {
3459
3752
  return { ...normalized, space: entry.space };
@@ -3498,14 +3791,14 @@ var _TinyCloudNode = class _TinyCloudNode {
3498
3791
  if (!this._address) {
3499
3792
  return void 0;
3500
3793
  }
3501
- return this.wasmBindings.makeSpaceId(this._address, this._chainId, import_sdk_core9.ACCOUNT_REGISTRY_SPACE);
3794
+ return this.wasmBindings.makeSpaceId(this._address, this._chainId, import_sdk_core10.ACCOUNT_REGISTRY_SPACE);
3502
3795
  }
3503
3796
  /**
3504
3797
  * Account-level application and delegation helpers.
3505
3798
  */
3506
3799
  get account() {
3507
3800
  if (!this._account) {
3508
- this._account = new import_sdk_core5.AccountService({
3801
+ this._account = new import_sdk_core6.AccountService({
3509
3802
  getDid: () => this.did,
3510
3803
  getHost: () => this.hosts[0] ?? this.config.host,
3511
3804
  getPrimarySpaceId: () => this.spaceId,
@@ -3551,7 +3844,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3551
3844
  }
3552
3845
  await this.accountRegistryTail;
3553
3846
  await this.wasmBindings.ensureInitialized?.();
3554
- this._address = (0, import_sdk_core9.canonicalizeAddress)(await this.signer.getAddress());
3847
+ this._address = (0, import_sdk_core10.canonicalizeAddress)(await this.signer.getAddress());
3555
3848
  this._chainId = await this.signer.getChainId();
3556
3849
  this._kv = void 0;
3557
3850
  this._sql = void 0;
@@ -3568,6 +3861,9 @@ var _TinyCloudNode = class _TinyCloudNode {
3568
3861
  this.confirmedHostedSpaceIds.clear();
3569
3862
  await this.tc.signIn(options);
3570
3863
  this.syncResolvedHostFromAuth();
3864
+ this.replicationDelegateSession = void 0;
3865
+ this.replicationScopeError = void 0;
3866
+ if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
3571
3867
  const oldGraph = this._serviceGraph;
3572
3868
  this._serviceGraph = this.createServiceGraphLifetime();
3573
3869
  oldGraph.retire();
@@ -3577,7 +3873,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3577
3873
  this.sessionKeyId = signedInSession.sessionKey;
3578
3874
  this.sessionKeyJwk = signedInSession.jwk;
3579
3875
  }
3580
- this.initializeServices();
3876
+ await this.initializeServices();
3581
3877
  const primarySession = this.currentTinyCloudSession();
3582
3878
  if (primarySession) {
3583
3879
  this.registerPrimarySessionGrant(primarySession);
@@ -3585,10 +3881,11 @@ var _TinyCloudNode = class _TinyCloudNode {
3585
3881
  const bootstrapped = await this.bootstrapAccountIfNeeded();
3586
3882
  await this.ensureRequestedEncryptionNetworks();
3587
3883
  if (!bootstrapped && this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
3588
- await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core9.SECRETS_SPACE));
3884
+ await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core10.SECRETS_SPACE));
3589
3885
  }
3590
3886
  if (!bootstrapped) {
3591
3887
  this.scheduleAccountRegistrySync();
3888
+ await this.accountRegistryTail;
3592
3889
  }
3593
3890
  this.notificationHandler.success("Successfully signed in");
3594
3891
  }
@@ -3616,7 +3913,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3616
3913
  this._bootstrapStatus = { skipped: true, reason: "interactive-signer" };
3617
3914
  return false;
3618
3915
  }
3619
- const steps = (0, import_sdk_core9.bootstrapSteps)(this._address, this._chainId);
3916
+ const steps = (0, import_sdk_core10.bootstrapSteps)(this._address, this._chainId);
3620
3917
  try {
3621
3918
  const decision = await this.resolveBootstrapDecision(steps);
3622
3919
  if (decision.action === "skip") {
@@ -3654,7 +3951,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3654
3951
  if (!auth) {
3655
3952
  throw new Error("Account bootstrap requires an active wallet session");
3656
3953
  }
3657
- const accountSpaceId = this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE);
3954
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core10.ACCOUNT_REGISTRY_SPACE);
3658
3955
  const skipped = auth.lastActivationSkippedSpaceIds;
3659
3956
  if (skipped.includes(accountSpaceId)) return { action: "run", mode: "fresh" };
3660
3957
  if (skipped.some((spaceId) => enshrinedSpaceIds.has(spaceId))) {
@@ -3677,7 +3974,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3677
3974
  }
3678
3975
  return { action: "run", mode: "repair" };
3679
3976
  }
3680
- if (marker.error.code === import_sdk_core9.ErrorCodes.KV_NOT_FOUND && this.markerReadIsUnhostedSpace(marker.error.meta)) {
3977
+ if (marker.error.code === import_sdk_core10.ErrorCodes.KV_NOT_FOUND && this.markerReadIsUnhostedSpace(marker.error.meta)) {
3681
3978
  return { action: "run", mode: "fresh" };
3682
3979
  }
3683
3980
  } catch (err) {
@@ -3691,7 +3988,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3691
3988
  return { action: "run", mode: "repair" };
3692
3989
  }
3693
3990
  async readBootstrapCompletionMarker() {
3694
- return this.kvForSpace(this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE)).get(
3991
+ return this.kvForSpace(this.ownedSpaceId(import_sdk_core10.ACCOUNT_REGISTRY_SPACE)).get(
3695
3992
  BOOTSTRAP_COMPLETION_MARKER_KEY
3696
3993
  );
3697
3994
  }
@@ -3700,7 +3997,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3700
3997
  throw new Error("Bootstrap completion marker requires an active wallet session");
3701
3998
  }
3702
3999
  const canonicalStepIds = new Set(
3703
- (0, import_sdk_core9.bootstrapSteps)(this._address, this._chainId).map((step) => step.id)
4000
+ (0, import_sdk_core10.bootstrapSteps)(this._address, this._chainId).map((step) => step.id)
3704
4001
  );
3705
4002
  const providedStepIds = new Set(steps.map((step) => step.id));
3706
4003
  if (canonicalStepIds.size !== providedStepIds.size || [...canonicalStepIds].some((stepId) => !providedStepIds.has(stepId))) {
@@ -3711,7 +4008,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3711
4008
  stepIds: [...canonicalStepIds],
3712
4009
  completedAt: (/* @__PURE__ */ new Date()).toISOString()
3713
4010
  };
3714
- const written = await this.kvForSpace(this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE)).put(
4011
+ const written = await this.kvForSpace(this.ownedSpaceId(import_sdk_core10.ACCOUNT_REGISTRY_SPACE)).put(
3715
4012
  BOOTSTRAP_COMPLETION_MARKER_KEY,
3716
4013
  marker
3717
4014
  );
@@ -3750,7 +4047,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3750
4047
  const warnings = [];
3751
4048
  const primarySession = auth.tinyCloudSession;
3752
4049
  const defaultSpaceId = this.ownedSpaceId("default");
3753
- const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default;
4050
+ const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core10.BOOTSTRAP_SESSION_REQUESTS.default;
3754
4051
  for (const step of steps) {
3755
4052
  if (step.kind !== "session") continue;
3756
4053
  if (step.space === "default" && canReusePrimaryBootstrapSession && primarySession) {
@@ -3765,7 +4062,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3765
4062
  try {
3766
4063
  session = await auth.createBootstrapSession({
3767
4064
  spaceId: step.spaceId,
3768
- capabilityRequest: step.request ?? import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS[step.space],
4065
+ capabilityRequest: step.request ?? import_sdk_core10.BOOTSTRAP_SESSION_REQUESTS[step.space],
3769
4066
  rawAbilities
3770
4067
  });
3771
4068
  } catch (err) {
@@ -3795,7 +4092,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3795
4092
  if (!session) {
3796
4093
  throw new Error(`Missing bootstrap session for ${step.space}`);
3797
4094
  }
3798
- const activated = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader);
4095
+ const activated = await (0, import_sdk_core10.activateSessionWithHost)(host, session.delegationHeader);
3799
4096
  if (!activated.success || activated.skipped?.includes(step.spaceId)) {
3800
4097
  throw Object.assign(
3801
4098
  new Error(
@@ -3806,7 +4103,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3806
4103
  }
3807
4104
  this.registerBootstrapRuntimeGrant(
3808
4105
  session,
3809
- import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS[step.space],
4106
+ import_sdk_core10.BOOTSTRAP_SESSION_REQUESTS[step.space],
3810
4107
  rawAbilitiesBySpace.get(step.space)
3811
4108
  );
3812
4109
  }
@@ -3855,7 +4152,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3855
4152
  }
3856
4153
  if (step.kind === "seed-applications") {
3857
4154
  const registered = await this.account.applications.register(
3858
- step.manifests.length > 0 ? [...step.manifests] : import_sdk_core9.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
4155
+ step.manifests.length > 0 ? [...step.manifests] : import_sdk_core10.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
3859
4156
  // The write is an INSERT OR REPLACE and is safe to repeat during a
3860
4157
  // repair, so skip the manifest-hash pre-read.
3861
4158
  { assumeUnregistered: true }
@@ -3874,7 +4171,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3874
4171
  migrations: [
3875
4172
  {
3876
4173
  id: "001_initial",
3877
- sql: [...import_sdk_core9.SECRET_RECORDS_SCHEMA]
4174
+ sql: [...import_sdk_core10.SECRET_RECORDS_SCHEMA]
3878
4175
  }
3879
4176
  ]
3880
4177
  });
@@ -4041,7 +4338,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4041
4338
  provenance: "primary"
4042
4339
  });
4043
4340
  }
4044
- async writeManifestRegistryRecords() {
4341
+ async writeManifestRegistryRecords(account, signal) {
4045
4342
  const request = this.capabilityRequest;
4046
4343
  if (!request || request.registryRecords.length === 0) {
4047
4344
  return;
@@ -4049,9 +4346,10 @@ var _TinyCloudNode = class _TinyCloudNode {
4049
4346
  if (!this.auth || !this.signer) {
4050
4347
  throw new Error("Manifest registry write requires wallet mode");
4051
4348
  }
4052
- const accountSpaceId = this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE);
4053
- await this.ensureOwnedSpaceHostedById(accountSpaceId);
4054
- const result = await this.account.applications.register(request.manifests);
4349
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core10.ACCOUNT_REGISTRY_SPACE);
4350
+ await this.ensureOwnedSpaceHostedById(accountSpaceId, signal);
4351
+ if (signal.aborted) throw signal.reason;
4352
+ const result = await account.applications.register(request.manifests);
4055
4353
  if (!result.ok) {
4056
4354
  throw Object.assign(
4057
4355
  new Error(`Failed to write manifest registry records: ${result.error.message}`),
@@ -4059,34 +4357,113 @@ var _TinyCloudNode = class _TinyCloudNode {
4059
4357
  );
4060
4358
  }
4061
4359
  }
4360
+ createAccountRegistryServices(context, signal) {
4361
+ const session = context.session;
4362
+ if (!session) throw new Error("Account registry requires an active service session");
4363
+ const contexts = [context];
4364
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core10.ACCOUNT_REGISTRY_SPACE);
4365
+ const createScopedContext = (spaceId) => {
4366
+ const scoped = this._serviceGraph.track(new import_sdk_core10.ServiceContext({
4367
+ invoke: context.invoke,
4368
+ invokeAny: context.invokeAny,
4369
+ fetch: context.fetch,
4370
+ hosts: context.hosts,
4371
+ telemetry: this.config.telemetry
4372
+ }));
4373
+ scoped.setOperationAbortSignal(signal);
4374
+ scoped.setSession({ ...session, spaceId });
4375
+ contexts.push(scoped);
4376
+ return scoped;
4377
+ };
4378
+ const sql = new import_sdk_core10.SQLService({});
4379
+ const sqlContext = createScopedContext(accountSpaceId);
4380
+ sql.initialize(sqlContext);
4381
+ const spaces = new import_sdk_core10.SpaceService({
4382
+ hosts: context.hosts,
4383
+ session,
4384
+ invoke: context.invoke,
4385
+ fetch: (url, init) => context.fetch(url, {
4386
+ ...init,
4387
+ signal: init?.signal ? AbortSignal.any([init.signal, signal]) : signal
4388
+ }),
4389
+ userDid: this.did,
4390
+ createKVService: (spaceId) => {
4391
+ const kv = new import_sdk_core10.KVService({});
4392
+ kv.initialize(createScopedContext(spaceId));
4393
+ return kv;
4394
+ }
4395
+ });
4396
+ return {
4397
+ contexts,
4398
+ account: new import_sdk_core6.AccountService({
4399
+ getDid: () => this.did,
4400
+ getHost: () => context.hosts[0] ?? this.config.host,
4401
+ getPrimarySpaceId: () => session.spaceId,
4402
+ getAccountSpaceId: () => accountSpaceId,
4403
+ getSpaces: () => spaces,
4404
+ getAccountDb: () => sql.db("account"),
4405
+ ensureAccountSpaceHosted: () => this.ensureOwnedSpaceHostedById(accountSpaceId, signal)
4406
+ })
4407
+ };
4408
+ }
4062
4409
  scheduleAccountRegistrySync() {
4063
4410
  const session = this.currentTinyCloudSession();
4064
4411
  if (!session || this.pendingAccountRegistrySync?.session === session) {
4065
4412
  return;
4066
4413
  }
4414
+ const controller = new AbortController();
4415
+ const deadline = setTimeout(
4416
+ () => controller.abort(new DOMException("Account registry deadline exceeded", "TimeoutError")),
4417
+ this.accountRegistryDeadlineMs
4418
+ );
4067
4419
  const promise = this.enqueueAccountRegistryOperation(session, async () => {
4068
- await this.withAccountRegistryRetry(async () => {
4069
- if (this.currentTinyCloudSession() !== session) {
4070
- return;
4071
- }
4072
- await this.account.index.ensure();
4073
- if (this.currentTinyCloudSession() !== session) {
4074
- return;
4075
- }
4076
- await this.writeManifestRegistryRecords();
4077
- if (this.currentTinyCloudSession() !== session) {
4078
- return;
4079
- }
4080
- if (this.currentSessionCanListSpaces()) {
4081
- const spaces = await this.account.spaces.syncAccessible();
4082
- if (!spaces.ok) {
4083
- throw Object.assign(
4084
- new Error(`Failed to sync account spaces: ${spaces.error.message}`),
4085
- { cause: spaces.error }
4086
- );
4420
+ const sharedContext = this._serviceContext;
4421
+ if (!sharedContext) return;
4422
+ const context = this._serviceGraph.track(new import_sdk_core10.ServiceContext({
4423
+ invoke: sharedContext.invoke,
4424
+ invokeAny: sharedContext.invokeAny,
4425
+ fetch: sharedContext.fetch,
4426
+ hosts: sharedContext.hosts,
4427
+ telemetry: this.config.telemetry
4428
+ }));
4429
+ context.setOperationAbortSignal(controller.signal);
4430
+ const current = this.currentTinyCloudSession();
4431
+ if (!current) return;
4432
+ context.setSession({
4433
+ delegationHeader: current.delegationHeader,
4434
+ delegationCid: current.delegationCid,
4435
+ spaceId: current.spaceId,
4436
+ verificationMethod: current.verificationMethod,
4437
+ jwk: current.jwk
4438
+ });
4439
+ const registry = this.createAccountRegistryServices(context, controller.signal);
4440
+ try {
4441
+ await this.withAccountRegistryRetry(async () => {
4442
+ if (controller.signal.aborted) throw controller.signal.reason;
4443
+ if (this.currentTinyCloudSession() !== session) return;
4444
+ await registry.account.index.ensure();
4445
+ if (controller.signal.aborted) throw controller.signal.reason;
4446
+ if (this.currentTinyCloudSession() !== session) return;
4447
+ await this.writeManifestRegistryRecords(registry.account, controller.signal);
4448
+ if (controller.signal.aborted) throw controller.signal.reason;
4449
+ if (this.currentTinyCloudSession() !== session) return;
4450
+ if (this.currentSessionCanListSpaces()) {
4451
+ const result = await registry.account.spaces.syncAccessible();
4452
+ if (controller.signal.aborted) throw controller.signal.reason;
4453
+ if (!result.ok) {
4454
+ throw Object.assign(
4455
+ new Error(`Failed to sync account spaces: ${result.error.message}`),
4456
+ { cause: result.error }
4457
+ );
4458
+ }
4087
4459
  }
4460
+ }, controller.signal);
4461
+ } finally {
4462
+ for (const operationContext of registry.contexts) {
4463
+ operationContext.retire();
4088
4464
  }
4089
- });
4465
+ clearTimeout(deadline);
4466
+ }
4090
4467
  });
4091
4468
  this.pendingAccountRegistrySync = { session, promise };
4092
4469
  const clearPendingSync = () => {
@@ -4095,6 +4472,10 @@ var _TinyCloudNode = class _TinyCloudNode {
4095
4472
  }
4096
4473
  };
4097
4474
  void promise.then(clearPendingSync, clearPendingSync);
4475
+ void promise.then(
4476
+ () => clearTimeout(deadline),
4477
+ () => clearTimeout(deadline)
4478
+ );
4098
4479
  }
4099
4480
  enqueueAccountRegistryOperation(session, task) {
4100
4481
  const operation = this.accountRegistryTail.then(async () => {
@@ -4130,15 +4511,23 @@ var _TinyCloudNode = class _TinyCloudNode {
4130
4511
  (operation) => operation.service === "space" && this.actionContains(operation.action, "tinycloud.space/list")
4131
4512
  );
4132
4513
  }
4133
- async withAccountRegistryRetry(task) {
4514
+ async withAccountRegistryRetry(task, signal) {
4134
4515
  const delays = [250, 1e3, 3e3];
4135
4516
  let lastError;
4136
4517
  for (let attempt = 0; attempt < delays.length; attempt += 1) {
4518
+ if (signal.aborted) {
4519
+ console.warn("TinyCloud account registry sync stopped: deadline exceeded", signal.reason);
4520
+ return;
4521
+ }
4137
4522
  try {
4138
4523
  await task();
4139
4524
  return;
4140
4525
  } catch (error) {
4141
- const verdict = (0, import_sdk_core9.authorizationVerdictOf)(error);
4526
+ if (signal.aborted) {
4527
+ console.warn("TinyCloud account registry sync stopped: deadline exceeded", error);
4528
+ return;
4529
+ }
4530
+ const verdict = (0, import_sdk_core10.authorizationVerdictOf)(error);
4142
4531
  const message = error instanceof Error ? error.message : String(error);
4143
4532
  const isAuthorizationVerdict = verdict === void 0 ? /Unauthorized Action|\b(?:401|403)\b/.test(message) : verdict !== "other";
4144
4533
  if (isAuthorizationVerdict) {
@@ -4148,13 +4537,29 @@ var _TinyCloudNode = class _TinyCloudNode {
4148
4537
  );
4149
4538
  return;
4150
4539
  }
4151
- if ((0, import_sdk_core9.isStorageFullError)(error) || (0, import_sdk_core9.isStorageFullError)(error?.cause) || message.includes(import_sdk_core9.STORAGE_FULL_MESSAGE) || message.includes(import_sdk_core9.STORAGE_WRITE_TOO_LARGE_MESSAGE)) {
4152
- console.warn("TinyCloud account registry sync stopped: storage is full", error);
4540
+ if ((0, import_sdk_core10.isStorageFullError)(error) || (0, import_sdk_core10.isStorageFullError)(error?.cause) || message.includes(import_sdk_core10.STORAGE_FULL_MESSAGE) || message.includes(import_sdk_core10.STORAGE_WRITE_TOO_LARGE_MESSAGE)) {
4541
+ console.warn(
4542
+ "TinyCloud account registry sync stopped: storage is full",
4543
+ error
4544
+ );
4153
4545
  return;
4154
4546
  }
4155
4547
  lastError = error;
4156
4548
  if (attempt < delays.length - 1) {
4157
- await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
4549
+ await new Promise((resolve, reject2) => {
4550
+ const timer = setTimeout(() => {
4551
+ signal.removeEventListener("abort", onAbort);
4552
+ resolve();
4553
+ }, delays[attempt]);
4554
+ const onAbort = () => {
4555
+ clearTimeout(timer);
4556
+ signal.removeEventListener("abort", onAbort);
4557
+ reject2(signal.reason);
4558
+ };
4559
+ signal.addEventListener("abort", onAbort, { once: true });
4560
+ }).catch((error2) => {
4561
+ if (!signal.aborted) throw error2;
4562
+ });
4158
4563
  }
4159
4564
  }
4160
4565
  }
@@ -4170,7 +4575,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4170
4575
  }
4171
4576
  const networkIds = /* @__PURE__ */ new Set();
4172
4577
  for (const resource of request.resources) {
4173
- if (resource.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
4578
+ if (resource.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
4174
4579
  networkIds.add(resource.path);
4175
4580
  }
4176
4581
  }
@@ -4181,7 +4586,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4181
4586
  return;
4182
4587
  }
4183
4588
  for (const networkId of this.requestedEncryptionNetworkIds()) {
4184
- const parsed = (0, import_sdk_core9.parseNetworkId)(networkId);
4589
+ const parsed = (0, import_sdk_core10.parseNetworkId)(networkId);
4185
4590
  if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
4186
4591
  continue;
4187
4592
  }
@@ -4204,7 +4609,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4204
4609
  * self-revealing: the next write to the space fails immediately and loudly
4205
4610
  * with `404 Space not found`.
4206
4611
  */
4207
- async ensureOwnedSpaceHostedById(spaceId) {
4612
+ async ensureOwnedSpaceHostedById(spaceId, signal) {
4208
4613
  if (!this.auth) {
4209
4614
  throw new Error("Owned space hosting requires wallet mode");
4210
4615
  }
@@ -4219,7 +4624,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4219
4624
  if (!host) {
4220
4625
  throw new Error("Owned space hosting requires a TinyCloud host");
4221
4626
  }
4222
- const activation = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader);
4627
+ const activation = await (0, import_sdk_core10.activateSessionWithHost)(host, session.delegationHeader, signal);
4223
4628
  if (activation.success && !activation.skipped?.includes(spaceId)) {
4224
4629
  this.confirmedHostedSpaceIds.add(spaceId);
4225
4630
  return;
@@ -4230,15 +4635,16 @@ var _TinyCloudNode = class _TinyCloudNode {
4230
4635
  { cause: activation }
4231
4636
  );
4232
4637
  }
4233
- const created = await this.auth.hostOwnedSpaceResult(spaceId);
4638
+ const authorization = this.auth;
4639
+ const created = signal ? await authorization.hostOwnedSpaceResult(spaceId, void 0, signal) : await authorization.hostOwnedSpaceResult(spaceId);
4234
4640
  if (!created.success) {
4235
4641
  throw Object.assign(
4236
4642
  new Error(`Failed to create owned space ${spaceId}: ${describeHostFailure2(created)}`),
4237
4643
  { cause: created }
4238
4644
  );
4239
4645
  }
4240
- await new Promise((resolve) => setTimeout(resolve, 100));
4241
- const retry = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader);
4646
+ if (signal?.aborted) throw signal.reason;
4647
+ const retry = await (0, import_sdk_core10.activateSessionWithHost)(host, session.delegationHeader, signal);
4242
4648
  if (!retry.success || retry.skipped?.includes(spaceId)) {
4243
4649
  throw Object.assign(
4244
4650
  new Error(
@@ -4286,7 +4692,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4286
4692
  { cause: hosted }
4287
4693
  );
4288
4694
  }
4289
- const activation = await (0, import_sdk_core9.activateSessionWithHost)(
4695
+ const activation = await (0, import_sdk_core10.activateSessionWithHost)(
4290
4696
  host,
4291
4697
  session.delegationHeader
4292
4698
  );
@@ -4474,7 +4880,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4474
4880
  }
4475
4881
  let restoredAddress;
4476
4882
  try {
4477
- restoredAddress = hasPersistedProof ? (0, import_sdk_core9.canonicalizeAddress)(sessionData.address) : void 0;
4883
+ restoredAddress = hasPersistedProof ? (0, import_sdk_core10.canonicalizeAddress)(sessionData.address) : void 0;
4478
4884
  } catch {
4479
4885
  throw new InvalidRestoredSessionError("Persisted session has an invalid wallet address.");
4480
4886
  }
@@ -4516,7 +4922,35 @@ var _TinyCloudNode = class _TinyCloudNode {
4516
4922
  const stagedHost = resolvedHost ?? this.config.host;
4517
4923
  const stagedAddress = restoredAddress;
4518
4924
  const stagedChainId = sessionData.chainId ?? 1;
4519
- const stagedNodeDid = stagedAddress ? (0, import_sdk_core9.pkhDid)(stagedAddress, stagedChainId) : canonicalVerificationMethod;
4925
+ let replicationPrincipal;
4926
+ let compactReplicationSession;
4927
+ let replicationScopeError;
4928
+ if (this.config.replication?.enabled) {
4929
+ if (stagedAddress !== void 0) {
4930
+ replicationPrincipal = (0, import_sdk_core10.pkhDid)(stagedAddress, stagedChainId);
4931
+ } else {
4932
+ const { replicationScopeFromSignedSession } = await getNodeReplicationLoaders().authority();
4933
+ const signedScope = replicationScopeFromSignedSession({
4934
+ delegationHeader: sessionData.delegationHeader,
4935
+ delegationCid: sessionData.delegationCid,
4936
+ verificationMethod: restoredVerificationMethod,
4937
+ persistedSpace: sessionData.spaceId
4938
+ });
4939
+ if (!signedScope) {
4940
+ replicationScopeError = "Persisted space does not match the locally verified delegation scope.";
4941
+ } else {
4942
+ replicationPrincipal = signedScope.principal;
4943
+ compactReplicationSession = {
4944
+ delegationHeader: sessionData.delegationHeader,
4945
+ delegationCid: sessionData.delegationCid,
4946
+ spaceId: signedScope.space,
4947
+ verificationMethod: restoredVerificationMethod,
4948
+ jwk: stagedJwk
4949
+ };
4950
+ }
4951
+ }
4952
+ }
4953
+ const stagedNodeDid = stagedAddress ? (0, import_sdk_core10.pkhDid)(stagedAddress, stagedChainId) : canonicalVerificationMethod;
4520
4954
  const serviceSession = {
4521
4955
  delegationHeader: sessionData.delegationHeader,
4522
4956
  delegationCid: sessionData.delegationCid,
@@ -4544,7 +4978,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4544
4978
  stagedSessionExpiry,
4545
4979
  stagedRecap
4546
4980
  );
4547
- const stagedAccountSpaceId = stagedAddress ? this.wasmBindings.makeSpaceId(stagedAddress, stagedChainId, import_sdk_core9.ACCOUNT_REGISTRY_SPACE) : void 0;
4981
+ const stagedAccountSpaceId = stagedAddress ? this.wasmBindings.makeSpaceId(stagedAddress, stagedChainId, import_sdk_core10.ACCOUNT_REGISTRY_SPACE) : void 0;
4548
4982
  const stagedGraph = this.stageRestoredServiceGraph({
4549
4983
  host: stagedHost,
4550
4984
  manager: stagedManager,
@@ -4594,7 +5028,18 @@ var _TinyCloudNode = class _TinyCloudNode {
4594
5028
  } else {
4595
5029
  this._restoredTcSession = stagedTcSession;
4596
5030
  }
5031
+ this.replicationDelegateSession = compactReplicationSession;
5032
+ this.replicationScopeError = replicationScopeError;
5033
+ if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
4597
5034
  oldGraph.retire();
5035
+ if (replicationScopeError) {
5036
+ stagedGraph.serviceContext.emit("replication.state", {
5037
+ state: "unavailable",
5038
+ code: "SESSION_SCOPE_MISMATCH",
5039
+ detail: replicationScopeError
5040
+ });
5041
+ }
5042
+ await this.bindReplicationRuntime(stagedGraph.serviceContext, serviceSession, stagedGraph.kv, replicationPrincipal);
4598
5043
  oldCore?.retireServices?.();
4599
5044
  }
4600
5045
  stagePrimarySessionState(session, verificationMethod, host, sessionExpiry, recap) {
@@ -4645,7 +5090,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4645
5090
  }
4646
5091
  stageRestoredServiceGraph(input) {
4647
5092
  const graph = this.createServiceGraphLifetime();
4648
- const core = this.auth ? new import_sdk_core9.TinyCloud(this.auth, {
5093
+ const core = this.auth ? new import_sdk_core10.TinyCloud(this.auth, {
4649
5094
  invokeAny: graph.invokeAny,
4650
5095
  telemetry: this.config.telemetry
4651
5096
  }) : null;
@@ -4654,23 +5099,23 @@ var _TinyCloudNode = class _TinyCloudNode {
4654
5099
  const coreContext = graph.track(core.serviceContext);
4655
5100
  coreContext.setSession(input.serviceSession);
4656
5101
  }
4657
- const serviceContext = graph.track(new import_sdk_core9.ServiceContext({
5102
+ const serviceContext = graph.track(new import_sdk_core10.ServiceContext({
4658
5103
  invoke: graph.invoke,
4659
5104
  invokeAny: graph.invokeAny,
4660
5105
  fetch: graph.fetch,
4661
5106
  hosts: [input.host],
4662
5107
  telemetry: this.config.telemetry
4663
5108
  }));
4664
- const kv = new import_sdk_core9.KVService({});
5109
+ const kv = new import_sdk_core10.KVService({});
4665
5110
  kv.initialize(serviceContext);
4666
5111
  serviceContext.registerService("kv", kv);
4667
- const sql = new import_sdk_core9.SQLService({});
5112
+ const sql = new import_sdk_core10.SQLService({});
4668
5113
  sql.initialize(serviceContext);
4669
5114
  serviceContext.registerService("sql", sql);
4670
- const duckdb = new import_sdk_core9.DuckDbService({});
5115
+ const duckdb = new import_sdk_core10.DuckDbService({});
4671
5116
  duckdb.initialize(serviceContext);
4672
5117
  serviceContext.registerService("duckdb", duckdb);
4673
- const hooks = new import_sdk_core9.HooksService({});
5118
+ const hooks = new import_sdk_core10.HooksService({});
4674
5119
  hooks.initialize(serviceContext);
4675
5120
  serviceContext.registerService("hooks", hooks);
4676
5121
  serviceContext.setSession(input.serviceSession);
@@ -4693,7 +5138,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4693
5138
  });
4694
5139
  vault.initialize(serviceContext);
4695
5140
  serviceContext.registerService("vault", vault);
4696
- const capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
5141
+ const capabilityRegistry = new import_sdk_core10.CapabilityKeyRegistry();
4697
5142
  if (input.tinyCloudSession) {
4698
5143
  const session = input.tinyCloudSession;
4699
5144
  const delegations = input.recap.map((entry) => ({
@@ -4717,7 +5162,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4717
5162
  }, delegations);
4718
5163
  }
4719
5164
  }
4720
- const delegationManager = new import_sdk_core9.DelegationManager({
5165
+ const delegationManager = new import_sdk_core10.DelegationManager({
4721
5166
  hosts: [input.host],
4722
5167
  accountSpaceId: input.accountSpaceId,
4723
5168
  session: input.serviceSession,
@@ -4726,7 +5171,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4726
5171
  fetch: graph.fetch
4727
5172
  });
4728
5173
  const keyProvider = new WasmKeyProvider({ sessionManager: input.manager });
4729
- const sharingService = new import_sdk_core9.SharingService({
5174
+ const sharingService = new import_sdk_core10.SharingService({
4730
5175
  hosts: [input.host],
4731
5176
  invoke: graph.invoke,
4732
5177
  fetch: graph.fetch,
@@ -4739,8 +5184,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4739
5184
  return this.wasmBindings.computeCid(data, codec);
4740
5185
  },
4741
5186
  createKVService: (config) => {
4742
- const service = new import_sdk_core9.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
4743
- const context = graph.track(new import_sdk_core9.ServiceContext({
5187
+ const service = new import_sdk_core10.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
5188
+ const context = graph.track(new import_sdk_core10.ServiceContext({
4744
5189
  invoke: config.invoke,
4745
5190
  fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
4746
5191
  hosts: config.hosts,
@@ -4748,6 +5193,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4748
5193
  }));
4749
5194
  context.setSession(config.session);
4750
5195
  service.initialize(context);
5196
+ this.attachReplicationKV(config.session.spaceId, service);
4751
5197
  return service;
4752
5198
  }
4753
5199
  });
@@ -4769,7 +5215,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4769
5215
  return delegation;
4770
5216
  } : void 0
4771
5217
  });
4772
- const spaceService = new import_sdk_core9.SpaceService({
5218
+ const spaceService = new import_sdk_core10.SpaceService({
4773
5219
  hosts: [input.host],
4774
5220
  session: input.serviceSession,
4775
5221
  invoke: graph.invoke,
@@ -4778,8 +5224,8 @@ var _TinyCloudNode = class _TinyCloudNode {
4778
5224
  userDid: input.nodeDid,
4779
5225
  createKVService: (spaceId) => {
4780
5226
  graph.assertActive();
4781
- const scopedKv = new import_sdk_core9.KVService({});
4782
- const context = graph.track(new import_sdk_core9.ServiceContext({
5227
+ const scopedKv = new import_sdk_core10.KVService({});
5228
+ const context = graph.track(new import_sdk_core10.ServiceContext({
4783
5229
  invoke: graph.invoke,
4784
5230
  invokeAny: graph.invokeAny,
4785
5231
  fetch: graph.fetch,
@@ -4788,12 +5234,13 @@ var _TinyCloudNode = class _TinyCloudNode {
4788
5234
  }));
4789
5235
  context.setSession({ ...input.serviceSession, spaceId });
4790
5236
  scopedKv.initialize(context);
5237
+ this.attachReplicationKV(spaceId, scopedKv);
4791
5238
  return scopedKv;
4792
5239
  },
4793
5240
  createVaultService: (spaceId) => {
4794
5241
  graph.assertActive();
4795
- const scopedKv = new import_sdk_core9.KVService({});
4796
- const context = graph.track(new import_sdk_core9.ServiceContext({
5242
+ const scopedKv = new import_sdk_core10.KVService({});
5243
+ const context = graph.track(new import_sdk_core10.ServiceContext({
4797
5244
  invoke: graph.invoke,
4798
5245
  invokeAny: graph.invokeAny,
4799
5246
  fetch: graph.fetch,
@@ -4802,6 +5249,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4802
5249
  }));
4803
5250
  context.setSession({ ...input.serviceSession, spaceId });
4804
5251
  scopedKv.initialize(context);
5252
+ this.attachReplicationKV(spaceId, scopedKv);
4805
5253
  const scopedVault = this.createVaultService(spaceId, scopedKv, encryption, {
4806
5254
  host: input.host,
4807
5255
  did: input.nodeDid,
@@ -4879,7 +5327,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4879
5327
  if (address === void 0 || chainId === void 0) {
4880
5328
  return void 0;
4881
5329
  }
4882
- const resolved = await (0, import_sdk_core9.resolveTinyCloudHosts)((0, import_sdk_core9.pkhDid)(address, chainId), {
5330
+ const resolved = await (0, import_sdk_core10.resolveTinyCloudHosts)((0, import_sdk_core10.pkhDid)(address, chainId), {
4883
5331
  registryUrl: this.config.tinycloudRegistryUrl,
4884
5332
  fallbackHosts: this.config.tinycloudFallbackHosts,
4885
5333
  autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
@@ -4931,7 +5379,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4931
5379
  nodeAudience: input.nodeAudience,
4932
5380
  ...input.role === "policy-enforcement" ? { enforcerDid: input.audienceDid } : {}
4933
5381
  };
4934
- const root = await (0, import_sdk_core9.signCompactUcanRootAuthorization)({
5382
+ const root = await (0, import_sdk_core10.signCompactUcanRootAuthorization)({
4935
5383
  issuerDid: ownerDid,
4936
5384
  audienceDid: input.audienceDid,
4937
5385
  attenuation: unifiedRootAttenuation(input.capabilities),
@@ -4973,7 +5421,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4973
5421
  if (decision.needsApproval) return void 0;
4974
5422
  throw new Error(decision.reason ?? "OpenKey automatic credential signing was rejected");
4975
5423
  }
4976
- if (typeof decision.signature !== "string" || !await (0, import_sdk_core9.verifyEip191MessageSignature)(
5424
+ if (typeof decision.signature !== "string" || !await (0, import_sdk_core10.verifyEip191MessageSignature)(
4977
5425
  request.message,
4978
5426
  decision.signature,
4979
5427
  request.address
@@ -4998,7 +5446,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4998
5446
  if (approval) {
4999
5447
  const decision = await approval(request);
5000
5448
  if (!decision.approved) throw new Error(decision.reason ?? "Credential signing was rejected");
5001
- if (decision.signature !== void 0 && !await (0, import_sdk_core9.verifyEip191MessageSignature)(
5449
+ if (decision.signature !== void 0 && !await (0, import_sdk_core10.verifyEip191MessageSignature)(
5002
5450
  request.message,
5003
5451
  decision.signature,
5004
5452
  request.address
@@ -5081,10 +5529,15 @@ var _TinyCloudNode = class _TinyCloudNode {
5081
5529
  nonce: this.config.nonce,
5082
5530
  siweConfig: this.config.siweConfig,
5083
5531
  manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
5084
- capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core9.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
5085
- includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
5532
+ capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core10.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core10.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
5533
+ includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions,
5534
+ replication: this.config.replication?.enabled === true ? {
5535
+ enabled: true,
5536
+ prefixes: this.config.replication.prefixes,
5537
+ allowSecrets: this.config.replication.allowSecrets === true
5538
+ } : void 0
5086
5539
  });
5087
- this.tc = new import_sdk_core9.TinyCloud(this.auth, {
5540
+ this.tc = new import_sdk_core10.TinyCloud(this.auth, {
5088
5541
  invokeAny: this.invokeAnyWithRuntimePermissions,
5089
5542
  telemetry: this.config.telemetry
5090
5543
  });
@@ -5134,10 +5587,15 @@ var _TinyCloudNode = class _TinyCloudNode {
5134
5587
  nonce: this.config.nonce,
5135
5588
  siweConfig: this.config.siweConfig,
5136
5589
  manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
5137
- capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core9.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
5138
- includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
5590
+ capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core10.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core10.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
5591
+ includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions,
5592
+ replication: this.config.replication?.enabled === true ? {
5593
+ enabled: true,
5594
+ prefixes: this.config.replication.prefixes,
5595
+ allowSecrets: this.config.replication.allowSecrets === true
5596
+ } : void 0
5139
5597
  });
5140
- this.tc = new import_sdk_core9.TinyCloud(this.auth, {
5598
+ this.tc = new import_sdk_core10.TinyCloud(this.auth, {
5141
5599
  invokeAny: this.invokeAnyWithRuntimePermissions,
5142
5600
  telemetry: this.config.telemetry
5143
5601
  });
@@ -5147,7 +5605,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5147
5605
  * Initialize the service context and KV service after sign-in.
5148
5606
  * @internal
5149
5607
  */
5150
- initializeServices() {
5608
+ async initializeServices() {
5151
5609
  const session = this.currentTinyCloudSession();
5152
5610
  if (!session) {
5153
5611
  return;
@@ -5158,28 +5616,28 @@ var _TinyCloudNode = class _TinyCloudNode {
5158
5616
  this._serviceGraph.fetch
5159
5617
  );
5160
5618
  this._serviceGraph.track(this.tc.serviceContext);
5161
- this._serviceContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
5619
+ this._serviceContext = this._serviceGraph.track(new import_sdk_core10.ServiceContext({
5162
5620
  invoke: this._serviceGraph.invoke,
5163
5621
  invokeAny: this._serviceGraph.invokeAny,
5164
5622
  fetch: this._serviceGraph.fetch,
5165
5623
  hosts: [this.config.host],
5166
5624
  telemetry: this.config.telemetry
5167
5625
  }));
5168
- this._kv = new import_sdk_core9.KVService({});
5626
+ this._kv = new import_sdk_core10.KVService({});
5169
5627
  this._kv.initialize(this._serviceContext);
5170
5628
  this._serviceContext.registerService("kv", this._kv);
5171
5629
  const features = this.nodeFeatures;
5172
5630
  if (features.length === 0 || features.includes("sql")) {
5173
- this._sql = new import_sdk_core9.SQLService({});
5631
+ this._sql = new import_sdk_core10.SQLService({});
5174
5632
  this._sql.initialize(this._serviceContext);
5175
5633
  this._serviceContext.registerService("sql", this._sql);
5176
5634
  }
5177
5635
  if (features.length === 0 || features.includes("duckdb")) {
5178
- this._duckdb = new import_sdk_core9.DuckDbService({});
5636
+ this._duckdb = new import_sdk_core10.DuckDbService({});
5179
5637
  this._duckdb.initialize(this._serviceContext);
5180
5638
  this._serviceContext.registerService("duckdb", this._duckdb);
5181
5639
  }
5182
- this._hooks = new import_sdk_core9.HooksService({});
5640
+ this._hooks = new import_sdk_core10.HooksService({});
5183
5641
  this._hooks.initialize(this._serviceContext);
5184
5642
  this._serviceContext.registerService("hooks", this._hooks);
5185
5643
  const serviceSession = {
@@ -5190,16 +5648,22 @@ var _TinyCloudNode = class _TinyCloudNode {
5190
5648
  jwk: session.jwk
5191
5649
  };
5192
5650
  this._serviceContext.setSession(serviceSession);
5651
+ await this.bindReplicationRuntime(this._serviceContext, serviceSession, this._kv);
5193
5652
  this.tc.serviceContext.setSession(serviceSession);
5194
5653
  this._vault = this.createVaultService(session.spaceId, this._kv);
5195
5654
  this._vault.initialize(this._serviceContext);
5196
5655
  this._serviceContext.registerService("vault", this._vault);
5197
5656
  this.initializeV2Services(serviceSession);
5198
5657
  }
5658
+ attachReplicationKV(spaceId, kvService) {
5659
+ if (!this.replicationRuntime) return;
5660
+ const attached = this.replicationRuntime.then((runtime) => runtime.attach(spaceId, kvService));
5661
+ kvService.setReadThroughReady(attached);
5662
+ }
5199
5663
  createSpaceScopedKVService(spaceId) {
5200
- const kvService = new import_sdk_core9.KVService({});
5664
+ const kvService = new import_sdk_core10.KVService({});
5201
5665
  if (this._serviceContext) {
5202
- const spaceScopedContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
5666
+ const spaceScopedContext = this._serviceGraph.track(new import_sdk_core10.ServiceContext({
5203
5667
  invoke: this._serviceContext.invoke,
5204
5668
  invokeAny: this._serviceContext.invokeAny,
5205
5669
  fetch: this._serviceContext.fetch,
@@ -5211,6 +5675,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5211
5675
  spaceScopedContext.setSession({ ...session, spaceId });
5212
5676
  }
5213
5677
  kvService.initialize(spaceScopedContext);
5678
+ this.attachReplicationKV(spaceId, kvService);
5214
5679
  }
5215
5680
  return kvService;
5216
5681
  }
@@ -5291,7 +5756,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5291
5756
  const shared = wasm.vault_x25519_dh(receiverPrivateKey, peerPublic);
5292
5757
  return columnDecrypt(shared, ciphertext);
5293
5758
  },
5294
- verifyNodeSignature: (nodeId, message, signature) => (0, import_sdk_core9.verifyDidKeyEd25519Signature)(nodeId, message, signature)
5759
+ verifyNodeSignature: (nodeId, message, signature) => (0, import_sdk_core10.verifyDidKeyEd25519Signature)(nodeId, message, signature)
5295
5760
  };
5296
5761
  }
5297
5762
  /**
@@ -5307,7 +5772,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5307
5772
  if (cached) return cached;
5308
5773
  const response = await fetch(`${this.config.host}/info`);
5309
5774
  if (!response.ok) {
5310
- throw await (0, import_sdk_core9.httpResponseError)(response, "Failed to fetch node info");
5775
+ throw await (0, import_sdk_core10.httpResponseError)(response, "Failed to fetch node info");
5311
5776
  }
5312
5777
  const info = await response.json();
5313
5778
  if (typeof info.nodeId !== "string" || info.nodeId.length === 0) {
@@ -5357,7 +5822,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5357
5822
  );
5358
5823
  if (response.status === 404) return null;
5359
5824
  if (!response.ok) {
5360
- throw await (0, import_sdk_core9.httpResponseError)(response, `Failed to fetch encryption network ${networkId}`);
5825
+ throw await (0, import_sdk_core10.httpResponseError)(response, `Failed to fetch encryption network ${networkId}`);
5361
5826
  }
5362
5827
  const body = await response.json();
5363
5828
  return "descriptor" in body && body.descriptor ? body.descriptor : body;
@@ -5388,17 +5853,17 @@ var _TinyCloudNode = class _TinyCloudNode {
5388
5853
  );
5389
5854
  graph.assertActive();
5390
5855
  if (!response.ok) {
5391
- const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services.parsePermissionHint)({
5856
+ const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services3.parsePermissionHint)({
5392
5857
  service: "tinycloud.encryption",
5393
5858
  path: networkId,
5394
5859
  actions: ["tinycloud.encryption/decrypt"]
5395
5860
  }) : void 0;
5396
- throw new import_sdk_core9.DecryptTransportResponseError(response.status, permissionHint);
5861
+ throw new import_sdk_core10.DecryptTransportResponseError(response.status, permissionHint);
5397
5862
  }
5398
5863
  return await response.json();
5399
5864
  }
5400
5865
  };
5401
- return new import_sdk_core9.EncryptionService({
5866
+ return new import_sdk_core10.EncryptionService({
5402
5867
  crypto: crypto2,
5403
5868
  signer: {
5404
5869
  signDecryptInvocation: async (input) => {
@@ -5412,7 +5877,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5412
5877
  graph.assertActive();
5413
5878
  return {
5414
5879
  ...signed,
5415
- canonicalBody: (0, import_sdk_core9.canonicalizeEncryptionJson)(
5880
+ canonicalBody: (0, import_sdk_core10.canonicalizeEncryptionJson)(
5416
5881
  input.body
5417
5882
  )
5418
5883
  };
@@ -5444,7 +5909,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5444
5909
  if (!address || !didPrincipalMatches2(principal, did)) {
5445
5910
  return null;
5446
5911
  }
5447
- const publicSpaceId = (0, import_sdk_core9.makePublicSpaceId)(address, chainId);
5912
+ const publicSpaceId = (0, import_sdk_core10.makePublicSpaceId)(address, chainId);
5448
5913
  const encodedKey = discoveryKey.split("/").map(encodeURIComponent).join("/");
5449
5914
  const response = await graph.fetch(
5450
5915
  `${host}/public/${encodeURIComponent(publicSpaceId)}/kv/${encodedKey}`,
@@ -5476,7 +5941,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5476
5941
  createVaultService(spaceId, kv, encryptionService = this.getEncryptionService(), nodeContext) {
5477
5942
  const wasm = this.wasmBindings;
5478
5943
  const serviceGraph = nodeContext?.serviceGraph ?? this._serviceGraph;
5479
- const vaultCrypto = (0, import_sdk_core9.createVaultCrypto)({
5944
+ const vaultCrypto = (0, import_sdk_core10.createVaultCrypto)({
5480
5945
  vault_encrypt: wasm.vault_encrypt,
5481
5946
  vault_decrypt: wasm.vault_decrypt,
5482
5947
  vault_derive_key: wasm.vault_derive_key,
@@ -5491,7 +5956,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5491
5956
  const chainId = nodeContext?.chainId ?? this._chainId;
5492
5957
  const host = nodeContext?.host ?? this.config.host;
5493
5958
  const ownerDid = this.ownerDidFromSpaceId(spaceId) ?? did;
5494
- return new import_sdk_core9.DataVaultService({
5959
+ return new import_sdk_core10.DataVaultService({
5495
5960
  spaceId,
5496
5961
  crypto: vaultCrypto,
5497
5962
  encryption: {
@@ -5516,8 +5981,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5516
5981
  serviceGraph.assertActive();
5517
5982
  return self._publicKV ?? self.tc.publicKV;
5518
5983
  },
5519
- readPublicSpace: (host2, targetSpaceId, key) => import_sdk_core9.TinyCloud.readPublicSpace(host2, targetSpaceId, key),
5520
- makePublicSpaceId: import_sdk_core9.TinyCloud.makePublicSpaceId,
5984
+ readPublicSpace: (host2, targetSpaceId, key) => import_sdk_core10.TinyCloud.readPublicSpace(host2, targetSpaceId, key),
5985
+ makePublicSpaceId: import_sdk_core10.TinyCloud.makePublicSpaceId,
5521
5986
  did,
5522
5987
  address: address ?? "",
5523
5988
  chainId,
@@ -5531,7 +5996,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5531
5996
  */
5532
5997
  initializeV2Services(serviceSession) {
5533
5998
  const graph = this._serviceGraph;
5534
- this._capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
5999
+ this._capabilityRegistry = new import_sdk_core10.CapabilityKeyRegistry();
5535
6000
  const tcSession = this.auth?.tinyCloudSession;
5536
6001
  if (tcSession && this._address) {
5537
6002
  const sessionKey = {
@@ -5571,7 +6036,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5571
6036
  }
5572
6037
  this._capabilityRegistry.registerKey(sessionKey, delegations);
5573
6038
  }
5574
- this._delegationManager = new import_sdk_core9.DelegationManager({
6039
+ this._delegationManager = new import_sdk_core10.DelegationManager({
5575
6040
  hosts: [this.config.host],
5576
6041
  accountSpaceId: this.accountSpaceId,
5577
6042
  session: serviceSession,
@@ -5579,7 +6044,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5579
6044
  invokeAny: graph.invokeAny,
5580
6045
  fetch: graph.fetch
5581
6046
  });
5582
- this._spaceService = new import_sdk_core9.SpaceService({
6047
+ this._spaceService = new import_sdk_core10.SpaceService({
5583
6048
  hosts: [this.config.host],
5584
6049
  session: serviceSession,
5585
6050
  invoke: graph.invoke,
@@ -5644,7 +6109,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5644
6109
  await this.account.spaces.register(space);
5645
6110
  }
5646
6111
  });
5647
- this._sharingService = new import_sdk_core9.SharingService({
6112
+ this._sharingService = new import_sdk_core10.SharingService({
5648
6113
  hosts: [this.config.host],
5649
6114
  session: serviceSession,
5650
6115
  invoke: graph.invoke,
@@ -5664,8 +6129,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5664
6129
  },
5665
6130
  createKVService: (config) => {
5666
6131
  graph.assertActive();
5667
- const service = new import_sdk_core9.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
5668
- const context = graph.track(new import_sdk_core9.ServiceContext({
6132
+ const service = new import_sdk_core10.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
6133
+ const context = graph.track(new import_sdk_core10.ServiceContext({
5669
6134
  invoke: config.invoke,
5670
6135
  fetch: config.fetch ?? graph.fetch,
5671
6136
  hosts: config.hosts,
@@ -5673,6 +6138,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5673
6138
  }));
5674
6139
  context.setSession(config.session);
5675
6140
  service.initialize(context);
6141
+ this.attachReplicationKV(config.session.spaceId, service);
5676
6142
  return service;
5677
6143
  },
5678
6144
  onRootDelegationNeeded: this.signer ? async (params) => {
@@ -5758,15 +6224,15 @@ var _TinyCloudNode = class _TinyCloudNode {
5758
6224
  }
5759
6225
  const permissions = ownerDelegationPermissions(params);
5760
6226
  const now = /* @__PURE__ */ new Date();
5761
- if (!(params.expiresAt instanceof Date) || params.expiresAt.getTime() <= now.getTime() || params.expiresAt.getTime() - now.getTime() > import_sdk_core9.EXPIRY.MAX_MS) {
6227
+ if (!(params.expiresAt instanceof Date) || params.expiresAt.getTime() <= now.getTime() || params.expiresAt.getTime() - now.getTime() > import_sdk_core10.EXPIRY.MAX_MS) {
5762
6228
  throw new Error("Owner delegation expiry must be explicit, future, and within EXPIRY.MAX_MS");
5763
6229
  }
5764
6230
  if (!this.signer) throw new Error("Owner wallet signer is required");
5765
6231
  const session = this.currentTinyCloudSession();
5766
6232
  if (!session) throw new Error("Owner session is required");
5767
- const ownerDid = (0, import_sdk_core9.pkhDid)(session.address, session.chainId);
6233
+ const ownerDid = (0, import_sdk_core10.pkhDid)(session.address, session.chainId);
5768
6234
  for (const permission of permissions) {
5769
- if (permission.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE && !(0, import_sdk_core9.principalDidEquals)((0, import_sdk_core9.parseNetworkId)(permission.path).ownerDid, ownerDid)) {
6235
+ if (permission.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE && !(0, import_sdk_core10.principalDidEquals)((0, import_sdk_core10.parseNetworkId)(permission.path).ownerDid, ownerDid)) {
5770
6236
  throw new Error("Owner delegation cannot grant a foreign encryption network");
5771
6237
  }
5772
6238
  }
@@ -5787,7 +6253,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5787
6253
  const signature = await this.signer.signMessage(prepared.siwe);
5788
6254
  assertOwnerGraphActive();
5789
6255
  const delegationSession = this.wasmBindings.completeSessionSetup({ ...prepared, signature });
5790
- const activation = await (0, import_sdk_core9.activateSessionWithHost)(host, delegationSession.delegationHeader);
6256
+ const activation = await (0, import_sdk_core10.activateSessionWithHost)(host, delegationSession.delegationHeader);
5791
6257
  assertOwnerGraphActive();
5792
6258
  if (!activation.success) {
5793
6259
  throw Object.assign(
@@ -5823,7 +6289,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5823
6289
  /** Register a signed policy and sibling roots with this Node's Policy/v3 runtime. */
5824
6290
  async registerPolicy(params) {
5825
6291
  this._serviceGraph.assertActive();
5826
- return (0, import_sdk_core9.registerPolicyV3)({
6292
+ return (0, import_sdk_core10.registerPolicyV3)({
5827
6293
  ...params,
5828
6294
  nodeOrigin: this.config.host,
5829
6295
  fetch: globalThis.fetch.bind(globalThis)
@@ -5850,23 +6316,23 @@ var _TinyCloudNode = class _TinyCloudNode {
5850
6316
  jti: base64UrlEncode(jtiDigest.slice(0, 16)),
5851
6317
  expiresAt: new Date(input.expiresAt).toISOString().replace(/\.\d{3}Z$/, "Z")
5852
6318
  };
5853
- const requestBodyDigest = base64UrlEncode(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode((0, import_sdk_core9.canonicalizeEncryptionJson)(body)))));
6319
+ const requestBodyDigest = base64UrlEncode(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode((0, import_sdk_core10.canonicalizeEncryptionJson)(body)))));
5854
6320
  const request = { ...body, requestBodyDigest };
5855
6321
  const authorization = authorizationHeader(this.invokeAnyWithRuntimePermissions(serviceSession, [{ spaceId: session.spaceId, service: "kv", path: input.resourcePath, action: "tinycloud.kv/get" }]));
5856
6322
  const response = await fetch(`${this.config.host}/policy/v3/deliveries/authorize`, {
5857
6323
  method: "POST",
5858
6324
  headers: { accept: "application/json", "content-type": "application/json", authorization },
5859
- body: (0, import_sdk_core9.canonicalizeEncryptionJson)(request)
6325
+ body: (0, import_sdk_core10.canonicalizeEncryptionJson)(request)
5860
6326
  });
5861
- if (!response.ok) throw await (0, import_sdk_core9.httpResponseError)(response, "V3 share delivery authorization failed");
5862
- const verified = (0, import_sdk_core9.validateShareDeliveryAuthorizationV3Bytes)(new Uint8Array(await response.arrayBuffer()), {
6327
+ if (!response.ok) throw await (0, import_sdk_core10.httpResponseError)(response, "V3 share delivery authorization failed");
6328
+ const verified = (0, import_sdk_core10.validateShareDeliveryAuthorizationV3Bytes)(new Uint8Array(await response.arrayBuffer()), {
5863
6329
  request,
5864
6330
  senderKeyDid: this.credentialHolderDid,
5865
6331
  deliveryAudience: input.deliveryAudience
5866
6332
  });
5867
6333
  const requestDigest = new Uint8Array(await crypto.subtle.digest(
5868
6334
  "SHA-256",
5869
- new TextEncoder().encode(`${import_sdk_core9.CREDENTIAL_INVITATION_REQUEST_DOMAIN}${(0, import_sdk_core9.canonicalizeEncryptionJson)(verified.request)}`)
6335
+ new TextEncoder().encode(`${import_sdk_core10.CREDENTIAL_INVITATION_REQUEST_DOMAIN}${(0, import_sdk_core10.canonicalizeEncryptionJson)(verified.request)}`)
5870
6336
  ));
5871
6337
  return {
5872
6338
  ...verified,
@@ -5934,7 +6400,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5934
6400
  if (!this._sql) {
5935
6401
  const features = this.nodeFeatures;
5936
6402
  if (features.length > 0 && !features.includes("sql")) {
5937
- throw new import_sdk_core9.UnsupportedFeatureError("sql", this.config.host, features);
6403
+ throw new import_sdk_core10.UnsupportedFeatureError("sql", this.config.host, features);
5938
6404
  }
5939
6405
  throw new Error("Not signed in. Call signIn() first.");
5940
6406
  }
@@ -5958,8 +6424,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5958
6424
  if (!this._serviceContext || !this._serviceContext.session) {
5959
6425
  throw new Error("Not signed in. Call signIn() first.");
5960
6426
  }
5961
- const sql = new import_sdk_core9.SQLService({});
5962
- const spaceScopedContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
6427
+ const sql = new import_sdk_core10.SQLService({});
6428
+ const spaceScopedContext = this._serviceGraph.track(new import_sdk_core10.ServiceContext({
5963
6429
  invoke: this._serviceContext.invoke,
5964
6430
  invokeAny: this._serviceContext.invokeAny,
5965
6431
  fetch: this._serviceContext.fetch,
@@ -5988,8 +6454,8 @@ var _TinyCloudNode = class _TinyCloudNode {
5988
6454
  if (!this._serviceContext || !this._serviceContext.session) {
5989
6455
  throw new Error("Not signed in. Call signIn() first.");
5990
6456
  }
5991
- const kv = new import_sdk_core9.KVService({});
5992
- const spaceScopedContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
6457
+ const kv = new import_sdk_core10.KVService({});
6458
+ const spaceScopedContext = this._serviceGraph.track(new import_sdk_core10.ServiceContext({
5993
6459
  invoke: this._serviceContext.invoke,
5994
6460
  invokeAny: this._serviceContext.invokeAny,
5995
6461
  fetch: this._serviceContext.fetch,
@@ -5997,6 +6463,7 @@ var _TinyCloudNode = class _TinyCloudNode {
5997
6463
  }));
5998
6464
  spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
5999
6465
  kv.initialize(spaceScopedContext);
6466
+ this.attachReplicationKV(spaceId, kv);
6000
6467
  return kv;
6001
6468
  }
6002
6469
  /**
@@ -6006,7 +6473,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6006
6473
  if (!this._duckdb) {
6007
6474
  const features = this.nodeFeatures;
6008
6475
  if (features.length > 0 && !features.includes("duckdb")) {
6009
- throw new import_sdk_core9.UnsupportedFeatureError("duckdb", this.config.host, features);
6476
+ throw new import_sdk_core10.UnsupportedFeatureError("duckdb", this.config.host, features);
6010
6477
  }
6011
6478
  throw new Error("Not signed in. Call signIn() first.");
6012
6479
  }
@@ -6050,7 +6517,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6050
6517
  type: NETWORK_ADMIN_TYPE,
6051
6518
  targetNode,
6052
6519
  networkId,
6053
- bodyHash: (0, import_sdk_core9.canonicalHashHex)(
6520
+ bodyHash: (0, import_sdk_core10.canonicalHashHex)(
6054
6521
  crypto2.sha256,
6055
6522
  body
6056
6523
  ),
@@ -6068,7 +6535,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6068
6535
  Authorization: signed.authorization,
6069
6536
  "Content-Type": "application/json"
6070
6537
  },
6071
- body: (0, import_sdk_core9.canonicalizeEncryptionJson)(
6538
+ body: (0, import_sdk_core10.canonicalizeEncryptionJson)(
6072
6539
  body
6073
6540
  )
6074
6541
  });
@@ -6080,7 +6547,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6080
6547
  );
6081
6548
  }
6082
6549
  if (!response.ok) {
6083
- throw await (0, import_sdk_core9.httpResponseError)(response, `Failed to create encryption network ${networkId}`);
6550
+ throw await (0, import_sdk_core10.httpResponseError)(response, `Failed to create encryption network ${networkId}`);
6084
6551
  }
6085
6552
  const created = await response.json();
6086
6553
  return created.descriptor;
@@ -6099,7 +6566,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6099
6566
  return existing;
6100
6567
  }
6101
6568
  }
6102
- const parsed = (0, import_sdk_core9.parseNetworkId)(networkId);
6569
+ const parsed = (0, import_sdk_core10.parseNetworkId)(networkId);
6103
6570
  if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
6104
6571
  throw new Error(
6105
6572
  `Cannot create encryption network ${networkId}: owner ${parsed.ownerDid} does not match signed-in DID ${this.did}`
@@ -6147,14 +6614,14 @@ var _TinyCloudNode = class _TinyCloudNode {
6147
6614
  * normal KV and encryption invocation paths.
6148
6615
  */
6149
6616
  async readSecret(input) {
6150
- const resolved = (0, import_sdk_core9.resolveSecretPath)(input.name, { scope: input.scope });
6617
+ const resolved = (0, import_sdk_core10.resolveSecretPath)(input.name, { scope: input.scope });
6151
6618
  const targetSpace = input.space.startsWith("tinycloud:") ? input.space : this.ownedSpaceId(input.space);
6152
6619
  const result = await this.getBaseVault(targetSpace).readNetworkEncrypted(
6153
6620
  resolved.vaultKey
6154
6621
  );
6155
6622
  if (result.status !== "ok") {
6156
6623
  if (result.status === "permission_required") {
6157
- const hint = (0, import_sdk_services.parsePermissionHint)(result.hint);
6624
+ const hint = (0, import_sdk_services3.parsePermissionHint)(result.hint);
6158
6625
  if (hint === void 0) return { status: "read_failed" };
6159
6626
  return {
6160
6627
  status: "permission_required",
@@ -6180,7 +6647,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6180
6647
  const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
6181
6648
  let secrets = this._baseSecrets.get(resolvedSpace);
6182
6649
  if (!secrets) {
6183
- secrets = new import_sdk_core9.SecretsService(() => this.getBaseVault(resolvedSpace));
6650
+ secrets = new import_sdk_core10.SecretsService(() => this.getBaseVault(resolvedSpace));
6184
6651
  this._baseSecrets.set(resolvedSpace, secrets);
6185
6652
  }
6186
6653
  return secrets;
@@ -6323,7 +6790,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6323
6790
  for (const grant of this.runtimePermissionGrants) {
6324
6791
  if (grant.provenance === "primary") continue;
6325
6792
  for (const operation of grant.operations) {
6326
- const service = import_sdk_core9.SERVICE_SHORT_TO_LONG[operation.service];
6793
+ const service = import_sdk_core10.SERVICE_SHORT_TO_LONG[operation.service];
6327
6794
  if (service === void 0 || typeof operation.path !== "string" || typeof operation.action !== "string") {
6328
6795
  continue;
6329
6796
  }
@@ -6341,7 +6808,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6341
6808
  service,
6342
6809
  ...space === void 0 ? {} : { space },
6343
6810
  path: operation.path,
6344
- caveats: (0, import_sdk_core9.canonicalizeRecapCaveats)(caveats)
6811
+ caveats: (0, import_sdk_core10.canonicalizeRecapCaveats)(caveats)
6345
6812
  });
6346
6813
  const existing = grouped.get(identity);
6347
6814
  if (existing === void 0) {
@@ -6386,7 +6853,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6386
6853
  delegationCid: grant.delegationCid,
6387
6854
  spaceId: grant.spaceId,
6388
6855
  jwk: this.sessionKeyJwk,
6389
- address: (0, import_sdk_core9.canonicalizeAddress)(grant.address),
6856
+ address: (0, import_sdk_core10.canonicalizeAddress)(grant.address),
6390
6857
  chainId: grant.chainId,
6391
6858
  siwe: grant.siwe,
6392
6859
  signature: grant.signature
@@ -6407,10 +6874,10 @@ var _TinyCloudNode = class _TinyCloudNode {
6407
6874
  async useRuntimeDelegation(delegation) {
6408
6875
  const session = this.currentTinyCloudSession();
6409
6876
  if (!session) {
6410
- throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
6877
+ throw new import_sdk_core10.SessionExpiredError(/* @__PURE__ */ new Date(0));
6411
6878
  }
6412
6879
  if (delegation.expiry.getTime() <= Date.now()) {
6413
- throw new import_sdk_core9.SessionExpiredError(delegation.expiry);
6880
+ throw new import_sdk_core10.SessionExpiredError(delegation.expiry);
6414
6881
  }
6415
6882
  const expectedDids = [session.verificationMethod, this.sessionDid];
6416
6883
  if (!expectedDids.some((did) => didPrincipalMatches2(delegation.delegateDID, did))) {
@@ -6419,10 +6886,18 @@ var _TinyCloudNode = class _TinyCloudNode {
6419
6886
  );
6420
6887
  }
6421
6888
  const targetHost = delegation.host ?? this.config.host;
6422
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
6423
- targetHost,
6424
- delegation.delegationHeader
6425
- );
6889
+ let activateResult;
6890
+ try {
6891
+ activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
6892
+ targetHost,
6893
+ delegation.delegationHeader
6894
+ );
6895
+ } catch (cause) {
6896
+ throw Object.assign(
6897
+ new Error("The TinyCloud host could not be reached to activate the delegation."),
6898
+ { code: "ACTIVATION_TRANSPORT_FAILED", cause }
6899
+ );
6900
+ }
6426
6901
  if (!activateResult.success) {
6427
6902
  if (this.operationsFromDelegation(delegation).some(
6428
6903
  (operation) => operation.resource?.startsWith("urn:cid:") === true && operation.service === "delegation" && operation.action === "tinycloud.delegation/revoke"
@@ -6455,13 +6930,13 @@ var _TinyCloudNode = class _TinyCloudNode {
6455
6930
  }
6456
6931
  const session = this.currentTinyCloudSession();
6457
6932
  if (!session) {
6458
- throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
6933
+ throw new import_sdk_core10.SessionExpiredError(/* @__PURE__ */ new Date(0));
6459
6934
  }
6460
6935
  const sessionExpiry = extractSiweExpiration(session.siwe);
6461
6936
  if (sessionExpiry !== void 0) {
6462
6937
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
6463
6938
  if (sessionExpiry.getTime() <= Date.now() + marginMs) {
6464
- throw new import_sdk_core9.SessionExpiredError(sessionExpiry);
6939
+ throw new import_sdk_core10.SessionExpiredError(sessionExpiry);
6465
6940
  }
6466
6941
  }
6467
6942
  const expanded = this.expandPermissionEntries(permissions);
@@ -6537,7 +7012,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6537
7012
  ...prepared,
6538
7013
  signature
6539
7014
  });
6540
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
7015
+ const activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
6541
7016
  this.config.host,
6542
7017
  delegatedSession.delegationHeader
6543
7018
  );
@@ -6710,10 +7185,10 @@ var _TinyCloudNode = class _TinyCloudNode {
6710
7185
  throw new Error("Public space not enabled. Set enablePublicSpace: true in config.");
6711
7186
  }
6712
7187
  await this.auth.hostPublicSpace(publicSpaceId);
6713
- const kvActions = [import_sdk_core9.KV.PUT, import_sdk_core9.KV.GET, import_sdk_core9.KV.DEL, import_sdk_core9.KV.LIST, import_sdk_core9.KV.METADATA];
7188
+ 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];
6714
7189
  const abilities = { kv: { "": kvActions } };
6715
7190
  const now = /* @__PURE__ */ new Date();
6716
- const expiryMs = import_sdk_core9.EXPIRY.EPHEMERAL_MS;
7191
+ const expiryMs = import_sdk_core10.EXPIRY.EPHEMERAL_MS;
6717
7192
  const expirationTime = new Date(now.getTime() + expiryMs);
6718
7193
  const prepared = this.wasmBindings.prepareSession({
6719
7194
  abilities,
@@ -6731,7 +7206,7 @@ var _TinyCloudNode = class _TinyCloudNode {
6731
7206
  ...prepared,
6732
7207
  signature
6733
7208
  });
6734
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
7209
+ const activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
6735
7210
  this.config.host,
6736
7211
  delegationSession.delegationHeader
6737
7212
  );
@@ -6761,8 +7236,8 @@ var _TinyCloudNode = class _TinyCloudNode {
6761
7236
  }]);
6762
7237
  }
6763
7238
  if (this._serviceContext) {
6764
- const publicKV = new import_sdk_core9.KVService({ prefix: "" });
6765
- const publicContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
7239
+ const publicKV = new import_sdk_core10.KVService({ prefix: "" });
7240
+ const publicContext = this._serviceGraph.track(new import_sdk_core10.ServiceContext({
6766
7241
  invoke: this._serviceGraph.invoke,
6767
7242
  fetch: this._serviceGraph.fetch,
6768
7243
  hosts: this._serviceContext.hosts,
@@ -6914,14 +7389,14 @@ var _TinyCloudNode = class _TinyCloudNode {
6914
7389
  }
6915
7390
  const session = this.currentTinyCloudSession();
6916
7391
  if (!session) {
6917
- throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
7392
+ throw new import_sdk_core10.SessionExpiredError(/* @__PURE__ */ new Date(0));
6918
7393
  }
6919
7394
  const sessionExpiry = extractSiweExpiration(session.siwe);
6920
7395
  if (sessionExpiry !== void 0) {
6921
7396
  const now2 = Date.now();
6922
7397
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
6923
7398
  if (sessionExpiry.getTime() <= now2 + marginMs) {
6924
- throw new import_sdk_core9.SessionExpiredError(sessionExpiry);
7399
+ throw new import_sdk_core10.SessionExpiredError(sessionExpiry);
6925
7400
  }
6926
7401
  }
6927
7402
  if (!Array.isArray(permissions) || permissions.length === 0) {
@@ -6951,31 +7426,31 @@ var _TinyCloudNode = class _TinyCloudNode {
6951
7426
  );
6952
7427
  return { delegation: delegation2, prompted: true };
6953
7428
  }
6954
- const granted = this.projectSignedRecapCapabilities(session.siwe);
6955
- const { subset, missing } = this.signedCapabilitySubset(expandedEntries, granted);
6956
- if (!subset) {
6957
- const runtimeOperations = this.permissionEntriesToOperations(expandedEntries, session);
6958
- const runtimeGrant = this.findGrantForOperations(
6959
- runtimeOperations,
6960
- { excludePrimary: true }
6961
- );
6962
- if (runtimeGrant) {
6963
- const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
6964
- if (runtimeGrant.expiresAt.getTime() <= Date.now() + marginMs) {
6965
- throw new import_sdk_core9.SessionExpiredError(runtimeGrant.expiresAt);
6966
- }
6967
- const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
6968
- const delegation2 = await this.createDelegationViaRuntimeGrant(
6969
- did,
6970
- expandedEntries,
6971
- runtimeExpiration,
6972
- runtimeGrant,
6973
- runtimeOperations,
6974
- onPrepared
6975
- );
6976
- return { delegation: delegation2, prompted: false };
7429
+ const plan = this.planDerivation(
7430
+ expandedEntries,
7431
+ session,
7432
+ effectiveExpiration,
7433
+ Date.now()
7434
+ );
7435
+ if ("refused" in plan) {
7436
+ if (plan.refused === "SESSION_EXPIRING") {
7437
+ throw new import_sdk_core10.SessionExpiredError(plan.expiredAt ?? sessionExpiry ?? /* @__PURE__ */ new Date(0));
7438
+ }
7439
+ if (plan.refused === "CAVEATED_AUTHORITY") {
7440
+ throw new import_sdk_core10.CaveatedDelegationUnsupportedError(plan.caveated ?? []);
6977
7441
  }
6978
- throw new import_sdk_core9.PermissionNotInManifestError(missing, granted);
7442
+ throw new import_sdk_core10.PermissionNotInManifestError(plan.missing ?? [], plan.granted ?? []);
7443
+ }
7444
+ if (plan.path === "runtime") {
7445
+ const delegation2 = await this.createDelegationViaRuntimeGrant(
7446
+ did,
7447
+ expandedEntries,
7448
+ plan.effectiveExpiration,
7449
+ plan.grant,
7450
+ plan.operations,
7451
+ onPrepared
7452
+ );
7453
+ return { delegation: delegation2, prompted: false };
6979
7454
  }
6980
7455
  const delegation = await this.createDelegationViaWasmPath(
6981
7456
  did,
@@ -6986,6 +7461,149 @@ var _TinyCloudNode = class _TinyCloudNode {
6986
7461
  );
6987
7462
  return { delegation, prompted: false };
6988
7463
  }
7464
+ /**
7465
+ * What `delegateTo` would select for `entries`, without signing or any
7466
+ * network call (TC-858 plan v3 §4.3): the session path when the signed
7467
+ * recap covers every entry, the runtime-grant path otherwise, or a
7468
+ * refusal. A refusal of `CAVEATED_AUTHORITY` means coverage exists only
7469
+ * through caveated branches, which the action-only WASM child-delegation
7470
+ * boundary cannot preserve — replication never derives authority through
7471
+ * them. `expiredAt`/`missing`/`granted`/`caveated` carry the payload
7472
+ * `delegateTo` turns back into its typed errors.
7473
+ * @internal
7474
+ */
7475
+ planDerivation(expandedEntries, session, effectiveExpiration, nowMs) {
7476
+ const caveatedRequest = expandedEntries.filter(
7477
+ (entry) => !(0, import_sdk_core10.recapCaveatsEqual)(entry.caveats, void 0)
7478
+ );
7479
+ if (caveatedRequest.length > 0) {
7480
+ return { refused: "CAVEATED_AUTHORITY", caveated: caveatedRequest };
7481
+ }
7482
+ const granted = this.projectSignedRecapCapabilities(session.siwe);
7483
+ const { subset, missing } = this.signedCapabilitySubset(expandedEntries, granted);
7484
+ if (subset) {
7485
+ return {
7486
+ path: "session",
7487
+ parentCid: session.delegationCid,
7488
+ expiresAt: effectiveExpiration.getTime(),
7489
+ effectiveExpiration
7490
+ };
7491
+ }
7492
+ const runtimeOperations = this.permissionEntriesToOperations(expandedEntries, session);
7493
+ const runtimeGrant = this.findGrantForOperations(
7494
+ runtimeOperations,
7495
+ { excludePrimary: true }
7496
+ );
7497
+ if (runtimeGrant) {
7498
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
7499
+ if (runtimeGrant.expiresAt.getTime() <= nowMs + marginMs) {
7500
+ return { refused: "SESSION_EXPIRING", expiredAt: runtimeGrant.expiresAt };
7501
+ }
7502
+ const caveated = this.caveatedRuntimeGrantEntries(
7503
+ expandedEntries,
7504
+ runtimeOperations,
7505
+ runtimeGrant
7506
+ );
7507
+ if (caveated.length > 0) {
7508
+ return { refused: "CAVEATED_AUTHORITY", caveated };
7509
+ }
7510
+ const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
7511
+ return {
7512
+ path: "runtime",
7513
+ parentCid: runtimeGrant.session.delegationCid,
7514
+ expiresAt: runtimeExpiration.getTime(),
7515
+ effectiveExpiration: runtimeExpiration,
7516
+ grant: runtimeGrant,
7517
+ operations: runtimeOperations
7518
+ };
7519
+ }
7520
+ const relaxedGranted = granted.map((entry) => ({ ...entry, caveats: void 0 }));
7521
+ const relaxedRequested = expandedEntries.map((entry) => ({ ...entry, caveats: void 0 }));
7522
+ const relaxed = this.signedCapabilitySubset(relaxedRequested, relaxedGranted);
7523
+ if (relaxed.subset) {
7524
+ return {
7525
+ refused: "CAVEATED_AUTHORITY",
7526
+ caveated: missing.map((entry) => ({ ...entry, caveats: [{ via: "session-recap" }] }))
7527
+ };
7528
+ }
7529
+ return { refused: "NOT_COVERED", missing, granted };
7530
+ }
7531
+ /**
7532
+ * The plan `delegateTo(device, entries)` would follow, as a pure lookup:
7533
+ * no WASM sign and no `POST /delegate`. Backs
7534
+ * `ReplicationAuthority.plan` (and `mint` inside it) so a predicted
7535
+ * parent and expiry can never disagree with what a mint would use (§4.3,
7536
+ * §4.4). Session expiry inside the 60 s margin refuses with
7537
+ * `SESSION_EXPIRING`; the same check delegateTo performs.
7538
+ * @internal
7539
+ */
7540
+ planDelegation(entries, options) {
7541
+ if (!Array.isArray(entries) || entries.length === 0) {
7542
+ throw new Error("planDelegation requires a non-empty permissions array");
7543
+ }
7544
+ const session = this.currentTinyCloudSession();
7545
+ if (!session) {
7546
+ return { refused: "SESSION_EXPIRING", expiredAt: /* @__PURE__ */ new Date(0) };
7547
+ }
7548
+ const nowMs = Date.now();
7549
+ const sessionExpiry = extractSiweExpiration(session.siwe);
7550
+ if (sessionExpiry !== void 0 && sessionExpiry.getTime() <= nowMs + _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS) {
7551
+ return { refused: "SESSION_EXPIRING", expiredAt: sessionExpiry };
7552
+ }
7553
+ const expandedEntries = this.expandPermissionEntries(entries);
7554
+ const expiryMs = resolveExpiryMs(options?.expiry);
7555
+ const expirationTime = new Date(nowMs + expiryMs);
7556
+ const effectiveExpiration = sessionExpiry !== void 0 && sessionExpiry < expirationTime ? sessionExpiry : expirationTime;
7557
+ return this.planDerivation(expandedEntries, session, effectiveExpiration, nowMs);
7558
+ }
7559
+ /**
7560
+ * The replication entries this node's sign-in request carries for the
7561
+ * current replication config and the signed-in or restored address: the
7562
+ * output of the same augmentation step `resolveSignInCapabilities` runs,
7563
+ * with the unrestricted-get and secrets gates applied (§4.1, §4.6).
7564
+ * Empty when replication is off or no address is known. Pure.
7565
+ */
7566
+ replicationSignInEntries() {
7567
+ if (this.config.replication?.enabled !== true) return [];
7568
+ const auth = this.auth;
7569
+ if (auth === void 0 || typeof auth.replicationSignInEntries !== "function") {
7570
+ return [];
7571
+ }
7572
+ return auth.replicationSignInEntries();
7573
+ }
7574
+ async replicationAuthority() {
7575
+ const { createReplicationAuthority } = await getNodeReplicationLoaders().authority();
7576
+ return createReplicationAuthority({
7577
+ replicationSession: () => this.currentTinyCloudSession() ?? this.replicationDelegateSession,
7578
+ siweExpiration: (siwe) => extractSiweExpiration(siwe),
7579
+ planDelegation: (entries, options) => this.planDelegation(entries, options),
7580
+ mintDelegation: async (deviceDid, entries) => {
7581
+ const result = await this.delegateTo((0, import_sdk_core10.principalDid)(deviceDid), entries);
7582
+ return {
7583
+ ucan: result.delegation.delegationHeader.Authorization,
7584
+ expiresAt: result.delegation.expiry.getTime()
7585
+ };
7586
+ }
7587
+ });
7588
+ }
7589
+ async bindReplicationRuntime(context, session, kv, principal) {
7590
+ if (!this.replicationRuntime) return;
7591
+ const identityPrincipal = principal ?? (this._address === void 0 ? void 0 : (0, import_sdk_core10.pkhDid)(this._address, this._chainId));
7592
+ if (identityPrincipal === void 0) return;
7593
+ const runtime = await this.replicationRuntime;
7594
+ const authority = await this.replicationAuthority();
7595
+ await runtime.bind({
7596
+ context,
7597
+ session,
7598
+ principal: identityPrincipal,
7599
+ authority,
7600
+ primaryKV: [{ space: session.spaceId, kv }]
7601
+ });
7602
+ }
7603
+ /** Stable control facade for this node's optional replication runtime. */
7604
+ get replication() {
7605
+ return this.replicationControl;
7606
+ }
6989
7607
  /**
6990
7608
  * Materialize one manifest-declared delegation using the current session key.
6991
7609
  * Delivery is intentionally out of band; callers decide how to transmit the
@@ -7059,7 +7677,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7059
7677
  const spaceId = resolvedSpaces.size === 1 ? [...resolvedSpaces][0] : session.spaceId;
7060
7678
  const abilities = {};
7061
7679
  for (const entry of entries) {
7062
- const shortService = import_sdk_core9.SERVICE_LONG_TO_SHORT[entry.service];
7680
+ const shortService = import_sdk_core10.SERVICE_LONG_TO_SHORT[entry.service];
7063
7681
  if (shortService === void 0) {
7064
7682
  throw new Error(
7065
7683
  `delegateTo: unknown service '${entry.service}' \u2014 no short-form mapping`
@@ -7116,7 +7734,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7116
7734
  if (onPrepared) {
7117
7735
  await onPrepared(delegation);
7118
7736
  }
7119
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
7737
+ const activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
7120
7738
  this.config.host,
7121
7739
  delegationHeader
7122
7740
  );
@@ -7158,7 +7776,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7158
7776
  if (onPrepared) {
7159
7777
  await onPrepared(delegation);
7160
7778
  }
7161
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
7779
+ const activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
7162
7780
  targetHost,
7163
7781
  delegationHeader
7164
7782
  );
@@ -7187,7 +7805,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7187
7805
  return this.wasmBindings.makeSpaceId(session.address, session.chainId, space);
7188
7806
  }
7189
7807
  expandPermissionEntries(permissions) {
7190
- return (0, import_sdk_core9.expandPermissionEntries)(permissions);
7808
+ return (0, import_sdk_core10.expandPermissionEntries)(permissions);
7191
7809
  }
7192
7810
  /**
7193
7811
  * The current WASM child-delegation APIs accept action-only maps. Refuse any
@@ -7195,10 +7813,10 @@ var _TinyCloudNode = class _TinyCloudNode {
7195
7813
  */
7196
7814
  assertDelegationCaveatsPreservable(entries) {
7197
7815
  const caveated = entries.filter(
7198
- (entry) => !(0, import_sdk_core9.recapCaveatsEqual)(entry.caveats, void 0)
7816
+ (entry) => !(0, import_sdk_core10.recapCaveatsEqual)(entry.caveats, void 0)
7199
7817
  );
7200
7818
  if (caveated.length > 0) {
7201
- throw new import_sdk_core9.CaveatedDelegationUnsupportedError(caveated);
7819
+ throw new import_sdk_core10.CaveatedDelegationUnsupportedError(caveated);
7202
7820
  }
7203
7821
  }
7204
7822
  /**
@@ -7208,6 +7826,18 @@ var _TinyCloudNode = class _TinyCloudNode {
7208
7826
  * it only accepts action maps, so reject the selected constrained branch.
7209
7827
  */
7210
7828
  assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant) {
7829
+ const caveated = this.caveatedRuntimeGrantEntries(entries, requestedOperations, grant);
7830
+ if (caveated.length > 0) {
7831
+ throw new import_sdk_core10.CaveatedDelegationUnsupportedError(caveated);
7832
+ }
7833
+ }
7834
+ /**
7835
+ * The entries of `grant` that cover a requested operation while carrying
7836
+ * caveats — the branches {@link assertRuntimeGrantCaveatsPreservable}
7837
+ * rejects and {@link planDerivation} classifies as `CAVEATED_AUTHORITY`.
7838
+ * Shared so the pure plan and the mint path can't disagree.
7839
+ */
7840
+ caveatedRuntimeGrantEntries(entries, requestedOperations, grant) {
7211
7841
  let operationIndex = 0;
7212
7842
  const caveated = [];
7213
7843
  for (const entry of entries) {
@@ -7215,7 +7845,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7215
7845
  const requested = requestedOperations[operationIndex++];
7216
7846
  if (!requested) continue;
7217
7847
  const constrained = grant.operations.find(
7218
- (granted) => this.operationCovers(granted, requested) && !(0, import_sdk_core9.recapCaveatsEqual)(granted.caveats, void 0)
7848
+ (granted) => this.operationCovers(granted, requested) && !(0, import_sdk_core10.recapCaveatsEqual)(granted.caveats, void 0)
7219
7849
  );
7220
7850
  if (constrained) {
7221
7851
  caveated.push({
@@ -7226,15 +7856,13 @@ var _TinyCloudNode = class _TinyCloudNode {
7226
7856
  }
7227
7857
  }
7228
7858
  }
7229
- if (caveated.length > 0) {
7230
- throw new import_sdk_core9.CaveatedDelegationUnsupportedError(caveated);
7231
- }
7859
+ return caveated;
7232
7860
  }
7233
7861
  /** Reject caveated parent branches before action-only child signing. */
7234
7862
  assertPortableDelegationCaveatsPreservable(delegation) {
7235
7863
  const entries = [];
7236
7864
  const add = (service, space, path, actions, caveats) => {
7237
- if ((0, import_sdk_core9.recapCaveatsEqual)(caveats, void 0)) return;
7865
+ if ((0, import_sdk_core10.recapCaveatsEqual)(caveats, void 0)) return;
7238
7866
  entries.push({
7239
7867
  service: service.startsWith("tinycloud.") ? service : `tinycloud.${service}`,
7240
7868
  space,
@@ -7254,11 +7882,11 @@ var _TinyCloudNode = class _TinyCloudNode {
7254
7882
  add(resource.service, resource.space, resource.path, resource.actions, resource.caveats);
7255
7883
  }
7256
7884
  if (entries.length > 0) {
7257
- throw new import_sdk_core9.CaveatedDelegationUnsupportedError(entries);
7885
+ throw new import_sdk_core10.CaveatedDelegationUnsupportedError(entries);
7258
7886
  }
7259
7887
  }
7260
7888
  shortServiceName(service) {
7261
- const short = import_sdk_core9.SERVICE_LONG_TO_SHORT[service];
7889
+ const short = import_sdk_core10.SERVICE_LONG_TO_SHORT[service];
7262
7890
  if (short === void 0) {
7263
7891
  throw new Error(
7264
7892
  `unknown service '${service}' \u2014 no short-form mapping`
@@ -7285,7 +7913,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7285
7913
  return abilities;
7286
7914
  }
7287
7915
  isEncryptionPermissionEntry(entry) {
7288
- return entry.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE && this.isEncryptionNetworkOperation("encryption", entry.path, entry.space);
7916
+ return entry.service === import_sdk_core10.ENCRYPTION_PERMISSION_SERVICE && this.isEncryptionNetworkOperation("encryption", entry.path, entry.space);
7289
7917
  }
7290
7918
  isRawRevocationPermissionEntry(entry) {
7291
7919
  return entry.service === "tinycloud.delegation" && entry.path === "" && entry.space?.startsWith("urn:cid:") === true && entry.actions.includes("tinycloud.delegation/revoke");
@@ -7333,7 +7961,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7333
7961
  const missing = requested.filter((entry) => {
7334
7962
  const raw = this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry);
7335
7963
  const comparable = raw && this.isEncryptionPermissionEntry(entry) ? { ...entry, space: "encryption" } : entry;
7336
- return !(0, import_sdk_core9.isCapabilitySubset)([comparable], raw ? rawGranted : spaceGranted).subset;
7964
+ return !(0, import_sdk_core10.isCapabilitySubset)([comparable], raw ? rawGranted : spaceGranted).subset;
7337
7965
  });
7338
7966
  return { subset: missing.length === 0, missing };
7339
7967
  }
@@ -7569,7 +8197,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7569
8197
  if (granted.service !== requested.service || !this.actionContains(granted.action, requested.action)) {
7570
8198
  return false;
7571
8199
  }
7572
- if (requested.caveats !== void 0 && !(0, import_sdk_core9.recapCaveatsEqual)(granted.caveats, requested.caveats)) {
8200
+ if (requested.caveats !== void 0 && !(0, import_sdk_core10.recapCaveatsEqual)(granted.caveats, requested.caveats)) {
7573
8201
  return false;
7574
8202
  }
7575
8203
  if (granted.resource !== void 0 || requested.resource !== void 0) {
@@ -7591,7 +8219,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7591
8219
  if (grantedAction === requestedAction) {
7592
8220
  return true;
7593
8221
  }
7594
- if ((0, import_sdk_core9.isExplicitOnlyAction)(requestedAction)) {
8222
+ if ((0, import_sdk_core10.isExplicitOnlyAction)(requestedAction)) {
7595
8223
  return false;
7596
8224
  }
7597
8225
  if (grantedAction.endsWith("/*")) {
@@ -7703,7 +8331,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7703
8331
  if (resolvedDelegateDID.endsWith(".eth") && this.config.ensResolver) {
7704
8332
  const address = await this.config.ensResolver.resolveAddress(resolvedDelegateDID);
7705
8333
  if (!address) throw new Error(`Could not resolve ENS name: ${resolvedDelegateDID}`);
7706
- resolvedDelegateDID = (0, import_sdk_core9.pkhDid)(address, 1);
8334
+ resolvedDelegateDID = (0, import_sdk_core10.pkhDid)(address, 1);
7707
8335
  }
7708
8336
  const entries = legacyParamsToPermissionEntries(
7709
8337
  params.actions,
@@ -7718,7 +8346,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7718
8346
  );
7719
8347
  return result.delegation;
7720
8348
  } catch (err) {
7721
- if (err instanceof import_sdk_core9.PermissionNotInManifestError) {
8349
+ if (err instanceof import_sdk_core10.PermissionNotInManifestError) {
7722
8350
  } else {
7723
8351
  throw err;
7724
8352
  }
@@ -7775,7 +8403,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7775
8403
  ...prepared,
7776
8404
  signature
7777
8405
  });
7778
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
8406
+ const activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
7779
8407
  this.config.host,
7780
8408
  delegationSession.delegationHeader
7781
8409
  );
@@ -7800,12 +8428,12 @@ var _TinyCloudNode = class _TinyCloudNode {
7800
8428
  };
7801
8429
  const hasKvActions = params.actions.some((a) => a.startsWith("tinycloud.kv/"));
7802
8430
  if (hasKvActions && params.includePublicSpace !== false) {
7803
- const publicSpaceId = (0, import_sdk_core9.makePublicSpaceId)(
8431
+ const publicSpaceId = (0, import_sdk_core10.makePublicSpaceId)(
7804
8432
  this.wasmBindings.ensureEip55(session.address),
7805
8433
  session.chainId
7806
8434
  );
7807
8435
  const publicAbilities = {
7808
- kv: { "": [import_sdk_core9.KV.GET, import_sdk_core9.KV.PUT, import_sdk_core9.KV.METADATA] }
8436
+ kv: { "": [import_sdk_core10.KV.GET, import_sdk_core10.KV.PUT, import_sdk_core10.KV.METADATA] }
7809
8437
  };
7810
8438
  const publicPrepared = this.wasmBindings.prepareSession({
7811
8439
  abilities: publicAbilities,
@@ -7823,7 +8451,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7823
8451
  ...publicPrepared,
7824
8452
  signature: publicSignature
7825
8453
  });
7826
- const publicActivateResult = await (0, import_sdk_core9.activateSessionWithHost)(
8454
+ const publicActivateResult = await (0, import_sdk_core10.activateSessionWithHost)(
7827
8455
  this.config.host,
7828
8456
  publicSession.delegationHeader
7829
8457
  );
@@ -7833,7 +8461,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7833
8461
  delegationHeader: publicSession.delegationHeader,
7834
8462
  spaceId: publicSpaceId,
7835
8463
  path: "",
7836
- actions: [import_sdk_core9.KV.GET, import_sdk_core9.KV.PUT, import_sdk_core9.KV.METADATA],
8464
+ actions: [import_sdk_core10.KV.GET, import_sdk_core10.KV.PUT, import_sdk_core10.KV.METADATA],
7837
8465
  disableSubDelegation: params.disableSubDelegation ?? false,
7838
8466
  expiry: expirationTime,
7839
8467
  delegateDID: params.delegateDID,
@@ -7928,7 +8556,7 @@ var _TinyCloudNode = class _TinyCloudNode {
7928
8556
  ...prepared,
7929
8557
  signature
7930
8558
  });
7931
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
8559
+ const activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
7932
8560
  targetHost,
7933
8561
  invokerSession.delegationHeader
7934
8562
  );
@@ -8048,7 +8676,7 @@ var _TinyCloudNode = class _TinyCloudNode {
8048
8676
  ...prepared,
8049
8677
  signature
8050
8678
  });
8051
- const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
8679
+ const activateResult = await (0, import_sdk_core10.activateSessionWithHost)(
8052
8680
  targetHost,
8053
8681
  subDelegationSession.delegationHeader
8054
8682
  );
@@ -8093,7 +8721,6 @@ _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS = 6e4;
8093
8721
  var TinyCloudNode = _TinyCloudNode;
8094
8722
 
8095
8723
  // src/core.ts
8096
- var import_sdk_core12 = require("@tinycloud/sdk-core");
8097
8724
  var import_sdk_core13 = require("@tinycloud/sdk-core");
8098
8725
  var import_sdk_core14 = require("@tinycloud/sdk-core");
8099
8726
  var import_sdk_core15 = require("@tinycloud/sdk-core");
@@ -8103,6 +8730,7 @@ var import_sdk_core18 = require("@tinycloud/sdk-core");
8103
8730
  var import_sdk_core19 = require("@tinycloud/sdk-core");
8104
8731
  var import_sdk_core20 = require("@tinycloud/sdk-core");
8105
8732
  var import_sdk_core21 = require("@tinycloud/sdk-core");
8733
+ var import_sdk_core22 = require("@tinycloud/sdk-core");
8106
8734
  // Annotate the CommonJS export names for ESM import in node:
8107
8735
  0 && (module.exports = {
8108
8736
  ACCOUNT_REGISTRY_PATH,
@@ -8196,6 +8824,7 @@ var import_sdk_core21 = require("@tinycloud/sdk-core");
8196
8824
  pkhDid,
8197
8825
  principalDid,
8198
8826
  principalDidEquals,
8827
+ registerReplicationLoaders,
8199
8828
  resolveManifest,
8200
8829
  resolveSecretListPrefix,
8201
8830
  resolveSecretPath,