@tinycloud/node-sdk 2.4.0-beta.1 → 2.4.0-beta.11

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,94 +30,95 @@ 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_core9.ACCOUNT_REGISTRY_PATH,
34
- ACCOUNT_REGISTRY_SPACE: () => import_sdk_core9.ACCOUNT_REGISTRY_SPACE,
35
- AutoApproveSpaceCreationHandler: () => import_sdk_core8.AutoApproveSpaceCreationHandler,
36
- CapabilityKeyRegistry: () => import_sdk_core15.CapabilityKeyRegistry,
37
- CapabilityKeyRegistryErrorCodes: () => import_sdk_core15.CapabilityKeyRegistryErrorCodes,
38
- DEFAULT_MANIFEST_SPACE: () => import_sdk_core9.DEFAULT_MANIFEST_SPACE,
39
- DEFAULT_MANIFEST_VERSION: () => import_sdk_core9.DEFAULT_MANIFEST_VERSION,
40
- DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => import_sdk_core10.DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
41
- DataVaultService: () => import_sdk_core13.DataVaultService,
42
- DatabaseHandle: () => import_sdk_core11.DatabaseHandle,
33
+ ACCOUNT_REGISTRY_PATH: () => import_sdk_core10.ACCOUNT_REGISTRY_PATH,
34
+ ACCOUNT_REGISTRY_SPACE: () => import_sdk_core10.ACCOUNT_REGISTRY_SPACE,
35
+ AccountService: () => import_sdk_core3.AccountService,
36
+ AutoApproveSpaceCreationHandler: () => import_sdk_core9.AutoApproveSpaceCreationHandler,
37
+ CapabilityKeyRegistry: () => import_sdk_core16.CapabilityKeyRegistry,
38
+ CapabilityKeyRegistryErrorCodes: () => import_sdk_core16.CapabilityKeyRegistryErrorCodes,
39
+ DEFAULT_MANIFEST_SPACE: () => import_sdk_core10.DEFAULT_MANIFEST_SPACE,
40
+ DEFAULT_MANIFEST_VERSION: () => import_sdk_core10.DEFAULT_MANIFEST_VERSION,
41
+ DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => import_sdk_core11.DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
42
+ DataVaultService: () => import_sdk_core14.DataVaultService,
43
+ DatabaseHandle: () => import_sdk_core12.DatabaseHandle,
43
44
  DelegatedAccess: () => DelegatedAccess,
44
- DelegationErrorCodes: () => import_sdk_core14.DelegationErrorCodes,
45
- DelegationManager: () => import_sdk_core14.DelegationManager,
46
- DuckDbAction: () => import_sdk_core12.DuckDbAction,
47
- DuckDbDatabaseHandle: () => import_sdk_core12.DuckDbDatabaseHandle,
48
- DuckDbService: () => import_sdk_core12.DuckDbService,
45
+ DelegationErrorCodes: () => import_sdk_core15.DelegationErrorCodes,
46
+ DelegationManager: () => import_sdk_core15.DelegationManager,
47
+ DuckDbAction: () => import_sdk_core13.DuckDbAction,
48
+ DuckDbDatabaseHandle: () => import_sdk_core13.DuckDbDatabaseHandle,
49
+ DuckDbService: () => import_sdk_core13.DuckDbService,
49
50
  FileSessionStorage: () => FileSessionStorage,
50
- IdentityParseError: () => import_sdk_core8.IdentityParseError,
51
- KVService: () => import_sdk_core10.KVService,
52
- ManifestValidationError: () => import_sdk_core9.ManifestValidationError,
51
+ IdentityParseError: () => import_sdk_core9.IdentityParseError,
52
+ KVService: () => import_sdk_core11.KVService,
53
+ ManifestValidationError: () => import_sdk_core10.ManifestValidationError,
53
54
  MemorySessionStorage: () => MemorySessionStorage,
54
55
  NodeUserAuthorization: () => NodeUserAuthorization,
55
- PermissionNotInManifestError: () => import_sdk_core9.PermissionNotInManifestError,
56
- PrefixedKVService: () => import_sdk_core10.PrefixedKVService,
57
- ProtocolMismatchError: () => import_sdk_core17.ProtocolMismatchError,
58
- SECRET_NAME_RE: () => import_sdk_core13.SECRET_NAME_RE,
59
- SQLAction: () => import_sdk_core11.SQLAction,
60
- SQLService: () => import_sdk_core11.SQLService,
61
- SecretsService: () => import_sdk_core13.SecretsService,
62
- ServiceContext: () => import_sdk_core18.ServiceContext,
63
- SessionExpiredError: () => import_sdk_core9.SessionExpiredError,
64
- SharingService: () => import_sdk_core14.SharingService,
65
- SilentNotificationHandler: () => import_sdk_core8.SilentNotificationHandler,
66
- Space: () => import_sdk_core16.Space,
67
- SpaceErrorCodes: () => import_sdk_core16.SpaceErrorCodes,
68
- SpaceService: () => import_sdk_core16.SpaceService,
69
- TinyCloud: () => import_sdk_core7.TinyCloud,
56
+ PermissionNotInManifestError: () => import_sdk_core10.PermissionNotInManifestError,
57
+ PrefixedKVService: () => import_sdk_core11.PrefixedKVService,
58
+ ProtocolMismatchError: () => import_sdk_core18.ProtocolMismatchError,
59
+ SECRET_NAME_RE: () => import_sdk_core14.SECRET_NAME_RE,
60
+ SQLAction: () => import_sdk_core12.SQLAction,
61
+ SQLService: () => import_sdk_core12.SQLService,
62
+ SecretsService: () => import_sdk_core14.SecretsService,
63
+ ServiceContext: () => import_sdk_core19.ServiceContext,
64
+ SessionExpiredError: () => import_sdk_core10.SessionExpiredError,
65
+ SharingService: () => import_sdk_core15.SharingService,
66
+ SilentNotificationHandler: () => import_sdk_core9.SilentNotificationHandler,
67
+ Space: () => import_sdk_core17.Space,
68
+ SpaceErrorCodes: () => import_sdk_core17.SpaceErrorCodes,
69
+ SpaceService: () => import_sdk_core17.SpaceService,
70
+ TinyCloud: () => import_sdk_core8.TinyCloud,
70
71
  TinyCloudNode: () => TinyCloudNode,
71
- UnsupportedFeatureError: () => import_sdk_core17.UnsupportedFeatureError,
72
- VAULT_PERMISSION_SERVICE: () => import_sdk_core9.VAULT_PERMISSION_SERVICE,
73
- VaultHeaders: () => import_sdk_core13.VaultHeaders,
74
- VaultPublicSpaceKVActions: () => import_sdk_core13.VaultPublicSpaceKVActions,
75
- VersionCheckError: () => import_sdk_core17.VersionCheckError,
72
+ UnsupportedFeatureError: () => import_sdk_core18.UnsupportedFeatureError,
73
+ VAULT_PERMISSION_SERVICE: () => import_sdk_core10.VAULT_PERMISSION_SERVICE,
74
+ VaultHeaders: () => import_sdk_core14.VaultHeaders,
75
+ VaultPublicSpaceKVActions: () => import_sdk_core14.VaultPublicSpaceKVActions,
76
+ VersionCheckError: () => import_sdk_core18.VersionCheckError,
76
77
  WasmKeyProvider: () => WasmKeyProvider,
77
- addressStorageKey: () => import_sdk_core8.addressStorageKey,
78
- buildSpaceUri: () => import_sdk_core16.buildSpaceUri,
79
- canonicalizeAddress: () => import_sdk_core8.canonicalizeAddress,
80
- canonicalizeDid: () => import_sdk_core8.canonicalizeDid,
81
- canonicalizeDidUrl: () => import_sdk_core8.canonicalizeDidUrl,
82
- canonicalizeNetworkId: () => import_sdk_core8.canonicalizeNetworkId,
83
- canonicalizeSecretScope: () => import_sdk_core13.canonicalizeSecretScope,
84
- checkNodeInfo: () => import_sdk_core17.checkNodeInfo,
85
- composeManifestRequest: () => import_sdk_core9.composeManifestRequest,
86
- createCapabilityKeyRegistry: () => import_sdk_core15.createCapabilityKeyRegistry,
87
- createSharingService: () => import_sdk_core14.createSharingService,
88
- createSpaceService: () => import_sdk_core16.createSpaceService,
89
- createVaultCrypto: () => import_sdk_core13.createVaultCrypto,
78
+ addressStorageKey: () => import_sdk_core9.addressStorageKey,
79
+ buildSpaceUri: () => import_sdk_core17.buildSpaceUri,
80
+ canonicalizeAddress: () => import_sdk_core9.canonicalizeAddress,
81
+ canonicalizeDid: () => import_sdk_core9.canonicalizeDid,
82
+ canonicalizeDidUrl: () => import_sdk_core9.canonicalizeDidUrl,
83
+ canonicalizeNetworkId: () => import_sdk_core9.canonicalizeNetworkId,
84
+ canonicalizeSecretScope: () => import_sdk_core14.canonicalizeSecretScope,
85
+ checkNodeInfo: () => import_sdk_core18.checkNodeInfo,
86
+ composeManifestRequest: () => import_sdk_core10.composeManifestRequest,
87
+ createCapabilityKeyRegistry: () => import_sdk_core16.createCapabilityKeyRegistry,
88
+ createSharingService: () => import_sdk_core15.createSharingService,
89
+ createSpaceService: () => import_sdk_core17.createSpaceService,
90
+ createVaultCrypto: () => import_sdk_core14.createVaultCrypto,
90
91
  createWasmKeyProvider: () => createWasmKeyProvider,
91
92
  defaultSignStrategy: () => defaultSignStrategy,
92
- defaultSpaceCreationHandler: () => import_sdk_core8.defaultSpaceCreationHandler,
93
+ defaultSpaceCreationHandler: () => import_sdk_core9.defaultSpaceCreationHandler,
93
94
  deserializeDelegation: () => deserializeDelegation,
94
- didCacheKey: () => import_sdk_core8.didCacheKey,
95
- didEquals: () => import_sdk_core8.didEquals,
96
- expandActionShortNames: () => import_sdk_core9.expandActionShortNames,
97
- expandPermissionEntries: () => import_sdk_core9.expandPermissionEntries,
98
- expandPermissionEntry: () => import_sdk_core9.expandPermissionEntry,
99
- isCapabilitySubset: () => import_sdk_core9.isCapabilitySubset,
100
- isEvmAddress: () => import_sdk_core8.isEvmAddress,
101
- loadManifest: () => import_sdk_core9.loadManifest,
102
- makePkhSpaceId: () => import_sdk_core8.makePkhSpaceId,
103
- makePublicSpaceId: () => import_sdk_core16.makePublicSpaceId,
104
- parseCanonicalNetworkId: () => import_sdk_core8.parseCanonicalNetworkId,
105
- parseExpiry: () => import_sdk_core9.parseExpiry,
106
- parsePkhDid: () => import_sdk_core8.parsePkhDid,
107
- parseSpaceUri: () => import_sdk_core16.parseSpaceUri,
108
- pkhDid: () => import_sdk_core8.pkhDid,
109
- principalDid: () => import_sdk_core8.principalDid,
110
- principalDidEquals: () => import_sdk_core8.principalDidEquals,
111
- resolveManifest: () => import_sdk_core9.resolveManifest,
112
- resolveSecretListPrefix: () => import_sdk_core13.resolveSecretListPrefix,
113
- resolveSecretPath: () => import_sdk_core13.resolveSecretPath,
114
- resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core9.resourceCapabilitiesToSpaceAbilitiesMap,
95
+ didCacheKey: () => import_sdk_core9.didCacheKey,
96
+ didEquals: () => import_sdk_core9.didEquals,
97
+ expandActionShortNames: () => import_sdk_core10.expandActionShortNames,
98
+ expandPermissionEntries: () => import_sdk_core10.expandPermissionEntries,
99
+ expandPermissionEntry: () => import_sdk_core10.expandPermissionEntry,
100
+ isCapabilitySubset: () => import_sdk_core10.isCapabilitySubset,
101
+ isEvmAddress: () => import_sdk_core9.isEvmAddress,
102
+ loadManifest: () => import_sdk_core10.loadManifest,
103
+ makePkhSpaceId: () => import_sdk_core9.makePkhSpaceId,
104
+ makePublicSpaceId: () => import_sdk_core17.makePublicSpaceId,
105
+ parseCanonicalNetworkId: () => import_sdk_core9.parseCanonicalNetworkId,
106
+ parseExpiry: () => import_sdk_core10.parseExpiry,
107
+ parsePkhDid: () => import_sdk_core9.parsePkhDid,
108
+ parseSpaceUri: () => import_sdk_core17.parseSpaceUri,
109
+ pkhDid: () => import_sdk_core9.pkhDid,
110
+ principalDid: () => import_sdk_core9.principalDid,
111
+ principalDidEquals: () => import_sdk_core9.principalDidEquals,
112
+ resolveManifest: () => import_sdk_core10.resolveManifest,
113
+ resolveSecretListPrefix: () => import_sdk_core14.resolveSecretListPrefix,
114
+ resolveSecretPath: () => import_sdk_core14.resolveSecretPath,
115
+ resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core10.resourceCapabilitiesToSpaceAbilitiesMap,
115
116
  serializeDelegation: () => serializeDelegation,
116
- validateManifest: () => import_sdk_core9.validateManifest
117
+ validateManifest: () => import_sdk_core10.validateManifest
117
118
  });
118
119
  module.exports = __toCommonJS(core_exports);
119
- var import_sdk_core7 = require("@tinycloud/sdk-core");
120
120
  var import_sdk_core8 = require("@tinycloud/sdk-core");
121
+ var import_sdk_core9 = require("@tinycloud/sdk-core");
121
122
 
122
123
  // src/storage/MemorySessionStorage.ts
123
124
  var MemorySessionStorage = class {
@@ -317,6 +318,25 @@ var import_sdk_core2 = require("@tinycloud/sdk-core");
317
318
  var defaultSignStrategy = { type: "auto-sign" };
318
319
 
319
320
  // src/authorization/NodeUserAuthorization.ts
321
+ var DECRYPT_ACTION = "tinycloud.encryption/decrypt";
322
+ var NETWORK_CREATE_ACTION = "tinycloud.encryption/network.create";
323
+ function didPrincipalMatches(actual, expected) {
324
+ try {
325
+ return (0, import_sdk_core2.principalDidEquals)(actual, expected);
326
+ } catch {
327
+ return actual === expected;
328
+ }
329
+ }
330
+ function addRawAbility(rawAbilities, resource, action) {
331
+ const actions = rawAbilities[resource];
332
+ if (actions === void 0) {
333
+ rawAbilities[resource] = [action];
334
+ return;
335
+ }
336
+ if (!actions.includes(action)) {
337
+ actions.push(action);
338
+ }
339
+ }
320
340
  var NodeUserAuthorization = class {
321
341
  constructor(config) {
322
342
  this.extensions = [];
@@ -343,6 +363,7 @@ var NodeUserAuthorization = class {
343
363
  "": [
344
364
  "tinycloud.sql/read",
345
365
  "tinycloud.sql/write",
366
+ "tinycloud.sql/ddl",
346
367
  "tinycloud.sql/admin",
347
368
  "tinycloud.sql/export"
348
369
  ]
@@ -434,12 +455,48 @@ var NodeUserAuthorization = class {
434
455
  * `siwe` is the load-bearing one because `extractSiweExpiration` returns
435
456
  * undefined for missing SIWEs and the SDK then treats the session as
436
457
  * expired-at-epoch-zero.
458
+ *
459
+ * @param hosts - The TinyCloud hosts this session was created against,
460
+ * as persisted in {@link PersistedSessionData.tinycloudHosts}. When
461
+ * present (and non-empty) they are adopted directly so the restored
462
+ * session resolves to the same node as the original sign-in without
463
+ * re-running registry/fallback resolution. When absent (old session)
464
+ * hosts are resolved lazily on the first host-needing call via
465
+ * {@link ensureTinyCloudHosts}.
437
466
  */
438
- setRestoredTinyCloudSession(session) {
467
+ setRestoredTinyCloudSession(session, hosts) {
439
468
  const address = (0, import_sdk_core2.canonicalizeAddress)(session.address);
440
469
  this._tinyCloudSession = { ...session, address };
441
470
  this._address = address;
442
471
  this._chainId = session.chainId;
472
+ if ((!this.tinycloudHosts || this.tinycloudHosts.length === 0) && hosts && hosts.length > 0) {
473
+ this.tinycloudHosts = [...hosts];
474
+ }
475
+ }
476
+ /**
477
+ * Ensure `tinycloudHosts` are resolved before a host-needing call.
478
+ *
479
+ * Fresh sign-in resolves hosts up front; a restored session may not have
480
+ * (old persisted sessions predate {@link PersistedSessionData.tinycloudHosts}).
481
+ * This guard makes a restored session resolve the node exactly like a fresh
482
+ * sign-in — persisted hosts are preferred (already set by
483
+ * {@link setRestoredTinyCloudSession}), otherwise the registry/fallback
484
+ * resolution runs lazily here. Idempotent: {@link resolveTinyCloudHostsForSignIn}
485
+ * early-returns when hosts are already set.
486
+ *
487
+ * Throws if hosts are unset and the restored session has no address/chainId
488
+ * to resolve from — a real failure that must surface, not be masked.
489
+ */
490
+ async ensureTinyCloudHosts() {
491
+ if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
492
+ return;
493
+ }
494
+ if (this._address === void 0 || this._chainId === void 0) {
495
+ throw new Error(
496
+ "Cannot resolve TinyCloud hosts: no address/chainId available. Sign in or restore a session first."
497
+ );
498
+ }
499
+ await this.resolveTinyCloudHostsForSignIn(this._address, this._chainId);
443
500
  }
444
501
  async resolveTinyCloudHostsForSignIn(address, chainId) {
445
502
  if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
@@ -546,20 +603,18 @@ var NodeUserAuthorization = class {
546
603
  };
547
604
  }
548
605
  const rawAbilities = {};
606
+ const currentDid = (0, import_sdk_core2.pkhDid)(address, chainId);
549
607
  const spaceResources = request.resources.filter((entry) => {
550
608
  if (entry.service !== import_sdk_core2.ENCRYPTION_PERMISSION_SERVICE) {
551
609
  return true;
552
610
  }
553
- const existing = rawAbilities[entry.path];
554
- if (existing === void 0) {
555
- rawAbilities[entry.path] = [...entry.actions];
556
- } else {
557
- const seen = new Set(existing);
558
- for (const action of entry.actions) {
559
- if (!seen.has(action)) {
560
- existing.push(action);
561
- seen.add(action);
562
- }
611
+ for (const action of entry.actions) {
612
+ addRawAbility(rawAbilities, entry.path, action);
613
+ }
614
+ if (entry.actions.includes(DECRYPT_ACTION)) {
615
+ const parsed = (0, import_sdk_core2.parseNetworkId)(entry.path);
616
+ if (didPrincipalMatches(parsed.ownerDid, currentDid)) {
617
+ addRawAbility(rawAbilities, entry.path, NETWORK_CREATE_ACTION);
563
618
  }
564
619
  }
565
620
  return false;
@@ -638,6 +693,7 @@ var NodeUserAuthorization = class {
638
693
  if (!this._tinyCloudSession || !this._address || !this._chainId) {
639
694
  throw new Error("Must be signed in to host space");
640
695
  }
696
+ await this.ensureTinyCloudHosts();
641
697
  const host = this.primaryTinyCloudHost;
642
698
  const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
643
699
  const peerId = await (0, import_sdk_core2.fetchPeerId)(host, spaceId);
@@ -680,6 +736,7 @@ var NodeUserAuthorization = class {
680
736
  if (!this._tinyCloudSession) {
681
737
  throw new Error("Must be signed in to ensure space exists");
682
738
  }
739
+ await this.ensureTinyCloudHosts();
683
740
  const host = this.primaryTinyCloudHost;
684
741
  const primarySpaceId = this._tinyCloudSession.spaceId;
685
742
  const result = await (0, import_sdk_core2.activateSessionWithHost)(
@@ -861,7 +918,8 @@ var NodeUserAuthorization = class {
861
918
  },
862
919
  expiresAt: expirationTime.toISOString(),
863
920
  createdAt: now.toISOString(),
864
- version: "1.0"
921
+ version: "1.0",
922
+ tinycloudHosts: this.tinycloudHosts
865
923
  };
866
924
  await this.sessionStorage.save(address, persistedData);
867
925
  this._session = clientSession;
@@ -1028,7 +1086,8 @@ var NodeUserAuthorization = class {
1028
1086
  },
1029
1087
  expiresAt,
1030
1088
  createdAt,
1031
- version: "1.0"
1089
+ version: "1.0",
1090
+ tinycloudHosts: this.tinycloudHosts
1032
1091
  };
1033
1092
  await this.sessionStorage.save(address, persistedData);
1034
1093
  this._session = clientSession;
@@ -1119,32 +1178,35 @@ var NodeUserAuthorization = class {
1119
1178
  };
1120
1179
 
1121
1180
  // src/TinyCloudNode.ts
1122
- var import_sdk_core6 = require("@tinycloud/sdk-core");
1181
+ var import_sdk_core7 = require("@tinycloud/sdk-core");
1123
1182
 
1124
- // src/DelegatedAccess.ts
1183
+ // src/account/AccountService.ts
1125
1184
  var import_sdk_core3 = require("@tinycloud/sdk-core");
1185
+
1186
+ // src/DelegatedAccess.ts
1187
+ var import_sdk_core4 = require("@tinycloud/sdk-core");
1126
1188
  var DelegatedAccess = class {
1127
1189
  constructor(session, delegation, host, invoke, telemetry) {
1128
1190
  this.session = session;
1129
1191
  this._delegation = delegation;
1130
1192
  this.host = host;
1131
- this._serviceContext = new import_sdk_core3.ServiceContext({
1193
+ this._serviceContext = new import_sdk_core4.ServiceContext({
1132
1194
  invoke,
1133
1195
  fetch: globalThis.fetch.bind(globalThis),
1134
1196
  hosts: [host],
1135
1197
  telemetry
1136
1198
  });
1137
1199
  const prefix = this._delegation.path.replace(/\/$/, "");
1138
- this._kv = new import_sdk_core3.KVService({ prefix });
1200
+ this._kv = new import_sdk_core4.KVService({ prefix });
1139
1201
  this._kv.initialize(this._serviceContext);
1140
1202
  this._serviceContext.registerService("kv", this._kv);
1141
- this._sql = new import_sdk_core3.SQLService({});
1203
+ this._sql = new import_sdk_core4.SQLService({});
1142
1204
  this._sql.initialize(this._serviceContext);
1143
1205
  this._serviceContext.registerService("sql", this._sql);
1144
- this._duckdb = new import_sdk_core3.DuckDbService({});
1206
+ this._duckdb = new import_sdk_core4.DuckDbService({});
1145
1207
  this._duckdb.initialize(this._serviceContext);
1146
1208
  this._serviceContext.registerService("duckdb", this._duckdb);
1147
- this._hooks = new import_sdk_core3.HooksService({});
1209
+ this._hooks = new import_sdk_core4.HooksService({});
1148
1210
  this._hooks.initialize(this._serviceContext);
1149
1211
  this._serviceContext.registerService("hooks", this._hooks);
1150
1212
  const serviceSession = {
@@ -1294,7 +1356,7 @@ function createWasmKeyProvider(sessionManager) {
1294
1356
  }
1295
1357
 
1296
1358
  // src/delegateToHelpers.ts
1297
- var import_sdk_core4 = require("@tinycloud/sdk-core");
1359
+ var import_sdk_core5 = require("@tinycloud/sdk-core");
1298
1360
  function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
1299
1361
  const byService = /* @__PURE__ */ new Map();
1300
1362
  for (const a of actions) {
@@ -1325,7 +1387,7 @@ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
1325
1387
  }
1326
1388
  return entries;
1327
1389
  }
1328
- var DEFAULT_DELEGATION_EXPIRY_MS = import_sdk_core4.EXPIRY.SESSION_MS;
1390
+ var DEFAULT_DELEGATION_EXPIRY_MS = import_sdk_core5.EXPIRY.SESSION_MS;
1329
1391
  function resolveExpiryMs(expiry) {
1330
1392
  if (expiry === void 0) {
1331
1393
  return DEFAULT_DELEGATION_EXPIRY_MS;
@@ -1338,10 +1400,10 @@ function resolveExpiryMs(expiry) {
1338
1400
  }
1339
1401
  return expiry;
1340
1402
  }
1341
- return (0, import_sdk_core4.parseExpiry)(expiry);
1403
+ return (0, import_sdk_core5.parseExpiry)(expiry);
1342
1404
  }
1343
1405
  function extractSiweExpiration(siwe) {
1344
- const parsed = new import_sdk_core4.SiweMessage(siwe);
1406
+ const parsed = new import_sdk_core5.SiweMessage(siwe);
1345
1407
  if (parsed.expirationTime === void 0 || parsed.expirationTime === null) {
1346
1408
  return void 0;
1347
1409
  }
@@ -1355,7 +1417,7 @@ function extractSiweExpiration(siwe) {
1355
1417
  }
1356
1418
 
1357
1419
  // src/NodeSecretsService.ts
1358
- var import_sdk_core5 = require("@tinycloud/sdk-core");
1420
+ var import_sdk_core6 = require("@tinycloud/sdk-core");
1359
1421
  var SECRETS_SPACE = "secrets";
1360
1422
  function ok() {
1361
1423
  return { ok: true, data: void 0 };
@@ -1388,7 +1450,7 @@ function secretActionName(action) {
1388
1450
  }
1389
1451
  function secretPermissionEntries(name, options, action, encryptionNetworkId) {
1390
1452
  const entries = [];
1391
- const path = action === "list" ? (0, import_sdk_core5.resolveSecretListPrefix)(options) : (0, import_sdk_core5.resolveSecretPath)(name, options).permissionPaths.vault;
1453
+ const path = action === "list" ? (0, import_sdk_core6.resolveSecretListPrefix)(options) : (0, import_sdk_core6.resolveSecretPath)(name, options).permissionPaths.vault;
1392
1454
  entries.push({
1393
1455
  service: "tinycloud.kv",
1394
1456
  space: SECRETS_SPACE,
@@ -1467,7 +1529,7 @@ var NodeSecretsService = class {
1467
1529
  );
1468
1530
  } catch (error) {
1469
1531
  return secretsError(
1470
- import_sdk_core5.ErrorCodes.INVALID_INPUT,
1532
+ import_sdk_core6.ErrorCodes.INVALID_INPUT,
1471
1533
  error instanceof Error ? error.message : String(error),
1472
1534
  error instanceof Error ? error : void 0
1473
1535
  );
@@ -1477,7 +1539,7 @@ var NodeSecretsService = class {
1477
1539
  }
1478
1540
  if (!this.config.canEscalate()) {
1479
1541
  return secretsError(
1480
- import_sdk_core5.ErrorCodes.PERMISSION_DENIED,
1542
+ import_sdk_core6.ErrorCodes.PERMISSION_DENIED,
1481
1543
  `Cannot autosign ${displayActionUrn(action)} for ${target}; TinyCloudNode needs wallet mode with a signer or privateKey.`
1482
1544
  );
1483
1545
  }
@@ -1486,7 +1548,7 @@ var NodeSecretsService = class {
1486
1548
  return this.restoreUnlockAfterEscalation();
1487
1549
  } catch (error) {
1488
1550
  return secretsError(
1489
- import_sdk_core5.ErrorCodes.PERMISSION_DENIED,
1551
+ import_sdk_core6.ErrorCodes.PERMISSION_DENIED,
1490
1552
  error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${target} failed.`,
1491
1553
  error instanceof Error ? error : void 0
1492
1554
  );
@@ -1507,10 +1569,10 @@ var NodeSecretsService = class {
1507
1569
  return false;
1508
1570
  }
1509
1571
  const manifests = Array.isArray(manifest) ? manifest : [manifest];
1510
- const requestedEntries = (0, import_sdk_core5.expandPermissionEntries)(permissionEntries);
1572
+ const requestedEntries = (0, import_sdk_core6.expandPermissionEntries)(permissionEntries);
1511
1573
  return requestedEntries.every(
1512
1574
  (entry) => manifests.some((candidate) => {
1513
- const resolved = (0, import_sdk_core5.resolveManifest)(candidate);
1575
+ const resolved = (0, import_sdk_core6.resolveManifest)(candidate);
1514
1576
  return resolved.resources.some(
1515
1577
  (resource) => resource.service === entry.service && resource.space === entry.space && resource.path === entry.path && entry.actions.every((action) => resource.actions.includes(action))
1516
1578
  );
@@ -1522,13 +1584,13 @@ var NodeSecretsService = class {
1522
1584
  // src/TinyCloudNode.ts
1523
1585
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
1524
1586
  var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
1525
- var NETWORK_CREATE_ACTION = "tinycloud.encryption/network.create";
1526
- var DECRYPT_ACTION = "tinycloud.encryption/decrypt";
1587
+ var NETWORK_CREATE_ACTION2 = "tinycloud.encryption/network.create";
1588
+ var DECRYPT_ACTION2 = "tinycloud.encryption/decrypt";
1527
1589
  var NETWORK_ADMIN_TYPE = "tinycloud.encryption.network-admin/v1";
1528
- var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core6.EXPIRY.SESSION_MS;
1529
- function didPrincipalMatches(actual, expected) {
1590
+ var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core7.EXPIRY.SESSION_MS;
1591
+ function didPrincipalMatches2(actual, expected) {
1530
1592
  try {
1531
- return (0, import_sdk_core6.principalDidEquals)(actual, expected);
1593
+ return (0, import_sdk_core7.principalDidEquals)(actual, expected);
1532
1594
  } catch {
1533
1595
  return actual === expected;
1534
1596
  }
@@ -1694,12 +1756,12 @@ var _TinyCloudNode = class _TinyCloudNode {
1694
1756
  throw new Error("Failed to get session key JWK");
1695
1757
  }
1696
1758
  this.sessionKeyJwk = JSON.parse(jwkStr);
1697
- this._capabilityRegistry = new import_sdk_core6.CapabilityKeyRegistry();
1759
+ this._capabilityRegistry = new import_sdk_core7.CapabilityKeyRegistry();
1698
1760
  this._keyProvider = new WasmKeyProvider({
1699
1761
  sessionManager: this.sessionManager
1700
1762
  });
1701
- this.notificationHandler = config.notificationHandler ?? new import_sdk_core6.SilentNotificationHandler();
1702
- this._sharingService = new import_sdk_core6.SharingService({
1763
+ this.notificationHandler = config.notificationHandler ?? new import_sdk_core7.SilentNotificationHandler();
1764
+ this._sharingService = new import_sdk_core7.SharingService({
1703
1765
  hosts: [this.config.host],
1704
1766
  // session: undefined - not needed for receive()
1705
1767
  invoke: this.invokeWithRuntimePermissions,
@@ -1709,8 +1771,8 @@ var _TinyCloudNode = class _TinyCloudNode {
1709
1771
  // delegationManager: undefined - not needed for receive()
1710
1772
  createKVService: (config2) => {
1711
1773
  const prefix = config2.pathPrefix?.replace(/\/$/, "");
1712
- const kvService = new import_sdk_core6.KVService({ prefix });
1713
- const kvContext = new import_sdk_core6.ServiceContext({
1774
+ const kvService = new import_sdk_core7.KVService({ prefix });
1775
+ const kvContext = new import_sdk_core7.ServiceContext({
1714
1776
  invoke: config2.invoke,
1715
1777
  fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
1716
1778
  hosts: config2.hosts,
@@ -1770,7 +1832,7 @@ var _TinyCloudNode = class _TinyCloudNode {
1770
1832
  capabilityRequest: config.capabilityRequest,
1771
1833
  includeAccountRegistryPermissions: config.includeAccountRegistryPermissions
1772
1834
  });
1773
- this.tc = new import_sdk_core6.TinyCloud(this.auth, {
1835
+ this.tc = new import_sdk_core7.TinyCloud(this.auth, {
1774
1836
  invokeAny: this.invokeAnyWithRuntimePermissions,
1775
1837
  telemetry: config.telemetry
1776
1838
  });
@@ -1831,7 +1893,7 @@ var _TinyCloudNode = class _TinyCloudNode {
1831
1893
  */
1832
1894
  get did() {
1833
1895
  if (this._address) {
1834
- return (0, import_sdk_core6.pkhDid)(this._address, this._chainId);
1896
+ return (0, import_sdk_core7.pkhDid)(this._address, this._chainId);
1835
1897
  }
1836
1898
  return this.sessionManager.getDID(this.sessionKeyId);
1837
1899
  }
@@ -1865,6 +1927,37 @@ var _TinyCloudNode = class _TinyCloudNode {
1865
1927
  get spaceId() {
1866
1928
  return this.auth?.tinyCloudSession?.spaceId;
1867
1929
  }
1930
+ /**
1931
+ * Get the account space ID for this wallet identity.
1932
+ * Available after wallet-backed sign-in or a restored session with address metadata.
1933
+ */
1934
+ get accountSpaceId() {
1935
+ if (!this._address) {
1936
+ return void 0;
1937
+ }
1938
+ return this.wasmBindings.makeSpaceId(this._address, this._chainId, import_sdk_core7.ACCOUNT_REGISTRY_SPACE);
1939
+ }
1940
+ /**
1941
+ * Account-level application and delegation helpers.
1942
+ */
1943
+ get account() {
1944
+ if (!this._account) {
1945
+ this._account = new import_sdk_core3.AccountService({
1946
+ getDid: () => this.did,
1947
+ getHost: () => this.hosts[0] ?? this.config.host,
1948
+ getPrimarySpaceId: () => this.spaceId,
1949
+ getAccountSpaceId: () => this.accountSpaceId,
1950
+ getSpaces: () => this.spaces,
1951
+ getAccountDb: () => this.accountSpaceId ? this.sqlForSpace(this.accountSpaceId).db("account") : void 0,
1952
+ ensureAccountSpaceHosted: async () => {
1953
+ if (this.accountSpaceId && this.auth) {
1954
+ await this.ensureOwnedSpaceHostedById(this.accountSpaceId);
1955
+ }
1956
+ }
1957
+ });
1958
+ }
1959
+ return this._account;
1960
+ }
1868
1961
  /**
1869
1962
  * Get the current TinyCloud session.
1870
1963
  * Available after signIn().
@@ -1886,7 +1979,7 @@ var _TinyCloudNode = class _TinyCloudNode {
1886
1979
  );
1887
1980
  }
1888
1981
  await this.wasmBindings.ensureInitialized?.();
1889
- this._address = (0, import_sdk_core6.canonicalizeAddress)(await this.signer.getAddress());
1982
+ this._address = (0, import_sdk_core7.canonicalizeAddress)(await this.signer.getAddress());
1890
1983
  this._chainId = await this.signer.getChainId();
1891
1984
  this._kv = void 0;
1892
1985
  this._sql = void 0;
@@ -1902,10 +1995,11 @@ var _TinyCloudNode = class _TinyCloudNode {
1902
1995
  await this.tc.signIn(options);
1903
1996
  this.syncResolvedHostFromAuth();
1904
1997
  this.initializeServices();
1998
+ await this.ensureRequestedEncryptionNetworks();
1905
1999
  if (this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
1906
- await this.ensureOwnedSpaceHosted(this.ownedSpaceId("secrets"));
2000
+ await this.ensureOwnedSpaceHostedById(this.ownedSpaceId("secrets"));
1907
2001
  }
1908
- await this.writeManifestRegistryRecords();
2002
+ this.scheduleAccountRegistrySync();
1909
2003
  this.notificationHandler.success("Successfully signed in");
1910
2004
  }
1911
2005
  ownedSpaceId(name) {
@@ -1922,23 +2016,69 @@ var _TinyCloudNode = class _TinyCloudNode {
1922
2016
  if (!this.auth || !this.signer) {
1923
2017
  throw new Error("Manifest registry write requires wallet mode");
1924
2018
  }
1925
- const accountSpaceId = this.ownedSpaceId(import_sdk_core6.ACCOUNT_REGISTRY_SPACE);
1926
- await this.ensureOwnedSpaceHosted(accountSpaceId);
1927
- const accountKV = this.spaces.get(accountSpaceId).kv;
1928
- for (const record of request.registryRecords) {
1929
- const result = await accountKV.put(record.key, {
1930
- app_id: record.app_id,
1931
- manifests: record.manifests,
1932
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1933
- });
1934
- if (!result.ok) {
1935
- throw new Error(
1936
- `Failed to write manifest registry record ${record.key}: ${result.error.message}`
1937
- );
2019
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core7.ACCOUNT_REGISTRY_SPACE);
2020
+ await this.ensureOwnedSpaceHostedById(accountSpaceId);
2021
+ const result = await this.account.applications.register(request.manifests);
2022
+ if (!result.ok) {
2023
+ throw new Error(
2024
+ `Failed to write manifest registry records: ${result.error.message}`
2025
+ );
2026
+ }
2027
+ }
2028
+ scheduleAccountRegistrySync() {
2029
+ void this.withAccountRegistryRetry(async () => {
2030
+ await this.writeManifestRegistryRecords();
2031
+ const spaces = await this.account.spaces.syncAccessible();
2032
+ if (!spaces.ok) {
2033
+ throw new Error(`Failed to sync account spaces: ${spaces.error.message}`);
2034
+ }
2035
+ });
2036
+ }
2037
+ async withAccountRegistryRetry(task) {
2038
+ const delays = [250, 1e3, 3e3];
2039
+ let lastError;
2040
+ for (let attempt = 0; attempt < delays.length; attempt += 1) {
2041
+ try {
2042
+ await task();
2043
+ return;
2044
+ } catch (error) {
2045
+ lastError = error;
2046
+ if (attempt < delays.length - 1) {
2047
+ await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
2048
+ }
1938
2049
  }
1939
2050
  }
2051
+ console.warn(
2052
+ "TinyCloud account registry sync failed after retries",
2053
+ lastError
2054
+ );
2055
+ }
2056
+ requestedEncryptionNetworkIds() {
2057
+ const request = this.capabilityRequest;
2058
+ if (!request) {
2059
+ return [];
2060
+ }
2061
+ const networkIds = /* @__PURE__ */ new Set();
2062
+ for (const resource of request.resources) {
2063
+ if (resource.service === import_sdk_core7.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
2064
+ networkIds.add(resource.path);
2065
+ }
2066
+ }
2067
+ return [...networkIds];
1940
2068
  }
1941
- async ensureOwnedSpaceHosted(spaceId) {
2069
+ async ensureRequestedEncryptionNetworks() {
2070
+ if (!this.signer || !this.auth) {
2071
+ return;
2072
+ }
2073
+ for (const networkId of this.requestedEncryptionNetworkIds()) {
2074
+ const parsed = (0, import_sdk_core7.parseNetworkId)(networkId);
2075
+ if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
2076
+ continue;
2077
+ }
2078
+ await this.ensureEncryptionNetwork(networkId);
2079
+ }
2080
+ }
2081
+ async ensureOwnedSpaceHostedById(spaceId) {
1942
2082
  if (!this.auth) {
1943
2083
  throw new Error("Owned space hosting requires wallet mode");
1944
2084
  }
@@ -1950,7 +2090,7 @@ var _TinyCloudNode = class _TinyCloudNode {
1950
2090
  if (!host) {
1951
2091
  throw new Error("Owned space hosting requires a TinyCloud host");
1952
2092
  }
1953
- const activation = await (0, import_sdk_core6.activateSessionWithHost)(host, session.delegationHeader);
2093
+ const activation = await (0, import_sdk_core7.activateSessionWithHost)(host, session.delegationHeader);
1954
2094
  if (activation.success && !activation.skipped?.includes(spaceId)) {
1955
2095
  return;
1956
2096
  }
@@ -1964,7 +2104,7 @@ var _TinyCloudNode = class _TinyCloudNode {
1964
2104
  throw new Error(`Failed to create owned space: ${spaceId}`);
1965
2105
  }
1966
2106
  await new Promise((resolve) => setTimeout(resolve, 100));
1967
- const retry = await (0, import_sdk_core6.activateSessionWithHost)(host, session.delegationHeader);
2107
+ const retry = await (0, import_sdk_core7.activateSessionWithHost)(host, session.delegationHeader);
1968
2108
  if (!retry.success || retry.skipped?.includes(spaceId)) {
1969
2109
  throw new Error(
1970
2110
  `Failed to activate session after creating owned space ${spaceId}: ${retry.error ?? "space was skipped"}`
@@ -1981,7 +2121,7 @@ var _TinyCloudNode = class _TinyCloudNode {
1981
2121
  * caller is the root authority of their own owned spaces, so no additional
1982
2122
  * delegation is required.
1983
2123
  *
1984
- * Unlike {@link ensureOwnedSpaceHosted}, this always submits the host
2124
+ * Unlike {@link ensureOwnedSpaceHostedById}, this always submits the host
1985
2125
  * delegation rather than inferring hosting from session activation: a space
1986
2126
  * the current session has never referenced is reported neither as
1987
2127
  * `activated` nor `skipped`, so activation-based detection would wrongly
@@ -2006,7 +2146,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2006
2146
  if (!hosted) {
2007
2147
  throw new Error(`Failed to host owned space: ${spaceId}`);
2008
2148
  }
2009
- const activation = await (0, import_sdk_core6.activateSessionWithHost)(
2149
+ const activation = await (0, import_sdk_core7.activateSessionWithHost)(
2010
2150
  host,
2011
2151
  this.auth.tinyCloudSession.delegationHeader
2012
2152
  );
@@ -2015,8 +2155,40 @@ var _TinyCloudNode = class _TinyCloudNode {
2015
2155
  `Failed to activate session for owned space ${spaceId}: ${activation.error ?? "space was skipped"}`
2016
2156
  );
2017
2157
  }
2158
+ void this.account.spaces.register({
2159
+ spaceId,
2160
+ name,
2161
+ ownerDid: this.did,
2162
+ type: "owned",
2163
+ permissions: ["*"],
2164
+ status: "active"
2165
+ }).catch(() => {
2166
+ });
2018
2167
  return spaceId;
2019
2168
  }
2169
+ /**
2170
+ * Ensure one of this user's owned spaces (e.g. `"secrets"`) is hosted on the
2171
+ * server.
2172
+ *
2173
+ * At sign-in, a full-authority session auto-hosts the owner's `secrets`
2174
+ * space, but a session created with a manifest / capabilityRequest does not.
2175
+ * Such a session can therefore hold valid `tinycloud.kv/*` capabilities for
2176
+ * the owned `secrets` space yet still fail its first scoped
2177
+ * `secrets.put(...)` with `404 Space not found`, because the space was never
2178
+ * registered on the node.
2179
+ *
2180
+ * Calling this resolves `name` to the owner's owned-space URI
2181
+ * (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`) and hosts it via the
2182
+ * host-SIWE delegation flow. The host SIWE is idempotent server-side, so it
2183
+ * is safe to call whether or not the space already exists; do not gate it on
2184
+ * a prior existence check. Must be called after {@link signIn}.
2185
+ *
2186
+ * @param name - The owned space name (e.g. `"secrets"`).
2187
+ * @returns The hosted owned-space URI.
2188
+ */
2189
+ async ensureOwnedSpaceHosted(name) {
2190
+ return this.hostOwnedSpace(name);
2191
+ }
2020
2192
  /**
2021
2193
  * Restore a previously established session from stored delegation data.
2022
2194
  *
@@ -2039,30 +2211,38 @@ var _TinyCloudNode = class _TinyCloudNode {
2039
2211
  this._spaceService = void 0;
2040
2212
  this._serviceContext = void 0;
2041
2213
  this.runtimePermissionGrants = [];
2042
- const restoredAddress = sessionData.address ? (0, import_sdk_core6.canonicalizeAddress)(sessionData.address) : void 0;
2214
+ const restoredAddress = sessionData.address ? (0, import_sdk_core7.canonicalizeAddress)(sessionData.address) : void 0;
2043
2215
  if (restoredAddress) {
2044
2216
  this._address = restoredAddress;
2045
2217
  }
2046
2218
  if (sessionData.chainId) {
2047
2219
  this._chainId = sessionData.chainId;
2048
2220
  }
2049
- this._serviceContext = new import_sdk_core6.ServiceContext({
2221
+ const resolvedHost = await this.resolveRestoredHost(
2222
+ sessionData.tinycloudHosts,
2223
+ restoredAddress,
2224
+ sessionData.chainId
2225
+ );
2226
+ if (resolvedHost) {
2227
+ this.config.host = resolvedHost;
2228
+ }
2229
+ this._serviceContext = new import_sdk_core7.ServiceContext({
2050
2230
  invoke: this.invokeWithRuntimePermissions,
2051
2231
  invokeAny: this.invokeAnyWithRuntimePermissions,
2052
2232
  fetch: globalThis.fetch.bind(globalThis),
2053
2233
  hosts: [this.config.host],
2054
2234
  telemetry: this.config.telemetry
2055
2235
  });
2056
- this._kv = new import_sdk_core6.KVService({});
2236
+ this._kv = new import_sdk_core7.KVService({});
2057
2237
  this._kv.initialize(this._serviceContext);
2058
2238
  this._serviceContext.registerService("kv", this._kv);
2059
- this._sql = new import_sdk_core6.SQLService({});
2239
+ this._sql = new import_sdk_core7.SQLService({});
2060
2240
  this._sql.initialize(this._serviceContext);
2061
2241
  this._serviceContext.registerService("sql", this._sql);
2062
- this._duckdb = new import_sdk_core6.DuckDbService({});
2242
+ this._duckdb = new import_sdk_core7.DuckDbService({});
2063
2243
  this._duckdb.initialize(this._serviceContext);
2064
2244
  this._serviceContext.registerService("duckdb", this._duckdb);
2065
- this._hooks = new import_sdk_core6.HooksService({});
2245
+ this._hooks = new import_sdk_core7.HooksService({});
2066
2246
  this._hooks.initialize(this._serviceContext);
2067
2247
  this._serviceContext.registerService("hooks", this._hooks);
2068
2248
  const serviceSession = {
@@ -2091,12 +2271,45 @@ var _TinyCloudNode = class _TinyCloudNode {
2091
2271
  signature: sessionData.signature ?? ""
2092
2272
  };
2093
2273
  if (this.auth) {
2094
- this.auth.setRestoredTinyCloudSession(tcSession);
2274
+ this.auth.setRestoredTinyCloudSession(
2275
+ tcSession,
2276
+ this.config.host ? [this.config.host] : void 0
2277
+ );
2095
2278
  } else {
2096
2279
  this._restoredTcSession = tcSession;
2097
2280
  }
2098
2281
  }
2099
2282
  }
2283
+ /**
2284
+ * Resolve the host a restored session should target.
2285
+ *
2286
+ * Mirrors fresh sign-in host resolution but for the restore path:
2287
+ * an explicit/pinned host always wins, then the hosts the session was
2288
+ * persisted with, then a lazy registry/fallback resolution for sessions
2289
+ * that predate the persisted `tinycloudHosts` field. Returns `undefined`
2290
+ * only when there's nothing to resolve from (no explicit host, no
2291
+ * persisted hosts, and no address/chainId) — in which case the existing
2292
+ * `config.host` (default) is left in place.
2293
+ *
2294
+ * Resolution failures are surfaced, not swallowed: a genuinely broken
2295
+ * registry lookup throws rather than silently falling back to a wrong host.
2296
+ */
2297
+ async resolveRestoredHost(persistedHosts, address, chainId) {
2298
+ if (this.explicitHost) {
2299
+ return this.explicitHost;
2300
+ }
2301
+ if (persistedHosts && persistedHosts.length > 0) {
2302
+ return persistedHosts[0];
2303
+ }
2304
+ if (address === void 0 || chainId === void 0) {
2305
+ return void 0;
2306
+ }
2307
+ const resolved = await (0, import_sdk_core7.resolveTinyCloudHosts)((0, import_sdk_core7.pkhDid)(address, chainId), {
2308
+ registryUrl: this.config.tinycloudRegistryUrl,
2309
+ fallbackHosts: this.config.tinycloudFallbackHosts
2310
+ });
2311
+ return resolved.hosts[0];
2312
+ }
2100
2313
  /**
2101
2314
  * Resolve the currently-active TinyCloudSession, preferring the auth
2102
2315
  * layer's value (wallet mode) and falling back to the node-level
@@ -2161,7 +2374,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2161
2374
  capabilityRequest: this.config.capabilityRequest,
2162
2375
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
2163
2376
  });
2164
- this.tc = new import_sdk_core6.TinyCloud(this.auth, {
2377
+ this.tc = new import_sdk_core7.TinyCloud(this.auth, {
2165
2378
  invokeAny: this.invokeAnyWithRuntimePermissions,
2166
2379
  telemetry: this.config.telemetry
2167
2380
  });
@@ -2206,7 +2419,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2206
2419
  capabilityRequest: this.config.capabilityRequest,
2207
2420
  includeAccountRegistryPermissions: this.config.includeAccountRegistryPermissions
2208
2421
  });
2209
- this.tc = new import_sdk_core6.TinyCloud(this.auth, {
2422
+ this.tc = new import_sdk_core7.TinyCloud(this.auth, {
2210
2423
  invokeAny: this.invokeAnyWithRuntimePermissions,
2211
2424
  telemetry: this.config.telemetry
2212
2425
  });
@@ -2222,28 +2435,28 @@ var _TinyCloudNode = class _TinyCloudNode {
2222
2435
  return;
2223
2436
  }
2224
2437
  this.tc.initializeServices(this.invokeWithRuntimePermissions, [this.config.host]);
2225
- this._serviceContext = new import_sdk_core6.ServiceContext({
2438
+ this._serviceContext = new import_sdk_core7.ServiceContext({
2226
2439
  invoke: this.invokeWithRuntimePermissions,
2227
2440
  invokeAny: this.invokeAnyWithRuntimePermissions,
2228
2441
  fetch: globalThis.fetch.bind(globalThis),
2229
2442
  hosts: [this.config.host],
2230
2443
  telemetry: this.config.telemetry
2231
2444
  });
2232
- this._kv = new import_sdk_core6.KVService({});
2445
+ this._kv = new import_sdk_core7.KVService({});
2233
2446
  this._kv.initialize(this._serviceContext);
2234
2447
  this._serviceContext.registerService("kv", this._kv);
2235
2448
  const features = this.nodeFeatures;
2236
2449
  if (features.length === 0 || features.includes("sql")) {
2237
- this._sql = new import_sdk_core6.SQLService({});
2450
+ this._sql = new import_sdk_core7.SQLService({});
2238
2451
  this._sql.initialize(this._serviceContext);
2239
2452
  this._serviceContext.registerService("sql", this._sql);
2240
2453
  }
2241
2454
  if (features.length === 0 || features.includes("duckdb")) {
2242
- this._duckdb = new import_sdk_core6.DuckDbService({});
2455
+ this._duckdb = new import_sdk_core7.DuckDbService({});
2243
2456
  this._duckdb.initialize(this._serviceContext);
2244
2457
  this._serviceContext.registerService("duckdb", this._duckdb);
2245
2458
  }
2246
- this._hooks = new import_sdk_core6.HooksService({});
2459
+ this._hooks = new import_sdk_core7.HooksService({});
2247
2460
  this._hooks.initialize(this._serviceContext);
2248
2461
  this._serviceContext.registerService("hooks", this._hooks);
2249
2462
  const serviceSession = {
@@ -2261,9 +2474,9 @@ var _TinyCloudNode = class _TinyCloudNode {
2261
2474
  this.initializeV2Services(serviceSession);
2262
2475
  }
2263
2476
  createSpaceScopedKVService(spaceId) {
2264
- const kvService = new import_sdk_core6.KVService({});
2477
+ const kvService = new import_sdk_core7.KVService({});
2265
2478
  if (this._serviceContext) {
2266
- const spaceScopedContext = new import_sdk_core6.ServiceContext({
2479
+ const spaceScopedContext = new import_sdk_core7.ServiceContext({
2267
2480
  invoke: this._serviceContext.invoke,
2268
2481
  fetch: this._serviceContext.fetch,
2269
2482
  hosts: this._serviceContext.hosts,
@@ -2328,7 +2541,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2328
2541
  const shared = wasm.vault_x25519_dh(receiverPrivateKey, peerPublic);
2329
2542
  return columnDecrypt(shared, ciphertext);
2330
2543
  },
2331
- verifyNodeSignature: (nodeId, message, signature) => (0, import_sdk_core6.verifyDidKeyEd25519Signature)(nodeId, message, signature)
2544
+ verifyNodeSignature: (nodeId, message, signature) => (0, import_sdk_core7.verifyDidKeyEd25519Signature)(nodeId, message, signature)
2332
2545
  };
2333
2546
  }
2334
2547
  async fetchNodeId() {
@@ -2399,19 +2612,19 @@ var _TinyCloudNode = class _TinyCloudNode {
2399
2612
  return await response.json();
2400
2613
  }
2401
2614
  };
2402
- return new import_sdk_core6.EncryptionService({
2615
+ return new import_sdk_core7.EncryptionService({
2403
2616
  crypto,
2404
2617
  signer: {
2405
2618
  signDecryptInvocation: async (input) => {
2406
2619
  const signed = await this.signRawNetworkAuthorization({
2407
2620
  targetNode: input.targetNode,
2408
2621
  networkId: input.networkId,
2409
- action: DECRYPT_ACTION,
2622
+ action: DECRYPT_ACTION2,
2410
2623
  facts: input.facts
2411
2624
  });
2412
2625
  return {
2413
2626
  ...signed,
2414
- canonicalBody: (0, import_sdk_core6.canonicalizeEncryptionJson)(
2627
+ canonicalBody: (0, import_sdk_core7.canonicalizeEncryptionJson)(
2415
2628
  input.body
2416
2629
  )
2417
2630
  };
@@ -2423,14 +2636,14 @@ var _TinyCloudNode = class _TinyCloudNode {
2423
2636
  },
2424
2637
  wellKnown: {
2425
2638
  fetchWellKnown: async (principal, discoveryKey) => {
2426
- if (!this._address || !didPrincipalMatches(principal, this.did)) {
2639
+ if (!this._address || !didPrincipalMatches2(principal, this.did)) {
2427
2640
  return null;
2428
2641
  }
2429
2642
  if (!this.config.host) {
2430
2643
  return null;
2431
2644
  }
2432
- const publicSpaceId = (0, import_sdk_core6.makePublicSpaceId)(this._address, this._chainId);
2433
- const result = await import_sdk_core6.TinyCloud.readPublicSpace(this.config.host, publicSpaceId, discoveryKey);
2645
+ const publicSpaceId = (0, import_sdk_core7.makePublicSpaceId)(this._address, this._chainId);
2646
+ const result = await import_sdk_core7.TinyCloud.readPublicSpace(this.config.host, publicSpaceId, discoveryKey);
2434
2647
  if (!result.ok) {
2435
2648
  return null;
2436
2649
  }
@@ -2453,7 +2666,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2453
2666
  }
2454
2667
  createVaultService(spaceId, kv) {
2455
2668
  const wasm = this.wasmBindings;
2456
- const vaultCrypto = (0, import_sdk_core6.createVaultCrypto)({
2669
+ const vaultCrypto = (0, import_sdk_core7.createVaultCrypto)({
2457
2670
  vault_encrypt: wasm.vault_encrypt,
2458
2671
  vault_decrypt: wasm.vault_decrypt,
2459
2672
  vault_derive_key: wasm.vault_derive_key,
@@ -2463,7 +2676,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2463
2676
  vault_sha256: wasm.vault_sha256
2464
2677
  });
2465
2678
  const self = this;
2466
- return new import_sdk_core6.DataVaultService({
2679
+ return new import_sdk_core7.DataVaultService({
2467
2680
  spaceId,
2468
2681
  crypto: vaultCrypto,
2469
2682
  encryption: {
@@ -2486,8 +2699,8 @@ var _TinyCloudNode = class _TinyCloudNode {
2486
2699
  get publicKV() {
2487
2700
  return self._publicKV ?? self.tc.publicKV;
2488
2701
  },
2489
- readPublicSpace: (host, targetSpaceId, key) => import_sdk_core6.TinyCloud.readPublicSpace(host, targetSpaceId, key),
2490
- makePublicSpaceId: import_sdk_core6.TinyCloud.makePublicSpaceId,
2702
+ readPublicSpace: (host, targetSpaceId, key) => import_sdk_core7.TinyCloud.readPublicSpace(host, targetSpaceId, key),
2703
+ makePublicSpaceId: import_sdk_core7.TinyCloud.makePublicSpaceId,
2491
2704
  did: this.did,
2492
2705
  address: this._address ?? "",
2493
2706
  chainId: this._chainId,
@@ -2500,7 +2713,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2500
2713
  * @internal
2501
2714
  */
2502
2715
  initializeV2Services(serviceSession) {
2503
- this._capabilityRegistry = new import_sdk_core6.CapabilityKeyRegistry();
2716
+ this._capabilityRegistry = new import_sdk_core7.CapabilityKeyRegistry();
2504
2717
  const tcSession = this.auth?.tinyCloudSession;
2505
2718
  if (tcSession && this._address) {
2506
2719
  const sessionKey = {
@@ -2574,13 +2787,13 @@ var _TinyCloudNode = class _TinyCloudNode {
2574
2787
  }
2575
2788
  this._capabilityRegistry.registerKey(sessionKey, delegations);
2576
2789
  }
2577
- this._delegationManager = new import_sdk_core6.DelegationManager({
2790
+ this._delegationManager = new import_sdk_core7.DelegationManager({
2578
2791
  hosts: [this.config.host],
2579
2792
  session: serviceSession,
2580
2793
  invoke: this.invokeWithRuntimePermissions,
2581
2794
  fetch: globalThis.fetch.bind(globalThis)
2582
2795
  });
2583
- this._spaceService = new import_sdk_core6.SpaceService({
2796
+ this._spaceService = new import_sdk_core7.SpaceService({
2584
2797
  hosts: [this.config.host],
2585
2798
  session: serviceSession,
2586
2799
  invoke: this.wasmBindings.invoke,
@@ -2632,6 +2845,9 @@ var _TinyCloudNode = class _TinyCloudNode {
2632
2845
  }
2633
2846
  };
2634
2847
  }
2848
+ },
2849
+ onSpaceRegistered: async (space) => {
2850
+ await this.account.spaces.register(space);
2635
2851
  }
2636
2852
  });
2637
2853
  this._sharingService.updateConfig({
@@ -2737,7 +2953,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2737
2953
  ...prepared,
2738
2954
  signature
2739
2955
  });
2740
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
2956
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
2741
2957
  host,
2742
2958
  delegationSession.delegationHeader
2743
2959
  );
@@ -2747,7 +2963,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2747
2963
  return {
2748
2964
  cid: delegationSession.delegationCid,
2749
2965
  delegateDID: params.shareKeyDID,
2750
- delegatorDID: (0, import_sdk_core6.pkhDid)(session.address, session.chainId),
2966
+ delegatorDID: (0, import_sdk_core7.pkhDid)(session.address, session.chainId),
2751
2967
  spaceId: params.spaceId,
2752
2968
  path: params.path,
2753
2969
  actions: params.actions,
@@ -2804,7 +3020,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2804
3020
  if (!this._sql) {
2805
3021
  const features = this.nodeFeatures;
2806
3022
  if (features.length > 0 && !features.includes("sql")) {
2807
- throw new import_sdk_core6.UnsupportedFeatureError("sql", this.config.host, features);
3023
+ throw new import_sdk_core7.UnsupportedFeatureError("sql", this.config.host, features);
2808
3024
  }
2809
3025
  throw new Error("Not signed in. Call signIn() first.");
2810
3026
  }
@@ -2828,8 +3044,8 @@ var _TinyCloudNode = class _TinyCloudNode {
2828
3044
  if (!this._serviceContext || !this._serviceContext.session) {
2829
3045
  throw new Error("Not signed in. Call signIn() first.");
2830
3046
  }
2831
- const sql = new import_sdk_core6.SQLService({});
2832
- const spaceScopedContext = new import_sdk_core6.ServiceContext({
3047
+ const sql = new import_sdk_core7.SQLService({});
3048
+ const spaceScopedContext = new import_sdk_core7.ServiceContext({
2833
3049
  invoke: this._serviceContext.invoke,
2834
3050
  fetch: this._serviceContext.fetch,
2835
3051
  hosts: this._serviceContext.hosts,
@@ -2857,8 +3073,8 @@ var _TinyCloudNode = class _TinyCloudNode {
2857
3073
  if (!this._serviceContext || !this._serviceContext.session) {
2858
3074
  throw new Error("Not signed in. Call signIn() first.");
2859
3075
  }
2860
- const kv = new import_sdk_core6.KVService({});
2861
- const spaceScopedContext = new import_sdk_core6.ServiceContext({
3076
+ const kv = new import_sdk_core7.KVService({});
3077
+ const spaceScopedContext = new import_sdk_core7.ServiceContext({
2862
3078
  invoke: this._serviceContext.invoke,
2863
3079
  fetch: this._serviceContext.fetch,
2864
3080
  hosts: this._serviceContext.hosts
@@ -2874,7 +3090,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2874
3090
  if (!this._duckdb) {
2875
3091
  const features = this.nodeFeatures;
2876
3092
  if (features.length > 0 && !features.includes("duckdb")) {
2877
- throw new import_sdk_core6.UnsupportedFeatureError("duckdb", this.config.host, features);
3093
+ throw new import_sdk_core7.UnsupportedFeatureError("duckdb", this.config.host, features);
2878
3094
  }
2879
3095
  throw new Error("Not signed in. Call signIn() first.");
2880
3096
  }
@@ -2926,16 +3142,16 @@ var _TinyCloudNode = class _TinyCloudNode {
2926
3142
  type: NETWORK_ADMIN_TYPE,
2927
3143
  targetNode,
2928
3144
  networkId,
2929
- bodyHash: (0, import_sdk_core6.canonicalHashHex)(
3145
+ bodyHash: (0, import_sdk_core7.canonicalHashHex)(
2930
3146
  crypto.sha256,
2931
3147
  body
2932
3148
  ),
2933
- action: NETWORK_CREATE_ACTION
3149
+ action: NETWORK_CREATE_ACTION2
2934
3150
  };
2935
3151
  const signed = await this.signRawNetworkAuthorization({
2936
3152
  targetNode,
2937
3153
  networkId,
2938
- action: NETWORK_CREATE_ACTION,
3154
+ action: NETWORK_CREATE_ACTION2,
2939
3155
  facts
2940
3156
  });
2941
3157
  const response = await fetch(`${this.config.host}/encryption/networks`, {
@@ -2944,7 +3160,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2944
3160
  Authorization: signed.authorization,
2945
3161
  "Content-Type": "application/json"
2946
3162
  },
2947
- body: (0, import_sdk_core6.canonicalizeEncryptionJson)(
3163
+ body: (0, import_sdk_core7.canonicalizeEncryptionJson)(
2948
3164
  body
2949
3165
  )
2950
3166
  });
@@ -2956,12 +3172,19 @@ var _TinyCloudNode = class _TinyCloudNode {
2956
3172
  const created = await response.json();
2957
3173
  return created.descriptor;
2958
3174
  }
2959
- async ensureEncryptionNetwork(name = DEFAULT_ENCRYPTION_NETWORK_NAME) {
2960
- const existing = await this.getEncryptionNetwork(name);
3175
+ async ensureEncryptionNetwork(nameOrNetworkId = DEFAULT_ENCRYPTION_NETWORK_NAME) {
3176
+ const networkId = nameOrNetworkId.startsWith("urn:tinycloud:encryption:") ? nameOrNetworkId : this.getDefaultEncryptionNetworkId(nameOrNetworkId);
3177
+ const existing = await this.getEncryptionNetwork(networkId);
2961
3178
  if (existing) {
2962
3179
  return existing;
2963
3180
  }
2964
- return this.createEncryptionNetwork(name);
3181
+ const parsed = (0, import_sdk_core7.parseNetworkId)(networkId);
3182
+ if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
3183
+ throw new Error(
3184
+ `Cannot create encryption network ${networkId}: owner ${parsed.ownerDid} does not match signed-in DID ${this.did}`
3185
+ );
3186
+ }
3187
+ return this.createEncryptionNetwork(parsed.name);
2965
3188
  }
2966
3189
  /**
2967
3190
  * App-facing secrets API backed by the `secrets` space vault.
@@ -2988,7 +3211,7 @@ var _TinyCloudNode = class _TinyCloudNode {
2988
3211
  throw new Error("Not signed in. Call signIn() first.");
2989
3212
  }
2990
3213
  if (!this._baseSecrets) {
2991
- this._baseSecrets = new import_sdk_core6.SecretsService(() => this.space("secrets").vault);
3214
+ this._baseSecrets = new import_sdk_core7.SecretsService(() => this.space("secrets").vault);
2992
3215
  }
2993
3216
  return this._baseSecrets;
2994
3217
  }
@@ -3103,19 +3326,19 @@ var _TinyCloudNode = class _TinyCloudNode {
3103
3326
  async useRuntimeDelegation(delegation) {
3104
3327
  const session = this.currentTinyCloudSession();
3105
3328
  if (!session) {
3106
- throw new import_sdk_core6.SessionExpiredError(/* @__PURE__ */ new Date(0));
3329
+ throw new import_sdk_core7.SessionExpiredError(/* @__PURE__ */ new Date(0));
3107
3330
  }
3108
3331
  if (delegation.expiry.getTime() <= Date.now()) {
3109
- throw new import_sdk_core6.SessionExpiredError(delegation.expiry);
3332
+ throw new import_sdk_core7.SessionExpiredError(delegation.expiry);
3110
3333
  }
3111
3334
  const expectedDids = [session.verificationMethod, this.sessionDid];
3112
- if (!expectedDids.some((did) => didPrincipalMatches(delegation.delegateDID, did))) {
3335
+ if (!expectedDids.some((did) => didPrincipalMatches2(delegation.delegateDID, did))) {
3113
3336
  throw new Error(
3114
3337
  `Runtime delegation targets ${delegation.delegateDID} but this session key is ${session.verificationMethod}.`
3115
3338
  );
3116
3339
  }
3117
3340
  const targetHost = delegation.host ?? this.config.host;
3118
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
3341
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
3119
3342
  targetHost,
3120
3343
  delegation.delegationHeader
3121
3344
  );
@@ -3142,13 +3365,13 @@ var _TinyCloudNode = class _TinyCloudNode {
3142
3365
  }
3143
3366
  const session = this.currentTinyCloudSession();
3144
3367
  if (!session) {
3145
- throw new import_sdk_core6.SessionExpiredError(/* @__PURE__ */ new Date(0));
3368
+ throw new import_sdk_core7.SessionExpiredError(/* @__PURE__ */ new Date(0));
3146
3369
  }
3147
3370
  const sessionExpiry = extractSiweExpiration(session.siwe);
3148
3371
  if (sessionExpiry !== void 0) {
3149
3372
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
3150
3373
  if (sessionExpiry.getTime() <= Date.now() + marginMs) {
3151
- throw new import_sdk_core6.SessionExpiredError(sessionExpiry);
3374
+ throw new import_sdk_core7.SessionExpiredError(sessionExpiry);
3152
3375
  }
3153
3376
  }
3154
3377
  const expanded = this.expandPermissionEntries(permissions);
@@ -3211,7 +3434,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3211
3434
  ...prepared,
3212
3435
  signature
3213
3436
  });
3214
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
3437
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
3215
3438
  this.config.host,
3216
3439
  delegatedSession.delegationHeader
3217
3440
  );
@@ -3384,7 +3607,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3384
3607
  ];
3385
3608
  const abilities = { kv: { "": kvActions } };
3386
3609
  const now = /* @__PURE__ */ new Date();
3387
- const expiryMs = import_sdk_core6.EXPIRY.EPHEMERAL_MS;
3610
+ const expiryMs = import_sdk_core7.EXPIRY.EPHEMERAL_MS;
3388
3611
  const expirationTime = new Date(now.getTime() + expiryMs);
3389
3612
  const prepared = this.wasmBindings.prepareSession({
3390
3613
  abilities,
@@ -3402,7 +3625,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3402
3625
  ...prepared,
3403
3626
  signature
3404
3627
  });
3405
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
3628
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
3406
3629
  this.config.host,
3407
3630
  delegationSession.delegationHeader
3408
3631
  );
@@ -3429,8 +3652,8 @@ var _TinyCloudNode = class _TinyCloudNode {
3429
3652
  }]);
3430
3653
  }
3431
3654
  if (this._serviceContext) {
3432
- const publicKV = new import_sdk_core6.KVService({ prefix: "" });
3433
- const publicContext = new import_sdk_core6.ServiceContext({
3655
+ const publicKV = new import_sdk_core7.KVService({ prefix: "" });
3656
+ const publicContext = new import_sdk_core7.ServiceContext({
3434
3657
  invoke: this.invokeWithRuntimePermissions,
3435
3658
  fetch: this._serviceContext.fetch,
3436
3659
  hosts: this._serviceContext.hosts,
@@ -3557,14 +3780,14 @@ var _TinyCloudNode = class _TinyCloudNode {
3557
3780
  async delegateTo(did, permissions, options) {
3558
3781
  const session = this.currentTinyCloudSession();
3559
3782
  if (!session) {
3560
- throw new import_sdk_core6.SessionExpiredError(/* @__PURE__ */ new Date(0));
3783
+ throw new import_sdk_core7.SessionExpiredError(/* @__PURE__ */ new Date(0));
3561
3784
  }
3562
3785
  const sessionExpiry = extractSiweExpiration(session.siwe);
3563
3786
  if (sessionExpiry !== void 0) {
3564
3787
  const now2 = Date.now();
3565
3788
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
3566
3789
  if (sessionExpiry.getTime() <= now2 + marginMs) {
3567
- throw new import_sdk_core6.SessionExpiredError(sessionExpiry);
3790
+ throw new import_sdk_core7.SessionExpiredError(sessionExpiry);
3568
3791
  }
3569
3792
  }
3570
3793
  if (!Array.isArray(permissions) || permissions.length === 0) {
@@ -3593,11 +3816,11 @@ var _TinyCloudNode = class _TinyCloudNode {
3593
3816
  );
3594
3817
  return { delegation: delegation2, prompted: true };
3595
3818
  }
3596
- const granted = (0, import_sdk_core6.parseRecapCapabilities)(
3819
+ const granted = (0, import_sdk_core7.parseRecapCapabilities)(
3597
3820
  (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
3598
3821
  session.siwe
3599
3822
  );
3600
- const { subset, missing } = (0, import_sdk_core6.isCapabilitySubset)(expandedEntries, granted);
3823
+ const { subset, missing } = (0, import_sdk_core7.isCapabilitySubset)(expandedEntries, granted);
3601
3824
  if (!subset) {
3602
3825
  const runtimeGrant = this.findGrantForOperations(
3603
3826
  this.permissionEntriesToOperations(expandedEntries, session)
@@ -3605,7 +3828,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3605
3828
  if (runtimeGrant) {
3606
3829
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
3607
3830
  if (runtimeGrant.expiresAt.getTime() <= Date.now() + marginMs) {
3608
- throw new import_sdk_core6.SessionExpiredError(runtimeGrant.expiresAt);
3831
+ throw new import_sdk_core7.SessionExpiredError(runtimeGrant.expiresAt);
3609
3832
  }
3610
3833
  const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
3611
3834
  const delegation2 = await this.createDelegationViaRuntimeGrant(
@@ -3616,7 +3839,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3616
3839
  );
3617
3840
  return { delegation: delegation2, prompted: false };
3618
3841
  }
3619
- throw new import_sdk_core6.PermissionNotInManifestError(missing, granted);
3842
+ throw new import_sdk_core7.PermissionNotInManifestError(missing, granted);
3620
3843
  }
3621
3844
  const delegation = await this.createDelegationViaWasmPath(
3622
3845
  did,
@@ -3638,7 +3861,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3638
3861
  );
3639
3862
  }
3640
3863
  const target = request.delegationTargets.find(
3641
- (entry) => didPrincipalMatches(entry.did, did)
3864
+ (entry) => didPrincipalMatches2(entry.did, did)
3642
3865
  );
3643
3866
  if (!target) {
3644
3867
  throw new Error(`No manifest delegation target found for DID ${did}`);
@@ -3698,7 +3921,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3698
3921
  const spaceId = resolvedSpaces.size === 1 ? [...resolvedSpaces][0] : session.spaceId;
3699
3922
  const abilities = {};
3700
3923
  for (const entry of entries) {
3701
- const shortService = import_sdk_core6.SERVICE_LONG_TO_SHORT[entry.service];
3924
+ const shortService = import_sdk_core7.SERVICE_LONG_TO_SHORT[entry.service];
3702
3925
  if (shortService === void 0) {
3703
3926
  throw new Error(
3704
3927
  `delegateTo: unknown service '${entry.service}' \u2014 no short-form mapping`
@@ -3738,7 +3961,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3738
3961
  });
3739
3962
  const primary = result.resources[0];
3740
3963
  const delegationHeader = { Authorization: result.delegation };
3741
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
3964
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
3742
3965
  this.config.host,
3743
3966
  delegationHeader
3744
3967
  );
@@ -3773,7 +3996,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3773
3996
  const primary = result.resources[0];
3774
3997
  const delegationHeader = { Authorization: result.delegation };
3775
3998
  const targetHost = grant.delegation.host ?? this.config.host;
3776
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
3999
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
3777
4000
  targetHost,
3778
4001
  delegationHeader
3779
4002
  );
@@ -3814,10 +4037,10 @@ var _TinyCloudNode = class _TinyCloudNode {
3814
4037
  return this.wasmBindings.makeSpaceId(session.address, session.chainId, space);
3815
4038
  }
3816
4039
  expandPermissionEntries(permissions) {
3817
- return (0, import_sdk_core6.expandPermissionEntries)(permissions);
4040
+ return (0, import_sdk_core7.expandPermissionEntries)(permissions);
3818
4041
  }
3819
4042
  shortServiceName(service) {
3820
- const short = import_sdk_core6.SERVICE_LONG_TO_SHORT[service];
4043
+ const short = import_sdk_core7.SERVICE_LONG_TO_SHORT[service];
3821
4044
  if (short === void 0) {
3822
4045
  throw new Error(
3823
4046
  `unknown service '${service}' \u2014 no short-form mapping`
@@ -3843,7 +4066,7 @@ var _TinyCloudNode = class _TinyCloudNode {
3843
4066
  return abilities;
3844
4067
  }
3845
4068
  isEncryptionPermissionEntry(entry) {
3846
- return entry.service === import_sdk_core6.ENCRYPTION_PERMISSION_SERVICE && entry.path.startsWith("urn:tinycloud:encryption:");
4069
+ return entry.service === import_sdk_core7.ENCRYPTION_PERMISSION_SERVICE && entry.path.startsWith("urn:tinycloud:encryption:");
3847
4070
  }
3848
4071
  permissionsToRawAbilities(entries) {
3849
4072
  const rawAbilities = {};
@@ -3876,11 +4099,11 @@ var _TinyCloudNode = class _TinyCloudNode {
3876
4099
  }
3877
4100
  sessionCoversPermissionEntries(session, entries) {
3878
4101
  try {
3879
- const granted = (0, import_sdk_core6.parseRecapCapabilities)(
4102
+ const granted = (0, import_sdk_core7.parseRecapCapabilities)(
3880
4103
  (siwe) => this.wasmBindings.parseRecapFromSiwe(siwe),
3881
4104
  session.siwe
3882
4105
  );
3883
- return (0, import_sdk_core6.isCapabilitySubset)(entries, granted).subset;
4106
+ return (0, import_sdk_core7.isCapabilitySubset)(entries, granted).subset;
3884
4107
  } catch {
3885
4108
  return false;
3886
4109
  }
@@ -4088,7 +4311,23 @@ var _TinyCloudNode = class _TinyCloudNode {
4088
4311
  if (granted.resource !== void 0 || requested.resource !== void 0) {
4089
4312
  return granted.resource !== void 0 && requested.resource !== void 0 && granted.resource === requested.resource && this.pathContains(granted.path, requested.path);
4090
4313
  }
4091
- return granted.spaceId !== void 0 && requested.spaceId !== void 0 && granted.spaceId === requested.spaceId && this.pathContains(granted.path, requested.path);
4314
+ return granted.spaceId !== void 0 && requested.spaceId !== void 0 && this.spaceIdsEqual(granted.spaceId, requested.spaceId) && this.pathContains(granted.path, requested.path);
4315
+ }
4316
+ // Space IDs are `tinycloud:pkh:eip155:<chain>:<0xADDR>:<name>`. The embedded
4317
+ // EIP-155 address is case-insensitive, but the CLI canonicalizes it to
4318
+ // lowercase when building a space URI while stored runtime delegations keep
4319
+ // the EIP-55 checksummed form — so a byte-for-byte compare spuriously rejects
4320
+ // an otherwise-valid grant. Lowercase ONLY the `eip155:<chain>:0x<addr>`
4321
+ // segment and leave everything else (crucially the case-sensitive space NAME)
4322
+ // byte-exact. Mirrors the CLI's `normalizeSpaceForCompare` (OPENKEY_SCOPE_MISMATCH fix).
4323
+ spaceIdsEqual(a, b) {
4324
+ return this.normalizeSpaceAddress(a) === this.normalizeSpaceAddress(b);
4325
+ }
4326
+ normalizeSpaceAddress(space) {
4327
+ return space.replace(
4328
+ /(eip155:\d+:)(0x[0-9a-fA-F]{40})/,
4329
+ (_match, prefix, addr) => prefix + addr.toLowerCase()
4330
+ );
4092
4331
  }
4093
4332
  actionContains(grantedAction, requestedAction) {
4094
4333
  if (grantedAction === requestedAction) {
@@ -4195,7 +4434,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4195
4434
  if (resolvedDelegateDID.endsWith(".eth") && this.config.ensResolver) {
4196
4435
  const address = await this.config.ensResolver.resolveAddress(resolvedDelegateDID);
4197
4436
  if (!address) throw new Error(`Could not resolve ENS name: ${resolvedDelegateDID}`);
4198
- resolvedDelegateDID = (0, import_sdk_core6.pkhDid)(address, 1);
4437
+ resolvedDelegateDID = (0, import_sdk_core7.pkhDid)(address, 1);
4199
4438
  }
4200
4439
  const entries = legacyParamsToPermissionEntries(
4201
4440
  params.actions,
@@ -4210,7 +4449,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4210
4449
  );
4211
4450
  return result.delegation;
4212
4451
  } catch (err) {
4213
- if (err instanceof import_sdk_core6.PermissionNotInManifestError) {
4452
+ if (err instanceof import_sdk_core7.PermissionNotInManifestError) {
4214
4453
  } else {
4215
4454
  throw err;
4216
4455
  }
@@ -4267,7 +4506,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4267
4506
  ...prepared,
4268
4507
  signature
4269
4508
  });
4270
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
4509
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
4271
4510
  this.config.host,
4272
4511
  delegationSession.delegationHeader
4273
4512
  );
@@ -4289,7 +4528,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4289
4528
  };
4290
4529
  const hasKvActions = params.actions.some((a) => a.startsWith("tinycloud.kv/"));
4291
4530
  if (hasKvActions && params.includePublicSpace !== false) {
4292
- const publicSpaceId = (0, import_sdk_core6.makePublicSpaceId)(
4531
+ const publicSpaceId = (0, import_sdk_core7.makePublicSpaceId)(
4293
4532
  this.wasmBindings.ensureEip55(session.address),
4294
4533
  session.chainId
4295
4534
  );
@@ -4312,7 +4551,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4312
4551
  ...publicPrepared,
4313
4552
  signature: publicSignature
4314
4553
  });
4315
- const publicActivateResult = await (0, import_sdk_core6.activateSessionWithHost)(
4554
+ const publicActivateResult = await (0, import_sdk_core7.activateSessionWithHost)(
4316
4555
  this.config.host,
4317
4556
  publicSession.delegationHeader
4318
4557
  );
@@ -4352,7 +4591,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4352
4591
  const targetHost = delegation.host ?? this.config.host;
4353
4592
  if (this.isSessionOnly) {
4354
4593
  const myDid = this.did;
4355
- if (!didPrincipalMatches(delegation.delegateDID, myDid)) {
4594
+ if (!didPrincipalMatches2(delegation.delegateDID, myDid)) {
4356
4595
  throw new Error(
4357
4596
  `Delegation targets ${delegation.delegateDID} but this user's DID is ${myDid}. The delegation must target this user's DID.`
4358
4597
  );
@@ -4417,7 +4656,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4417
4656
  ...prepared,
4418
4657
  signature
4419
4658
  });
4420
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
4659
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
4421
4660
  targetHost,
4422
4661
  invokerSession.delegationHeader
4423
4662
  );
@@ -4523,7 +4762,7 @@ var _TinyCloudNode = class _TinyCloudNode {
4523
4762
  ...prepared,
4524
4763
  signature
4525
4764
  });
4526
- const activateResult = await (0, import_sdk_core6.activateSessionWithHost)(
4765
+ const activateResult = await (0, import_sdk_core7.activateSessionWithHost)(
4527
4766
  targetHost,
4528
4767
  subDelegationSession.delegationHeader
4529
4768
  );
@@ -4559,7 +4798,7 @@ _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS = 6e4;
4559
4798
  var TinyCloudNode = _TinyCloudNode;
4560
4799
 
4561
4800
  // src/core.ts
4562
- var import_sdk_core9 = require("@tinycloud/sdk-core");
4801
+ var import_sdk_core10 = require("@tinycloud/sdk-core");
4563
4802
 
4564
4803
  // src/delegation.ts
4565
4804
  function serializeDelegation(delegation) {
@@ -4578,7 +4817,6 @@ function deserializeDelegation(data) {
4578
4817
  }
4579
4818
 
4580
4819
  // src/core.ts
4581
- var import_sdk_core10 = require("@tinycloud/sdk-core");
4582
4820
  var import_sdk_core11 = require("@tinycloud/sdk-core");
4583
4821
  var import_sdk_core12 = require("@tinycloud/sdk-core");
4584
4822
  var import_sdk_core13 = require("@tinycloud/sdk-core");
@@ -4587,10 +4825,12 @@ var import_sdk_core15 = require("@tinycloud/sdk-core");
4587
4825
  var import_sdk_core16 = require("@tinycloud/sdk-core");
4588
4826
  var import_sdk_core17 = require("@tinycloud/sdk-core");
4589
4827
  var import_sdk_core18 = require("@tinycloud/sdk-core");
4828
+ var import_sdk_core19 = require("@tinycloud/sdk-core");
4590
4829
  // Annotate the CommonJS export names for ESM import in node:
4591
4830
  0 && (module.exports = {
4592
4831
  ACCOUNT_REGISTRY_PATH,
4593
4832
  ACCOUNT_REGISTRY_SPACE,
4833
+ AccountService,
4594
4834
  AutoApproveSpaceCreationHandler,
4595
4835
  CapabilityKeyRegistry,
4596
4836
  CapabilityKeyRegistryErrorCodes,