@tinycloud/sdk-core 2.4.0-beta.8 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -30,10 +30,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ ACCOUNT_INDEX_SCHEMA: () => import_bootstrap2.ACCOUNT_INDEX_SCHEMA,
33
34
  ACCOUNT_REGISTRY_PATH: () => ACCOUNT_REGISTRY_PATH,
34
35
  ACCOUNT_REGISTRY_SPACE: () => ACCOUNT_REGISTRY_SPACE,
35
36
  AccountService: () => AccountService,
36
37
  AutoApproveSpaceCreationHandler: () => AutoApproveSpaceCreationHandler,
38
+ BOOTSTRAP_ALLOWLIST: () => import_bootstrap2.BOOTSTRAP_ALLOWLIST,
39
+ BOOTSTRAP_DEFAULT_SPACE: () => import_bootstrap2.BOOTSTRAP_DEFAULT_SPACE,
40
+ BOOTSTRAP_ENCRYPTION_NETWORK_NAME: () => import_bootstrap2.BOOTSTRAP_ENCRYPTION_NETWORK_NAME,
41
+ BOOTSTRAP_ENCRYPTION_NETWORK_RESOURCE_TEMPLATE: () => import_bootstrap2.BOOTSTRAP_ENCRYPTION_NETWORK_RESOURCE_TEMPLATE,
42
+ BOOTSTRAP_MANIFEST: () => import_bootstrap2.BOOTSTRAP_MANIFEST,
43
+ BOOTSTRAP_PERSISTED_APPLICATION_MANIFESTS: () => import_bootstrap2.BOOTSTRAP_PERSISTED_APPLICATION_MANIFESTS,
44
+ BOOTSTRAP_PUBLIC_SPACE: () => import_bootstrap2.BOOTSTRAP_PUBLIC_SPACE,
45
+ BOOTSTRAP_SESSION_REQUESTS: () => import_bootstrap2.BOOTSTRAP_SESSION_REQUESTS,
46
+ BOOTSTRAP_SPACE_MANIFESTS: () => import_bootstrap2.BOOTSTRAP_SPACE_MANIFESTS,
47
+ BOOTSTRAP_SPACE_NAMES: () => import_bootstrap2.BOOTSTRAP_SPACE_NAMES,
37
48
  CapabilityKeyRegistry: () => CapabilityKeyRegistry,
38
49
  CapabilityKeyRegistryErrorCodes: () => CapabilityKeyRegistryErrorCodes,
39
50
  ClientSessionSchema: () => ClientSessionSchema,
@@ -45,6 +56,7 @@ __export(index_exports, {
45
56
  DEFAULT_ENCRYPTION_ALG: () => import_sdk_services7.DEFAULT_ENCRYPTION_ALG,
46
57
  DEFAULT_EXPIRY: () => DEFAULT_EXPIRY,
47
58
  DEFAULT_KEY_VERSION: () => import_sdk_services7.DEFAULT_KEY_VERSION,
59
+ DEFAULT_KNOWLEDGE_ROOT: () => DEFAULT_KNOWLEDGE_ROOT,
48
60
  DEFAULT_MANIFEST_SPACE: () => DEFAULT_MANIFEST_SPACE,
49
61
  DEFAULT_MANIFEST_VERSION: () => DEFAULT_MANIFEST_VERSION,
50
62
  DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
@@ -77,7 +89,9 @@ __export(index_exports, {
77
89
  PermissionNotInManifestError: () => PermissionNotInManifestError,
78
90
  PrefixedKVService: () => import_sdk_services7.PrefixedKVService,
79
91
  ProtocolMismatchError: () => ProtocolMismatchError,
92
+ SECRETS_SPACE: () => SECRETS_SPACE,
80
93
  SECRET_NAME_RE: () => import_sdk_services7.SECRET_NAME_RE,
94
+ SECRET_RECORDS_SCHEMA: () => import_bootstrap2.SECRET_RECORDS_SCHEMA,
81
95
  SERVICE_LONG_TO_SHORT: () => SERVICE_LONG_TO_SHORT,
82
96
  SERVICE_SHORT_TO_LONG: () => SERVICE_SHORT_TO_LONG,
83
97
  SQLAction: () => import_sdk_services7.SQLAction,
@@ -92,7 +106,13 @@ __export(index_exports, {
92
106
  Space: () => Space,
93
107
  SpaceErrorCodes: () => SpaceErrorCodes,
94
108
  SpaceService: () => SpaceService,
109
+ TINYCLOUD_ACCOUNT_SPACE_MANIFEST: () => import_bootstrap2.TINYCLOUD_ACCOUNT_SPACE_MANIFEST,
110
+ TINYCLOUD_APPLICATIONS_SPACE_MANIFEST: () => import_bootstrap2.TINYCLOUD_APPLICATIONS_SPACE_MANIFEST,
111
+ TINYCLOUD_DEFAULT_SPACE_MANIFEST: () => import_bootstrap2.TINYCLOUD_DEFAULT_SPACE_MANIFEST,
112
+ TINYCLOUD_PUBLIC_SPACE_MANIFEST: () => import_bootstrap2.TINYCLOUD_PUBLIC_SPACE_MANIFEST,
113
+ TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST: () => import_bootstrap2.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
95
114
  TinyCloud: () => TinyCloud,
115
+ TinyCloudDebugLogger: () => import_sdk_services7.TinyCloudDebugLogger,
96
116
  UnsupportedFeatureError: () => UnsupportedFeatureError,
97
117
  VAULT_PERMISSION_SERVICE: () => VAULT_PERMISSION_SERVICE,
98
118
  VaultHeaders: () => import_sdk_services7.VaultHeaders,
@@ -101,6 +121,9 @@ __export(index_exports, {
101
121
  activateSessionWithHost: () => activateSessionWithHost,
102
122
  addressStorageKey: () => addressStorageKey,
103
123
  applyPrefix: () => applyPrefix,
124
+ bootstrapEncryptionNetworkId: () => import_bootstrap2.bootstrapEncryptionNetworkId,
125
+ bootstrapSpaceId: () => import_bootstrap2.bootstrapSpaceId,
126
+ bootstrapSteps: () => import_bootstrap2.bootstrapSteps,
104
127
  buildCanonicalDecryptRequest: () => import_sdk_services7.buildCanonicalDecryptRequest,
105
128
  buildDecryptAttenuation: () => import_sdk_services7.buildDecryptAttenuation,
106
129
  buildDecryptFacts: () => import_sdk_services7.buildDecryptFacts,
@@ -118,8 +141,11 @@ __export(index_exports, {
118
141
  canonicalizeSecretScope: () => import_sdk_services7.canonicalizeSecretScope,
119
142
  checkDecryptInvocationInput: () => import_sdk_services7.checkDecryptInvocationInput,
120
143
  checkNodeInfo: () => checkNodeInfo,
144
+ clearTinyCloudDebugLogs: () => import_sdk_services7.clearTinyCloudDebugLogs,
145
+ composeBootstrapSpaceManifest: () => import_bootstrap2.composeBootstrapSpaceManifest,
121
146
  composeManifestRequest: () => composeManifestRequest,
122
147
  createCapabilityKeyRegistry: () => createCapabilityKeyRegistry,
148
+ createOpenKeyCallbackSigningStrategy: () => createOpenKeyCallbackSigningStrategy,
123
149
  createSharingService: () => createSharingService,
124
150
  createSpaceService: () => createSpaceService,
125
151
  createVaultCrypto: () => import_sdk_services7.createVaultCrypto,
@@ -130,7 +156,9 @@ __export(index_exports, {
130
156
  deriveSignedReceiverKey: () => import_sdk_services7.deriveSignedReceiverKey,
131
157
  didCacheKey: () => didCacheKey,
132
158
  didEquals: () => didEquals,
159
+ disableTinyCloudDebug: () => import_sdk_services7.disableTinyCloudDebug,
133
160
  discoverNetwork: () => import_sdk_services7.discoverNetwork,
161
+ enableTinyCloudDebug: () => import_sdk_services7.enableTinyCloudDebug,
134
162
  encryptToNetwork: () => import_sdk_services7.encryptToNetwork,
135
163
  encryptionBase64Decode: () => import_sdk_services7.base64Decode,
136
164
  encryptionBase64Encode: () => import_sdk_services7.base64Encode,
@@ -145,9 +173,11 @@ __export(index_exports, {
145
173
  fetchLocationRecord: () => fetchLocationRecord,
146
174
  fetchPeerId: () => fetchPeerId,
147
175
  generateRandomReceiverKey: () => import_sdk_services7.generateRandomReceiverKey,
176
+ getTinyCloudDebugLogs: () => import_sdk_services7.getTinyCloudDebugLogs,
148
177
  hexDecode: () => import_sdk_services7.hexDecode,
149
178
  hexEncode: () => import_sdk_services7.hexEncode,
150
179
  httpUrlToMultiaddr: () => httpUrlToMultiaddr,
180
+ installTinyCloudDebugGlobals: () => import_sdk_services7.installTinyCloudDebugGlobals,
151
181
  isCapabilitySubset: () => isCapabilitySubset,
152
182
  isEvmAddress: () => isEvmAddress,
153
183
  isNetworkId: () => import_sdk_services7.isNetworkId,
@@ -172,6 +202,7 @@ __export(index_exports, {
172
202
  principalDidEquals: () => principalDidEquals,
173
203
  resolveCloudLocation: () => resolveCloudLocation,
174
204
  resolveManifest: () => resolveManifest,
205
+ resolveManifestKnowledgeRoot: () => resolveManifestKnowledgeRoot,
175
206
  resolveSecretListPrefix: () => import_sdk_services7.resolveSecretListPrefix,
176
207
  resolveSecretPath: () => import_sdk_services7.resolveSecretPath,
177
208
  resolveTinyCloudHosts: () => resolveTinyCloudHosts,
@@ -180,6 +211,7 @@ __export(index_exports, {
180
211
  serviceError: () => import_sdk_services7.serviceError,
181
212
  signLocationRecord: () => signLocationRecord,
182
213
  submitHostDelegation: () => submitHostDelegation,
214
+ tinyCloudDebugLogger: () => import_sdk_services7.tinyCloudDebugLogger,
183
215
  validateClientSession: () => validateClientSession,
184
216
  validateEnvelope: () => import_sdk_services7.validateEnvelope,
185
217
  validateLocationRecord: () => validateLocationRecord,
@@ -379,7 +411,15 @@ var PersistedSessionDataSchema = import_zod2.z.object({
379
411
  /** Schema version for migrations */
380
412
  version: import_zod2.z.string(),
381
413
  /** Optional ENS data */
382
- ens: EnsDataSchema2.optional()
414
+ ens: EnsDataSchema2.optional(),
415
+ /**
416
+ * TinyCloud hosts this session was created against. Persisted so a
417
+ * restored session resolves to the same node without re-running the
418
+ * registry/fallback resolution (or the wallet sign-in flow). Optional
419
+ * for backward compatibility with sessions persisted before this field
420
+ * existed — those restore and lazily re-resolve their hosts.
421
+ */
422
+ tinycloudHosts: import_zod2.z.array(import_zod2.z.string()).optional()
383
423
  });
384
424
  var TinyCloudSessionSchema = import_zod2.z.object({
385
425
  /** User's Ethereum address */
@@ -2349,6 +2389,7 @@ var import_sdk_services5 = require("@tinycloud/sdk-services");
2349
2389
  // src/manifest.ts
2350
2390
  var import_ms = __toESM(require("ms"), 1);
2351
2391
  var import_sdk_services4 = require("@tinycloud/sdk-services");
2392
+ var DEFAULT_KNOWLEDGE_ROOT = "knowledge/index.md";
2352
2393
  var ManifestValidationError = class extends Error {
2353
2394
  constructor(message) {
2354
2395
  super(`Manifest validation failed: ${message}`);
@@ -2403,7 +2444,7 @@ var DEFAULT_ADMIN_ENTRIES = [
2403
2444
  service: "tinycloud.sql",
2404
2445
  space: DEFAULT_MANIFEST_SPACE,
2405
2446
  path: "/",
2406
- actions: ["read", "write", "ddl"]
2447
+ actions: ["read", "write", "schema"]
2407
2448
  }
2408
2449
  ];
2409
2450
  var DEFAULT_ALL_ENTRIES = [
@@ -2417,7 +2458,7 @@ var DEFAULT_ALL_ENTRIES = [
2417
2458
  service: "tinycloud.sql",
2418
2459
  space: DEFAULT_MANIFEST_SPACE,
2419
2460
  path: "/",
2420
- actions: ["read", "write", "ddl"]
2461
+ actions: ["read", "write", "schema"]
2421
2462
  },
2422
2463
  {
2423
2464
  service: "tinycloud.duckdb",
@@ -2575,6 +2616,9 @@ function validateManifest(input) {
2575
2616
  if (m.expiry !== void 0) {
2576
2617
  parseExpiry(m.expiry);
2577
2618
  }
2619
+ if (m.knowledge !== void 0) {
2620
+ resolveManifestKnowledgeRoot(m.knowledge);
2621
+ }
2578
2622
  if (m.permissions !== void 0) {
2579
2623
  if (!Array.isArray(m.permissions)) {
2580
2624
  throw new ManifestValidationError(
@@ -2590,6 +2634,25 @@ function validateManifest(input) {
2590
2634
  }
2591
2635
  return m;
2592
2636
  }
2637
+ function resolveManifestKnowledgeRoot(knowledge) {
2638
+ if (knowledge === void 0) {
2639
+ return void 0;
2640
+ }
2641
+ if (knowledge === true) {
2642
+ return DEFAULT_KNOWLEDGE_ROOT;
2643
+ }
2644
+ if (typeof knowledge !== "string" || knowledge.length === 0) {
2645
+ throw new ManifestValidationError(
2646
+ "manifest.knowledge must be true or a knowledge/*.md root path"
2647
+ );
2648
+ }
2649
+ if (!/^knowledge\/.+\.md$/.test(knowledge)) {
2650
+ throw new ManifestValidationError(
2651
+ "manifest.knowledge must be true or a knowledge/*.md root path"
2652
+ );
2653
+ }
2654
+ return knowledge;
2655
+ }
2593
2656
  function validateManifestSecrets(secrets) {
2594
2657
  if (secrets === null || typeof secrets !== "object" || Array.isArray(secrets)) {
2595
2658
  throw new ManifestValidationError("manifest.secrets must be an object");
@@ -2989,7 +3052,7 @@ function accountRegistryIndexPermission() {
2989
3052
  service: "tinycloud.sql",
2990
3053
  space: ACCOUNT_REGISTRY_SPACE,
2991
3054
  path: "account",
2992
- actions: ["tinycloud.sql/read", "tinycloud.sql/write", "tinycloud.sql/ddl"]
3055
+ actions: ["tinycloud.sql/read", "tinycloud.sql/write", "tinycloud.sql/schema"]
2993
3056
  };
2994
3057
  }
2995
3058
  function composeManifestRequest(inputs, options = {}) {
@@ -3094,14 +3157,26 @@ function manifestAbilitiesUnion(resolved) {
3094
3157
  }
3095
3158
 
3096
3159
  // src/account/AccountService.ts
3160
+ var import_bootstrap = require("@tinycloud/bootstrap");
3097
3161
  var SERVICE_NAME2 = "account";
3098
3162
  var ACCOUNT_INDEX_DB = "account";
3163
+ var ACCOUNT_INDEX_NAMESPACE = "tinycloud.account.index";
3099
3164
  var ACCOUNT_SPACES_PATH = "spaces/";
3100
3165
  var AccountService = class {
3101
3166
  constructor(config) {
3102
3167
  this.config = config;
3103
3168
  this.applications = {
3104
- list: async () => {
3169
+ list: async (options = {}) => {
3170
+ if (options.preferIndex) {
3171
+ const indexed = await this.index.applications.list();
3172
+ if (indexed.ok && indexed.data.length > 0) return indexed;
3173
+ if (!indexed.ok && !isMissingIndexError(indexed.error)) return indexed;
3174
+ const canonical = await this.applications.list();
3175
+ if (canonical.ok && options.refreshIndex !== false) {
3176
+ await this.replaceApplicationsIndexQuietly(canonical.data);
3177
+ }
3178
+ return canonical;
3179
+ }
3105
3180
  const kvResult = this.accountKV();
3106
3181
  if (!kvResult.ok) return kvResult;
3107
3182
  const listed = await kvResult.data.list({ prefix: ACCOUNT_REGISTRY_PATH });
@@ -3160,8 +3235,7 @@ var AccountService = class {
3160
3235
  const written = await kvResult.data.put(record.key, stored);
3161
3236
  if (!written.ok) return accountErr(written.error);
3162
3237
  registered = applicationFromRecord(record.key, stored);
3163
- const indexed = await this.upsertApplicationIndex(registered);
3164
- if (!indexed.ok) return indexed;
3238
+ await this.upsertApplicationIndexQuietly(registered);
3165
3239
  }
3166
3240
  return (0, import_sdk_services5.ok)(registered);
3167
3241
  },
@@ -3170,13 +3244,22 @@ var AccountService = class {
3170
3244
  if (!kvResult.ok) return kvResult;
3171
3245
  const removed = await kvResult.data.delete(applicationKey(appId));
3172
3246
  if (!removed.ok) return accountErr(removed.error);
3173
- const indexed = await this.deleteApplicationIndex(appId);
3174
- if (!indexed.ok) return indexed;
3247
+ await this.deleteApplicationIndexQuietly(appId);
3175
3248
  return (0, import_sdk_services5.ok)(void 0);
3176
3249
  }
3177
3250
  };
3178
3251
  this.spaces = {
3179
- list: async () => {
3252
+ list: async (options = {}) => {
3253
+ if (options.preferIndex) {
3254
+ const indexed = await this.index.spaces.list();
3255
+ if (indexed.ok && indexed.data.length > 0) return indexed;
3256
+ if (!indexed.ok && !isMissingIndexError(indexed.error)) return indexed;
3257
+ const canonical = await this.spaces.syncAccessible();
3258
+ if (canonical.ok && options.refreshIndex !== false) {
3259
+ await this.replaceSpacesIndexQuietly(canonical.data);
3260
+ }
3261
+ return canonical;
3262
+ }
3180
3263
  const kvResult = this.accountKV();
3181
3264
  if (!kvResult.ok) return kvResult;
3182
3265
  const listed = await kvResult.data.list({ prefix: ACCOUNT_SPACES_PATH });
@@ -3205,8 +3288,7 @@ var AccountService = class {
3205
3288
  const written = await kvResult.data.put(spaceKey(stored.space_id), stored);
3206
3289
  if (!written.ok) return accountErr(written.error);
3207
3290
  const registered = spaceFromRecord(spaceKey(stored.space_id), stored);
3208
- const indexed = await this.upsertSpaceIndex(registered);
3209
- if (!indexed.ok) return indexed;
3291
+ await this.upsertSpaceIndexQuietly(registered);
3210
3292
  return (0, import_sdk_services5.ok)(registered);
3211
3293
  },
3212
3294
  syncAccessible: async () => {
@@ -3225,13 +3307,25 @@ var AccountService = class {
3225
3307
  if (!kvResult.ok) return kvResult;
3226
3308
  const removed = await kvResult.data.delete(spaceKey(spaceId));
3227
3309
  if (!removed.ok) return accountErr(removed.error);
3228
- const indexed = await this.deleteSpaceIndex(spaceId);
3229
- if (!indexed.ok) return indexed;
3310
+ await this.deleteSpaceIndexQuietly(spaceId);
3230
3311
  return (0, import_sdk_services5.ok)(void 0);
3231
3312
  }
3232
3313
  };
3233
3314
  this.delegations = {
3234
3315
  list: async (options = {}) => {
3316
+ if (options.preferIndex) {
3317
+ const indexed = await this.index.delegations.list(options);
3318
+ if (indexed.ok && indexed.data.length > 0) return indexed;
3319
+ if (!indexed.ok && !isMissingIndexError(indexed.error)) return indexed;
3320
+ const live = await this.delegations.list({
3321
+ direction: options.direction,
3322
+ space: options.space
3323
+ });
3324
+ if (live.ok && options.refreshIndex !== false) {
3325
+ await this.replaceDelegationsIndexQuietly(live.data);
3326
+ }
3327
+ return live;
3328
+ }
3235
3329
  const spaces = await this.config.getSpaces().list();
3236
3330
  if (!spaces.ok) return accountErr(spaces.error);
3237
3331
  const targetSpaces = options.space ? spaces.data.filter((space) => space.id === options.space || space.name === options.space) : spaces.data;
@@ -3261,6 +3355,13 @@ var AccountService = class {
3261
3355
  }
3262
3356
  };
3263
3357
  this.index = {
3358
+ ensure: async () => {
3359
+ const dbResult = this.accountDb();
3360
+ if (!dbResult.ok) return dbResult;
3361
+ const schema = await this.ensureAccountIndex(dbResult.data);
3362
+ if (!schema.ok) return schema;
3363
+ return (0, import_sdk_services5.ok)({ database: ACCOUNT_INDEX_DB });
3364
+ },
3264
3365
  rebuild: async () => {
3265
3366
  const dbResult = this.accountDb();
3266
3367
  if (!dbResult.ok) return dbResult;
@@ -3271,8 +3372,9 @@ var AccountService = class {
3271
3372
  const delegations = await this.delegations.list();
3272
3373
  if (!delegations.ok) return delegations;
3273
3374
  const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
3375
+ const schema = await this.ensureAccountIndex(dbResult.data);
3376
+ if (!schema.ok) return schema;
3274
3377
  const statements = [
3275
- ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3276
3378
  { sql: "DELETE FROM applications" },
3277
3379
  { sql: "DELETE FROM application_state" },
3278
3380
  { sql: "DELETE FROM spaces" },
@@ -3404,9 +3506,15 @@ var AccountService = class {
3404
3506
  const queried = await dbResult.data.query(
3405
3507
  "SELECT source, synced_at, count FROM sync_state ORDER BY source"
3406
3508
  );
3407
- if (!queried.ok) return accountErr(queried.error);
3509
+ if (!queried.ok) {
3510
+ if (isMissingIndexError(queried.error)) {
3511
+ return (0, import_sdk_services5.ok)({ database: ACCOUNT_INDEX_DB, state: "missing", sources: [] });
3512
+ }
3513
+ return accountErr(queried.error);
3514
+ }
3408
3515
  return (0, import_sdk_services5.ok)({
3409
3516
  database: ACCOUNT_INDEX_DB,
3517
+ state: "ready",
3410
3518
  sources: queried.data.rows.map(([source, syncedAt, count]) => ({
3411
3519
  source,
3412
3520
  syncedAt,
@@ -3463,7 +3571,7 @@ var AccountService = class {
3463
3571
  async indexHasApplicationHash(appId, manifestHash) {
3464
3572
  const dbResult = this.accountDb();
3465
3573
  if (!dbResult.ok) return false;
3466
- const schema = await dbResult.data.batch(ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })));
3574
+ const schema = await this.ensureAccountIndex(dbResult.data);
3467
3575
  if (!schema.ok) return false;
3468
3576
  const queried = await dbResult.data.query(
3469
3577
  "SELECT 1 FROM application_state WHERE app_id = ? AND manifest_hash = ? LIMIT 1",
@@ -3471,13 +3579,17 @@ var AccountService = class {
3471
3579
  );
3472
3580
  return queried.ok && queried.data.rows.length > 0;
3473
3581
  }
3582
+ async upsertApplicationIndexQuietly(app) {
3583
+ await ignoreIndexFailure(() => this.upsertApplicationIndex(app));
3584
+ }
3474
3585
  async upsertApplicationIndex(app) {
3475
3586
  const dbResult = this.accountDb();
3476
3587
  if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3588
+ const schema = await this.ensureAccountIndex(dbResult.data);
3589
+ if (!schema.ok) return schema;
3477
3590
  const updatedAt = app.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
3478
3591
  const manifestHash = app.manifestHash ?? hashJson(app.manifests);
3479
3592
  const written = await dbResult.data.batch([
3480
- ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3481
3593
  {
3482
3594
  sql: "INSERT OR REPLACE INTO applications (app_id, name, description, updated_at, manifest_json) VALUES (?, ?, ?, ?, ?)",
3483
3595
  params: [
@@ -3496,23 +3608,31 @@ var AccountService = class {
3496
3608
  if (!written.ok) return accountErr(written.error);
3497
3609
  return (0, import_sdk_services5.ok)(void 0);
3498
3610
  }
3611
+ async deleteApplicationIndexQuietly(appId) {
3612
+ await ignoreIndexFailure(() => this.deleteApplicationIndex(appId));
3613
+ }
3499
3614
  async deleteApplicationIndex(appId) {
3500
3615
  const dbResult = this.accountDb();
3501
3616
  if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3617
+ const schema = await this.ensureAccountIndex(dbResult.data);
3618
+ if (!schema.ok) return schema;
3502
3619
  const deleted = await dbResult.data.batch([
3503
- ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3504
3620
  { sql: "DELETE FROM applications WHERE app_id = ?", params: [appId] },
3505
3621
  { sql: "DELETE FROM application_state WHERE app_id = ?", params: [appId] }
3506
3622
  ]);
3507
3623
  if (!deleted.ok) return accountErr(deleted.error);
3508
3624
  return (0, import_sdk_services5.ok)(void 0);
3509
3625
  }
3626
+ async upsertSpaceIndexQuietly(space) {
3627
+ await ignoreIndexFailure(() => this.upsertSpaceIndex(space));
3628
+ }
3510
3629
  async upsertSpaceIndex(space) {
3511
3630
  const dbResult = this.accountDb();
3512
3631
  if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3632
+ const schema = await this.ensureAccountIndex(dbResult.data);
3633
+ if (!schema.ok) return schema;
3513
3634
  const updatedAt = space.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
3514
3635
  const written = await dbResult.data.batch([
3515
- ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3516
3636
  {
3517
3637
  sql: "INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
3518
3638
  params: [
@@ -3531,11 +3651,15 @@ var AccountService = class {
3531
3651
  if (!written.ok) return accountErr(written.error);
3532
3652
  return (0, import_sdk_services5.ok)(void 0);
3533
3653
  }
3654
+ async deleteSpaceIndexQuietly(spaceId) {
3655
+ await ignoreIndexFailure(() => this.deleteSpaceIndex(spaceId));
3656
+ }
3534
3657
  async deleteSpaceIndex(spaceId) {
3535
3658
  const dbResult = this.accountDb();
3536
3659
  if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3660
+ const schema = await this.ensureAccountIndex(dbResult.data);
3661
+ if (!schema.ok) return schema;
3537
3662
  const deleted = await dbResult.data.batch([
3538
- ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3539
3663
  { sql: "DELETE FROM spaces WHERE space_id = ?", params: [spaceId] }
3540
3664
  ]);
3541
3665
  if (!deleted.ok) return accountErr(deleted.error);
@@ -3552,57 +3676,115 @@ var AccountService = class {
3552
3676
  }
3553
3677
  return (0, import_sdk_services5.ok)(found);
3554
3678
  }
3679
+ async replaceApplicationsIndexQuietly(applications) {
3680
+ await ignoreIndexFailure(async () => {
3681
+ const dbResult = this.accountDb();
3682
+ if (!dbResult.ok) return;
3683
+ const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
3684
+ const schema = await this.ensureAccountIndex(dbResult.data);
3685
+ if (!schema.ok) return;
3686
+ await dbResult.data.batch([
3687
+ { sql: "DELETE FROM applications" },
3688
+ { sql: "DELETE FROM application_state" },
3689
+ ...applications.map((app) => ({
3690
+ sql: "INSERT OR REPLACE INTO applications (app_id, name, description, updated_at, manifest_json) VALUES (?, ?, ?, ?, ?)",
3691
+ params: [
3692
+ app.appId,
3693
+ app.name ?? null,
3694
+ app.description ?? null,
3695
+ app.updatedAt ?? syncedAt,
3696
+ JSON.stringify(app.manifests)
3697
+ ]
3698
+ })),
3699
+ ...applications.map((app) => ({
3700
+ sql: "INSERT OR REPLACE INTO application_state (app_id, manifest_hash, indexed_at) VALUES (?, ?, ?)",
3701
+ params: [app.appId, app.manifestHash ?? hashJson(app.manifests), syncedAt]
3702
+ })),
3703
+ {
3704
+ sql: "INSERT OR REPLACE INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
3705
+ params: ["applications", syncedAt, applications.length]
3706
+ }
3707
+ ]);
3708
+ });
3709
+ }
3710
+ async replaceSpacesIndexQuietly(spaces) {
3711
+ await ignoreIndexFailure(async () => {
3712
+ const dbResult = this.accountDb();
3713
+ if (!dbResult.ok) return;
3714
+ const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
3715
+ const schema = await this.ensureAccountIndex(dbResult.data);
3716
+ if (!schema.ok) return;
3717
+ await dbResult.data.batch([
3718
+ { sql: "DELETE FROM spaces" },
3719
+ ...spaces.map((space) => ({
3720
+ sql: "INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
3721
+ params: [
3722
+ space.spaceId,
3723
+ space.name,
3724
+ space.ownerDid,
3725
+ space.type,
3726
+ JSON.stringify(space.permissions),
3727
+ space.status,
3728
+ space.registeredAt ?? syncedAt,
3729
+ space.updatedAt ?? syncedAt,
3730
+ space.expiresAt?.toISOString() ?? null
3731
+ ]
3732
+ })),
3733
+ {
3734
+ sql: "INSERT OR REPLACE INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
3735
+ params: ["spaces", syncedAt, spaces.length]
3736
+ }
3737
+ ]);
3738
+ });
3739
+ }
3740
+ async replaceDelegationsIndexQuietly(delegations) {
3741
+ await ignoreIndexFailure(async () => {
3742
+ const dbResult = this.accountDb();
3743
+ if (!dbResult.ok) return;
3744
+ const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
3745
+ const schema = await this.ensureAccountIndex(dbResult.data);
3746
+ if (!schema.ok) return;
3747
+ await dbResult.data.batch([
3748
+ { sql: "DELETE FROM delegations" },
3749
+ ...delegations.map((delegation) => ({
3750
+ sql: "INSERT OR REPLACE INTO delegations (cid, direction, space_id, space_name, counterparty_did, delegate_did, delegator_did, path, actions_json, expiry, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
3751
+ params: [
3752
+ delegation.cid,
3753
+ delegation.direction,
3754
+ delegation.spaceId,
3755
+ delegation.spaceName ?? null,
3756
+ delegation.counterpartyDid,
3757
+ delegation.delegateDid,
3758
+ delegation.delegatorDid ?? null,
3759
+ delegation.path,
3760
+ JSON.stringify(delegation.actions),
3761
+ delegation.expiry.toISOString(),
3762
+ delegation.status,
3763
+ delegation.createdAt?.toISOString() ?? null,
3764
+ syncedAt
3765
+ ]
3766
+ })),
3767
+ {
3768
+ sql: "INSERT OR REPLACE INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
3769
+ params: ["delegations", syncedAt, delegations.length]
3770
+ }
3771
+ ]);
3772
+ });
3773
+ }
3774
+ async ensureAccountIndex(db) {
3775
+ const migrated = await db.migrations.apply({
3776
+ namespace: ACCOUNT_INDEX_NAMESPACE,
3777
+ migrations: [
3778
+ {
3779
+ id: "001_initial",
3780
+ sql: [...import_bootstrap.ACCOUNT_INDEX_SCHEMA]
3781
+ }
3782
+ ]
3783
+ });
3784
+ if (!migrated.ok) return accountErr(migrated.error);
3785
+ return (0, import_sdk_services5.ok)(void 0);
3786
+ }
3555
3787
  };
3556
- var ACCOUNT_INDEX_SCHEMA = [
3557
- `CREATE TABLE IF NOT EXISTS applications (
3558
- app_id TEXT PRIMARY KEY,
3559
- name TEXT,
3560
- description TEXT,
3561
- updated_at TEXT,
3562
- manifest_json TEXT NOT NULL
3563
- )`,
3564
- `CREATE TABLE IF NOT EXISTS application_state (
3565
- app_id TEXT PRIMARY KEY,
3566
- manifest_hash TEXT NOT NULL,
3567
- indexed_at TEXT NOT NULL
3568
- )`,
3569
- `CREATE TABLE IF NOT EXISTS spaces (
3570
- space_id TEXT PRIMARY KEY,
3571
- name TEXT NOT NULL,
3572
- owner_did TEXT NOT NULL,
3573
- type TEXT NOT NULL,
3574
- permissions_json TEXT NOT NULL,
3575
- status TEXT NOT NULL,
3576
- registered_at TEXT,
3577
- updated_at TEXT NOT NULL,
3578
- expires_at TEXT
3579
- )`,
3580
- `CREATE TABLE IF NOT EXISTS delegations (
3581
- cid TEXT PRIMARY KEY,
3582
- direction TEXT NOT NULL,
3583
- space_id TEXT NOT NULL,
3584
- space_name TEXT,
3585
- counterparty_did TEXT NOT NULL,
3586
- delegate_did TEXT NOT NULL,
3587
- delegator_did TEXT,
3588
- path TEXT NOT NULL,
3589
- actions_json TEXT NOT NULL,
3590
- expiry TEXT NOT NULL,
3591
- status TEXT NOT NULL,
3592
- created_at TEXT,
3593
- updated_at TEXT NOT NULL
3594
- )`,
3595
- `CREATE TABLE IF NOT EXISTS sync_state (
3596
- source TEXT PRIMARY KEY,
3597
- synced_at TEXT NOT NULL,
3598
- count INTEGER NOT NULL
3599
- )`,
3600
- "CREATE INDEX IF NOT EXISTS idx_delegations_direction ON delegations(direction)",
3601
- "CREATE INDEX IF NOT EXISTS idx_delegations_space ON delegations(space_id)",
3602
- "CREATE INDEX IF NOT EXISTS idx_delegations_counterparty ON delegations(counterparty_did)",
3603
- "CREATE INDEX IF NOT EXISTS idx_spaces_owner ON spaces(owner_did)",
3604
- "CREATE INDEX IF NOT EXISTS idx_spaces_type ON spaces(type)"
3605
- ];
3606
3788
  function applicationKey(appId) {
3607
3789
  return `${ACCOUNT_REGISTRY_PATH}${appId}`;
3608
3790
  }
@@ -3758,6 +3940,15 @@ function mapDelegation(delegation, space, direction) {
3758
3940
  function accountErr(error) {
3759
3941
  return (0, import_sdk_services5.err)((0, import_sdk_services5.serviceError)(error.code, error.message, SERVICE_NAME2, { cause: error.cause, meta: error.meta }));
3760
3942
  }
3943
+ function isMissingIndexError(error) {
3944
+ return /no such table:/i.test(error.message);
3945
+ }
3946
+ async function ignoreIndexFailure(task) {
3947
+ try {
3948
+ await task();
3949
+ } catch {
3950
+ }
3951
+ }
3761
3952
 
3762
3953
  // src/index.ts
3763
3954
  var import_sdk_services7 = require("@tinycloud/sdk-services");
@@ -5503,6 +5694,76 @@ function createCapabilityKeyRegistry() {
5503
5694
  }
5504
5695
 
5505
5696
  // src/authorization/strategies.ts
5697
+ async function resolveOpenKeyToken(token) {
5698
+ return typeof token === "function" ? token() : token;
5699
+ }
5700
+ async function resolveOpenKeyHeaders(headers) {
5701
+ return typeof headers === "function" ? headers() : headers ?? {};
5702
+ }
5703
+ function openKeyApprovalReason(body) {
5704
+ if (body.reason) return body.reason;
5705
+ if (body.error) return body.error;
5706
+ if (body.approvalUrl) {
5707
+ return `OpenKey explicit approval required: ${body.approvalUrl}`;
5708
+ }
5709
+ return "OpenKey explicit approval required";
5710
+ }
5711
+ function createOpenKeyCallbackSigningStrategy(options) {
5712
+ return {
5713
+ type: "callback",
5714
+ openKeyAutoSign: true,
5715
+ handler: async (request) => {
5716
+ const fetchImpl = options.fetch ?? globalThis.fetch;
5717
+ if (!fetchImpl) {
5718
+ throw new Error("OpenKey signing strategy requires a fetch implementation");
5719
+ }
5720
+ const token = await resolveOpenKeyToken(options.token);
5721
+ const extraHeaders = await resolveOpenKeyHeaders(options.headers);
5722
+ const body = {
5723
+ ...request,
5724
+ ...options.keyId ? { keyId: options.keyId } : {}
5725
+ };
5726
+ const response = await fetchImpl(options.endpoint, {
5727
+ method: "POST",
5728
+ credentials: options.credentials,
5729
+ headers: {
5730
+ "content-type": "application/json",
5731
+ ...token ? { authorization: `Bearer ${token}` } : {},
5732
+ ...extraHeaders
5733
+ },
5734
+ body: JSON.stringify(body)
5735
+ });
5736
+ let parsed;
5737
+ try {
5738
+ parsed = await response.json();
5739
+ } catch {
5740
+ parsed = void 0;
5741
+ }
5742
+ if (!response.ok) {
5743
+ return {
5744
+ approved: false,
5745
+ reason: parsed?.reason ?? parsed?.error ?? `OpenKey signing failed with HTTP ${response.status}`
5746
+ };
5747
+ }
5748
+ if (parsed?.needsApproval || parsed?.approved === false) {
5749
+ return {
5750
+ approved: false,
5751
+ reason: openKeyApprovalReason(parsed)
5752
+ };
5753
+ }
5754
+ if (typeof parsed?.signature === "string" && parsed.signature.length > 0) {
5755
+ return {
5756
+ approved: true,
5757
+ signature: parsed.signature
5758
+ };
5759
+ }
5760
+ return {
5761
+ approved: false,
5762
+ reason: "OpenKey signing response did not include a signature"
5763
+ };
5764
+ }
5765
+ };
5766
+ }
5506
5767
  var defaultSignStrategy = { type: "auto-sign" };
5507
5768
 
5508
5769
  // src/authorization/spaceCreation.ts
@@ -5578,6 +5839,9 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
5578
5839
  };
5579
5840
  }
5580
5841
 
5842
+ // src/index.ts
5843
+ var import_bootstrap2 = require("@tinycloud/bootstrap");
5844
+
5581
5845
  // src/location.ts
5582
5846
  var import_multiaddr = require("@multiformats/multiaddr");
5583
5847
  var import_multiaddr_to_uri = require("@multiformats/multiaddr-to-uri");
@@ -6088,10 +6352,21 @@ function parseRecapCapabilities(parseWasm, siwe) {
6088
6352
  }
6089
6353
  // Annotate the CommonJS export names for ESM import in node:
6090
6354
  0 && (module.exports = {
6355
+ ACCOUNT_INDEX_SCHEMA,
6091
6356
  ACCOUNT_REGISTRY_PATH,
6092
6357
  ACCOUNT_REGISTRY_SPACE,
6093
6358
  AccountService,
6094
6359
  AutoApproveSpaceCreationHandler,
6360
+ BOOTSTRAP_ALLOWLIST,
6361
+ BOOTSTRAP_DEFAULT_SPACE,
6362
+ BOOTSTRAP_ENCRYPTION_NETWORK_NAME,
6363
+ BOOTSTRAP_ENCRYPTION_NETWORK_RESOURCE_TEMPLATE,
6364
+ BOOTSTRAP_MANIFEST,
6365
+ BOOTSTRAP_PERSISTED_APPLICATION_MANIFESTS,
6366
+ BOOTSTRAP_PUBLIC_SPACE,
6367
+ BOOTSTRAP_SESSION_REQUESTS,
6368
+ BOOTSTRAP_SPACE_MANIFESTS,
6369
+ BOOTSTRAP_SPACE_NAMES,
6095
6370
  CapabilityKeyRegistry,
6096
6371
  CapabilityKeyRegistryErrorCodes,
6097
6372
  ClientSessionSchema,
@@ -6103,6 +6378,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
6103
6378
  DEFAULT_ENCRYPTION_ALG,
6104
6379
  DEFAULT_EXPIRY,
6105
6380
  DEFAULT_KEY_VERSION,
6381
+ DEFAULT_KNOWLEDGE_ROOT,
6106
6382
  DEFAULT_MANIFEST_SPACE,
6107
6383
  DEFAULT_MANIFEST_VERSION,
6108
6384
  DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
@@ -6135,7 +6411,9 @@ function parseRecapCapabilities(parseWasm, siwe) {
6135
6411
  PermissionNotInManifestError,
6136
6412
  PrefixedKVService,
6137
6413
  ProtocolMismatchError,
6414
+ SECRETS_SPACE,
6138
6415
  SECRET_NAME_RE,
6416
+ SECRET_RECORDS_SCHEMA,
6139
6417
  SERVICE_LONG_TO_SHORT,
6140
6418
  SERVICE_SHORT_TO_LONG,
6141
6419
  SQLAction,
@@ -6150,7 +6428,13 @@ function parseRecapCapabilities(parseWasm, siwe) {
6150
6428
  Space,
6151
6429
  SpaceErrorCodes,
6152
6430
  SpaceService,
6431
+ TINYCLOUD_ACCOUNT_SPACE_MANIFEST,
6432
+ TINYCLOUD_APPLICATIONS_SPACE_MANIFEST,
6433
+ TINYCLOUD_DEFAULT_SPACE_MANIFEST,
6434
+ TINYCLOUD_PUBLIC_SPACE_MANIFEST,
6435
+ TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
6153
6436
  TinyCloud,
6437
+ TinyCloudDebugLogger,
6154
6438
  UnsupportedFeatureError,
6155
6439
  VAULT_PERMISSION_SERVICE,
6156
6440
  VaultHeaders,
@@ -6159,6 +6443,9 @@ function parseRecapCapabilities(parseWasm, siwe) {
6159
6443
  activateSessionWithHost,
6160
6444
  addressStorageKey,
6161
6445
  applyPrefix,
6446
+ bootstrapEncryptionNetworkId,
6447
+ bootstrapSpaceId,
6448
+ bootstrapSteps,
6162
6449
  buildCanonicalDecryptRequest,
6163
6450
  buildDecryptAttenuation,
6164
6451
  buildDecryptFacts,
@@ -6176,8 +6463,11 @@ function parseRecapCapabilities(parseWasm, siwe) {
6176
6463
  canonicalizeSecretScope,
6177
6464
  checkDecryptInvocationInput,
6178
6465
  checkNodeInfo,
6466
+ clearTinyCloudDebugLogs,
6467
+ composeBootstrapSpaceManifest,
6179
6468
  composeManifestRequest,
6180
6469
  createCapabilityKeyRegistry,
6470
+ createOpenKeyCallbackSigningStrategy,
6181
6471
  createSharingService,
6182
6472
  createSpaceService,
6183
6473
  createVaultCrypto,
@@ -6188,7 +6478,9 @@ function parseRecapCapabilities(parseWasm, siwe) {
6188
6478
  deriveSignedReceiverKey,
6189
6479
  didCacheKey,
6190
6480
  didEquals,
6481
+ disableTinyCloudDebug,
6191
6482
  discoverNetwork,
6483
+ enableTinyCloudDebug,
6192
6484
  encryptToNetwork,
6193
6485
  encryptionBase64Decode,
6194
6486
  encryptionBase64Encode,
@@ -6203,9 +6495,11 @@ function parseRecapCapabilities(parseWasm, siwe) {
6203
6495
  fetchLocationRecord,
6204
6496
  fetchPeerId,
6205
6497
  generateRandomReceiverKey,
6498
+ getTinyCloudDebugLogs,
6206
6499
  hexDecode,
6207
6500
  hexEncode,
6208
6501
  httpUrlToMultiaddr,
6502
+ installTinyCloudDebugGlobals,
6209
6503
  isCapabilitySubset,
6210
6504
  isEvmAddress,
6211
6505
  isNetworkId,
@@ -6230,6 +6524,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
6230
6524
  principalDidEquals,
6231
6525
  resolveCloudLocation,
6232
6526
  resolveManifest,
6527
+ resolveManifestKnowledgeRoot,
6233
6528
  resolveSecretListPrefix,
6234
6529
  resolveSecretPath,
6235
6530
  resolveTinyCloudHosts,
@@ -6238,6 +6533,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
6238
6533
  serviceError,
6239
6534
  signLocationRecord,
6240
6535
  submitHostDelegation,
6536
+ tinyCloudDebugLogger,
6241
6537
  validateClientSession,
6242
6538
  validateEnvelope,
6243
6539
  validateLocationRecord,