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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __typeError = (msg) => {
9
+ throw TypeError(msg);
10
+ };
8
11
  var __esm = (fn, res) => function __init() {
9
12
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
13
  };
@@ -32,6 +35,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
32
35
  mod
33
36
  ));
34
37
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
39
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
40
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
41
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
42
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
35
43
 
36
44
  // ../../node_modules/bn.js/lib/bn.js
37
45
  var require_bn = __commonJS({
@@ -14350,8 +14358,8 @@ function searchPath(object, path) {
14350
14358
  }
14351
14359
  return currentChild;
14352
14360
  }
14353
- function uuidV4(randomBytes2) {
14354
- const bytes = arrayify(randomBytes2);
14361
+ function uuidV4(randomBytes3) {
14362
+ const bytes = arrayify(randomBytes3);
14355
14363
  bytes[6] = bytes[6] & 15 | 64;
14356
14364
  bytes[8] = bytes[8] & 63 | 128;
14357
14365
  const value = hexlify(bytes);
@@ -17022,166 +17030,632 @@ var require_utils2 = __commonJS({
17022
17030
  }
17023
17031
  });
17024
17032
 
17033
+ // src/replication/config.ts
17034
+ function assertValidReplicationConfig(replication) {
17035
+ if (replication === void 0 || replication.enabled !== true) return;
17036
+ if (replication.storage === void 0 || replication.storage === null) {
17037
+ throw new TypeError("replication.enabled requires replication.storage");
17038
+ }
17039
+ if (!Array.isArray(replication.prefixes) || replication.prefixes.length === 0) {
17040
+ throw new TypeError("replication.prefixes must be a non-empty array");
17041
+ }
17042
+ for (const prefix of replication.prefixes) {
17043
+ if (typeof prefix !== "string" || prefix === "") {
17044
+ throw new TypeError("replication.prefixes must not contain an empty prefix");
17045
+ }
17046
+ }
17047
+ for (const [index, prefix] of replication.prefixes.entries()) {
17048
+ for (const other of replication.prefixes.slice(index + 1)) {
17049
+ if ((0, import_sdk_services.kvPrefixCovers)(prefix, other) || (0, import_sdk_services.kvPrefixCovers)(other, prefix)) {
17050
+ throw new TypeError(
17051
+ `replication.prefixes must not overlap: ${JSON.stringify(prefix)} and ${JSON.stringify(other)}`
17052
+ );
17053
+ }
17054
+ }
17055
+ if (prefix.split("/", 1)[0] === "vault" && replication.allowSecrets !== true) {
17056
+ throw new TypeError(
17057
+ `replication prefix ${JSON.stringify(prefix)} overlaps the vault namespace; pass allowSecrets to opt in`
17058
+ );
17059
+ }
17060
+ }
17061
+ }
17062
+ var import_sdk_services;
17063
+ var init_config = __esm({
17064
+ "src/replication/config.ts"() {
17065
+ "use strict";
17066
+ import_sdk_services = require("@tinycloud/sdk-services");
17067
+ }
17068
+ });
17069
+
17070
+ // src/replication/authority-sign-in.ts
17071
+ function hasUnrestrictedGetCoverage(entries, spaceId, prefix) {
17072
+ const requiredPaths = (0, import_sdk_core2.grantPathsForSelector)(prefix);
17073
+ return (0, import_sdk_core2.isCapabilitySubset)(
17074
+ requiredPaths.map((path) => ({ service: KV_SERVICE, space: spaceId, path, actions: [KV_GET] })),
17075
+ [...entries]
17076
+ ).subset;
17077
+ }
17078
+ function augmentSignInEntriesWithReplication(input) {
17079
+ const out = [];
17080
+ const replication = input.replication;
17081
+ if (replication === void 0) return out;
17082
+ for (const prefix of replication.prefixes) {
17083
+ if ((0, import_sdk_services2.requiresSecretsOptIn)(input.primarySpaceId, prefix) && replication.allowSecrets !== true) {
17084
+ continue;
17085
+ }
17086
+ if (!hasUnrestrictedGetCoverage(input.entries, input.primarySpaceId, prefix)) {
17087
+ continue;
17088
+ }
17089
+ for (const path of (0, import_sdk_core2.grantPathsForSelector)(prefix)) {
17090
+ out.push({
17091
+ service: KV_SERVICE,
17092
+ space: input.primarySpaceId,
17093
+ path,
17094
+ actions: [KV_GET, KV_SYNC]
17095
+ });
17096
+ }
17097
+ }
17098
+ return out;
17099
+ }
17100
+ var import_sdk_core2, import_sdk_services2, KV_GET, KV_SYNC, KV_SERVICE;
17101
+ var init_authority_sign_in = __esm({
17102
+ "src/replication/authority-sign-in.ts"() {
17103
+ "use strict";
17104
+ import_sdk_core2 = require("@tinycloud/sdk-core");
17105
+ import_sdk_services2 = require("@tinycloud/sdk-services");
17106
+ KV_GET = import_sdk_core2.KV.GET;
17107
+ KV_SYNC = import_sdk_core2.KV.SYNC;
17108
+ KV_SERVICE = "tinycloud.kv";
17109
+ }
17110
+ });
17111
+
17112
+ // src/replication/runtime.ts
17113
+ var runtime_exports = {};
17114
+ __export(runtime_exports, {
17115
+ ReplicationRuntime: () => ReplicationRuntime
17116
+ });
17117
+ function resolvedOptions(options) {
17118
+ return {
17119
+ ...options,
17120
+ syncIntervalMs: options.syncIntervalMs ?? 6e4,
17121
+ maxStalenessMs: options.maxStalenessMs ?? 12e4,
17122
+ staleSyncTimeoutMs: options.staleSyncTimeoutMs ?? 5e3,
17123
+ allowSecrets: options.allowSecrets === true,
17124
+ verify: options.verify === true
17125
+ };
17126
+ }
17127
+ var import_sdk_core10, scheduler, ReplicationRuntime;
17128
+ var init_runtime = __esm({
17129
+ "src/replication/runtime.ts"() {
17130
+ "use strict";
17131
+ import_sdk_core10 = require("@tinycloud/sdk-core");
17132
+ scheduler = {
17133
+ now: () => Date.now(),
17134
+ setTimeout(fn, ms) {
17135
+ const timer = setTimeout(fn, ms);
17136
+ timer.unref?.();
17137
+ return () => clearTimeout(timer);
17138
+ }
17139
+ };
17140
+ ReplicationRuntime = class {
17141
+ constructor(options, clock = scheduler) {
17142
+ this.options = options;
17143
+ this.clock = clock;
17144
+ this.pending = /* @__PURE__ */ new Map();
17145
+ this.attached = /* @__PURE__ */ new Map();
17146
+ this.previous = Promise.resolve();
17147
+ this.binding = Promise.resolve();
17148
+ this.generation = 0;
17149
+ this.bindingActive = false;
17150
+ this.pendingPurgeSet = false;
17151
+ this.closed = false;
17152
+ this.control = {
17153
+ status: async () => {
17154
+ await this.binding;
17155
+ return this.current ? this.current.status() : [];
17156
+ },
17157
+ sync: async (input) => {
17158
+ await this.binding;
17159
+ if (this.purgedGeneration === this.generation) return;
17160
+ if (this.current) await this.current.sync(input);
17161
+ },
17162
+ purge: (input) => {
17163
+ if (this.bindingActive) {
17164
+ this.pendingPurge = input;
17165
+ this.pendingPurgeSet = true;
17166
+ const existing = this.current ?? this.lastController;
17167
+ if (existing) {
17168
+ this.pendingPurgeResult = existing.purge(input);
17169
+ this.purgedGeneration = this.generation;
17170
+ }
17171
+ return this.binding.then(() => this.pendingPurgeResult ?? { purged: [], failed: [] });
17172
+ }
17173
+ const controller = this.current ?? this.lastController;
17174
+ if (!controller) return Promise.resolve({ purged: [], failed: [] });
17175
+ this.purgedGeneration = this.generation;
17176
+ return controller.purge(input);
17177
+ },
17178
+ clearPending: async () => {
17179
+ await this.binding;
17180
+ if (this.current) return this.current.clearPending();
17181
+ const pending = this.lastPending;
17182
+ if (!pending) return 0;
17183
+ return pending.update((state) => {
17184
+ const before = state.records.length;
17185
+ state.records = state.records.filter(
17186
+ (record) => record.state === "committed" || record.state === "in_flight" && this.clock.now() - Date.parse(record.at) <= 10 * 6e4
17187
+ );
17188
+ return before - state.records.length;
17189
+ });
17190
+ },
17191
+ close: async () => {
17192
+ this.closed = true;
17193
+ this.unbind();
17194
+ await this.binding.catch(() => void 0);
17195
+ await this.previous;
17196
+ }
17197
+ };
17198
+ }
17199
+ loadServices() {
17200
+ return this.services ?? (this.services = import("@tinycloud/sdk-services/kv/replication"));
17201
+ }
17202
+ detachAll() {
17203
+ for (const kv of this.attached.keys()) kv.setReadThrough(null);
17204
+ this.attached.clear();
17205
+ }
17206
+ bind(input) {
17207
+ if (this.closed || !this.options.enabled) return Promise.resolve();
17208
+ this.bindingActive = true;
17209
+ const generation = ++this.generation;
17210
+ this.purgedGeneration = void 0;
17211
+ const { context, session } = input;
17212
+ const emit = (event) => {
17213
+ try {
17214
+ this.options.onEvent?.(event);
17215
+ } catch {
17216
+ }
17217
+ const { type, ...data } = event;
17218
+ context.emit(type, data);
17219
+ };
17220
+ const previous = this.current;
17221
+ this.current = void 0;
17222
+ for (const kv of this.attached.keys()) kv.setReadThrough(null);
17223
+ this.primarySpace = session.spaceId;
17224
+ const close = previous ? previous.close().catch(() => void 0) : Promise.resolve();
17225
+ this.previous = this.previous.then(() => close);
17226
+ const previousClose = this.previous;
17227
+ this.binding = this.loadServices().then((services) => {
17228
+ if (generation !== this.generation || this.closed) return;
17229
+ let identity;
17230
+ try {
17231
+ identity = services.canonicalReplicationIdentity({
17232
+ host: context.hosts[0],
17233
+ space: session.spaceId,
17234
+ principal: input.principal ?? (0, import_sdk_core10.pkhDid)(input.address, input.chainId)
17235
+ });
17236
+ } catch {
17237
+ for (const prefix of this.options.prefixes) {
17238
+ emit({ type: "replication.state", at: new Date(this.clock.now()).toISOString(), space: session.spaceId, replica: prefix, state: "unavailable", code: "CONFIG_INVALID" });
17239
+ }
17240
+ return;
17241
+ }
17242
+ const key2 = services.replicationIdentityKey(identity);
17243
+ let pending = this.pending.get(key2);
17244
+ if (!pending) {
17245
+ pending = this.options.storage.pendingWrites?.(identity) ?? services.createMemoryPendingStore(identity);
17246
+ this.pending.set(key2, pending);
17247
+ }
17248
+ this.lastPending = pending;
17249
+ const controller = services.createKVReplication({
17250
+ options: resolvedOptions(this.options),
17251
+ mode: this.options.mode ?? "background",
17252
+ storage: this.options.storage,
17253
+ identity,
17254
+ session: { id: session.delegationCid, did: session.verificationMethod, space: session.spaceId },
17255
+ authority: input.authority,
17256
+ pending,
17257
+ scheduler: this.clock,
17258
+ emit,
17259
+ fetch: context.fetch,
17260
+ previous: previousClose
17261
+ });
17262
+ this.current = controller;
17263
+ this.lastController = controller;
17264
+ this.lastIdentity = identity;
17265
+ for (const [kv, space] of this.attached) {
17266
+ kv.setReadThrough(space === this.primarySpace ? controller : null);
17267
+ }
17268
+ for (const scoped of input.primaryKV) this.attach(scoped.space, scoped.kv);
17269
+ if (this.pendingPurgeSet) {
17270
+ this.pendingPurgeResult = controller.purge(this.pendingPurge);
17271
+ this.purgedGeneration = generation;
17272
+ this.pendingPurge = void 0;
17273
+ this.pendingPurgeSet = false;
17274
+ }
17275
+ }).finally(() => {
17276
+ if (generation === this.generation) this.bindingActive = false;
17277
+ });
17278
+ for (const kv of this.attached.keys()) kv.setReadThroughReady?.(this.binding);
17279
+ return this.binding;
17280
+ }
17281
+ attach(space, kv) {
17282
+ this.attached.set(kv, space);
17283
+ kv.setReadThrough(space === this.primarySpace ? this.current ?? null : null);
17284
+ return this.binding.then(() => {
17285
+ kv.setReadThrough(space === this.primarySpace ? this.current ?? null : null);
17286
+ });
17287
+ }
17288
+ unbind() {
17289
+ this.generation++;
17290
+ this.bindingActive = false;
17291
+ this.pendingPurgeSet = false;
17292
+ const controller = this.current;
17293
+ this.current = void 0;
17294
+ this.primarySpace = void 0;
17295
+ this.detachAll();
17296
+ const binding = this.binding;
17297
+ const close = binding.then(() => controller?.close()).catch(() => void 0);
17298
+ this.previous = this.previous.then(() => close);
17299
+ return this.previous;
17300
+ }
17301
+ get boundIdentity() {
17302
+ return this.lastIdentity;
17303
+ }
17304
+ };
17305
+ }
17306
+ });
17307
+
17308
+ // src/replication/authority.ts
17309
+ var authority_exports = {};
17310
+ __export(authority_exports, {
17311
+ AUTHORITY_EXPIRY_MARGIN_MS: () => AUTHORITY_EXPIRY_MARGIN_MS,
17312
+ assertValidReplicationConfig: () => assertValidReplicationConfig,
17313
+ augmentSignInEntriesWithReplication: () => augmentSignInEntriesWithReplication,
17314
+ createReplicationAuthority: () => createReplicationAuthority,
17315
+ hasUnrestrictedGetCoverage: () => hasUnrestrictedGetCoverage,
17316
+ replicationScopeFromSignedSession: () => replicationScopeFromSignedSession,
17317
+ ucanAttCovers: () => ucanAttCovers,
17318
+ ucanAttUnconstrainedFor: () => ucanAttUnconstrainedFor
17319
+ });
17320
+ function replicationEntries(spaceId, prefix) {
17321
+ return (0, import_sdk_core11.grantPathsForSelector)(prefix).map((path) => ({
17322
+ service: KV_SERVICE2,
17323
+ space: spaceId,
17324
+ path,
17325
+ actions: [KV_GET2, KV_SYNC2]
17326
+ }));
17327
+ }
17328
+ function caveatBranchesUnconstrained(value) {
17329
+ if (value === void 0 || value === null) return true;
17330
+ if (typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0) {
17331
+ return true;
17332
+ }
17333
+ if (!Array.isArray(value)) return false;
17334
+ try {
17335
+ return (0, import_sdk_core11.canonicalizeRecapCaveats)(value) === (0, import_sdk_core11.canonicalizeRecapCaveats)(void 0);
17336
+ } catch {
17337
+ return false;
17338
+ }
17339
+ }
17340
+ function kvPathInResource(resource, space) {
17341
+ for (const base2 of [`${space}/kv/`, `tinycloud://${space}/kv/`]) {
17342
+ if (resource.startsWith(base2)) return resource.slice(base2.length);
17343
+ }
17344
+ return void 0;
17345
+ }
17346
+ function ucanAttCovers(att, space, prefix, ability, options) {
17347
+ const requiredPaths = prefix.endsWith("/") ? [prefix] : [prefix, `${prefix}/`];
17348
+ return requiredPaths.every((requestedPath) => {
17349
+ for (const [resource, abilities] of Object.entries(att)) {
17350
+ const path = kvPathInResource(resource, space);
17351
+ if (path === void 0) continue;
17352
+ for (const [granted, caveats] of Object.entries(abilities)) {
17353
+ if (!(0, import_sdk_core11.actionContains)(granted, ability)) continue;
17354
+ if (!(0, import_sdk_core11.isCapabilitySubset)(
17355
+ [{ service: KV_SERVICE2, space, path: requestedPath, actions: [ability] }],
17356
+ [{ service: KV_SERVICE2, space, path, actions: [granted] }]
17357
+ ).subset) continue;
17358
+ if (options?.ignoreCaveats === true || caveatBranchesUnconstrained(caveats)) return true;
17359
+ }
17360
+ }
17361
+ return false;
17362
+ });
17363
+ }
17364
+ function ucanAttUnconstrainedFor(att, space, prefix) {
17365
+ return ucanAttCovers(att, space, prefix, KV_GET2) && ucanAttCovers(att, space, prefix, KV_SYNC2);
17366
+ }
17367
+ function replicationScopeFromSignedSession(input) {
17368
+ let grant;
17369
+ try {
17370
+ grant = parseUcanGrant(input.delegationHeader.Authorization);
17371
+ } catch {
17372
+ return void 0;
17373
+ }
17374
+ const bareDid = (value) => value.split("#", 1)[0];
17375
+ if (grant.cid !== input.delegationCid || bareDid(grant.audience) !== bareDid(input.verificationMethod)) return void 0;
17376
+ for (const resource of Object.keys(grant.att)) {
17377
+ const space = resource.match(/^(?:tinycloud:\/\/)?(.+?)\/kv\//)?.[1];
17378
+ if (space !== input.persistedSpace) continue;
17379
+ const owner = (0, import_sdk_core11.parseSpaceUri)(space);
17380
+ if (owner?.owner && owner.address && owner.chainId) return { space, principal: owner.owner };
17381
+ }
17382
+ return void 0;
17383
+ }
17384
+ function createReplicationAuthority(host) {
17385
+ const planOrRefusal = (entries) => {
17386
+ const plan = host.planDelegation(entries);
17387
+ if ("refused" in plan) return plan;
17388
+ return { path: plan.path, parentCid: plan.parentCid, expiresAt: plan.expiresAt };
17389
+ };
17390
+ const sessionAudience = (value) => value.split("#", 1)[0];
17391
+ const signedSessionGrant = (session) => {
17392
+ const grant = parseUcanGrant(session.delegationHeader.Authorization);
17393
+ if (grant.cid !== session.delegationCid || sessionAudience(grant.audience) !== sessionAudience(session.verificationMethod)) return void 0;
17394
+ return grant;
17395
+ };
17396
+ const authority = {
17397
+ get sessionOnly() {
17398
+ const session = host.replicationSession();
17399
+ return session !== void 0 && session.siwe === void 0;
17400
+ },
17401
+ sessionGrant(prefix) {
17402
+ const session = host.replicationSession();
17403
+ if (session === void 0) return { refused: "SESSION_EXPIRING" };
17404
+ const siweExpiry = session.siwe ? host.siweExpiration(session.siwe)?.getTime() : void 0;
17405
+ if (siweExpiry !== void 0 && siweExpiry <= Date.now() + AUTHORITY_EXPIRY_MARGIN_MS) {
17406
+ return { refused: "SESSION_EXPIRING" };
17407
+ }
17408
+ let grant;
17409
+ try {
17410
+ const verified = signedSessionGrant(session);
17411
+ if (!verified) return { refused: "NOT_COVERED" };
17412
+ grant = verified;
17413
+ } catch {
17414
+ return { refused: "NOT_COVERED" };
17415
+ }
17416
+ const tokenExpiry = grant.expiresAt === null ? void 0 : grant.expiresAt * 1e3;
17417
+ if (tokenExpiry === void 0 || tokenExpiry <= Date.now() + AUTHORITY_EXPIRY_MARGIN_MS) {
17418
+ return { refused: "SESSION_EXPIRING" };
17419
+ }
17420
+ const covered = ucanAttCovers(grant.att, session.spaceId, prefix, KV_GET2, { ignoreCaveats: true }) && ucanAttCovers(grant.att, session.spaceId, prefix, KV_SYNC2, { ignoreCaveats: true });
17421
+ if (!covered) return { refused: "NOT_COVERED" };
17422
+ if (!ucanAttUnconstrainedFor(grant.att, session.spaceId, prefix)) {
17423
+ return { refused: "CAVEATED_AUTHORITY" };
17424
+ }
17425
+ return {
17426
+ ucan: grant.jwt,
17427
+ device: { did: session.verificationMethod, jwk: session.jwk }
17428
+ };
17429
+ },
17430
+ plan(prefix) {
17431
+ const session = host.replicationSession();
17432
+ if (session === void 0) return { refused: "SESSION_EXPIRING" };
17433
+ const sessionGrant = this.sessionGrant(prefix);
17434
+ if (!("refused" in sessionGrant)) {
17435
+ const signed2 = signedSessionGrant(session);
17436
+ if (!signed2 || signed2.expiresAt === null) return { refused: "NOT_COVERED" };
17437
+ return {
17438
+ path: "session",
17439
+ parentCid: session.delegationCid,
17440
+ expiresAt: signed2.expiresAt * 1e3
17441
+ };
17442
+ }
17443
+ if (authority.sessionOnly) return sessionGrant;
17444
+ return planOrRefusal(replicationEntries(session.spaceId, prefix));
17445
+ },
17446
+ async mint(deviceDid, prefix, signal) {
17447
+ if (authority.sessionOnly) throw new Error("compact delegate sessions cannot mint device grants");
17448
+ const session = host.replicationSession();
17449
+ if (session === void 0) throw new Error("replication mint without a session");
17450
+ const entries = replicationEntries(session.spaceId, prefix);
17451
+ const plan = planOrRefusal(entries);
17452
+ if ("refused" in plan) {
17453
+ throw Object.assign(
17454
+ new Error(`replication authority refused the mint: ${plan.refused}`),
17455
+ { refused: plan.refused }
17456
+ );
17457
+ }
17458
+ signal.throwIfAborted();
17459
+ const minted = await new Promise((resolve, reject2) => {
17460
+ const onAbort = () => reject2(signal.reason ?? new Error("replication mint aborted"));
17461
+ signal.addEventListener("abort", onAbort, { once: true });
17462
+ host.mintDelegation(deviceDid, entries).then(
17463
+ (result) => {
17464
+ signal.removeEventListener("abort", onAbort);
17465
+ resolve(result);
17466
+ },
17467
+ (error) => {
17468
+ signal.removeEventListener("abort", onAbort);
17469
+ reject2(error instanceof Error ? error : new Error(String(error)));
17470
+ }
17471
+ );
17472
+ });
17473
+ return { ucan: minted.ucan, parentCid: plan.parentCid, expiresAt: minted.expiresAt };
17474
+ }
17475
+ };
17476
+ return authority;
17477
+ }
17478
+ var import_sdk_core11, import_replica, parseUcanGrant, KV_GET2, KV_SYNC2, KV_SERVICE2, AUTHORITY_EXPIRY_MARGIN_MS;
17479
+ var init_authority = __esm({
17480
+ "src/replication/authority.ts"() {
17481
+ "use strict";
17482
+ import_sdk_core11 = require("@tinycloud/sdk-core");
17483
+ import_replica = require("@tinycloud/replica");
17484
+ init_config();
17485
+ init_authority_sign_in();
17486
+ parseUcanGrant = import_replica.parseUcanGrant;
17487
+ KV_GET2 = import_sdk_core11.KV.GET;
17488
+ KV_SYNC2 = import_sdk_core11.KV.SYNC;
17489
+ KV_SERVICE2 = "tinycloud.kv";
17490
+ AUTHORITY_EXPIRY_MARGIN_MS = 6e4;
17491
+ }
17492
+ });
17493
+
17025
17494
  // src/index.ts
17026
- var index_exports = {};
17027
- __export(index_exports, {
17495
+ var src_exports = {};
17496
+ __export(src_exports, {
17028
17497
  ACCEPTED_MARKER_VERSIONS: () => ACCEPTED_MARKER_VERSIONS,
17029
- ACCOUNT_REGISTRY_PATH: () => import_sdk_core12.ACCOUNT_REGISTRY_PATH,
17030
- ACCOUNT_REGISTRY_SPACE: () => import_sdk_core12.ACCOUNT_REGISTRY_SPACE,
17031
- AccountService: () => import_sdk_core4.AccountService,
17032
- AutoApproveSpaceCreationHandler: () => import_sdk_core11.AutoApproveSpaceCreationHandler,
17498
+ ACCOUNT_REGISTRY_PATH: () => import_sdk_core16.ACCOUNT_REGISTRY_PATH,
17499
+ ACCOUNT_REGISTRY_SPACE: () => import_sdk_core16.ACCOUNT_REGISTRY_SPACE,
17500
+ AccountService: () => import_sdk_core5.AccountService,
17501
+ AutoApproveSpaceCreationHandler: () => import_sdk_core15.AutoApproveSpaceCreationHandler,
17033
17502
  BOOTSTRAP_COMPLETION_MARKER_KEY: () => BOOTSTRAP_COMPLETION_MARKER_KEY,
17034
17503
  BOOTSTRAP_COMPLETION_MARKER_VERSION: () => BOOTSTRAP_COMPLETION_MARKER_VERSION,
17035
- CapabilityKeyRegistry: () => import_sdk_core20.CapabilityKeyRegistry,
17036
- CapabilityKeyRegistryErrorCodes: () => import_sdk_core20.CapabilityKeyRegistryErrorCodes,
17037
- CaveatedDelegationUnsupportedError: () => import_sdk_core12.CaveatedDelegationUnsupportedError,
17038
- DECRYPT_ACTION: () => import_sdk_core17.DECRYPT_ACTION,
17039
- DECRYPT_FACT_TYPE: () => import_sdk_core17.DECRYPT_FACT_TYPE,
17040
- DECRYPT_RESULT_TYPE: () => import_sdk_core17.DECRYPT_RESULT_TYPE,
17041
- DEFAULT_ENCRYPTION_ALG: () => import_sdk_core17.DEFAULT_ENCRYPTION_ALG,
17042
- DEFAULT_KEY_VERSION: () => import_sdk_core17.DEFAULT_KEY_VERSION,
17043
- DEFAULT_MANIFEST_SPACE: () => import_sdk_core12.DEFAULT_MANIFEST_SPACE,
17044
- DEFAULT_MANIFEST_VERSION: () => import_sdk_core12.DEFAULT_MANIFEST_VERSION,
17045
- DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => import_sdk_core13.DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
17046
- DataVaultService: () => import_sdk_core16.DataVaultService,
17047
- DatabaseHandle: () => import_sdk_core14.DatabaseHandle,
17048
- DecryptTransportResponseError: () => import_sdk_core17.DecryptTransportResponseError,
17504
+ CapabilityKeyRegistry: () => import_sdk_core24.CapabilityKeyRegistry,
17505
+ CapabilityKeyRegistryErrorCodes: () => import_sdk_core24.CapabilityKeyRegistryErrorCodes,
17506
+ CaveatedDelegationUnsupportedError: () => import_sdk_core16.CaveatedDelegationUnsupportedError,
17507
+ DECRYPT_ACTION: () => import_sdk_core21.DECRYPT_ACTION,
17508
+ DECRYPT_FACT_TYPE: () => import_sdk_core21.DECRYPT_FACT_TYPE,
17509
+ DECRYPT_RESULT_TYPE: () => import_sdk_core21.DECRYPT_RESULT_TYPE,
17510
+ DEFAULT_ENCRYPTION_ALG: () => import_sdk_core21.DEFAULT_ENCRYPTION_ALG,
17511
+ DEFAULT_KEY_VERSION: () => import_sdk_core21.DEFAULT_KEY_VERSION,
17512
+ DEFAULT_MANIFEST_SPACE: () => import_sdk_core16.DEFAULT_MANIFEST_SPACE,
17513
+ DEFAULT_MANIFEST_VERSION: () => import_sdk_core16.DEFAULT_MANIFEST_VERSION,
17514
+ DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => import_sdk_core17.DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
17515
+ DataVaultService: () => import_sdk_core20.DataVaultService,
17516
+ DatabaseHandle: () => import_sdk_core18.DatabaseHandle,
17517
+ DecryptTransportResponseError: () => import_sdk_core21.DecryptTransportResponseError,
17049
17518
  DelegatedAccess: () => DelegatedAccess,
17050
- DelegationErrorCodes: () => import_sdk_core19.DelegationErrorCodes,
17051
- DelegationManager: () => import_sdk_core19.DelegationManager,
17052
- DuckDbAction: () => import_sdk_core15.DuckDbAction,
17053
- DuckDbDatabaseHandle: () => import_sdk_core15.DuckDbDatabaseHandle,
17054
- DuckDbService: () => import_sdk_core15.DuckDbService,
17055
- ENCRYPTION_NETWORK_URN_PREFIX: () => import_sdk_core17.ENCRYPTION_NETWORK_URN_PREFIX,
17056
- ENCRYPTION_SERVICE: () => import_sdk_core17.ENCRYPTION_SERVICE,
17057
- ENCRYPTION_SERVICE_SHORT: () => import_sdk_core17.ENCRYPTION_SERVICE_SHORT,
17058
- ENVELOPE_VERSION: () => import_sdk_core17.ENVELOPE_VERSION,
17059
- EncryptionService: () => import_sdk_core17.EncryptionService,
17519
+ DelegationErrorCodes: () => import_sdk_core23.DelegationErrorCodes,
17520
+ DelegationManager: () => import_sdk_core23.DelegationManager,
17521
+ DuckDbAction: () => import_sdk_core19.DuckDbAction,
17522
+ DuckDbDatabaseHandle: () => import_sdk_core19.DuckDbDatabaseHandle,
17523
+ DuckDbService: () => import_sdk_core19.DuckDbService,
17524
+ ENCRYPTION_NETWORK_URN_PREFIX: () => import_sdk_core21.ENCRYPTION_NETWORK_URN_PREFIX,
17525
+ ENCRYPTION_SERVICE: () => import_sdk_core21.ENCRYPTION_SERVICE,
17526
+ ENCRYPTION_SERVICE_SHORT: () => import_sdk_core21.ENCRYPTION_SERVICE_SHORT,
17527
+ ENVELOPE_VERSION: () => import_sdk_core21.ENVELOPE_VERSION,
17528
+ EncryptionService: () => import_sdk_core21.EncryptionService,
17060
17529
  FileSessionStorage: () => FileSessionStorage,
17061
- HooksService: () => import_sdk_core18.HooksService,
17062
- IdentityParseError: () => import_sdk_core11.IdentityParseError,
17530
+ HooksService: () => import_sdk_core22.HooksService,
17531
+ IdentityParseError: () => import_sdk_core15.IdentityParseError,
17063
17532
  InvalidRestoredSessionError: () => InvalidRestoredSessionError,
17064
- KVService: () => import_sdk_core13.KVService,
17065
- ManifestValidationError: () => import_sdk_core12.ManifestValidationError,
17533
+ KVService: () => import_sdk_core17.KVService,
17534
+ MAX_SECRET_SCOPE_LENGTH: () => import_sdk_core20.MAX_SECRET_SCOPE_LENGTH,
17535
+ ManifestValidationError: () => import_sdk_core16.ManifestValidationError,
17066
17536
  MemorySessionStorage: () => MemorySessionStorage,
17067
- NETWORK_NAME_PATTERN: () => import_sdk_core17.NETWORK_NAME_PATTERN,
17068
- NetworkIdError: () => import_sdk_core17.NetworkIdError,
17537
+ NETWORK_NAME_PATTERN: () => import_sdk_core21.NETWORK_NAME_PATTERN,
17538
+ NetworkIdError: () => import_sdk_core21.NetworkIdError,
17069
17539
  NodeUserAuthorization: () => NodeUserAuthorization,
17070
17540
  NodeWasmBindings: () => NodeWasmBindings,
17071
- PermissionNotInManifestError: () => import_sdk_core12.PermissionNotInManifestError,
17072
- PrefixedKVService: () => import_sdk_core13.PrefixedKVService,
17541
+ PermissionNotInManifestError: () => import_sdk_core16.PermissionNotInManifestError,
17542
+ PrefixedKVService: () => import_sdk_core17.PrefixedKVService,
17073
17543
  PrivateKeySigner: () => PrivateKeySigner,
17074
- ProtocolMismatchError: () => import_sdk_core22.ProtocolMismatchError,
17544
+ ProtocolMismatchError: () => import_sdk_core26.ProtocolMismatchError,
17075
17545
  RUNTIME_DELEGATION_REJECTIONS: () => RUNTIME_DELEGATION_REJECTIONS,
17076
17546
  RuntimeDelegationRejectedError: () => RuntimeDelegationRejectedError,
17077
- SECRET_NAME_RE: () => import_sdk_core16.SECRET_NAME_RE,
17078
- SQLAction: () => import_sdk_core14.SQLAction,
17079
- SQLService: () => import_sdk_core14.SQLService,
17080
- STORAGE_FULL_MESSAGE: () => import_sdk_core11.STORAGE_FULL_MESSAGE,
17081
- STORAGE_WRITE_TOO_LARGE_MESSAGE: () => import_sdk_core11.STORAGE_WRITE_TOO_LARGE_MESSAGE,
17082
- SecretsService: () => import_sdk_core16.SecretsService,
17083
- ServiceContext: () => import_sdk_core23.ServiceContext,
17084
- SessionExpiredError: () => import_sdk_core12.SessionExpiredError,
17085
- SharingService: () => import_sdk_core19.SharingService,
17086
- SilentNotificationHandler: () => import_sdk_core11.SilentNotificationHandler,
17087
- Space: () => import_sdk_core21.Space,
17088
- SpaceErrorCodes: () => import_sdk_core21.SpaceErrorCodes,
17089
- SpaceService: () => import_sdk_core21.SpaceService,
17090
- TinyCloud: () => import_sdk_core10.TinyCloud,
17091
- TinyCloudDebugLogger: () => import_sdk_core11.TinyCloudDebugLogger,
17547
+ SECRET_NAME_RE: () => import_sdk_core20.SECRET_NAME_RE,
17548
+ SECRET_SCOPE_RE: () => import_sdk_core20.SECRET_SCOPE_RE,
17549
+ SQLAction: () => import_sdk_core18.SQLAction,
17550
+ SQLService: () => import_sdk_core18.SQLService,
17551
+ STORAGE_FULL_MESSAGE: () => import_sdk_core15.STORAGE_FULL_MESSAGE,
17552
+ STORAGE_WRITE_TOO_LARGE_MESSAGE: () => import_sdk_core15.STORAGE_WRITE_TOO_LARGE_MESSAGE,
17553
+ SecretsService: () => import_sdk_core20.SecretsService,
17554
+ ServiceContext: () => import_sdk_core27.ServiceContext,
17555
+ SessionExpiredError: () => import_sdk_core16.SessionExpiredError,
17556
+ SharingService: () => import_sdk_core23.SharingService,
17557
+ SilentNotificationHandler: () => import_sdk_core15.SilentNotificationHandler,
17558
+ Space: () => import_sdk_core25.Space,
17559
+ SpaceErrorCodes: () => import_sdk_core25.SpaceErrorCodes,
17560
+ SpaceService: () => import_sdk_core25.SpaceService,
17561
+ TC832_RESERVED_SCOPES: () => import_sdk_core20.TC832_RESERVED_SCOPES,
17562
+ TinyCloud: () => import_sdk_core14.TinyCloud,
17563
+ TinyCloudDebugLogger: () => import_sdk_core15.TinyCloudDebugLogger,
17092
17564
  TinyCloudNode: () => TinyCloudNode,
17093
- UnsupportedFeatureError: () => import_sdk_core22.UnsupportedFeatureError,
17565
+ UnsupportedFeatureError: () => import_sdk_core26.UnsupportedFeatureError,
17094
17566
  UnsupportedSessionRestoreError: () => UnsupportedSessionRestoreError,
17095
- VAULT_PERMISSION_SERVICE: () => import_sdk_core12.VAULT_PERMISSION_SERVICE,
17096
- VaultHeaders: () => import_sdk_core16.VaultHeaders,
17097
- VaultPublicSpaceKVActions: () => import_sdk_core16.VaultPublicSpaceKVActions,
17098
- VersionCheckError: () => import_sdk_core22.VersionCheckError,
17567
+ VAULT_PERMISSION_SERVICE: () => import_sdk_core16.VAULT_PERMISSION_SERVICE,
17568
+ VaultHeaders: () => import_sdk_core20.VaultHeaders,
17569
+ VaultPublicSpaceKVActions: () => import_sdk_core20.VaultPublicSpaceKVActions,
17570
+ VersionCheckError: () => import_sdk_core26.VersionCheckError,
17099
17571
  WasmKeyProvider: () => WasmKeyProvider,
17100
17572
  activateCompactRuntimeDelegation: () => activateCompactRuntimeDelegation,
17101
17573
  activateValidatedRuntimeDelegation: () => activateValidatedRuntimeDelegation,
17102
- addressStorageKey: () => import_sdk_core11.addressStorageKey,
17103
- buildCanonicalDecryptRequest: () => import_sdk_core17.buildCanonicalDecryptRequest,
17104
- buildDecryptAttenuation: () => import_sdk_core17.buildDecryptAttenuation,
17105
- buildDecryptFacts: () => import_sdk_core17.buildDecryptFacts,
17106
- buildDecryptInvocation: () => import_sdk_core17.buildDecryptInvocation,
17107
- buildNetworkId: () => import_sdk_core17.buildNetworkId,
17108
- buildSpaceUri: () => import_sdk_core21.buildSpaceUri,
17109
- canonicalHashHex: () => import_sdk_core17.canonicalHashHex,
17110
- canonicalSignedResponse: () => import_sdk_core17.canonicalSignedResponse,
17111
- canonicalizeAddress: () => import_sdk_core11.canonicalizeAddress,
17112
- canonicalizeDid: () => import_sdk_core11.canonicalizeDid,
17113
- canonicalizeDidUrl: () => import_sdk_core11.canonicalizeDidUrl,
17114
- canonicalizeEncryptionJson: () => import_sdk_core17.canonicalizeEncryptionJson,
17115
- canonicalizeNetworkId: () => import_sdk_core11.canonicalizeNetworkId,
17116
- canonicalizeSecretScope: () => import_sdk_core16.canonicalizeSecretScope,
17117
- checkDecryptInvocationInput: () => import_sdk_core17.checkDecryptInvocationInput,
17118
- checkNodeInfo: () => import_sdk_core22.checkNodeInfo,
17119
- clearTinyCloudDebugLogs: () => import_sdk_core11.clearTinyCloudDebugLogs,
17120
- composeManifestRequest: () => import_sdk_core12.composeManifestRequest,
17121
- createCapabilityKeyRegistry: () => import_sdk_core20.createCapabilityKeyRegistry,
17122
- createOpenKeyCallbackSigningStrategy: () => import_sdk_core2.createOpenKeyCallbackSigningStrategy,
17123
- createSharingService: () => import_sdk_core19.createSharingService,
17124
- createSpaceService: () => import_sdk_core21.createSpaceService,
17125
- createVaultCrypto: () => import_sdk_core16.createVaultCrypto,
17574
+ addressStorageKey: () => import_sdk_core15.addressStorageKey,
17575
+ appSecretScope: () => import_sdk_core20.appSecretScope,
17576
+ buildCanonicalDecryptRequest: () => import_sdk_core21.buildCanonicalDecryptRequest,
17577
+ buildDecryptAttenuation: () => import_sdk_core21.buildDecryptAttenuation,
17578
+ buildDecryptFacts: () => import_sdk_core21.buildDecryptFacts,
17579
+ buildDecryptInvocation: () => import_sdk_core21.buildDecryptInvocation,
17580
+ buildNetworkId: () => import_sdk_core21.buildNetworkId,
17581
+ buildSpaceUri: () => import_sdk_core25.buildSpaceUri,
17582
+ canonicalHashHex: () => import_sdk_core21.canonicalHashHex,
17583
+ canonicalSignedResponse: () => import_sdk_core21.canonicalSignedResponse,
17584
+ canonicalizeAddress: () => import_sdk_core15.canonicalizeAddress,
17585
+ canonicalizeDid: () => import_sdk_core15.canonicalizeDid,
17586
+ canonicalizeDidUrl: () => import_sdk_core15.canonicalizeDidUrl,
17587
+ canonicalizeEncryptionJson: () => import_sdk_core21.canonicalizeEncryptionJson,
17588
+ canonicalizeNetworkId: () => import_sdk_core15.canonicalizeNetworkId,
17589
+ canonicalizeSecretScope: () => import_sdk_core20.canonicalizeSecretScope,
17590
+ checkDecryptInvocationInput: () => import_sdk_core21.checkDecryptInvocationInput,
17591
+ checkNodeInfo: () => import_sdk_core26.checkNodeInfo,
17592
+ clearTinyCloudDebugLogs: () => import_sdk_core15.clearTinyCloudDebugLogs,
17593
+ composeManifestRequest: () => import_sdk_core16.composeManifestRequest,
17594
+ createCapabilityKeyRegistry: () => import_sdk_core24.createCapabilityKeyRegistry,
17595
+ createOpenKeyCallbackSigningStrategy: () => import_sdk_core3.createOpenKeyCallbackSigningStrategy,
17596
+ createSharingService: () => import_sdk_core23.createSharingService,
17597
+ createSpaceService: () => import_sdk_core25.createSpaceService,
17598
+ createVaultCrypto: () => import_sdk_core20.createVaultCrypto,
17126
17599
  createWasmKeyProvider: () => createWasmKeyProvider,
17127
- decryptEnvelopeWithKey: () => import_sdk_core17.decryptEnvelopeWithKey,
17600
+ decryptEnvelopeWithKey: () => import_sdk_core21.decryptEnvelopeWithKey,
17128
17601
  defaultSignStrategy: () => defaultSignStrategy,
17129
- defaultSpaceCreationHandler: () => import_sdk_core11.defaultSpaceCreationHandler,
17130
- deriveSignedReceiverKey: () => import_sdk_core17.deriveSignedReceiverKey,
17602
+ defaultSpaceCreationHandler: () => import_sdk_core15.defaultSpaceCreationHandler,
17603
+ deriveSignedReceiverKey: () => import_sdk_core21.deriveSignedReceiverKey,
17131
17604
  deserializeDelegation: () => deserializeDelegation,
17132
- didCacheKey: () => import_sdk_core11.didCacheKey,
17133
- didEquals: () => import_sdk_core11.didEquals,
17134
- disableTinyCloudDebug: () => import_sdk_core11.disableTinyCloudDebug,
17135
- discoverNetwork: () => import_sdk_core17.discoverNetwork,
17136
- enableTinyCloudDebug: () => import_sdk_core11.enableTinyCloudDebug,
17137
- encryptToNetwork: () => import_sdk_core17.encryptToNetwork,
17138
- encryptionBase64Decode: () => import_sdk_core17.encryptionBase64Decode,
17139
- encryptionBase64Encode: () => import_sdk_core17.encryptionBase64Encode,
17140
- encryptionError: () => import_sdk_core17.encryptionError,
17141
- encryptionUtf8Decode: () => import_sdk_core17.encryptionUtf8Decode,
17142
- encryptionUtf8Encode: () => import_sdk_core17.encryptionUtf8Encode,
17143
- ensureNetworkUsableForDecrypt: () => import_sdk_core17.ensureNetworkUsableForDecrypt,
17144
- expandActionShortNames: () => import_sdk_core12.expandActionShortNames,
17145
- expandPermissionEntries: () => import_sdk_core12.expandPermissionEntries,
17146
- expandPermissionEntry: () => import_sdk_core12.expandPermissionEntry,
17605
+ didCacheKey: () => import_sdk_core15.didCacheKey,
17606
+ didEquals: () => import_sdk_core15.didEquals,
17607
+ disableTinyCloudDebug: () => import_sdk_core15.disableTinyCloudDebug,
17608
+ discoverNetwork: () => import_sdk_core21.discoverNetwork,
17609
+ enableTinyCloudDebug: () => import_sdk_core15.enableTinyCloudDebug,
17610
+ encryptToNetwork: () => import_sdk_core21.encryptToNetwork,
17611
+ encryptionBase64Decode: () => import_sdk_core21.encryptionBase64Decode,
17612
+ encryptionBase64Encode: () => import_sdk_core21.encryptionBase64Encode,
17613
+ encryptionError: () => import_sdk_core21.encryptionError,
17614
+ encryptionUtf8Decode: () => import_sdk_core21.encryptionUtf8Decode,
17615
+ encryptionUtf8Encode: () => import_sdk_core21.encryptionUtf8Encode,
17616
+ ensureNetworkUsableForDecrypt: () => import_sdk_core21.ensureNetworkUsableForDecrypt,
17617
+ expandActionShortNames: () => import_sdk_core16.expandActionShortNames,
17618
+ expandPermissionEntries: () => import_sdk_core16.expandPermissionEntries,
17619
+ expandPermissionEntry: () => import_sdk_core16.expandPermissionEntry,
17147
17620
  extractSiweExpiration: () => extractSiweExpiration,
17148
- generateRandomReceiverKey: () => import_sdk_core17.generateRandomReceiverKey,
17149
- getTinyCloudDebugLogs: () => import_sdk_core11.getTinyCloudDebugLogs,
17621
+ generateRandomReceiverKey: () => import_sdk_core21.generateRandomReceiverKey,
17622
+ getTinyCloudDebugLogs: () => import_sdk_core15.getTinyCloudDebugLogs,
17150
17623
  grantAuthRequest: () => grantAuthRequest,
17151
- hexDecode: () => import_sdk_core17.hexDecode,
17152
- hexEncode: () => import_sdk_core17.hexEncode,
17153
- installTinyCloudDebugGlobals: () => import_sdk_core11.installTinyCloudDebugGlobals,
17154
- isCapabilitySubset: () => import_sdk_core12.isCapabilitySubset,
17155
- isEvmAddress: () => import_sdk_core11.isEvmAddress,
17156
- isNetworkId: () => import_sdk_core17.isNetworkId,
17157
- isStorageFullError: () => import_sdk_core11.isStorageFullError,
17158
- loadManifest: () => import_sdk_core12.loadManifest,
17159
- makePkhSpaceId: () => import_sdk_core11.makePkhSpaceId,
17160
- makePublicSpaceId: () => import_sdk_core21.makePublicSpaceId,
17161
- networkDiscoveryKey: () => import_sdk_core17.networkDiscoveryKey,
17162
- openWrappedKey: () => import_sdk_core17.openWrappedKey,
17163
- parseCanonicalNetworkId: () => import_sdk_core11.parseCanonicalNetworkId,
17164
- parseExpiry: () => import_sdk_core12.parseExpiry,
17165
- parseNetworkId: () => import_sdk_core17.parseNetworkId,
17166
- parsePkhDid: () => import_sdk_core11.parsePkhDid,
17167
- parseSecretCatalogKey: () => import_sdk_core16.parseSecretCatalogKey,
17168
- parseSpaceUri: () => import_sdk_core21.parseSpaceUri,
17169
- pkhDid: () => import_sdk_core11.pkhDid,
17170
- principalDid: () => import_sdk_core11.principalDid,
17171
- principalDidEquals: () => import_sdk_core11.principalDidEquals,
17172
- resolveManifest: () => import_sdk_core12.resolveManifest,
17173
- resolveSecretListPrefix: () => import_sdk_core16.resolveSecretListPrefix,
17174
- resolveSecretPath: () => import_sdk_core16.resolveSecretPath,
17175
- resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core12.resourceCapabilitiesToSpaceAbilitiesMap,
17624
+ hexDecode: () => import_sdk_core21.hexDecode,
17625
+ hexEncode: () => import_sdk_core21.hexEncode,
17626
+ installTinyCloudDebugGlobals: () => import_sdk_core15.installTinyCloudDebugGlobals,
17627
+ isCapabilitySubset: () => import_sdk_core16.isCapabilitySubset,
17628
+ isEvmAddress: () => import_sdk_core15.isEvmAddress,
17629
+ isNetworkId: () => import_sdk_core21.isNetworkId,
17630
+ isStorageFullError: () => import_sdk_core15.isStorageFullError,
17631
+ loadManifest: () => import_sdk_core16.loadManifest,
17632
+ makePkhSpaceId: () => import_sdk_core15.makePkhSpaceId,
17633
+ makePublicSpaceId: () => import_sdk_core25.makePublicSpaceId,
17634
+ networkDiscoveryKey: () => import_sdk_core21.networkDiscoveryKey,
17635
+ openWrappedKey: () => import_sdk_core21.openWrappedKey,
17636
+ parseCanonicalNetworkId: () => import_sdk_core15.parseCanonicalNetworkId,
17637
+ parseExpiry: () => import_sdk_core16.parseExpiry,
17638
+ parseNetworkId: () => import_sdk_core21.parseNetworkId,
17639
+ parsePkhDid: () => import_sdk_core15.parsePkhDid,
17640
+ parseSecretCatalogKey: () => import_sdk_core20.parseSecretCatalogKey,
17641
+ parseSpaceUri: () => import_sdk_core25.parseSpaceUri,
17642
+ pkhDid: () => import_sdk_core15.pkhDid,
17643
+ principalDid: () => import_sdk_core15.principalDid,
17644
+ principalDidEquals: () => import_sdk_core15.principalDidEquals,
17645
+ resolveManifest: () => import_sdk_core16.resolveManifest,
17646
+ resolveSecretListPrefix: () => import_sdk_core20.resolveSecretListPrefix,
17647
+ resolveSecretPath: () => import_sdk_core20.resolveSecretPath,
17648
+ resourceCapabilitiesToSpaceAbilitiesMap: () => import_sdk_core16.resourceCapabilitiesToSpaceAbilitiesMap,
17176
17649
  serializeDelegation: () => serializeDelegation,
17177
17650
  signedCompactUcanExpiry: () => signedCompactUcanExpiry,
17178
- tinyCloudDebugLogger: () => import_sdk_core11.tinyCloudDebugLogger,
17179
- validateEnvelope: () => import_sdk_core17.validateEnvelope,
17180
- validateManifest: () => import_sdk_core12.validateManifest,
17181
- verifyDecryptResponse: () => import_sdk_core17.verifyDecryptResponse,
17651
+ sqliteReplicaStorage: () => sqliteReplicaStorage,
17652
+ tinyCloudDebugLogger: () => import_sdk_core15.tinyCloudDebugLogger,
17653
+ validateEnvelope: () => import_sdk_core21.validateEnvelope,
17654
+ validateManifest: () => import_sdk_core16.validateManifest,
17655
+ verifyDecryptResponse: () => import_sdk_core21.verifyDecryptResponse,
17182
17656
  wireOpenKeyAuthorize: () => wireOpenKeyAuthorize
17183
17657
  });
17184
- module.exports = __toCommonJS(index_exports);
17658
+ module.exports = __toCommonJS(src_exports);
17185
17659
 
17186
17660
  // src/NodeWasmBindings.ts
17187
17661
  var import_node_sdk_wasm = require("@tinycloud/node-sdk-wasm");
@@ -17303,7 +17777,9 @@ var RUNTIME_DELEGATION_REJECTIONS = [
17303
17777
  "audience_mismatch",
17304
17778
  "resources_mismatch",
17305
17779
  "unsupported",
17306
- "activation_rejected"
17780
+ "activation_rejected",
17781
+ "activation_unavailable",
17782
+ "activation_unauthenticated"
17307
17783
  ];
17308
17784
  var RuntimeDelegationRejectedError = class extends Error {
17309
17785
  constructor(reason, message) {
@@ -17312,6 +17788,18 @@ var RuntimeDelegationRejectedError = class extends Error {
17312
17788
  this.reason = reason;
17313
17789
  }
17314
17790
  };
17791
+ function activationRejectionReason(error) {
17792
+ if (typeof error !== "object" || error === null) return "activation_rejected";
17793
+ if ("code" in error && error.code === "ACTIVATION_TRANSPORT_FAILED") {
17794
+ return "activation_unavailable";
17795
+ }
17796
+ const cause = "cause" in error ? error.cause : void 0;
17797
+ const status = typeof cause === "object" && cause !== null && "status" in cause ? cause.status : void 0;
17798
+ if (typeof status !== "number") return "activation_rejected";
17799
+ if (status === 408 || status === 429 || status >= 500) return "activation_unavailable";
17800
+ if (status === 401) return "activation_unauthenticated";
17801
+ return "activation_rejected";
17802
+ }
17315
17803
  function reject(reason, message) {
17316
17804
  throw new RuntimeDelegationRejectedError(reason, message);
17317
17805
  }
@@ -17696,7 +18184,10 @@ async function activateValidatedRuntimeDelegation(node, delegation, options) {
17696
18184
  await node.useRuntimeDelegation(installedCandidate);
17697
18185
  }
17698
18186
  } catch (error) {
17699
- reject("activation_rejected", error instanceof Error ? error.message : String(error));
18187
+ reject(
18188
+ activationRejectionReason(error),
18189
+ error instanceof Error ? error.message : String(error)
18190
+ );
17700
18191
  }
17701
18192
  const installed = node.getRuntimePermissionDelegations().find((candidate) => candidate.cid === cid);
17702
18193
  if (!installed) {
@@ -17796,16 +18287,32 @@ function deserializeDelegation(data) {
17796
18287
  }
17797
18288
 
17798
18289
  // src/TinyCloudNode.ts
17799
- var import_sdk_core8 = require("@tinycloud/sdk-core");
17800
- var import_sdk_services = require("@tinycloud/sdk-services");
18290
+ init_config();
18291
+
18292
+ // src/replication/module-registry.ts
18293
+ var nodeLoaders;
18294
+ function registerReplicationLoaders(loaders) {
18295
+ nodeLoaders = loaders;
18296
+ }
18297
+ function getNodeReplicationLoaders() {
18298
+ if (nodeLoaders === void 0) {
18299
+ throw new Error("Replication requires registering replication controller loaders.");
18300
+ }
18301
+ return nodeLoaders;
18302
+ }
18303
+
18304
+ // src/TinyCloudNode.ts
18305
+ var import_sdk_core9 = require("@tinycloud/sdk-core");
18306
+ var import_sdk_services3 = require("@tinycloud/sdk-services");
17801
18307
 
17802
18308
  // src/authorization/NodeUserAuthorization.ts
17803
18309
  var import_node_crypto = require("crypto");
17804
18310
  var import_siwe = require("siwe");
17805
- var import_sdk_core3 = require("@tinycloud/sdk-core");
18311
+ var import_sdk_core4 = require("@tinycloud/sdk-core");
18312
+ init_authority_sign_in();
17806
18313
 
17807
18314
  // src/authorization/strategies.ts
17808
- var import_sdk_core2 = require("@tinycloud/sdk-core");
18315
+ var import_sdk_core3 = require("@tinycloud/sdk-core");
17809
18316
  var defaultSignStrategy = { type: "auto-sign" };
17810
18317
 
17811
18318
  // src/storage/MemorySessionStorage.ts
@@ -17880,8 +18387,8 @@ var MemorySessionStorage = class {
17880
18387
  };
17881
18388
 
17882
18389
  // src/authorization/NodeUserAuthorization.ts
17883
- var DECRYPT_ACTION = import_sdk_core3.ENCRYPTION.DECRYPT;
17884
- var NETWORK_CREATE_ACTION = import_sdk_core3.ENCRYPTION.NETWORK_CREATE;
18390
+ var DECRYPT_ACTION = import_sdk_core4.ENCRYPTION.DECRYPT;
18391
+ var NETWORK_CREATE_ACTION = import_sdk_core4.ENCRYPTION.NETWORK_CREATE;
17885
18392
  function describeHostFailure(result) {
17886
18393
  const text = result.error?.trim();
17887
18394
  return text ? `${result.status} - ${text}` : `${result.status}`;
@@ -17909,7 +18416,7 @@ function canonicalOpenKeyManifestSha256Hex(value) {
17909
18416
  }
17910
18417
  function didPrincipalMatches(actual, expected) {
17911
18418
  try {
17912
- return (0, import_sdk_core3.principalDidEquals)(actual, expected);
18419
+ return (0, import_sdk_core4.principalDidEquals)(actual, expected);
17913
18420
  } catch {
17914
18421
  return actual === expected;
17915
18422
  }
@@ -17950,30 +18457,30 @@ var NodeUserAuthorization = class {
17950
18457
  this.spacePrefix = config.spacePrefix ?? "default";
17951
18458
  this.defaultActions = config.defaultActions ?? {
17952
18459
  kv: {
17953
- "": [import_sdk_core3.KV.PUT, import_sdk_core3.KV.GET, import_sdk_core3.KV.DEL, import_sdk_core3.KV.LIST, import_sdk_core3.KV.METADATA]
18460
+ "": [import_sdk_core4.KV.PUT, import_sdk_core4.KV.GET, import_sdk_core4.KV.DEL, import_sdk_core4.KV.LIST, import_sdk_core4.KV.METADATA]
17954
18461
  },
17955
18462
  sql: {
17956
- "": [import_sdk_core3.SQL.READ, import_sdk_core3.SQL.WRITE, import_sdk_core3.SQL.SCHEMA, import_sdk_core3.SQL.ADMIN, import_sdk_core3.SQL.EXPORT]
18463
+ "": [import_sdk_core4.SQL.READ, import_sdk_core4.SQL.WRITE, import_sdk_core4.SQL.SCHEMA, import_sdk_core4.SQL.ADMIN, import_sdk_core4.SQL.EXPORT]
17957
18464
  },
17958
18465
  duckdb: {
17959
18466
  "": [
17960
- import_sdk_core3.DUCKDB.READ,
17961
- import_sdk_core3.DUCKDB.WRITE,
17962
- import_sdk_core3.DUCKDB.ADMIN,
17963
- import_sdk_core3.DUCKDB.DESCRIBE,
17964
- import_sdk_core3.DUCKDB.EXPORT,
17965
- import_sdk_core3.DUCKDB.IMPORT,
17966
- import_sdk_core3.DUCKDB.EXECUTE
18467
+ import_sdk_core4.DUCKDB.READ,
18468
+ import_sdk_core4.DUCKDB.WRITE,
18469
+ import_sdk_core4.DUCKDB.ADMIN,
18470
+ import_sdk_core4.DUCKDB.DESCRIBE,
18471
+ import_sdk_core4.DUCKDB.EXPORT,
18472
+ import_sdk_core4.DUCKDB.IMPORT,
18473
+ import_sdk_core4.DUCKDB.EXECUTE
17967
18474
  ]
17968
18475
  },
17969
18476
  capabilities: {
17970
- "": [import_sdk_core3.CAPABILITIES.READ]
18477
+ "": [import_sdk_core4.CAPABILITIES.READ]
17971
18478
  },
17972
18479
  hooks: {
17973
- "": [import_sdk_core3.HOOKS.SUBSCRIBE, import_sdk_core3.HOOKS.REGISTER, import_sdk_core3.HOOKS.LIST, import_sdk_core3.HOOKS.UNREGISTER]
18480
+ "": [import_sdk_core4.HOOKS.SUBSCRIBE, import_sdk_core4.HOOKS.REGISTER, import_sdk_core4.HOOKS.LIST, import_sdk_core4.HOOKS.UNREGISTER]
17974
18481
  }
17975
18482
  };
17976
- this.sessionExpirationMs = config.sessionExpirationMs ?? import_sdk_core3.EXPIRY.SESSION_MS;
18483
+ this.sessionExpirationMs = config.sessionExpirationMs ?? import_sdk_core4.EXPIRY.SESSION_MS;
17977
18484
  this.autoCreateSpace = config.autoCreateSpace ?? false;
17978
18485
  this.spaceCreationHandler = config.spaceCreationHandler;
17979
18486
  this.tinycloudHosts = config.tinycloudHosts;
@@ -17988,6 +18495,7 @@ var NodeUserAuthorization = class {
17988
18495
  this.nonce = config.nonce;
17989
18496
  this.siweConfig = config.siweConfig;
17990
18497
  this.includeAccountRegistryPermissions = config.includeAccountRegistryPermissions ?? true;
18498
+ this.replication = config.replication?.enabled === true ? config.replication : void 0;
17991
18499
  this._manifest = config.manifest;
17992
18500
  this._capabilityRequest = config.capabilityRequest;
17993
18501
  this.sessionManager = config.sessionManager ?? this.wasm.createSessionManager();
@@ -18052,7 +18560,7 @@ var NodeUserAuthorization = class {
18052
18560
  * {@link ensureTinyCloudHosts}.
18053
18561
  */
18054
18562
  setRestoredTinyCloudSession(session, hosts) {
18055
- const address = (0, import_sdk_core3.canonicalizeAddress)(session.address);
18563
+ const address = (0, import_sdk_core4.canonicalizeAddress)(session.address);
18056
18564
  this._tinyCloudSession = { ...session, address };
18057
18565
  this._address = address;
18058
18566
  this._chainId = session.chainId;
@@ -18113,8 +18621,8 @@ var NodeUserAuthorization = class {
18113
18621
  if (this.tinycloudHosts && this.tinycloudHosts.length > 0) {
18114
18622
  return;
18115
18623
  }
18116
- const subject = (0, import_sdk_core3.pkhDid)(address, chainId);
18117
- const resolved = await (0, import_sdk_core3.resolveTinyCloudHosts)(subject, {
18624
+ const subject = (0, import_sdk_core4.pkhDid)(address, chainId);
18625
+ const resolved = await (0, import_sdk_core4.resolveTinyCloudHosts)(subject, {
18118
18626
  registryUrl: this.tinycloudRegistryUrl,
18119
18627
  fallbackHosts: this.tinycloudFallbackHosts,
18120
18628
  autoDiscoverLocalNode: this.autoDiscoverLocalNode,
@@ -18182,7 +18690,7 @@ var NodeUserAuthorization = class {
18182
18690
  if (this._manifest === void 0) {
18183
18691
  return void 0;
18184
18692
  }
18185
- this._capabilityRequest = (0, import_sdk_core3.composeManifestRequest)(
18693
+ this._capabilityRequest = (0, import_sdk_core4.composeManifestRequest)(
18186
18694
  Array.isArray(this._manifest) ? this._manifest : [this._manifest],
18187
18695
  {
18188
18696
  includeAccountRegistryPermissions: this.includeAccountRegistryPermissions
@@ -18194,50 +18702,173 @@ var NodeUserAuthorization = class {
18194
18702
  if (space.startsWith("tinycloud:")) {
18195
18703
  return space;
18196
18704
  }
18197
- return (0, import_sdk_core3.makePkhSpaceId)(address, chainId, space);
18705
+ return (0, import_sdk_core4.makePkhSpaceId)(address, chainId, space);
18706
+ }
18707
+ /**
18708
+ * The plain-session primary abilities: `defaultActions` (the shared table)
18709
+ * unless the primary space IS the account space, where account-registry
18710
+ * permissions merge into a private clone so the shared table is never
18711
+ * mutated. Shared between `resolveSignInCapabilities` and
18712
+ * `signInPermissionInputs` so sign-in and `replicationSignInEntries`
18713
+ * can't disagree (§4.6).
18714
+ */
18715
+ primaryActionsForSignIn() {
18716
+ const primaryActions = this.includeAccountRegistryPermissions && this.spacePrefix === import_sdk_core4.ACCOUNT_REGISTRY_SPACE ? cloneAbilitiesMap(this.defaultActions) : this.defaultActions;
18717
+ if (this.includeAccountRegistryPermissions && this.spacePrefix === import_sdk_core4.ACCOUNT_REGISTRY_SPACE) {
18718
+ const accountAbilities = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(
18719
+ import_sdk_core4.ACCOUNT_MANIFEST_PERMISSIONS
18720
+ );
18721
+ for (const [service, paths] of Object.entries(accountAbilities)) {
18722
+ const existingPaths = primaryActions[service] ?? (primaryActions[service] = {});
18723
+ for (const [path, actions] of Object.entries(paths)) {
18724
+ const existingActions = existingPaths[path] ?? (existingPaths[path] = []);
18725
+ for (const action of actions) {
18726
+ if (!existingActions.includes(action)) existingActions.push(action);
18727
+ }
18728
+ }
18729
+ }
18730
+ }
18731
+ return primaryActions;
18732
+ }
18733
+ /**
18734
+ * The abilities a `spacePrefix: "secrets"` plain session actually requests
18735
+ * for its primary space: the vault-secrets subtree only — the
18736
+ * `defaultActions` root `get` is REPLACED, not merged (sign-in installs
18737
+ * this map under the primary space id). Shared between
18738
+ * `resolveSignInCapabilities` and `signInPermissionInputs` so the
18739
+ * replication augmentation measures coverage against the effective
18740
+ * pre-replication request, never the uninstalled `primaryActions` (§4.1).
18741
+ */
18742
+ secretsPrimaryAbilities() {
18743
+ return {
18744
+ kv: {
18745
+ "vault/secrets/": [
18746
+ import_sdk_core4.KV.GET,
18747
+ import_sdk_core4.KV.PUT,
18748
+ import_sdk_core4.KV.DEL,
18749
+ import_sdk_core4.KV.LIST,
18750
+ import_sdk_core4.KV.METADATA
18751
+ ]
18752
+ }
18753
+ };
18754
+ }
18755
+ /**
18756
+ * The effective sign-in request as `PermissionEntry`s plus the resolved
18757
+ * primary space id — the inputs to the replication augmentation (§4.1).
18758
+ * `resolveSignInCapabilities` merges the augmented entries into its
18759
+ * abilities; `replicationSignInEntries()` returns them verbatim, so the
18760
+ * entries the SIWE recap carries and the restore check sees are the same.
18761
+ */
18762
+ signInPermissionInputs(address, chainId) {
18763
+ const request = this.getCapabilityRequest();
18764
+ if (request === void 0) {
18765
+ const primarySpaceId2 = (0, import_sdk_core4.makePkhSpaceId)(address, chainId, this.spacePrefix);
18766
+ const effectivePrimary = this.spacePrefix === "secrets" ? this.secretsPrimaryAbilities() : this.primaryActionsForSignIn();
18767
+ const kvPaths = effectivePrimary["kv"] ?? {};
18768
+ return {
18769
+ primarySpaceId: primarySpaceId2,
18770
+ entries: Object.entries(kvPaths).map(([path, actions]) => ({
18771
+ service: "tinycloud.kv",
18772
+ space: primarySpaceId2,
18773
+ path,
18774
+ actions: [...actions]
18775
+ }))
18776
+ };
18777
+ }
18778
+ const spaceResources = request.resources.filter(
18779
+ (entry) => entry.service !== import_sdk_core4.ENCRYPTION_PERMISSION_SERVICE
18780
+ );
18781
+ const primarySpaceName = spaceResources.find((entry) => entry.space !== "account")?.space ?? import_sdk_core4.DEFAULT_MANIFEST_SPACE;
18782
+ const primarySpaceId = this.resolveSpaceName(
18783
+ primarySpaceName,
18784
+ address,
18785
+ chainId
18786
+ );
18787
+ return {
18788
+ primarySpaceId,
18789
+ entries: spaceResources.map((entry) => ({
18790
+ service: entry.service,
18791
+ space: this.resolveSpaceName(entry.space, address, chainId),
18792
+ path: entry.path,
18793
+ actions: [...entry.actions]
18794
+ }))
18795
+ };
18796
+ }
18797
+ /**
18798
+ * Merge replication augmentation entries into a space's abilities map
18799
+ * without mutating shared tables (`defaultActions` may back the base map):
18800
+ * the primary entry in `spaceAbilities` is replaced with a copy whose `kv`
18801
+ * paths gain `get`/`sync`. Returns the merged map for `abilities`.
18802
+ */
18803
+ mergeReplicationEntries(spaceAbilities, primarySpaceId, abilities, entries) {
18804
+ var _a;
18805
+ if (entries.length === 0) {
18806
+ return abilities;
18807
+ }
18808
+ const base2 = spaceAbilities[primarySpaceId] ?? abilities;
18809
+ const kv = {};
18810
+ for (const [path, actions] of Object.entries(base2["kv"] ?? {})) {
18811
+ kv[path] = [...actions];
18812
+ }
18813
+ for (const entry of entries) {
18814
+ const list = kv[_a = entry.path] ?? (kv[_a] = []);
18815
+ for (const action of entry.actions) {
18816
+ if (!list.includes(action)) list.push(action);
18817
+ }
18818
+ }
18819
+ const merged = { ...base2, kv };
18820
+ spaceAbilities[primarySpaceId] = merged;
18821
+ return merged;
18822
+ }
18823
+ /**
18824
+ * The replication entries this authorization's sign-in request carries
18825
+ * for the signed-in or restored address (TC-858 §4.1/§4.6): the output of
18826
+ * the same augmentation `resolveSignInCapabilities` runs — one
18827
+ * `{tinycloud.kv, primarySpace, prefix, [get, sync]}` per configured
18828
+ * prefix that already has an unrestricted covering `get` and passes the
18829
+ * secrets opt-in gate. Empty when replication is off or no address is
18830
+ * known. Pure.
18831
+ */
18832
+ replicationSignInEntries() {
18833
+ if (this.replication === void 0) return [];
18834
+ const address = this._address ?? this._tinyCloudSession?.address;
18835
+ const chainId = this._chainId ?? this._tinyCloudSession?.chainId;
18836
+ if (address === void 0 || chainId === void 0) return [];
18837
+ const { entries, primarySpaceId } = this.signInPermissionInputs(address, chainId);
18838
+ return augmentSignInEntriesWithReplication({
18839
+ entries,
18840
+ primarySpaceId,
18841
+ replication: this.replication
18842
+ });
18198
18843
  }
18199
18844
  defaultEncryptionNetworkId(address, chainId) {
18200
- return `urn:tinycloud:encryption:${(0, import_sdk_core3.pkhDid)(address, chainId)}:default`;
18845
+ return `urn:tinycloud:encryption:${(0, import_sdk_core4.pkhDid)(address, chainId)}:default`;
18201
18846
  }
18202
18847
  resolveSignInCapabilities(address, chainId) {
18203
18848
  const request = this.getCapabilityRequest();
18204
18849
  if (request === void 0) {
18205
18850
  const defaultNetworkId = this.defaultEncryptionNetworkId(address, chainId);
18206
- const primarySpaceId2 = (0, import_sdk_core3.makePkhSpaceId)(address, chainId, this.spacePrefix);
18207
- const secretsSpaceId = (0, import_sdk_core3.makePkhSpaceId)(address, chainId, "secrets");
18208
- const primaryActions = this.includeAccountRegistryPermissions && this.spacePrefix === import_sdk_core3.ACCOUNT_REGISTRY_SPACE ? cloneAbilitiesMap(this.defaultActions) : this.defaultActions;
18851
+ const primarySpaceId2 = (0, import_sdk_core4.makePkhSpaceId)(address, chainId, this.spacePrefix);
18852
+ const secretsSpaceId = (0, import_sdk_core4.makePkhSpaceId)(address, chainId, "secrets");
18853
+ const primaryActions = this.primaryActionsForSignIn();
18209
18854
  const spaceAbilities2 = {
18210
18855
  [primarySpaceId2]: primaryActions,
18211
- [secretsSpaceId]: {
18212
- kv: {
18213
- "vault/secrets/": [
18214
- import_sdk_core3.KV.GET,
18215
- import_sdk_core3.KV.PUT,
18216
- import_sdk_core3.KV.DEL,
18217
- import_sdk_core3.KV.LIST,
18218
- import_sdk_core3.KV.METADATA
18219
- ]
18220
- }
18221
- }
18856
+ [secretsSpaceId]: this.secretsPrimaryAbilities()
18222
18857
  };
18223
- if (this.includeAccountRegistryPermissions && this.spacePrefix !== import_sdk_core3.ACCOUNT_REGISTRY_SPACE) {
18224
- spaceAbilities2[(0, import_sdk_core3.makePkhSpaceId)(address, chainId, import_sdk_core3.ACCOUNT_REGISTRY_SPACE)] = (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)(import_sdk_core3.ACCOUNT_MANIFEST_PERMISSIONS);
18225
- } else if (this.includeAccountRegistryPermissions) {
18226
- const accountAbilities = (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)(
18227
- import_sdk_core3.ACCOUNT_MANIFEST_PERMISSIONS
18228
- );
18229
- for (const [service, paths] of Object.entries(accountAbilities)) {
18230
- const existingPaths = primaryActions[service] ?? (primaryActions[service] = {});
18231
- for (const [path, actions] of Object.entries(paths)) {
18232
- const existingActions = existingPaths[path] ?? (existingPaths[path] = []);
18233
- for (const action of actions) {
18234
- if (!existingActions.includes(action)) existingActions.push(action);
18235
- }
18236
- }
18237
- }
18238
- }
18858
+ if (this.includeAccountRegistryPermissions && this.spacePrefix !== import_sdk_core4.ACCOUNT_REGISTRY_SPACE) {
18859
+ spaceAbilities2[(0, import_sdk_core4.makePkhSpaceId)(address, chainId, import_sdk_core4.ACCOUNT_REGISTRY_SPACE)] = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(import_sdk_core4.ACCOUNT_MANIFEST_PERMISSIONS);
18860
+ }
18861
+ const mergedPrimary = this.mergeReplicationEntries(
18862
+ spaceAbilities2,
18863
+ primarySpaceId2,
18864
+ primaryActions,
18865
+ augmentSignInEntriesWithReplication({
18866
+ ...this.signInPermissionInputs(address, chainId),
18867
+ replication: this.replication
18868
+ })
18869
+ );
18239
18870
  return {
18240
- abilities: primaryActions,
18871
+ abilities: mergedPrimary,
18241
18872
  spaceId: primarySpaceId2,
18242
18873
  spaceAbilities: spaceAbilities2,
18243
18874
  rawAbilities: {
@@ -18246,35 +18877,44 @@ var NodeUserAuthorization = class {
18246
18877
  };
18247
18878
  }
18248
18879
  const rawAbilities = {};
18249
- const currentDid = (0, import_sdk_core3.pkhDid)(address, chainId);
18880
+ const currentDid = (0, import_sdk_core4.pkhDid)(address, chainId);
18250
18881
  const spaceResources = request.resources.filter((entry) => {
18251
- if (entry.service !== import_sdk_core3.ENCRYPTION_PERMISSION_SERVICE) {
18882
+ if (entry.service !== import_sdk_core4.ENCRYPTION_PERMISSION_SERVICE) {
18252
18883
  return true;
18253
18884
  }
18254
18885
  for (const action of entry.actions) {
18255
18886
  addRawAbility(rawAbilities, entry.path, action);
18256
18887
  }
18257
18888
  if (entry.actions.includes(DECRYPT_ACTION)) {
18258
- const parsed = (0, import_sdk_core3.parseNetworkId)(entry.path);
18889
+ const parsed = (0, import_sdk_core4.parseNetworkId)(entry.path);
18259
18890
  if (didPrincipalMatches(parsed.ownerDid, currentDid)) {
18260
18891
  addRawAbility(rawAbilities, entry.path, NETWORK_CREATE_ACTION);
18261
18892
  }
18262
18893
  }
18263
18894
  return false;
18264
18895
  });
18265
- const primarySpaceName = spaceResources.find((entry) => entry.space !== "account")?.space ?? import_sdk_core3.DEFAULT_MANIFEST_SPACE;
18896
+ const primarySpaceName = spaceResources.find((entry) => entry.space !== "account")?.space ?? import_sdk_core4.DEFAULT_MANIFEST_SPACE;
18266
18897
  const primarySpaceId = this.resolveSpaceName(
18267
18898
  primarySpaceName,
18268
18899
  address,
18269
18900
  chainId
18270
18901
  );
18271
- const bySpace = (0, import_sdk_core3.resourceCapabilitiesToSpaceAbilitiesMap)(spaceResources);
18902
+ const bySpace = (0, import_sdk_core4.resourceCapabilitiesToSpaceAbilitiesMap)(spaceResources);
18272
18903
  const spaceAbilities = {};
18273
18904
  for (const [space, abilities] of Object.entries(bySpace)) {
18274
18905
  spaceAbilities[this.resolveSpaceName(space, address, chainId)] = abilities;
18275
18906
  }
18907
+ const mergedPrimaryAbilities = this.mergeReplicationEntries(
18908
+ spaceAbilities,
18909
+ primarySpaceId,
18910
+ spaceAbilities[primarySpaceId] ?? (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)([]),
18911
+ augmentSignInEntriesWithReplication({
18912
+ ...this.signInPermissionInputs(address, chainId),
18913
+ replication: this.replication
18914
+ })
18915
+ );
18276
18916
  return {
18277
- abilities: spaceAbilities[primarySpaceId] ?? (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)([]),
18917
+ abilities: mergedPrimaryAbilities,
18278
18918
  spaceId: primarySpaceId,
18279
18919
  spaceAbilities,
18280
18920
  rawAbilities: Object.keys(rawAbilities).length > 0 ? rawAbilities : void 0
@@ -18332,14 +18972,14 @@ var NodeUserAuthorization = class {
18332
18972
  * Create the space on the TinyCloud server (host delegation).
18333
18973
  * This registers the user as the owner of the space.
18334
18974
  */
18335
- async hostSpace(targetSpaceId, purpose) {
18975
+ async hostSpace(targetSpaceId, purpose, signal) {
18336
18976
  if (!this._tinyCloudSession || !this._address || !this._chainId) {
18337
18977
  throw new Error("Must be signed in to host space");
18338
18978
  }
18339
18979
  await this.ensureTinyCloudHosts();
18340
18980
  const host = this.primaryTinyCloudHost;
18341
18981
  const spaceId = targetSpaceId ?? this._tinyCloudSession.spaceId;
18342
- const peerId = await (0, import_sdk_core3.fetchPeerId)(host, spaceId);
18982
+ const peerId = await (0, import_sdk_core4.fetchPeerId)(host, spaceId, signal);
18343
18983
  const siwe = this.wasm.generateHostSIWEMessage({
18344
18984
  address: this._address,
18345
18985
  chainId: this._chainId,
@@ -18348,9 +18988,28 @@ var NodeUserAuthorization = class {
18348
18988
  spaceId,
18349
18989
  peerId
18350
18990
  });
18351
- const signature2 = await this.signMessage(siwe, purpose);
18991
+ if (signal?.aborted) throw signal.reason;
18992
+ const signing = this.signMessage(siwe, purpose);
18993
+ let signature2;
18994
+ if (!signal) {
18995
+ signature2 = await signing;
18996
+ } else {
18997
+ let rejectOnAbort;
18998
+ const aborted = new Promise((_resolve, reject2) => {
18999
+ rejectOnAbort = reject2;
19000
+ });
19001
+ const onAbort = () => rejectOnAbort(signal.reason);
19002
+ signal.addEventListener("abort", onAbort, { once: true });
19003
+ if (signal.aborted) onAbort();
19004
+ try {
19005
+ signature2 = await Promise.race([signing, aborted]);
19006
+ } finally {
19007
+ signal.removeEventListener("abort", onAbort);
19008
+ }
19009
+ }
19010
+ if (signal?.aborted) throw signal.reason;
18352
19011
  const headers = this.wasm.siweToDelegationHeaders({ siwe, signature: signature2 });
18353
- return (0, import_sdk_core3.submitHostDelegation)(host, headers);
19012
+ return (0, import_sdk_core4.submitHostDelegation)(host, headers, signal);
18354
19013
  }
18355
19014
  /**
18356
19015
  * Create a specific space on the server via host delegation.
@@ -18371,8 +19030,8 @@ var NodeUserAuthorization = class {
18371
19030
  * keeps its HTTP status (e.g. a typed 401/403) instead of collapsing to
18372
19031
  * `false`.
18373
19032
  */
18374
- async hostOwnedSpaceResult(spaceId, purpose) {
18375
- return this.hostSpace(spaceId, purpose);
19033
+ async hostOwnedSpaceResult(spaceId, purpose, signal) {
19034
+ return this.hostSpace(spaceId, purpose, signal);
18376
19035
  }
18377
19036
  /**
18378
19037
  * Ensure the user's space exists on the TinyCloud server.
@@ -18389,12 +19048,12 @@ var NodeUserAuthorization = class {
18389
19048
  await this.ensureTinyCloudHosts();
18390
19049
  const host = this.primaryTinyCloudHost;
18391
19050
  const primarySpaceId = this._tinyCloudSession.spaceId;
18392
- const result = await (0, import_sdk_core3.activateSessionWithHost)(
19051
+ const result = await (0, import_sdk_core4.activateSessionWithHost)(
18393
19052
  host,
18394
19053
  this._tinyCloudSession.delegationHeader
18395
19054
  );
18396
19055
  this.recordActivationSkippedSpaces(result, primarySpaceId);
18397
- const handler = this.spaceCreationHandler ?? (this.autoCreateSpace ? new import_sdk_core3.AutoApproveSpaceCreationHandler() : void 0);
19056
+ const handler = this.spaceCreationHandler ?? (this.autoCreateSpace ? new import_sdk_core4.AutoApproveSpaceCreationHandler() : void 0);
18398
19057
  const creationContext = {
18399
19058
  spaceId: primarySpaceId,
18400
19059
  address: this._address,
@@ -18430,7 +19089,7 @@ var NodeUserAuthorization = class {
18430
19089
  throw error;
18431
19090
  }
18432
19091
  await new Promise((resolve) => setTimeout(resolve, 100));
18433
- const retryResult = await (0, import_sdk_core3.activateSessionWithHost)(
19092
+ const retryResult = await (0, import_sdk_core4.activateSessionWithHost)(
18434
19093
  host,
18435
19094
  this._tinyCloudSession.delegationHeader
18436
19095
  );
@@ -18470,7 +19129,7 @@ var NodeUserAuthorization = class {
18470
19129
  throw error;
18471
19130
  }
18472
19131
  await new Promise((resolve) => setTimeout(resolve, 100));
18473
- const retryResult = await (0, import_sdk_core3.activateSessionWithHost)(
19132
+ const retryResult = await (0, import_sdk_core4.activateSessionWithHost)(
18474
19133
  host,
18475
19134
  this._tinyCloudSession.delegationHeader
18476
19135
  );
@@ -18512,7 +19171,7 @@ var NodeUserAuthorization = class {
18512
19171
  const jwk = JSON.parse(jwkString);
18513
19172
  const now = /* @__PURE__ */ new Date();
18514
19173
  const expirationTime = new Date(now.getTime() + this.sessionExpirationMs);
18515
- const abilities = (0, import_sdk_core3.resourceCapabilitiesToAbilitiesMap)(
19174
+ const abilities = (0, import_sdk_core4.resourceCapabilitiesToAbilitiesMap)(
18516
19175
  options.capabilityRequest.resources
18517
19176
  );
18518
19177
  const prepared = this.wasm.prepareSession({
@@ -18563,7 +19222,7 @@ var NodeUserAuthorization = class {
18563
19222
  * @param options - Optional per-call SIWE overrides for this sign-in only
18564
19223
  */
18565
19224
  async signIn(options) {
18566
- this._address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
19225
+ this._address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
18567
19226
  this._chainId = await this.signer.getChainId();
18568
19227
  const address = this._address;
18569
19228
  const chainId = this._chainId;
@@ -18612,7 +19271,7 @@ var NodeUserAuthorization = class {
18612
19271
  siwe: prepared.siwe,
18613
19272
  signature: signature2
18614
19273
  };
18615
- const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core3.makePkhSpaceId)(address, chainId, "public") } : void 0;
19274
+ const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core4.makePkhSpaceId)(address, chainId, "public") } : void 0;
18616
19275
  const tinyCloudSession = {
18617
19276
  address,
18618
19277
  chainId,
@@ -18650,7 +19309,7 @@ var NodeUserAuthorization = class {
18650
19309
  this._address = address;
18651
19310
  this._chainId = chainId;
18652
19311
  const infoHost = this.primaryTinyCloudHost;
18653
- const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
19312
+ const nodeInfo = await (0, import_sdk_core4.checkNodeInfo)(
18654
19313
  infoHost,
18655
19314
  this.wasm.protocolVersion()
18656
19315
  );
@@ -18690,7 +19349,7 @@ var NodeUserAuthorization = class {
18690
19349
  */
18691
19350
  async signMessage(message, purpose) {
18692
19351
  if (!this._address) {
18693
- this._address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
19352
+ this._address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
18694
19353
  }
18695
19354
  if (!this._chainId) {
18696
19355
  this._chainId = await this.signer.getChainId();
@@ -18718,7 +19377,7 @@ var NodeUserAuthorization = class {
18718
19377
  * ```
18719
19378
  */
18720
19379
  async prepareSessionForSigning() {
18721
- const address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
19380
+ const address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
18722
19381
  const chainId = await this.signer.getChainId();
18723
19382
  const keyId = `session-${Date.now()}`;
18724
19383
  this.sessionManager.renameSessionKeyId(this.activeSessionKeyId, keyId);
@@ -18769,7 +19428,7 @@ var NodeUserAuthorization = class {
18769
19428
  ...prepared,
18770
19429
  signature: signature2
18771
19430
  });
18772
- const address = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
19431
+ const address = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
18773
19432
  const chainId = await this.signer.getChainId();
18774
19433
  await this.resolveTinyCloudHostsForSignIn(address, chainId);
18775
19434
  const clientSession = {
@@ -18780,7 +19439,7 @@ var NodeUserAuthorization = class {
18780
19439
  siwe: prepared.siwe,
18781
19440
  signature: signature2
18782
19441
  };
18783
- const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core3.makePkhSpaceId)(address, chainId, "public") } : void 0;
19442
+ const spacesMetadata = this.enablePublicSpace ? { public: (0, import_sdk_core4.makePkhSpaceId)(address, chainId, "public") } : void 0;
18784
19443
  const tinyCloudSession = {
18785
19444
  address,
18786
19445
  chainId,
@@ -18822,7 +19481,7 @@ var NodeUserAuthorization = class {
18822
19481
  this._address = address;
18823
19482
  this._chainId = chainId;
18824
19483
  const infoHost = this.primaryTinyCloudHost;
18825
- const nodeInfo = await (0, import_sdk_core3.checkNodeInfo)(
19484
+ const nodeInfo = await (0, import_sdk_core4.checkNodeInfo)(
18826
19485
  infoHost,
18827
19486
  this.wasm.protocolVersion()
18828
19487
  );
@@ -18878,7 +19537,7 @@ var NodeUserAuthorization = class {
18878
19537
  }
18879
19538
  this.tinycloudHosts = [overrideHost];
18880
19539
  }
18881
- const signingAddress = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
19540
+ const signingAddress = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
18882
19541
  const signingChainId = await this.signer.getChainId();
18883
19542
  await this.resolveTinyCloudHostsForSignIn(signingAddress, signingChainId);
18884
19543
  const { prepared, keyId, jwk } = await this.prepareSessionForSigning();
@@ -18983,8 +19642,8 @@ var NodeUserAuthorization = class {
18983
19642
  "signInWithOpenKeyResult requires prepared.siwe (the SDK-generated SIWE the sign-in was proposed with)"
18984
19643
  );
18985
19644
  }
18986
- const expectedAddress = (0, import_sdk_core3.canonicalizeAddress)(await this.signer.getAddress());
18987
- if ((0, import_sdk_core3.canonicalizeAddress)(result.address) !== expectedAddress) {
19645
+ const expectedAddress = (0, import_sdk_core4.canonicalizeAddress)(await this.signer.getAddress());
19646
+ if ((0, import_sdk_core4.canonicalizeAddress)(result.address) !== expectedAddress) {
18988
19647
  throw new Error(
18989
19648
  `OpenKey returned signature from ${result.address} but expected ${expectedAddress}`
18990
19649
  );
@@ -19009,15 +19668,15 @@ var NodeUserAuthorization = class {
19009
19668
  `OpenKey signature verification failed${type ? `: ${type}` : ""}${details}`
19010
19669
  );
19011
19670
  }
19012
- if ((0, import_sdk_core3.canonicalizeAddress)(parsedSignedSiwe.address) !== expectedAddress) {
19671
+ if ((0, import_sdk_core4.canonicalizeAddress)(parsedSignedSiwe.address) !== expectedAddress) {
19013
19672
  throw new Error(
19014
19673
  `OpenKey signedMessage.address (${parsedSignedSiwe.address}) does not match local signer address (${expectedAddress})`
19015
19674
  );
19016
19675
  }
19017
19676
  const originalHasRecap = /(?:^|\n)-\s+urn:recap:/i.test(prepared.siwe);
19018
- const originalFields = (0, import_sdk_core3.extractImmutableSiweFields)(prepared.siwe);
19019
- const signedFields = (0, import_sdk_core3.extractImmutableSiweFields)(result.signedMessage);
19020
- const changedFields = (0, import_sdk_core3.diffImmutableSiweFields)(originalFields, signedFields, {
19677
+ const originalFields = (0, import_sdk_core4.extractImmutableSiweFields)(prepared.siwe);
19678
+ const signedFields = (0, import_sdk_core4.extractImmutableSiweFields)(result.signedMessage);
19679
+ const changedFields = (0, import_sdk_core4.diffImmutableSiweFields)(originalFields, signedFields, {
19021
19680
  originalHasRecap
19022
19681
  });
19023
19682
  if (changedFields.length > 0) {
@@ -19028,20 +19687,20 @@ var NodeUserAuthorization = class {
19028
19687
  let originalCaps;
19029
19688
  let signedCaps;
19030
19689
  try {
19031
- originalCaps = (0, import_sdk_core3.extractRecapAttenuations)(prepared.siwe);
19690
+ originalCaps = (0, import_sdk_core4.extractRecapAttenuations)(prepared.siwe);
19032
19691
  } catch (err) {
19033
19692
  throw new Error(
19034
19693
  `Failed to decode prepared SIWE recap: ${err.message}`
19035
19694
  );
19036
19695
  }
19037
19696
  try {
19038
- signedCaps = (0, import_sdk_core3.extractRecapAttenuations)(result.signedMessage);
19697
+ signedCaps = (0, import_sdk_core4.extractRecapAttenuations)(result.signedMessage);
19039
19698
  } catch (err) {
19040
19699
  throw new Error(
19041
19700
  `Failed to decode OpenKey signedMessage recap: ${err.message}`
19042
19701
  );
19043
19702
  }
19044
- const unauthorized = (0, import_sdk_core3.unauthorizedRecapCapabilities)(signedCaps, originalCaps);
19703
+ const unauthorized = (0, import_sdk_core4.unauthorizedRecapCapabilities)(signedCaps, originalCaps);
19045
19704
  if (unauthorized.length > 0) {
19046
19705
  const previewLimit = 5;
19047
19706
  const preview = unauthorized.slice(0, previewLimit).map((u) => `${u.resource}::${u.action}`).join(", ");
@@ -19058,7 +19717,7 @@ var NodeUserAuthorization = class {
19058
19717
  const grantedPairs = /* @__PURE__ */ new Set();
19059
19718
  const grantedFourPartIndex = /* @__PURE__ */ new Map();
19060
19719
  for (const [resource, actions] of Object.entries(signedCaps)) {
19061
- const { space, path } = (0, import_sdk_core3.parseCanonicalRecapResource)(resource);
19720
+ const { space, path } = (0, import_sdk_core4.parseCanonicalRecapResource)(resource);
19062
19721
  for (const action of Object.keys(actions)) {
19063
19722
  grantedPairs.add(`${resource}\0${action}`);
19064
19723
  const slashIdx = action.indexOf("/");
@@ -19299,16 +19958,16 @@ var NodeUserAuthorization = class {
19299
19958
  };
19300
19959
 
19301
19960
  // src/account/AccountService.ts
19302
- var import_sdk_core4 = require("@tinycloud/sdk-core");
19961
+ var import_sdk_core5 = require("@tinycloud/sdk-core");
19303
19962
 
19304
19963
  // src/DelegatedAccess.ts
19305
- var import_sdk_core5 = require("@tinycloud/sdk-core");
19964
+ var import_sdk_core6 = require("@tinycloud/sdk-core");
19306
19965
  var DelegatedAccess = class {
19307
19966
  constructor(session, delegation, host, invoke2, invokeAny2, telemetry) {
19308
19967
  this.session = session;
19309
19968
  this._delegation = delegation;
19310
19969
  this.host = host;
19311
- this._serviceContext = new import_sdk_core5.ServiceContext({
19970
+ this._serviceContext = new import_sdk_core6.ServiceContext({
19312
19971
  invoke: invoke2,
19313
19972
  invokeAny: invokeAny2,
19314
19973
  fetch: globalThis.fetch.bind(globalThis),
@@ -19316,16 +19975,16 @@ var DelegatedAccess = class {
19316
19975
  telemetry
19317
19976
  });
19318
19977
  const prefix = this._delegation.path.replace(/\/$/, "");
19319
- this._kv = new import_sdk_core5.KVService({ prefix });
19978
+ this._kv = new import_sdk_core6.KVService({ prefix });
19320
19979
  this._kv.initialize(this._serviceContext);
19321
19980
  this._serviceContext.registerService("kv", this._kv);
19322
- this._sql = new import_sdk_core5.SQLService({});
19981
+ this._sql = new import_sdk_core6.SQLService({});
19323
19982
  this._sql.initialize(this._serviceContext);
19324
19983
  this._serviceContext.registerService("sql", this._sql);
19325
- this._duckdb = new import_sdk_core5.DuckDbService({});
19984
+ this._duckdb = new import_sdk_core6.DuckDbService({});
19326
19985
  this._duckdb.initialize(this._serviceContext);
19327
19986
  this._serviceContext.registerService("duckdb", this._duckdb);
19328
- this._hooks = new import_sdk_core5.HooksService({});
19987
+ this._hooks = new import_sdk_core6.HooksService({});
19329
19988
  this._hooks.initialize(this._serviceContext);
19330
19989
  this._serviceContext.registerService("hooks", this._hooks);
19331
19990
  const serviceSession = {
@@ -19475,7 +20134,7 @@ function createWasmKeyProvider(sessionManager) {
19475
20134
  }
19476
20135
 
19477
20136
  // src/delegateToHelpers.ts
19478
- var import_sdk_core6 = require("@tinycloud/sdk-core");
20137
+ var import_sdk_core7 = require("@tinycloud/sdk-core");
19479
20138
  function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
19480
20139
  const byService = /* @__PURE__ */ new Map();
19481
20140
  for (const a of actions) {
@@ -19506,7 +20165,7 @@ function legacyParamsToPermissionEntries(actions, path, spaceIdOverride) {
19506
20165
  }
19507
20166
  return entries;
19508
20167
  }
19509
- var DEFAULT_DELEGATION_EXPIRY_MS = import_sdk_core6.EXPIRY.SESSION_MS;
20168
+ var DEFAULT_DELEGATION_EXPIRY_MS = import_sdk_core7.EXPIRY.SESSION_MS;
19510
20169
  function resolveExpiryMs(expiry) {
19511
20170
  if (expiry === void 0) {
19512
20171
  return DEFAULT_DELEGATION_EXPIRY_MS;
@@ -19519,10 +20178,10 @@ function resolveExpiryMs(expiry) {
19519
20178
  }
19520
20179
  return expiry;
19521
20180
  }
19522
- return (0, import_sdk_core6.parseExpiry)(expiry);
20181
+ return (0, import_sdk_core7.parseExpiry)(expiry);
19523
20182
  }
19524
20183
  function extractSiweExpiration(siwe) {
19525
- const parsed = new import_sdk_core6.SiweMessage(siwe);
20184
+ const parsed = new import_sdk_core7.SiweMessage(siwe);
19526
20185
  if (parsed.expirationTime === void 0 || parsed.expirationTime === null) {
19527
20186
  return void 0;
19528
20187
  }
@@ -19536,7 +20195,7 @@ function extractSiweExpiration(siwe) {
19536
20195
  }
19537
20196
 
19538
20197
  // src/NodeSecretsService.ts
19539
- var import_sdk_core7 = require("@tinycloud/sdk-core");
20198
+ var import_sdk_core8 = require("@tinycloud/sdk-core");
19540
20199
  var SECRETS_SPACE = "secrets";
19541
20200
  function ok() {
19542
20201
  return { ok: true, data: void 0 };
@@ -19569,7 +20228,7 @@ function secretActionName(action) {
19569
20228
  }
19570
20229
  function secretPermissionEntries(name, options, action, space, encryptionNetworkId) {
19571
20230
  const entries = [];
19572
- const path = action === "list" ? (0, import_sdk_core7.resolveSecretListPrefix)(options) : (0, import_sdk_core7.resolveSecretPath)(name, options).permissionPaths.vault;
20231
+ const path = action === "list" ? (0, import_sdk_core8.resolveSecretListPrefix)(options) : (0, import_sdk_core8.resolveSecretPath)(name, options).permissionPaths.vault;
19573
20232
  entries.push({
19574
20233
  service: "tinycloud.kv",
19575
20234
  space,
@@ -19666,7 +20325,7 @@ var NodeSecretsService = class {
19666
20325
  );
19667
20326
  } catch (error) {
19668
20327
  return secretsError(
19669
- import_sdk_core7.ErrorCodes.INVALID_INPUT,
20328
+ import_sdk_core8.ErrorCodes.INVALID_INPUT,
19670
20329
  error instanceof Error ? error.message : String(error),
19671
20330
  error instanceof Error ? error : void 0
19672
20331
  );
@@ -19676,7 +20335,7 @@ var NodeSecretsService = class {
19676
20335
  }
19677
20336
  if (!this.config.canEscalate()) {
19678
20337
  return secretsError(
19679
- import_sdk_core7.ErrorCodes.PERMISSION_DENIED,
20338
+ import_sdk_core8.ErrorCodes.PERMISSION_DENIED,
19680
20339
  `Cannot autosign ${displayActionUrn(action)} for ${target}; TinyCloudNode needs wallet mode with a signer or privateKey.`
19681
20340
  );
19682
20341
  }
@@ -19685,7 +20344,7 @@ var NodeSecretsService = class {
19685
20344
  return this.restoreUnlockAfterEscalation();
19686
20345
  } catch (error) {
19687
20346
  return secretsError(
19688
- import_sdk_core7.ErrorCodes.PERMISSION_DENIED,
20347
+ import_sdk_core8.ErrorCodes.PERMISSION_DENIED,
19689
20348
  error instanceof Error ? error.message : `Autosign escalation for ${displayActionUrn(action)} on ${target} failed.`,
19690
20349
  error instanceof Error ? error : void 0
19691
20350
  );
@@ -19706,10 +20365,10 @@ var NodeSecretsService = class {
19706
20365
  return false;
19707
20366
  }
19708
20367
  const manifests = Array.isArray(manifest) ? manifest : [manifest];
19709
- const requestedEntries = (0, import_sdk_core7.expandPermissionEntries)(permissionEntries);
20368
+ const requestedEntries = (0, import_sdk_core8.expandPermissionEntries)(permissionEntries);
19710
20369
  return requestedEntries.every(
19711
20370
  (entry) => manifests.some((candidate) => {
19712
- const resolved = (0, import_sdk_core7.resolveManifest)(candidate);
20371
+ const resolved = (0, import_sdk_core8.resolveManifest)(candidate);
19713
20372
  return resolved.resources.some(
19714
20373
  (resource) => resource.service === entry.service && spaceMatches(
19715
20374
  resource.space,
@@ -19725,8 +20384,8 @@ var NodeSecretsService = class {
19725
20384
  // src/TinyCloudNode.ts
19726
20385
  var DEFAULT_HOST = "https://node.tinycloud.xyz";
19727
20386
  var DEFAULT_ENCRYPTION_NETWORK_NAME = "default";
19728
- var NETWORK_CREATE_ACTION2 = import_sdk_core8.ENCRYPTION.NETWORK_CREATE;
19729
- var DECRYPT_ACTION2 = import_sdk_core8.ENCRYPTION.DECRYPT;
20387
+ var NETWORK_CREATE_ACTION2 = import_sdk_core9.ENCRYPTION.NETWORK_CREATE;
20388
+ var DECRYPT_ACTION2 = import_sdk_core9.ENCRYPTION.DECRYPT;
19730
20389
  var BOOTSTRAP_COMPLETION_MARKER_KEY = "system/bootstrap/complete";
19731
20390
  var BOOTSTRAP_COMPLETION_MARKER_VERSION = 1;
19732
20391
  var ACCEPTED_MARKER_VERSIONS = [BOOTSTRAP_COMPLETION_MARKER_VERSION];
@@ -19735,24 +20394,24 @@ function isSecretPayload(value) {
19735
20394
  return typeof value === "object" && value !== null && "value" in value && typeof value.value === "string" && "createdAt" in value && typeof value.createdAt === "string" && "updatedAt" in value && typeof value.updatedAt === "string";
19736
20395
  }
19737
20396
  var ROOT_DELEGATION_ACTIONS = [
19738
- import_sdk_core8.KV.PUT,
19739
- import_sdk_core8.KV.GET,
19740
- import_sdk_core8.KV.DEL,
19741
- import_sdk_core8.KV.LIST,
19742
- import_sdk_core8.KV.METADATA,
19743
- import_sdk_core8.SQL.READ,
19744
- import_sdk_core8.SQL.WRITE,
19745
- import_sdk_core8.SQL.ADMIN,
19746
- import_sdk_core8.SQL.ALL,
19747
- import_sdk_core8.DUCKDB.READ,
19748
- import_sdk_core8.DUCKDB.WRITE,
19749
- import_sdk_core8.DUCKDB.ADMIN,
19750
- import_sdk_core8.DUCKDB.DESCRIBE,
19751
- import_sdk_core8.DUCKDB.EXPORT,
19752
- import_sdk_core8.DUCKDB.IMPORT,
19753
- import_sdk_core8.DUCKDB.ALL
20397
+ import_sdk_core9.KV.PUT,
20398
+ import_sdk_core9.KV.GET,
20399
+ import_sdk_core9.KV.DEL,
20400
+ import_sdk_core9.KV.LIST,
20401
+ import_sdk_core9.KV.METADATA,
20402
+ import_sdk_core9.SQL.READ,
20403
+ import_sdk_core9.SQL.WRITE,
20404
+ import_sdk_core9.SQL.ADMIN,
20405
+ import_sdk_core9.SQL.ALL,
20406
+ import_sdk_core9.DUCKDB.READ,
20407
+ import_sdk_core9.DUCKDB.WRITE,
20408
+ import_sdk_core9.DUCKDB.ADMIN,
20409
+ import_sdk_core9.DUCKDB.DESCRIBE,
20410
+ import_sdk_core9.DUCKDB.EXPORT,
20411
+ import_sdk_core9.DUCKDB.IMPORT,
20412
+ import_sdk_core9.DUCKDB.ALL
19754
20413
  ];
19755
- var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core8.EXPIRY.SESSION_MS;
20414
+ var DEFAULT_SESSION_EXPIRATION_MS = import_sdk_core9.EXPIRY.SESSION_MS;
19756
20415
  function unifiedRootAttenuation(capabilities) {
19757
20416
  const attenuation = {};
19758
20417
  for (const capability of capabilities) {
@@ -19798,7 +20457,7 @@ function isInteractiveSigner(config) {
19798
20457
  }
19799
20458
  function didPrincipalMatches2(actual, expected) {
19800
20459
  try {
19801
- return (0, import_sdk_core8.principalDidEquals)(actual, expected);
20460
+ return (0, import_sdk_core9.principalDidEquals)(actual, expected);
19802
20461
  } catch {
19803
20462
  return actual === expected;
19804
20463
  }
@@ -20009,7 +20668,7 @@ function ownerDelegationPermissions(params) {
20009
20668
  }
20010
20669
  const slash = action.indexOf("/");
20011
20670
  const service = slash === -1 ? "" : action.slice(0, slash);
20012
- if (import_sdk_core8.SERVICE_LONG_TO_SHORT[service] === void 0) {
20671
+ if (import_sdk_core9.SERVICE_LONG_TO_SHORT[service] === void 0) {
20013
20672
  throw new Error("Owner delegation capabilities are unsupported");
20014
20673
  }
20015
20674
  const actions = byService.get(service) ?? [];
@@ -20025,7 +20684,7 @@ function ownerDelegationPermissions(params) {
20025
20684
  }
20026
20685
  const resources = /* @__PURE__ */ new Set();
20027
20686
  for (const permission of permissions) {
20028
- if (typeof permission.service !== "string" || import_sdk_core8.SERVICE_LONG_TO_SHORT[permission.service] === void 0 || typeof permission.path !== "string" || permission.path.length === 0 || permission.path.trim() !== permission.path || /[\u0000-\u001f\u007f\\*]/.test(permission.path) || !Array.isArray(permission.actions) || permission.actions.length === 0 || permission.actions.length > 32) {
20687
+ if (typeof permission.service !== "string" || import_sdk_core9.SERVICE_LONG_TO_SHORT[permission.service] === void 0 || typeof permission.path !== "string" || permission.path.length === 0 || permission.path.trim() !== permission.path || /[\u0000-\u001f\u007f\\*]/.test(permission.path) || !Array.isArray(permission.actions) || permission.actions.length === 0 || permission.actions.length > 32) {
20029
20688
  throw new Error("Owner delegation requires bounded capabilities");
20030
20689
  }
20031
20690
  const resourceKey = `${permission.service}\0${permission.path}`;
@@ -20040,9 +20699,9 @@ function ownerDelegationPermissions(params) {
20040
20699
  }
20041
20700
  actions.add(action);
20042
20701
  }
20043
- if (permission.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE) {
20702
+ if (permission.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE) {
20044
20703
  try {
20045
- (0, import_sdk_core8.parseNetworkId)(permission.path);
20704
+ (0, import_sdk_core9.parseNetworkId)(permission.path);
20046
20705
  } catch {
20047
20706
  throw new Error("Owner delegation encryption permission requires a canonical network URN");
20048
20707
  }
@@ -20054,11 +20713,11 @@ function ownerPermissionsToAbilities(permissions) {
20054
20713
  const abilities = {};
20055
20714
  const rawAbilities = {};
20056
20715
  for (const permission of permissions) {
20057
- if (permission.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE) {
20716
+ if (permission.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE) {
20058
20717
  rawAbilities[permission.path] = [...permission.actions];
20059
20718
  continue;
20060
20719
  }
20061
- const shortService = import_sdk_core8.SERVICE_LONG_TO_SHORT[permission.service];
20720
+ const shortService = import_sdk_core9.SERVICE_LONG_TO_SHORT[permission.service];
20062
20721
  abilities[shortService] ?? (abilities[shortService] = {});
20063
20722
  abilities[shortService][permission.path] = [...permission.actions];
20064
20723
  }
@@ -20190,6 +20849,8 @@ var _TinyCloudNode = class _TinyCloudNode {
20190
20849
  this.confirmedHostedSpaceIds = /* @__PURE__ */ new Set();
20191
20850
  /** Serializes account-registry writes for the active node instance. */
20192
20851
  this.accountRegistryTail = Promise.resolve();
20852
+ /** Bounds best-effort registry work on the sign-in critical path. */
20853
+ this.accountRegistryDeadlineMs = 4e3;
20193
20854
  /**
20194
20855
  * True when the last signIn() detected an interactive signer and skipped
20195
20856
  * client-side bootstrap. Apps can read this to know whether bootstrap was
@@ -20261,18 +20922,53 @@ var _TinyCloudNode = class _TinyCloudNode {
20261
20922
  if (!granted?.caveats?.length) {
20262
20923
  return entry;
20263
20924
  }
20264
- if (entry.caveats !== void 0 && !(0, import_sdk_core8.recapCaveatsEqual)(entry.caveats, granted.caveats)) {
20925
+ if (entry.caveats !== void 0 && !(0, import_sdk_core9.recapCaveatsEqual)(entry.caveats, granted.caveats)) {
20265
20926
  throw new Error("Invocation caveats do not match signed ReCap authority.");
20266
20927
  }
20267
20928
  return { ...entry, caveats: cloneRecapCaveats(granted.caveats) };
20268
20929
  });
20269
20930
  return this.wasmBindings.invokeAny(invocationSession, caveatPreservingEntries, facts);
20270
20931
  };
20932
+ assertValidReplicationConfig(config.replication);
20271
20933
  this.explicitHost = config.host;
20272
20934
  this.config = {
20273
20935
  ...config,
20274
20936
  host: config.host ?? DEFAULT_HOST
20275
20937
  };
20938
+ if (this.config.replication?.enabled) {
20939
+ const runtime = getNodeReplicationLoaders().runtime().then(({ ReplicationRuntime: ReplicationRuntime2 }) => {
20940
+ const instance = new ReplicationRuntime2(this.config.replication);
20941
+ this.replicationRuntimeInstance = instance;
20942
+ return instance;
20943
+ });
20944
+ this.replicationRuntime = runtime;
20945
+ this.replicationControl = {
20946
+ status: async () => {
20947
+ const status = await runtime.then((ready) => ready.control.status());
20948
+ const scopeError = this.replicationScopeError;
20949
+ if (!scopeError) return status;
20950
+ return this.config.replication.prefixes.map((prefix) => ({
20951
+ prefix,
20952
+ state: "unavailable",
20953
+ lastError: {
20954
+ at: (/* @__PURE__ */ new Date()).toISOString(),
20955
+ code: "SESSION_SCOPE_MISMATCH",
20956
+ message: scopeError
20957
+ },
20958
+ pending: { inFlight: 0, committed: 0, ambiguous: 0 },
20959
+ pinned: [],
20960
+ lagMs: null
20961
+ }));
20962
+ },
20963
+ sync: async (input) => (await runtime).control.sync(input),
20964
+ purge: (input) => {
20965
+ const instance = this.replicationRuntimeInstance;
20966
+ return instance ? instance.control.purge(input) : runtime.then((ready) => ready.control.purge(input));
20967
+ },
20968
+ clearPending: async () => (await runtime).control.clearPending(),
20969
+ close: async () => (await runtime).control.close()
20970
+ };
20971
+ }
20276
20972
  if (config.wasmBindings) {
20277
20973
  this.wasmBindings = config.wasmBindings;
20278
20974
  } else if (_TinyCloudNode.nodeDefaults) {
@@ -20296,13 +20992,13 @@ var _TinyCloudNode = class _TinyCloudNode {
20296
20992
  }
20297
20993
  this.sessionKeyJwk = JSON.parse(jwkStr);
20298
20994
  this._serviceGraph = this.createServiceGraphLifetime();
20299
- this._capabilityRegistry = new import_sdk_core8.CapabilityKeyRegistry();
20995
+ this._capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
20300
20996
  this._keyProvider = new WasmKeyProvider({
20301
20997
  sessionManager: this.sessionManager
20302
20998
  });
20303
- this.notificationHandler = config.notificationHandler ?? new import_sdk_core8.SilentNotificationHandler();
20999
+ this.notificationHandler = config.notificationHandler ?? new import_sdk_core9.SilentNotificationHandler();
20304
21000
  const receiveOnlyGraph = this._serviceGraph;
20305
- this._sharingService = new import_sdk_core8.SharingService({
21001
+ this._sharingService = new import_sdk_core9.SharingService({
20306
21002
  hosts: [this.config.host],
20307
21003
  // session: undefined - not needed for receive()
20308
21004
  invoke: receiveOnlyGraph.invoke,
@@ -20318,8 +21014,8 @@ var _TinyCloudNode = class _TinyCloudNode {
20318
21014
  // delegationManager: undefined - not needed for receive()
20319
21015
  createKVService: (config2) => {
20320
21016
  const prefix = config2.pathPrefix?.replace(/\/$/, "");
20321
- const kvService = new import_sdk_core8.KVService({ prefix });
20322
- const kvContext = receiveOnlyGraph.track(new import_sdk_core8.ServiceContext({
21017
+ const kvService = new import_sdk_core9.KVService({ prefix });
21018
+ const kvContext = receiveOnlyGraph.track(new import_sdk_core9.ServiceContext({
20323
21019
  invoke: config2.invoke,
20324
21020
  fetch: config2.fetch ?? globalThis.fetch.bind(globalThis),
20325
21021
  hosts: config2.hosts,
@@ -20392,10 +21088,17 @@ var _TinyCloudNode = class _TinyCloudNode {
20392
21088
  nonce: config.nonce,
20393
21089
  siweConfig: config.siweConfig,
20394
21090
  manifest: useBootstrapSignInRequest ? void 0 : config.manifest,
20395
- capabilityRequest: useBootstrapSignInRequest ? config.includeAccountRegistryPermissions === false ? import_sdk_core8.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core8.BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
20396
- includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : config.includeAccountRegistryPermissions
21091
+ capabilityRequest: useBootstrapSignInRequest ? config.includeAccountRegistryPermissions === false ? import_sdk_core9.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default : config.capabilityRequest,
21092
+ includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : config.includeAccountRegistryPermissions,
21093
+ // Sign-in needs only the entry inputs (prefixes + secrets opt-in);
21094
+ // storage and scheduling never leave TinyCloudNode.
21095
+ replication: config.replication?.enabled === true ? {
21096
+ enabled: true,
21097
+ prefixes: config.replication.prefixes,
21098
+ allowSecrets: config.replication.allowSecrets === true
21099
+ } : void 0
20397
21100
  });
20398
- this.tc = new import_sdk_core8.TinyCloud(this.auth, {
21101
+ this.tc = new import_sdk_core9.TinyCloud(this.auth, {
20399
21102
  invokeAny: this.invokeAnyWithRuntimePermissions,
20400
21103
  telemetry: config.telemetry
20401
21104
  });
@@ -20475,7 +21178,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20475
21178
  /** Publish the active owner Node as a session-signed registry record. */
20476
21179
  async publishActiveNodeLocation(registryUrl, fetchFn = globalThis.fetch.bind(globalThis)) {
20477
21180
  const node = await this.activeNodeIdentity();
20478
- return (0, import_sdk_core8.publishLocationRecord)({
21181
+ return (0, import_sdk_core9.publishLocationRecord)({
20479
21182
  registryUrl,
20480
21183
  subject: this.credentialHolderDid,
20481
21184
  nodeOrigin: node.origin,
@@ -20492,7 +21195,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20492
21195
  */
20493
21196
  get did() {
20494
21197
  if (this._address) {
20495
- return (0, import_sdk_core8.pkhDid)(this._address, this._chainId);
21198
+ return (0, import_sdk_core9.pkhDid)(this._address, this._chainId);
20496
21199
  }
20497
21200
  return this.sessionManager.getDID(this.sessionKeyId);
20498
21201
  }
@@ -20529,7 +21232,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20529
21232
  /** Normalize signed capabilities without collapsing nested encryption into raw authority. */
20530
21233
  projectSignedRecapCapabilities(siwe) {
20531
21234
  const projected = this.parseRecapWithCaveats(siwe).map((entry) => {
20532
- const normalized = (0, import_sdk_core8.parseRecapCapabilities)(() => [entry], siwe)[0];
21235
+ const normalized = (0, import_sdk_core9.parseRecapCapabilities)(() => [entry], siwe)[0];
20533
21236
  if (normalized.service !== "tinycloud.encryption") return normalized;
20534
21237
  if (!this.isEncryptionNetworkOperation("encryption", entry.path, entry.space)) {
20535
21238
  return { ...normalized, space: entry.space };
@@ -20574,14 +21277,14 @@ var _TinyCloudNode = class _TinyCloudNode {
20574
21277
  if (!this._address) {
20575
21278
  return void 0;
20576
21279
  }
20577
- return this.wasmBindings.makeSpaceId(this._address, this._chainId, import_sdk_core8.ACCOUNT_REGISTRY_SPACE);
21280
+ return this.wasmBindings.makeSpaceId(this._address, this._chainId, import_sdk_core9.ACCOUNT_REGISTRY_SPACE);
20578
21281
  }
20579
21282
  /**
20580
21283
  * Account-level application and delegation helpers.
20581
21284
  */
20582
21285
  get account() {
20583
21286
  if (!this._account) {
20584
- this._account = new import_sdk_core4.AccountService({
21287
+ this._account = new import_sdk_core5.AccountService({
20585
21288
  getDid: () => this.did,
20586
21289
  getHost: () => this.hosts[0] ?? this.config.host,
20587
21290
  getPrimarySpaceId: () => this.spaceId,
@@ -20627,7 +21330,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20627
21330
  }
20628
21331
  await this.accountRegistryTail;
20629
21332
  await this.wasmBindings.ensureInitialized?.();
20630
- this._address = (0, import_sdk_core8.canonicalizeAddress)(await this.signer.getAddress());
21333
+ this._address = (0, import_sdk_core9.canonicalizeAddress)(await this.signer.getAddress());
20631
21334
  this._chainId = await this.signer.getChainId();
20632
21335
  this._kv = void 0;
20633
21336
  this._sql = void 0;
@@ -20644,6 +21347,9 @@ var _TinyCloudNode = class _TinyCloudNode {
20644
21347
  this.confirmedHostedSpaceIds.clear();
20645
21348
  await this.tc.signIn(options);
20646
21349
  this.syncResolvedHostFromAuth();
21350
+ this.replicationDelegateSession = void 0;
21351
+ this.replicationScopeError = void 0;
21352
+ if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
20647
21353
  const oldGraph = this._serviceGraph;
20648
21354
  this._serviceGraph = this.createServiceGraphLifetime();
20649
21355
  oldGraph.retire();
@@ -20653,7 +21359,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20653
21359
  this.sessionKeyId = signedInSession.sessionKey;
20654
21360
  this.sessionKeyJwk = signedInSession.jwk;
20655
21361
  }
20656
- this.initializeServices();
21362
+ await this.initializeServices();
20657
21363
  const primarySession = this.currentTinyCloudSession();
20658
21364
  if (primarySession) {
20659
21365
  this.registerPrimarySessionGrant(primarySession);
@@ -20661,10 +21367,11 @@ var _TinyCloudNode = class _TinyCloudNode {
20661
21367
  const bootstrapped = await this.bootstrapAccountIfNeeded();
20662
21368
  await this.ensureRequestedEncryptionNetworks();
20663
21369
  if (!bootstrapped && this.config.manifest === void 0 && this.config.capabilityRequest === void 0) {
20664
- await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core8.SECRETS_SPACE));
21370
+ await this.ensureOwnedSpaceHostedById(this.ownedSpaceId(import_sdk_core9.SECRETS_SPACE));
20665
21371
  }
20666
21372
  if (!bootstrapped) {
20667
21373
  this.scheduleAccountRegistrySync();
21374
+ await this.accountRegistryTail;
20668
21375
  }
20669
21376
  this.notificationHandler.success("Successfully signed in");
20670
21377
  }
@@ -20692,7 +21399,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20692
21399
  this._bootstrapStatus = { skipped: true, reason: "interactive-signer" };
20693
21400
  return false;
20694
21401
  }
20695
- const steps = (0, import_sdk_core8.bootstrapSteps)(this._address, this._chainId);
21402
+ const steps = (0, import_sdk_core9.bootstrapSteps)(this._address, this._chainId);
20696
21403
  try {
20697
21404
  const decision = await this.resolveBootstrapDecision(steps);
20698
21405
  if (decision.action === "skip") {
@@ -20730,7 +21437,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20730
21437
  if (!auth) {
20731
21438
  throw new Error("Account bootstrap requires an active wallet session");
20732
21439
  }
20733
- const accountSpaceId = this.ownedSpaceId(import_sdk_core8.ACCOUNT_REGISTRY_SPACE);
21440
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE);
20734
21441
  const skipped = auth.lastActivationSkippedSpaceIds;
20735
21442
  if (skipped.includes(accountSpaceId)) return { action: "run", mode: "fresh" };
20736
21443
  if (skipped.some((spaceId) => enshrinedSpaceIds.has(spaceId))) {
@@ -20753,7 +21460,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20753
21460
  }
20754
21461
  return { action: "run", mode: "repair" };
20755
21462
  }
20756
- if (marker.error.code === import_sdk_core8.ErrorCodes.KV_NOT_FOUND && this.markerReadIsUnhostedSpace(marker.error.meta)) {
21463
+ if (marker.error.code === import_sdk_core9.ErrorCodes.KV_NOT_FOUND && this.markerReadIsUnhostedSpace(marker.error.meta)) {
20757
21464
  return { action: "run", mode: "fresh" };
20758
21465
  }
20759
21466
  } catch (err) {
@@ -20767,7 +21474,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20767
21474
  return { action: "run", mode: "repair" };
20768
21475
  }
20769
21476
  async readBootstrapCompletionMarker() {
20770
- return this.kvForSpace(this.ownedSpaceId(import_sdk_core8.ACCOUNT_REGISTRY_SPACE)).get(
21477
+ return this.kvForSpace(this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE)).get(
20771
21478
  BOOTSTRAP_COMPLETION_MARKER_KEY
20772
21479
  );
20773
21480
  }
@@ -20776,7 +21483,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20776
21483
  throw new Error("Bootstrap completion marker requires an active wallet session");
20777
21484
  }
20778
21485
  const canonicalStepIds = new Set(
20779
- (0, import_sdk_core8.bootstrapSteps)(this._address, this._chainId).map((step) => step.id)
21486
+ (0, import_sdk_core9.bootstrapSteps)(this._address, this._chainId).map((step) => step.id)
20780
21487
  );
20781
21488
  const providedStepIds = new Set(steps.map((step) => step.id));
20782
21489
  if (canonicalStepIds.size !== providedStepIds.size || [...canonicalStepIds].some((stepId) => !providedStepIds.has(stepId))) {
@@ -20787,7 +21494,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20787
21494
  stepIds: [...canonicalStepIds],
20788
21495
  completedAt: (/* @__PURE__ */ new Date()).toISOString()
20789
21496
  };
20790
- const written = await this.kvForSpace(this.ownedSpaceId(import_sdk_core8.ACCOUNT_REGISTRY_SPACE)).put(
21497
+ const written = await this.kvForSpace(this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE)).put(
20791
21498
  BOOTSTRAP_COMPLETION_MARKER_KEY,
20792
21499
  marker
20793
21500
  );
@@ -20826,7 +21533,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20826
21533
  const warnings = [];
20827
21534
  const primarySession = auth.tinyCloudSession;
20828
21535
  const defaultSpaceId = this.ownedSpaceId("default");
20829
- const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core8.BOOTSTRAP_SESSION_REQUESTS.default;
21536
+ const canReusePrimaryBootstrapSession = primarySession?.spaceId === defaultSpaceId && auth.capabilityRequest === import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default;
20830
21537
  for (const step of steps) {
20831
21538
  if (step.kind !== "session") continue;
20832
21539
  if (step.space === "default" && canReusePrimaryBootstrapSession && primarySession) {
@@ -20841,7 +21548,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20841
21548
  try {
20842
21549
  session = await auth.createBootstrapSession({
20843
21550
  spaceId: step.spaceId,
20844
- capabilityRequest: step.request ?? import_sdk_core8.BOOTSTRAP_SESSION_REQUESTS[step.space],
21551
+ capabilityRequest: step.request ?? import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS[step.space],
20845
21552
  rawAbilities
20846
21553
  });
20847
21554
  } catch (err) {
@@ -20871,7 +21578,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20871
21578
  if (!session) {
20872
21579
  throw new Error(`Missing bootstrap session for ${step.space}`);
20873
21580
  }
20874
- const activated = await (0, import_sdk_core8.activateSessionWithHost)(host, session.delegationHeader);
21581
+ const activated = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader);
20875
21582
  if (!activated.success || activated.skipped?.includes(step.spaceId)) {
20876
21583
  throw Object.assign(
20877
21584
  new Error(
@@ -20882,7 +21589,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20882
21589
  }
20883
21590
  this.registerBootstrapRuntimeGrant(
20884
21591
  session,
20885
- import_sdk_core8.BOOTSTRAP_SESSION_REQUESTS[step.space],
21592
+ import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS[step.space],
20886
21593
  rawAbilitiesBySpace.get(step.space)
20887
21594
  );
20888
21595
  }
@@ -20931,7 +21638,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20931
21638
  }
20932
21639
  if (step.kind === "seed-applications") {
20933
21640
  const registered = await this.account.applications.register(
20934
- step.manifests.length > 0 ? [...step.manifests] : import_sdk_core8.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
21641
+ step.manifests.length > 0 ? [...step.manifests] : import_sdk_core9.TINYCLOUD_SECRETS_BOOTSTRAP_MANIFEST,
20935
21642
  // The write is an INSERT OR REPLACE and is safe to repeat during a
20936
21643
  // repair, so skip the manifest-hash pre-read.
20937
21644
  { assumeUnregistered: true }
@@ -20950,7 +21657,7 @@ var _TinyCloudNode = class _TinyCloudNode {
20950
21657
  migrations: [
20951
21658
  {
20952
21659
  id: "001_initial",
20953
- sql: [...import_sdk_core8.SECRET_RECORDS_SCHEMA]
21660
+ sql: [...import_sdk_core9.SECRET_RECORDS_SCHEMA]
20954
21661
  }
20955
21662
  ]
20956
21663
  });
@@ -21117,7 +21824,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21117
21824
  provenance: "primary"
21118
21825
  });
21119
21826
  }
21120
- async writeManifestRegistryRecords() {
21827
+ async writeManifestRegistryRecords(account, signal) {
21121
21828
  const request = this.capabilityRequest;
21122
21829
  if (!request || request.registryRecords.length === 0) {
21123
21830
  return;
@@ -21125,9 +21832,10 @@ var _TinyCloudNode = class _TinyCloudNode {
21125
21832
  if (!this.auth || !this.signer) {
21126
21833
  throw new Error("Manifest registry write requires wallet mode");
21127
21834
  }
21128
- const accountSpaceId = this.ownedSpaceId(import_sdk_core8.ACCOUNT_REGISTRY_SPACE);
21129
- await this.ensureOwnedSpaceHostedById(accountSpaceId);
21130
- const result = await this.account.applications.register(request.manifests);
21835
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE);
21836
+ await this.ensureOwnedSpaceHostedById(accountSpaceId, signal);
21837
+ if (signal.aborted) throw signal.reason;
21838
+ const result = await account.applications.register(request.manifests);
21131
21839
  if (!result.ok) {
21132
21840
  throw Object.assign(
21133
21841
  new Error(`Failed to write manifest registry records: ${result.error.message}`),
@@ -21135,34 +21843,113 @@ var _TinyCloudNode = class _TinyCloudNode {
21135
21843
  );
21136
21844
  }
21137
21845
  }
21846
+ createAccountRegistryServices(context, signal) {
21847
+ const session = context.session;
21848
+ if (!session) throw new Error("Account registry requires an active service session");
21849
+ const contexts = [context];
21850
+ const accountSpaceId = this.ownedSpaceId(import_sdk_core9.ACCOUNT_REGISTRY_SPACE);
21851
+ const createScopedContext = (spaceId) => {
21852
+ const scoped = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
21853
+ invoke: context.invoke,
21854
+ invokeAny: context.invokeAny,
21855
+ fetch: context.fetch,
21856
+ hosts: context.hosts,
21857
+ telemetry: this.config.telemetry
21858
+ }));
21859
+ scoped.setOperationAbortSignal(signal);
21860
+ scoped.setSession({ ...session, spaceId });
21861
+ contexts.push(scoped);
21862
+ return scoped;
21863
+ };
21864
+ const sql = new import_sdk_core9.SQLService({});
21865
+ const sqlContext = createScopedContext(accountSpaceId);
21866
+ sql.initialize(sqlContext);
21867
+ const spaces = new import_sdk_core9.SpaceService({
21868
+ hosts: context.hosts,
21869
+ session,
21870
+ invoke: context.invoke,
21871
+ fetch: (url, init2) => context.fetch(url, {
21872
+ ...init2,
21873
+ signal: init2?.signal ? AbortSignal.any([init2.signal, signal]) : signal
21874
+ }),
21875
+ userDid: this.did,
21876
+ createKVService: (spaceId) => {
21877
+ const kv = new import_sdk_core9.KVService({});
21878
+ kv.initialize(createScopedContext(spaceId));
21879
+ return kv;
21880
+ }
21881
+ });
21882
+ return {
21883
+ contexts,
21884
+ account: new import_sdk_core5.AccountService({
21885
+ getDid: () => this.did,
21886
+ getHost: () => context.hosts[0] ?? this.config.host,
21887
+ getPrimarySpaceId: () => session.spaceId,
21888
+ getAccountSpaceId: () => accountSpaceId,
21889
+ getSpaces: () => spaces,
21890
+ getAccountDb: () => sql.db("account"),
21891
+ ensureAccountSpaceHosted: () => this.ensureOwnedSpaceHostedById(accountSpaceId, signal)
21892
+ })
21893
+ };
21894
+ }
21138
21895
  scheduleAccountRegistrySync() {
21139
21896
  const session = this.currentTinyCloudSession();
21140
21897
  if (!session || this.pendingAccountRegistrySync?.session === session) {
21141
21898
  return;
21142
21899
  }
21900
+ const controller = new AbortController();
21901
+ const deadline = setTimeout(
21902
+ () => controller.abort(new DOMException("Account registry deadline exceeded", "TimeoutError")),
21903
+ this.accountRegistryDeadlineMs
21904
+ );
21143
21905
  const promise = this.enqueueAccountRegistryOperation(session, async () => {
21144
- await this.withAccountRegistryRetry(async () => {
21145
- if (this.currentTinyCloudSession() !== session) {
21146
- return;
21147
- }
21148
- await this.account.index.ensure();
21149
- if (this.currentTinyCloudSession() !== session) {
21150
- return;
21151
- }
21152
- await this.writeManifestRegistryRecords();
21153
- if (this.currentTinyCloudSession() !== session) {
21154
- return;
21155
- }
21156
- if (this.currentSessionCanListSpaces()) {
21157
- const spaces = await this.account.spaces.syncAccessible();
21158
- if (!spaces.ok) {
21159
- throw Object.assign(
21160
- new Error(`Failed to sync account spaces: ${spaces.error.message}`),
21161
- { cause: spaces.error }
21162
- );
21906
+ const sharedContext = this._serviceContext;
21907
+ if (!sharedContext) return;
21908
+ const context = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
21909
+ invoke: sharedContext.invoke,
21910
+ invokeAny: sharedContext.invokeAny,
21911
+ fetch: sharedContext.fetch,
21912
+ hosts: sharedContext.hosts,
21913
+ telemetry: this.config.telemetry
21914
+ }));
21915
+ context.setOperationAbortSignal(controller.signal);
21916
+ const current = this.currentTinyCloudSession();
21917
+ if (!current) return;
21918
+ context.setSession({
21919
+ delegationHeader: current.delegationHeader,
21920
+ delegationCid: current.delegationCid,
21921
+ spaceId: current.spaceId,
21922
+ verificationMethod: current.verificationMethod,
21923
+ jwk: current.jwk
21924
+ });
21925
+ const registry = this.createAccountRegistryServices(context, controller.signal);
21926
+ try {
21927
+ await this.withAccountRegistryRetry(async () => {
21928
+ if (controller.signal.aborted) throw controller.signal.reason;
21929
+ if (this.currentTinyCloudSession() !== session) return;
21930
+ await registry.account.index.ensure();
21931
+ if (controller.signal.aborted) throw controller.signal.reason;
21932
+ if (this.currentTinyCloudSession() !== session) return;
21933
+ await this.writeManifestRegistryRecords(registry.account, controller.signal);
21934
+ if (controller.signal.aborted) throw controller.signal.reason;
21935
+ if (this.currentTinyCloudSession() !== session) return;
21936
+ if (this.currentSessionCanListSpaces()) {
21937
+ const result = await registry.account.spaces.syncAccessible();
21938
+ if (controller.signal.aborted) throw controller.signal.reason;
21939
+ if (!result.ok) {
21940
+ throw Object.assign(
21941
+ new Error(`Failed to sync account spaces: ${result.error.message}`),
21942
+ { cause: result.error }
21943
+ );
21944
+ }
21163
21945
  }
21946
+ }, controller.signal);
21947
+ } finally {
21948
+ for (const operationContext of registry.contexts) {
21949
+ operationContext.retire();
21164
21950
  }
21165
- });
21951
+ clearTimeout(deadline);
21952
+ }
21166
21953
  });
21167
21954
  this.pendingAccountRegistrySync = { session, promise };
21168
21955
  const clearPendingSync = () => {
@@ -21171,6 +21958,10 @@ var _TinyCloudNode = class _TinyCloudNode {
21171
21958
  }
21172
21959
  };
21173
21960
  void promise.then(clearPendingSync, clearPendingSync);
21961
+ void promise.then(
21962
+ () => clearTimeout(deadline),
21963
+ () => clearTimeout(deadline)
21964
+ );
21174
21965
  }
21175
21966
  enqueueAccountRegistryOperation(session, task) {
21176
21967
  const operation = this.accountRegistryTail.then(async () => {
@@ -21206,15 +21997,23 @@ var _TinyCloudNode = class _TinyCloudNode {
21206
21997
  (operation) => operation.service === "space" && this.actionContains(operation.action, "tinycloud.space/list")
21207
21998
  );
21208
21999
  }
21209
- async withAccountRegistryRetry(task) {
22000
+ async withAccountRegistryRetry(task, signal) {
21210
22001
  const delays = [250, 1e3, 3e3];
21211
22002
  let lastError;
21212
22003
  for (let attempt = 0; attempt < delays.length; attempt += 1) {
22004
+ if (signal.aborted) {
22005
+ console.warn("TinyCloud account registry sync stopped: deadline exceeded", signal.reason);
22006
+ return;
22007
+ }
21213
22008
  try {
21214
22009
  await task();
21215
22010
  return;
21216
22011
  } catch (error) {
21217
- const verdict = (0, import_sdk_core8.authorizationVerdictOf)(error);
22012
+ if (signal.aborted) {
22013
+ console.warn("TinyCloud account registry sync stopped: deadline exceeded", error);
22014
+ return;
22015
+ }
22016
+ const verdict = (0, import_sdk_core9.authorizationVerdictOf)(error);
21218
22017
  const message = error instanceof Error ? error.message : String(error);
21219
22018
  const isAuthorizationVerdict = verdict === void 0 ? /Unauthorized Action|\b(?:401|403)\b/.test(message) : verdict !== "other";
21220
22019
  if (isAuthorizationVerdict) {
@@ -21224,14 +22023,30 @@ var _TinyCloudNode = class _TinyCloudNode {
21224
22023
  );
21225
22024
  return;
21226
22025
  }
21227
- if ((0, import_sdk_core8.isStorageFullError)(error) || (0, import_sdk_core8.isStorageFullError)(error?.cause) || message.includes(import_sdk_core8.STORAGE_FULL_MESSAGE) || message.includes(import_sdk_core8.STORAGE_WRITE_TOO_LARGE_MESSAGE)) {
21228
- console.warn("TinyCloud account registry sync stopped: storage is full", error);
22026
+ if ((0, import_sdk_core9.isStorageFullError)(error) || (0, import_sdk_core9.isStorageFullError)(error?.cause) || message.includes(import_sdk_core9.STORAGE_FULL_MESSAGE) || message.includes(import_sdk_core9.STORAGE_WRITE_TOO_LARGE_MESSAGE)) {
22027
+ console.warn(
22028
+ "TinyCloud account registry sync stopped: storage is full",
22029
+ error
22030
+ );
21229
22031
  return;
21230
22032
  }
21231
22033
  lastError = error;
21232
22034
  if (attempt < delays.length - 1) {
21233
- await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
21234
- }
22035
+ await new Promise((resolve, reject2) => {
22036
+ const timer = setTimeout(() => {
22037
+ signal.removeEventListener("abort", onAbort);
22038
+ resolve();
22039
+ }, delays[attempt]);
22040
+ const onAbort = () => {
22041
+ clearTimeout(timer);
22042
+ signal.removeEventListener("abort", onAbort);
22043
+ reject2(signal.reason);
22044
+ };
22045
+ signal.addEventListener("abort", onAbort, { once: true });
22046
+ }).catch((error2) => {
22047
+ if (!signal.aborted) throw error2;
22048
+ });
22049
+ }
21235
22050
  }
21236
22051
  }
21237
22052
  console.warn(
@@ -21246,7 +22061,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21246
22061
  }
21247
22062
  const networkIds = /* @__PURE__ */ new Set();
21248
22063
  for (const resource of request.resources) {
21249
- if (resource.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
22064
+ if (resource.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE && resource.path.startsWith("urn:tinycloud:encryption:") && resource.actions.includes(DECRYPT_ACTION2)) {
21250
22065
  networkIds.add(resource.path);
21251
22066
  }
21252
22067
  }
@@ -21257,7 +22072,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21257
22072
  return;
21258
22073
  }
21259
22074
  for (const networkId of this.requestedEncryptionNetworkIds()) {
21260
- const parsed = (0, import_sdk_core8.parseNetworkId)(networkId);
22075
+ const parsed = (0, import_sdk_core9.parseNetworkId)(networkId);
21261
22076
  if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
21262
22077
  continue;
21263
22078
  }
@@ -21280,7 +22095,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21280
22095
  * self-revealing: the next write to the space fails immediately and loudly
21281
22096
  * with `404 Space not found`.
21282
22097
  */
21283
- async ensureOwnedSpaceHostedById(spaceId) {
22098
+ async ensureOwnedSpaceHostedById(spaceId, signal) {
21284
22099
  if (!this.auth) {
21285
22100
  throw new Error("Owned space hosting requires wallet mode");
21286
22101
  }
@@ -21295,7 +22110,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21295
22110
  if (!host) {
21296
22111
  throw new Error("Owned space hosting requires a TinyCloud host");
21297
22112
  }
21298
- const activation = await (0, import_sdk_core8.activateSessionWithHost)(host, session.delegationHeader);
22113
+ const activation = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader, signal);
21299
22114
  if (activation.success && !activation.skipped?.includes(spaceId)) {
21300
22115
  this.confirmedHostedSpaceIds.add(spaceId);
21301
22116
  return;
@@ -21306,15 +22121,16 @@ var _TinyCloudNode = class _TinyCloudNode {
21306
22121
  { cause: activation }
21307
22122
  );
21308
22123
  }
21309
- const created = await this.auth.hostOwnedSpaceResult(spaceId);
22124
+ const authorization = this.auth;
22125
+ const created = signal ? await authorization.hostOwnedSpaceResult(spaceId, void 0, signal) : await authorization.hostOwnedSpaceResult(spaceId);
21310
22126
  if (!created.success) {
21311
22127
  throw Object.assign(
21312
22128
  new Error(`Failed to create owned space ${spaceId}: ${describeHostFailure2(created)}`),
21313
22129
  { cause: created }
21314
22130
  );
21315
22131
  }
21316
- await new Promise((resolve) => setTimeout(resolve, 100));
21317
- const retry = await (0, import_sdk_core8.activateSessionWithHost)(host, session.delegationHeader);
22132
+ if (signal?.aborted) throw signal.reason;
22133
+ const retry = await (0, import_sdk_core9.activateSessionWithHost)(host, session.delegationHeader, signal);
21318
22134
  if (!retry.success || retry.skipped?.includes(spaceId)) {
21319
22135
  throw Object.assign(
21320
22136
  new Error(
@@ -21362,7 +22178,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21362
22178
  { cause: hosted }
21363
22179
  );
21364
22180
  }
21365
- const activation = await (0, import_sdk_core8.activateSessionWithHost)(
22181
+ const activation = await (0, import_sdk_core9.activateSessionWithHost)(
21366
22182
  host,
21367
22183
  session.delegationHeader
21368
22184
  );
@@ -21550,7 +22366,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21550
22366
  }
21551
22367
  let restoredAddress;
21552
22368
  try {
21553
- restoredAddress = hasPersistedProof ? (0, import_sdk_core8.canonicalizeAddress)(sessionData.address) : void 0;
22369
+ restoredAddress = hasPersistedProof ? (0, import_sdk_core9.canonicalizeAddress)(sessionData.address) : void 0;
21554
22370
  } catch {
21555
22371
  throw new InvalidRestoredSessionError("Persisted session has an invalid wallet address.");
21556
22372
  }
@@ -21592,7 +22408,35 @@ var _TinyCloudNode = class _TinyCloudNode {
21592
22408
  const stagedHost = resolvedHost ?? this.config.host;
21593
22409
  const stagedAddress = restoredAddress;
21594
22410
  const stagedChainId = sessionData.chainId ?? 1;
21595
- const stagedNodeDid = stagedAddress ? (0, import_sdk_core8.pkhDid)(stagedAddress, stagedChainId) : canonicalVerificationMethod;
22411
+ let replicationPrincipal;
22412
+ let compactReplicationSession;
22413
+ let replicationScopeError;
22414
+ if (this.config.replication?.enabled) {
22415
+ if (stagedAddress !== void 0) {
22416
+ replicationPrincipal = (0, import_sdk_core9.pkhDid)(stagedAddress, stagedChainId);
22417
+ } else {
22418
+ const { replicationScopeFromSignedSession: replicationScopeFromSignedSession2 } = await getNodeReplicationLoaders().authority();
22419
+ const signedScope = replicationScopeFromSignedSession2({
22420
+ delegationHeader: sessionData.delegationHeader,
22421
+ delegationCid: sessionData.delegationCid,
22422
+ verificationMethod: restoredVerificationMethod,
22423
+ persistedSpace: sessionData.spaceId
22424
+ });
22425
+ if (!signedScope) {
22426
+ replicationScopeError = "Persisted space does not match the locally verified delegation scope.";
22427
+ } else {
22428
+ replicationPrincipal = signedScope.principal;
22429
+ compactReplicationSession = {
22430
+ delegationHeader: sessionData.delegationHeader,
22431
+ delegationCid: sessionData.delegationCid,
22432
+ spaceId: signedScope.space,
22433
+ verificationMethod: restoredVerificationMethod,
22434
+ jwk: stagedJwk
22435
+ };
22436
+ }
22437
+ }
22438
+ }
22439
+ const stagedNodeDid = stagedAddress ? (0, import_sdk_core9.pkhDid)(stagedAddress, stagedChainId) : canonicalVerificationMethod;
21596
22440
  const serviceSession = {
21597
22441
  delegationHeader: sessionData.delegationHeader,
21598
22442
  delegationCid: sessionData.delegationCid,
@@ -21620,7 +22464,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21620
22464
  stagedSessionExpiry,
21621
22465
  stagedRecap
21622
22466
  );
21623
- const stagedAccountSpaceId = stagedAddress ? this.wasmBindings.makeSpaceId(stagedAddress, stagedChainId, import_sdk_core8.ACCOUNT_REGISTRY_SPACE) : void 0;
22467
+ const stagedAccountSpaceId = stagedAddress ? this.wasmBindings.makeSpaceId(stagedAddress, stagedChainId, import_sdk_core9.ACCOUNT_REGISTRY_SPACE) : void 0;
21624
22468
  const stagedGraph = this.stageRestoredServiceGraph({
21625
22469
  host: stagedHost,
21626
22470
  manager: stagedManager,
@@ -21670,7 +22514,18 @@ var _TinyCloudNode = class _TinyCloudNode {
21670
22514
  } else {
21671
22515
  this._restoredTcSession = stagedTcSession;
21672
22516
  }
22517
+ this.replicationDelegateSession = compactReplicationSession;
22518
+ this.replicationScopeError = replicationScopeError;
22519
+ if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
21673
22520
  oldGraph.retire();
22521
+ if (replicationScopeError) {
22522
+ stagedGraph.serviceContext.emit("replication.state", {
22523
+ state: "unavailable",
22524
+ code: "SESSION_SCOPE_MISMATCH",
22525
+ detail: replicationScopeError
22526
+ });
22527
+ }
22528
+ await this.bindReplicationRuntime(stagedGraph.serviceContext, serviceSession, stagedGraph.kv, replicationPrincipal);
21674
22529
  oldCore?.retireServices?.();
21675
22530
  }
21676
22531
  stagePrimarySessionState(session, verificationMethod, host, sessionExpiry, recap) {
@@ -21721,7 +22576,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21721
22576
  }
21722
22577
  stageRestoredServiceGraph(input) {
21723
22578
  const graph = this.createServiceGraphLifetime();
21724
- const core = this.auth ? new import_sdk_core8.TinyCloud(this.auth, {
22579
+ const core = this.auth ? new import_sdk_core9.TinyCloud(this.auth, {
21725
22580
  invokeAny: graph.invokeAny,
21726
22581
  telemetry: this.config.telemetry
21727
22582
  }) : null;
@@ -21730,23 +22585,23 @@ var _TinyCloudNode = class _TinyCloudNode {
21730
22585
  const coreContext = graph.track(core.serviceContext);
21731
22586
  coreContext.setSession(input.serviceSession);
21732
22587
  }
21733
- const serviceContext = graph.track(new import_sdk_core8.ServiceContext({
22588
+ const serviceContext = graph.track(new import_sdk_core9.ServiceContext({
21734
22589
  invoke: graph.invoke,
21735
22590
  invokeAny: graph.invokeAny,
21736
22591
  fetch: graph.fetch,
21737
22592
  hosts: [input.host],
21738
22593
  telemetry: this.config.telemetry
21739
22594
  }));
21740
- const kv = new import_sdk_core8.KVService({});
22595
+ const kv = new import_sdk_core9.KVService({});
21741
22596
  kv.initialize(serviceContext);
21742
22597
  serviceContext.registerService("kv", kv);
21743
- const sql = new import_sdk_core8.SQLService({});
22598
+ const sql = new import_sdk_core9.SQLService({});
21744
22599
  sql.initialize(serviceContext);
21745
22600
  serviceContext.registerService("sql", sql);
21746
- const duckdb = new import_sdk_core8.DuckDbService({});
22601
+ const duckdb = new import_sdk_core9.DuckDbService({});
21747
22602
  duckdb.initialize(serviceContext);
21748
22603
  serviceContext.registerService("duckdb", duckdb);
21749
- const hooks = new import_sdk_core8.HooksService({});
22604
+ const hooks = new import_sdk_core9.HooksService({});
21750
22605
  hooks.initialize(serviceContext);
21751
22606
  serviceContext.registerService("hooks", hooks);
21752
22607
  serviceContext.setSession(input.serviceSession);
@@ -21769,7 +22624,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21769
22624
  });
21770
22625
  vault.initialize(serviceContext);
21771
22626
  serviceContext.registerService("vault", vault);
21772
- const capabilityRegistry = new import_sdk_core8.CapabilityKeyRegistry();
22627
+ const capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
21773
22628
  if (input.tinyCloudSession) {
21774
22629
  const session = input.tinyCloudSession;
21775
22630
  const delegations = input.recap.map((entry) => ({
@@ -21793,7 +22648,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21793
22648
  }, delegations);
21794
22649
  }
21795
22650
  }
21796
- const delegationManager = new import_sdk_core8.DelegationManager({
22651
+ const delegationManager = new import_sdk_core9.DelegationManager({
21797
22652
  hosts: [input.host],
21798
22653
  accountSpaceId: input.accountSpaceId,
21799
22654
  session: input.serviceSession,
@@ -21802,7 +22657,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21802
22657
  fetch: graph.fetch
21803
22658
  });
21804
22659
  const keyProvider = new WasmKeyProvider({ sessionManager: input.manager });
21805
- const sharingService = new import_sdk_core8.SharingService({
22660
+ const sharingService = new import_sdk_core9.SharingService({
21806
22661
  hosts: [input.host],
21807
22662
  invoke: graph.invoke,
21808
22663
  fetch: graph.fetch,
@@ -21815,8 +22670,8 @@ var _TinyCloudNode = class _TinyCloudNode {
21815
22670
  return this.wasmBindings.computeCid(data, codec);
21816
22671
  },
21817
22672
  createKVService: (config) => {
21818
- const service = new import_sdk_core8.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
21819
- const context = graph.track(new import_sdk_core8.ServiceContext({
22673
+ const service = new import_sdk_core9.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
22674
+ const context = graph.track(new import_sdk_core9.ServiceContext({
21820
22675
  invoke: config.invoke,
21821
22676
  fetch: config.fetch ?? globalThis.fetch.bind(globalThis),
21822
22677
  hosts: config.hosts,
@@ -21824,6 +22679,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21824
22679
  }));
21825
22680
  context.setSession(config.session);
21826
22681
  service.initialize(context);
22682
+ this.attachReplicationKV(config.session.spaceId, service);
21827
22683
  return service;
21828
22684
  }
21829
22685
  });
@@ -21845,7 +22701,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21845
22701
  return delegation;
21846
22702
  } : void 0
21847
22703
  });
21848
- const spaceService = new import_sdk_core8.SpaceService({
22704
+ const spaceService = new import_sdk_core9.SpaceService({
21849
22705
  hosts: [input.host],
21850
22706
  session: input.serviceSession,
21851
22707
  invoke: graph.invoke,
@@ -21854,8 +22710,8 @@ var _TinyCloudNode = class _TinyCloudNode {
21854
22710
  userDid: input.nodeDid,
21855
22711
  createKVService: (spaceId) => {
21856
22712
  graph.assertActive();
21857
- const scopedKv = new import_sdk_core8.KVService({});
21858
- const context = graph.track(new import_sdk_core8.ServiceContext({
22713
+ const scopedKv = new import_sdk_core9.KVService({});
22714
+ const context = graph.track(new import_sdk_core9.ServiceContext({
21859
22715
  invoke: graph.invoke,
21860
22716
  invokeAny: graph.invokeAny,
21861
22717
  fetch: graph.fetch,
@@ -21864,12 +22720,13 @@ var _TinyCloudNode = class _TinyCloudNode {
21864
22720
  }));
21865
22721
  context.setSession({ ...input.serviceSession, spaceId });
21866
22722
  scopedKv.initialize(context);
22723
+ this.attachReplicationKV(spaceId, scopedKv);
21867
22724
  return scopedKv;
21868
22725
  },
21869
22726
  createVaultService: (spaceId) => {
21870
22727
  graph.assertActive();
21871
- const scopedKv = new import_sdk_core8.KVService({});
21872
- const context = graph.track(new import_sdk_core8.ServiceContext({
22728
+ const scopedKv = new import_sdk_core9.KVService({});
22729
+ const context = graph.track(new import_sdk_core9.ServiceContext({
21873
22730
  invoke: graph.invoke,
21874
22731
  invokeAny: graph.invokeAny,
21875
22732
  fetch: graph.fetch,
@@ -21878,6 +22735,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21878
22735
  }));
21879
22736
  context.setSession({ ...input.serviceSession, spaceId });
21880
22737
  scopedKv.initialize(context);
22738
+ this.attachReplicationKV(spaceId, scopedKv);
21881
22739
  const scopedVault = this.createVaultService(spaceId, scopedKv, encryption, {
21882
22740
  host: input.host,
21883
22741
  did: input.nodeDid,
@@ -21955,7 +22813,7 @@ var _TinyCloudNode = class _TinyCloudNode {
21955
22813
  if (address === void 0 || chainId === void 0) {
21956
22814
  return void 0;
21957
22815
  }
21958
- const resolved = await (0, import_sdk_core8.resolveTinyCloudHosts)((0, import_sdk_core8.pkhDid)(address, chainId), {
22816
+ const resolved = await (0, import_sdk_core9.resolveTinyCloudHosts)((0, import_sdk_core9.pkhDid)(address, chainId), {
21959
22817
  registryUrl: this.config.tinycloudRegistryUrl,
21960
22818
  fallbackHosts: this.config.tinycloudFallbackHosts,
21961
22819
  autoDiscoverLocalNode: this.config.autoDiscoverLocalNode,
@@ -22007,7 +22865,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22007
22865
  nodeAudience: input.nodeAudience,
22008
22866
  ...input.role === "policy-enforcement" ? { enforcerDid: input.audienceDid } : {}
22009
22867
  };
22010
- const root = await (0, import_sdk_core8.signCompactUcanRootAuthorization)({
22868
+ const root = await (0, import_sdk_core9.signCompactUcanRootAuthorization)({
22011
22869
  issuerDid: ownerDid,
22012
22870
  audienceDid: input.audienceDid,
22013
22871
  attenuation: unifiedRootAttenuation(input.capabilities),
@@ -22049,7 +22907,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22049
22907
  if (decision.needsApproval) return void 0;
22050
22908
  throw new Error(decision.reason ?? "OpenKey automatic credential signing was rejected");
22051
22909
  }
22052
- if (typeof decision.signature !== "string" || !await (0, import_sdk_core8.verifyEip191MessageSignature)(
22910
+ if (typeof decision.signature !== "string" || !await (0, import_sdk_core9.verifyEip191MessageSignature)(
22053
22911
  request.message,
22054
22912
  decision.signature,
22055
22913
  request.address
@@ -22074,7 +22932,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22074
22932
  if (approval) {
22075
22933
  const decision = await approval(request);
22076
22934
  if (!decision.approved) throw new Error(decision.reason ?? "Credential signing was rejected");
22077
- if (decision.signature !== void 0 && !await (0, import_sdk_core8.verifyEip191MessageSignature)(
22935
+ if (decision.signature !== void 0 && !await (0, import_sdk_core9.verifyEip191MessageSignature)(
22078
22936
  request.message,
22079
22937
  decision.signature,
22080
22938
  request.address
@@ -22157,10 +23015,15 @@ var _TinyCloudNode = class _TinyCloudNode {
22157
23015
  nonce: this.config.nonce,
22158
23016
  siweConfig: this.config.siweConfig,
22159
23017
  manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
22160
- capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core8.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core8.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
22161
- includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
23018
+ capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core9.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
23019
+ includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions,
23020
+ replication: this.config.replication?.enabled === true ? {
23021
+ enabled: true,
23022
+ prefixes: this.config.replication.prefixes,
23023
+ allowSecrets: this.config.replication.allowSecrets === true
23024
+ } : void 0
22162
23025
  });
22163
- this.tc = new import_sdk_core8.TinyCloud(this.auth, {
23026
+ this.tc = new import_sdk_core9.TinyCloud(this.auth, {
22164
23027
  invokeAny: this.invokeAnyWithRuntimePermissions,
22165
23028
  telemetry: this.config.telemetry
22166
23029
  });
@@ -22210,10 +23073,15 @@ var _TinyCloudNode = class _TinyCloudNode {
22210
23073
  nonce: this.config.nonce,
22211
23074
  siweConfig: this.config.siweConfig,
22212
23075
  manifest: useBootstrapSignInRequest ? void 0 : this.config.manifest,
22213
- capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core8.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core8.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
22214
- includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions
23076
+ capabilityRequest: useBootstrapSignInRequest ? this.config.includeAccountRegistryPermissions === false ? import_sdk_core9.BOOTSTRAP_DEFAULT_ONLY_SESSION_REQUEST : import_sdk_core9.BOOTSTRAP_SESSION_REQUESTS.default : this.config.capabilityRequest,
23077
+ includeAccountRegistryPermissions: useBootstrapSignInRequest ? false : this.config.includeAccountRegistryPermissions,
23078
+ replication: this.config.replication?.enabled === true ? {
23079
+ enabled: true,
23080
+ prefixes: this.config.replication.prefixes,
23081
+ allowSecrets: this.config.replication.allowSecrets === true
23082
+ } : void 0
22215
23083
  });
22216
- this.tc = new import_sdk_core8.TinyCloud(this.auth, {
23084
+ this.tc = new import_sdk_core9.TinyCloud(this.auth, {
22217
23085
  invokeAny: this.invokeAnyWithRuntimePermissions,
22218
23086
  telemetry: this.config.telemetry
22219
23087
  });
@@ -22223,7 +23091,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22223
23091
  * Initialize the service context and KV service after sign-in.
22224
23092
  * @internal
22225
23093
  */
22226
- initializeServices() {
23094
+ async initializeServices() {
22227
23095
  const session = this.currentTinyCloudSession();
22228
23096
  if (!session) {
22229
23097
  return;
@@ -22234,28 +23102,28 @@ var _TinyCloudNode = class _TinyCloudNode {
22234
23102
  this._serviceGraph.fetch
22235
23103
  );
22236
23104
  this._serviceGraph.track(this.tc.serviceContext);
22237
- this._serviceContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
23105
+ this._serviceContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
22238
23106
  invoke: this._serviceGraph.invoke,
22239
23107
  invokeAny: this._serviceGraph.invokeAny,
22240
23108
  fetch: this._serviceGraph.fetch,
22241
23109
  hosts: [this.config.host],
22242
23110
  telemetry: this.config.telemetry
22243
23111
  }));
22244
- this._kv = new import_sdk_core8.KVService({});
23112
+ this._kv = new import_sdk_core9.KVService({});
22245
23113
  this._kv.initialize(this._serviceContext);
22246
23114
  this._serviceContext.registerService("kv", this._kv);
22247
23115
  const features = this.nodeFeatures;
22248
23116
  if (features.length === 0 || features.includes("sql")) {
22249
- this._sql = new import_sdk_core8.SQLService({});
23117
+ this._sql = new import_sdk_core9.SQLService({});
22250
23118
  this._sql.initialize(this._serviceContext);
22251
23119
  this._serviceContext.registerService("sql", this._sql);
22252
23120
  }
22253
23121
  if (features.length === 0 || features.includes("duckdb")) {
22254
- this._duckdb = new import_sdk_core8.DuckDbService({});
23122
+ this._duckdb = new import_sdk_core9.DuckDbService({});
22255
23123
  this._duckdb.initialize(this._serviceContext);
22256
23124
  this._serviceContext.registerService("duckdb", this._duckdb);
22257
23125
  }
22258
- this._hooks = new import_sdk_core8.HooksService({});
23126
+ this._hooks = new import_sdk_core9.HooksService({});
22259
23127
  this._hooks.initialize(this._serviceContext);
22260
23128
  this._serviceContext.registerService("hooks", this._hooks);
22261
23129
  const serviceSession = {
@@ -22266,16 +23134,22 @@ var _TinyCloudNode = class _TinyCloudNode {
22266
23134
  jwk: session.jwk
22267
23135
  };
22268
23136
  this._serviceContext.setSession(serviceSession);
23137
+ await this.bindReplicationRuntime(this._serviceContext, serviceSession, this._kv);
22269
23138
  this.tc.serviceContext.setSession(serviceSession);
22270
23139
  this._vault = this.createVaultService(session.spaceId, this._kv);
22271
23140
  this._vault.initialize(this._serviceContext);
22272
23141
  this._serviceContext.registerService("vault", this._vault);
22273
23142
  this.initializeV2Services(serviceSession);
22274
23143
  }
23144
+ attachReplicationKV(spaceId, kvService) {
23145
+ if (!this.replicationRuntime) return;
23146
+ const attached = this.replicationRuntime.then((runtime) => runtime.attach(spaceId, kvService));
23147
+ kvService.setReadThroughReady(attached);
23148
+ }
22275
23149
  createSpaceScopedKVService(spaceId) {
22276
- const kvService = new import_sdk_core8.KVService({});
23150
+ const kvService = new import_sdk_core9.KVService({});
22277
23151
  if (this._serviceContext) {
22278
- const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
23152
+ const spaceScopedContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
22279
23153
  invoke: this._serviceContext.invoke,
22280
23154
  invokeAny: this._serviceContext.invokeAny,
22281
23155
  fetch: this._serviceContext.fetch,
@@ -22287,6 +23161,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22287
23161
  spaceScopedContext.setSession({ ...session, spaceId });
22288
23162
  }
22289
23163
  kvService.initialize(spaceScopedContext);
23164
+ this.attachReplicationKV(spaceId, kvService);
22290
23165
  }
22291
23166
  return kvService;
22292
23167
  }
@@ -22367,7 +23242,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22367
23242
  const shared = wasm.vault_x25519_dh(receiverPrivateKey, peerPublic);
22368
23243
  return columnDecrypt(shared, ciphertext);
22369
23244
  },
22370
- verifyNodeSignature: (nodeId, message, signature2) => (0, import_sdk_core8.verifyDidKeyEd25519Signature)(nodeId, message, signature2)
23245
+ verifyNodeSignature: (nodeId, message, signature2) => (0, import_sdk_core9.verifyDidKeyEd25519Signature)(nodeId, message, signature2)
22371
23246
  };
22372
23247
  }
22373
23248
  /**
@@ -22383,7 +23258,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22383
23258
  if (cached) return cached;
22384
23259
  const response = await fetch(`${this.config.host}/info`);
22385
23260
  if (!response.ok) {
22386
- throw await (0, import_sdk_core8.httpResponseError)(response, "Failed to fetch node info");
23261
+ throw await (0, import_sdk_core9.httpResponseError)(response, "Failed to fetch node info");
22387
23262
  }
22388
23263
  const info = await response.json();
22389
23264
  if (typeof info.nodeId !== "string" || info.nodeId.length === 0) {
@@ -22433,7 +23308,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22433
23308
  );
22434
23309
  if (response.status === 404) return null;
22435
23310
  if (!response.ok) {
22436
- throw await (0, import_sdk_core8.httpResponseError)(response, `Failed to fetch encryption network ${networkId}`);
23311
+ throw await (0, import_sdk_core9.httpResponseError)(response, `Failed to fetch encryption network ${networkId}`);
22437
23312
  }
22438
23313
  const body = await response.json();
22439
23314
  return "descriptor" in body && body.descriptor ? body.descriptor : body;
@@ -22464,17 +23339,17 @@ var _TinyCloudNode = class _TinyCloudNode {
22464
23339
  );
22465
23340
  graph.assertActive();
22466
23341
  if (!response.ok) {
22467
- const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services.parsePermissionHint)({
23342
+ const permissionHint = response.status === 401 || response.status === 403 ? (0, import_sdk_services3.parsePermissionHint)({
22468
23343
  service: "tinycloud.encryption",
22469
23344
  path: networkId,
22470
23345
  actions: ["tinycloud.encryption/decrypt"]
22471
23346
  }) : void 0;
22472
- throw new import_sdk_core8.DecryptTransportResponseError(response.status, permissionHint);
23347
+ throw new import_sdk_core9.DecryptTransportResponseError(response.status, permissionHint);
22473
23348
  }
22474
23349
  return await response.json();
22475
23350
  }
22476
23351
  };
22477
- return new import_sdk_core8.EncryptionService({
23352
+ return new import_sdk_core9.EncryptionService({
22478
23353
  crypto: crypto3,
22479
23354
  signer: {
22480
23355
  signDecryptInvocation: async (input) => {
@@ -22488,7 +23363,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22488
23363
  graph.assertActive();
22489
23364
  return {
22490
23365
  ...signed2,
22491
- canonicalBody: (0, import_sdk_core8.canonicalizeEncryptionJson)(
23366
+ canonicalBody: (0, import_sdk_core9.canonicalizeEncryptionJson)(
22492
23367
  input.body
22493
23368
  )
22494
23369
  };
@@ -22520,7 +23395,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22520
23395
  if (!address || !didPrincipalMatches2(principal, did)) {
22521
23396
  return null;
22522
23397
  }
22523
- const publicSpaceId = (0, import_sdk_core8.makePublicSpaceId)(address, chainId);
23398
+ const publicSpaceId = (0, import_sdk_core9.makePublicSpaceId)(address, chainId);
22524
23399
  const encodedKey = discoveryKey.split("/").map(encodeURIComponent).join("/");
22525
23400
  const response = await graph.fetch(
22526
23401
  `${host}/public/${encodeURIComponent(publicSpaceId)}/kv/${encodedKey}`,
@@ -22552,7 +23427,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22552
23427
  createVaultService(spaceId, kv, encryptionService = this.getEncryptionService(), nodeContext) {
22553
23428
  const wasm = this.wasmBindings;
22554
23429
  const serviceGraph = nodeContext?.serviceGraph ?? this._serviceGraph;
22555
- const vaultCrypto = (0, import_sdk_core8.createVaultCrypto)({
23430
+ const vaultCrypto = (0, import_sdk_core9.createVaultCrypto)({
22556
23431
  vault_encrypt: wasm.vault_encrypt,
22557
23432
  vault_decrypt: wasm.vault_decrypt,
22558
23433
  vault_derive_key: wasm.vault_derive_key,
@@ -22567,7 +23442,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22567
23442
  const chainId = nodeContext?.chainId ?? this._chainId;
22568
23443
  const host = nodeContext?.host ?? this.config.host;
22569
23444
  const ownerDid = this.ownerDidFromSpaceId(spaceId) ?? did;
22570
- return new import_sdk_core8.DataVaultService({
23445
+ return new import_sdk_core9.DataVaultService({
22571
23446
  spaceId,
22572
23447
  crypto: vaultCrypto,
22573
23448
  encryption: {
@@ -22592,8 +23467,8 @@ var _TinyCloudNode = class _TinyCloudNode {
22592
23467
  serviceGraph.assertActive();
22593
23468
  return self2._publicKV ?? self2.tc.publicKV;
22594
23469
  },
22595
- readPublicSpace: (host2, targetSpaceId, key2) => import_sdk_core8.TinyCloud.readPublicSpace(host2, targetSpaceId, key2),
22596
- makePublicSpaceId: import_sdk_core8.TinyCloud.makePublicSpaceId,
23470
+ readPublicSpace: (host2, targetSpaceId, key2) => import_sdk_core9.TinyCloud.readPublicSpace(host2, targetSpaceId, key2),
23471
+ makePublicSpaceId: import_sdk_core9.TinyCloud.makePublicSpaceId,
22597
23472
  did,
22598
23473
  address: address ?? "",
22599
23474
  chainId,
@@ -22607,7 +23482,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22607
23482
  */
22608
23483
  initializeV2Services(serviceSession) {
22609
23484
  const graph = this._serviceGraph;
22610
- this._capabilityRegistry = new import_sdk_core8.CapabilityKeyRegistry();
23485
+ this._capabilityRegistry = new import_sdk_core9.CapabilityKeyRegistry();
22611
23486
  const tcSession = this.auth?.tinyCloudSession;
22612
23487
  if (tcSession && this._address) {
22613
23488
  const sessionKey = {
@@ -22647,7 +23522,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22647
23522
  }
22648
23523
  this._capabilityRegistry.registerKey(sessionKey, delegations);
22649
23524
  }
22650
- this._delegationManager = new import_sdk_core8.DelegationManager({
23525
+ this._delegationManager = new import_sdk_core9.DelegationManager({
22651
23526
  hosts: [this.config.host],
22652
23527
  accountSpaceId: this.accountSpaceId,
22653
23528
  session: serviceSession,
@@ -22655,7 +23530,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22655
23530
  invokeAny: graph.invokeAny,
22656
23531
  fetch: graph.fetch
22657
23532
  });
22658
- this._spaceService = new import_sdk_core8.SpaceService({
23533
+ this._spaceService = new import_sdk_core9.SpaceService({
22659
23534
  hosts: [this.config.host],
22660
23535
  session: serviceSession,
22661
23536
  invoke: graph.invoke,
@@ -22720,7 +23595,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22720
23595
  await this.account.spaces.register(space);
22721
23596
  }
22722
23597
  });
22723
- this._sharingService = new import_sdk_core8.SharingService({
23598
+ this._sharingService = new import_sdk_core9.SharingService({
22724
23599
  hosts: [this.config.host],
22725
23600
  session: serviceSession,
22726
23601
  invoke: graph.invoke,
@@ -22740,8 +23615,8 @@ var _TinyCloudNode = class _TinyCloudNode {
22740
23615
  },
22741
23616
  createKVService: (config) => {
22742
23617
  graph.assertActive();
22743
- const service = new import_sdk_core8.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
22744
- const context = graph.track(new import_sdk_core8.ServiceContext({
23618
+ const service = new import_sdk_core9.KVService({ prefix: config.pathPrefix?.replace(/\/$/, "") });
23619
+ const context = graph.track(new import_sdk_core9.ServiceContext({
22745
23620
  invoke: config.invoke,
22746
23621
  fetch: config.fetch ?? graph.fetch,
22747
23622
  hosts: config.hosts,
@@ -22749,6 +23624,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22749
23624
  }));
22750
23625
  context.setSession(config.session);
22751
23626
  service.initialize(context);
23627
+ this.attachReplicationKV(config.session.spaceId, service);
22752
23628
  return service;
22753
23629
  },
22754
23630
  onRootDelegationNeeded: this.signer ? async (params) => {
@@ -22834,15 +23710,15 @@ var _TinyCloudNode = class _TinyCloudNode {
22834
23710
  }
22835
23711
  const permissions = ownerDelegationPermissions(params);
22836
23712
  const now = /* @__PURE__ */ new Date();
22837
- if (!(params.expiresAt instanceof Date) || params.expiresAt.getTime() <= now.getTime() || params.expiresAt.getTime() - now.getTime() > import_sdk_core8.EXPIRY.MAX_MS) {
23713
+ if (!(params.expiresAt instanceof Date) || params.expiresAt.getTime() <= now.getTime() || params.expiresAt.getTime() - now.getTime() > import_sdk_core9.EXPIRY.MAX_MS) {
22838
23714
  throw new Error("Owner delegation expiry must be explicit, future, and within EXPIRY.MAX_MS");
22839
23715
  }
22840
23716
  if (!this.signer) throw new Error("Owner wallet signer is required");
22841
23717
  const session = this.currentTinyCloudSession();
22842
23718
  if (!session) throw new Error("Owner session is required");
22843
- const ownerDid = (0, import_sdk_core8.pkhDid)(session.address, session.chainId);
23719
+ const ownerDid = (0, import_sdk_core9.pkhDid)(session.address, session.chainId);
22844
23720
  for (const permission of permissions) {
22845
- if (permission.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE && !(0, import_sdk_core8.principalDidEquals)((0, import_sdk_core8.parseNetworkId)(permission.path).ownerDid, ownerDid)) {
23721
+ if (permission.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE && !(0, import_sdk_core9.principalDidEquals)((0, import_sdk_core9.parseNetworkId)(permission.path).ownerDid, ownerDid)) {
22846
23722
  throw new Error("Owner delegation cannot grant a foreign encryption network");
22847
23723
  }
22848
23724
  }
@@ -22863,7 +23739,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22863
23739
  const signature2 = await this.signer.signMessage(prepared.siwe);
22864
23740
  assertOwnerGraphActive();
22865
23741
  const delegationSession = this.wasmBindings.completeSessionSetup({ ...prepared, signature: signature2 });
22866
- const activation = await (0, import_sdk_core8.activateSessionWithHost)(host, delegationSession.delegationHeader);
23742
+ const activation = await (0, import_sdk_core9.activateSessionWithHost)(host, delegationSession.delegationHeader);
22867
23743
  assertOwnerGraphActive();
22868
23744
  if (!activation.success) {
22869
23745
  throw Object.assign(
@@ -22899,7 +23775,7 @@ var _TinyCloudNode = class _TinyCloudNode {
22899
23775
  /** Register a signed policy and sibling roots with this Node's Policy/v3 runtime. */
22900
23776
  async registerPolicy(params) {
22901
23777
  this._serviceGraph.assertActive();
22902
- return (0, import_sdk_core8.registerPolicyV3)({
23778
+ return (0, import_sdk_core9.registerPolicyV3)({
22903
23779
  ...params,
22904
23780
  nodeOrigin: this.config.host,
22905
23781
  fetch: globalThis.fetch.bind(globalThis)
@@ -22926,23 +23802,23 @@ var _TinyCloudNode = class _TinyCloudNode {
22926
23802
  jti: base64UrlEncode(jtiDigest.slice(0, 16)),
22927
23803
  expiresAt: new Date(input.expiresAt).toISOString().replace(/\.\d{3}Z$/, "Z")
22928
23804
  };
22929
- const requestBodyDigest = base64UrlEncode(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode((0, import_sdk_core8.canonicalizeEncryptionJson)(body)))));
23805
+ const requestBodyDigest = base64UrlEncode(new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode((0, import_sdk_core9.canonicalizeEncryptionJson)(body)))));
22930
23806
  const request = { ...body, requestBodyDigest };
22931
23807
  const authorization = authorizationHeader(this.invokeAnyWithRuntimePermissions(serviceSession, [{ spaceId: session.spaceId, service: "kv", path: input.resourcePath, action: "tinycloud.kv/get" }]));
22932
23808
  const response = await fetch(`${this.config.host}/policy/v3/deliveries/authorize`, {
22933
23809
  method: "POST",
22934
23810
  headers: { accept: "application/json", "content-type": "application/json", authorization },
22935
- body: (0, import_sdk_core8.canonicalizeEncryptionJson)(request)
23811
+ body: (0, import_sdk_core9.canonicalizeEncryptionJson)(request)
22936
23812
  });
22937
- if (!response.ok) throw await (0, import_sdk_core8.httpResponseError)(response, "V3 share delivery authorization failed");
22938
- const verified = (0, import_sdk_core8.validateShareDeliveryAuthorizationV3Bytes)(new Uint8Array(await response.arrayBuffer()), {
23813
+ if (!response.ok) throw await (0, import_sdk_core9.httpResponseError)(response, "V3 share delivery authorization failed");
23814
+ const verified = (0, import_sdk_core9.validateShareDeliveryAuthorizationV3Bytes)(new Uint8Array(await response.arrayBuffer()), {
22939
23815
  request,
22940
23816
  senderKeyDid: this.credentialHolderDid,
22941
23817
  deliveryAudience: input.deliveryAudience
22942
23818
  });
22943
23819
  const requestDigest = new Uint8Array(await crypto.subtle.digest(
22944
23820
  "SHA-256",
22945
- new TextEncoder().encode(`${import_sdk_core8.CREDENTIAL_INVITATION_REQUEST_DOMAIN}${(0, import_sdk_core8.canonicalizeEncryptionJson)(verified.request)}`)
23821
+ new TextEncoder().encode(`${import_sdk_core9.CREDENTIAL_INVITATION_REQUEST_DOMAIN}${(0, import_sdk_core9.canonicalizeEncryptionJson)(verified.request)}`)
22946
23822
  ));
22947
23823
  return {
22948
23824
  ...verified,
@@ -23010,7 +23886,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23010
23886
  if (!this._sql) {
23011
23887
  const features = this.nodeFeatures;
23012
23888
  if (features.length > 0 && !features.includes("sql")) {
23013
- throw new import_sdk_core8.UnsupportedFeatureError("sql", this.config.host, features);
23889
+ throw new import_sdk_core9.UnsupportedFeatureError("sql", this.config.host, features);
23014
23890
  }
23015
23891
  throw new Error("Not signed in. Call signIn() first.");
23016
23892
  }
@@ -23034,8 +23910,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23034
23910
  if (!this._serviceContext || !this._serviceContext.session) {
23035
23911
  throw new Error("Not signed in. Call signIn() first.");
23036
23912
  }
23037
- const sql = new import_sdk_core8.SQLService({});
23038
- const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
23913
+ const sql = new import_sdk_core9.SQLService({});
23914
+ const spaceScopedContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
23039
23915
  invoke: this._serviceContext.invoke,
23040
23916
  invokeAny: this._serviceContext.invokeAny,
23041
23917
  fetch: this._serviceContext.fetch,
@@ -23064,8 +23940,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23064
23940
  if (!this._serviceContext || !this._serviceContext.session) {
23065
23941
  throw new Error("Not signed in. Call signIn() first.");
23066
23942
  }
23067
- const kv = new import_sdk_core8.KVService({});
23068
- const spaceScopedContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
23943
+ const kv = new import_sdk_core9.KVService({});
23944
+ const spaceScopedContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
23069
23945
  invoke: this._serviceContext.invoke,
23070
23946
  invokeAny: this._serviceContext.invokeAny,
23071
23947
  fetch: this._serviceContext.fetch,
@@ -23073,6 +23949,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23073
23949
  }));
23074
23950
  spaceScopedContext.setSession({ ...this._serviceContext.session, spaceId });
23075
23951
  kv.initialize(spaceScopedContext);
23952
+ this.attachReplicationKV(spaceId, kv);
23076
23953
  return kv;
23077
23954
  }
23078
23955
  /**
@@ -23082,7 +23959,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23082
23959
  if (!this._duckdb) {
23083
23960
  const features = this.nodeFeatures;
23084
23961
  if (features.length > 0 && !features.includes("duckdb")) {
23085
- throw new import_sdk_core8.UnsupportedFeatureError("duckdb", this.config.host, features);
23962
+ throw new import_sdk_core9.UnsupportedFeatureError("duckdb", this.config.host, features);
23086
23963
  }
23087
23964
  throw new Error("Not signed in. Call signIn() first.");
23088
23965
  }
@@ -23126,7 +24003,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23126
24003
  type: NETWORK_ADMIN_TYPE,
23127
24004
  targetNode,
23128
24005
  networkId,
23129
- bodyHash: (0, import_sdk_core8.canonicalHashHex)(
24006
+ bodyHash: (0, import_sdk_core9.canonicalHashHex)(
23130
24007
  crypto3.sha256,
23131
24008
  body
23132
24009
  ),
@@ -23144,7 +24021,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23144
24021
  Authorization: signed2.authorization,
23145
24022
  "Content-Type": "application/json"
23146
24023
  },
23147
- body: (0, import_sdk_core8.canonicalizeEncryptionJson)(
24024
+ body: (0, import_sdk_core9.canonicalizeEncryptionJson)(
23148
24025
  body
23149
24026
  )
23150
24027
  });
@@ -23156,7 +24033,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23156
24033
  );
23157
24034
  }
23158
24035
  if (!response.ok) {
23159
- throw await (0, import_sdk_core8.httpResponseError)(response, `Failed to create encryption network ${networkId}`);
24036
+ throw await (0, import_sdk_core9.httpResponseError)(response, `Failed to create encryption network ${networkId}`);
23160
24037
  }
23161
24038
  const created = await response.json();
23162
24039
  return created.descriptor;
@@ -23175,7 +24052,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23175
24052
  return existing;
23176
24053
  }
23177
24054
  }
23178
- const parsed = (0, import_sdk_core8.parseNetworkId)(networkId);
24055
+ const parsed = (0, import_sdk_core9.parseNetworkId)(networkId);
23179
24056
  if (!didPrincipalMatches2(parsed.ownerDid, this.did)) {
23180
24057
  throw new Error(
23181
24058
  `Cannot create encryption network ${networkId}: owner ${parsed.ownerDid} does not match signed-in DID ${this.did}`
@@ -23223,14 +24100,14 @@ var _TinyCloudNode = class _TinyCloudNode {
23223
24100
  * normal KV and encryption invocation paths.
23224
24101
  */
23225
24102
  async readSecret(input) {
23226
- const resolved = (0, import_sdk_core8.resolveSecretPath)(input.name, { scope: input.scope });
24103
+ const resolved = (0, import_sdk_core9.resolveSecretPath)(input.name, { scope: input.scope });
23227
24104
  const targetSpace = input.space.startsWith("tinycloud:") ? input.space : this.ownedSpaceId(input.space);
23228
24105
  const result = await this.getBaseVault(targetSpace).readNetworkEncrypted(
23229
24106
  resolved.vaultKey
23230
24107
  );
23231
24108
  if (result.status !== "ok") {
23232
24109
  if (result.status === "permission_required") {
23233
- const hint = (0, import_sdk_services.parsePermissionHint)(result.hint);
24110
+ const hint = (0, import_sdk_services3.parsePermissionHint)(result.hint);
23234
24111
  if (hint === void 0) return { status: "read_failed" };
23235
24112
  return {
23236
24113
  status: "permission_required",
@@ -23256,7 +24133,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23256
24133
  const resolvedSpace = spaceId.startsWith("tinycloud:") ? spaceId : this.ownedSpaceId(spaceId);
23257
24134
  let secrets = this._baseSecrets.get(resolvedSpace);
23258
24135
  if (!secrets) {
23259
- secrets = new import_sdk_core8.SecretsService(() => this.getBaseVault(resolvedSpace));
24136
+ secrets = new import_sdk_core9.SecretsService(() => this.getBaseVault(resolvedSpace));
23260
24137
  this._baseSecrets.set(resolvedSpace, secrets);
23261
24138
  }
23262
24139
  return secrets;
@@ -23399,7 +24276,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23399
24276
  for (const grant of this.runtimePermissionGrants) {
23400
24277
  if (grant.provenance === "primary") continue;
23401
24278
  for (const operation of grant.operations) {
23402
- const service = import_sdk_core8.SERVICE_SHORT_TO_LONG[operation.service];
24279
+ const service = import_sdk_core9.SERVICE_SHORT_TO_LONG[operation.service];
23403
24280
  if (service === void 0 || typeof operation.path !== "string" || typeof operation.action !== "string") {
23404
24281
  continue;
23405
24282
  }
@@ -23417,7 +24294,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23417
24294
  service,
23418
24295
  ...space === void 0 ? {} : { space },
23419
24296
  path: operation.path,
23420
- caveats: (0, import_sdk_core8.canonicalizeRecapCaveats)(caveats)
24297
+ caveats: (0, import_sdk_core9.canonicalizeRecapCaveats)(caveats)
23421
24298
  });
23422
24299
  const existing = grouped.get(identity);
23423
24300
  if (existing === void 0) {
@@ -23462,7 +24339,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23462
24339
  delegationCid: grant.delegationCid,
23463
24340
  spaceId: grant.spaceId,
23464
24341
  jwk: this.sessionKeyJwk,
23465
- address: (0, import_sdk_core8.canonicalizeAddress)(grant.address),
24342
+ address: (0, import_sdk_core9.canonicalizeAddress)(grant.address),
23466
24343
  chainId: grant.chainId,
23467
24344
  siwe: grant.siwe,
23468
24345
  signature: grant.signature
@@ -23483,10 +24360,10 @@ var _TinyCloudNode = class _TinyCloudNode {
23483
24360
  async useRuntimeDelegation(delegation) {
23484
24361
  const session = this.currentTinyCloudSession();
23485
24362
  if (!session) {
23486
- throw new import_sdk_core8.SessionExpiredError(/* @__PURE__ */ new Date(0));
24363
+ throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
23487
24364
  }
23488
24365
  if (delegation.expiry.getTime() <= Date.now()) {
23489
- throw new import_sdk_core8.SessionExpiredError(delegation.expiry);
24366
+ throw new import_sdk_core9.SessionExpiredError(delegation.expiry);
23490
24367
  }
23491
24368
  const expectedDids = [session.verificationMethod, this.sessionDid];
23492
24369
  if (!expectedDids.some((did) => didPrincipalMatches2(delegation.delegateDID, did))) {
@@ -23495,10 +24372,18 @@ var _TinyCloudNode = class _TinyCloudNode {
23495
24372
  );
23496
24373
  }
23497
24374
  const targetHost = delegation.host ?? this.config.host;
23498
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
23499
- targetHost,
23500
- delegation.delegationHeader
23501
- );
24375
+ let activateResult;
24376
+ try {
24377
+ activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
24378
+ targetHost,
24379
+ delegation.delegationHeader
24380
+ );
24381
+ } catch (cause) {
24382
+ throw Object.assign(
24383
+ new Error("The TinyCloud host could not be reached to activate the delegation."),
24384
+ { code: "ACTIVATION_TRANSPORT_FAILED", cause }
24385
+ );
24386
+ }
23502
24387
  if (!activateResult.success) {
23503
24388
  if (this.operationsFromDelegation(delegation).some(
23504
24389
  (operation) => operation.resource?.startsWith("urn:cid:") === true && operation.service === "delegation" && operation.action === "tinycloud.delegation/revoke"
@@ -23531,13 +24416,13 @@ var _TinyCloudNode = class _TinyCloudNode {
23531
24416
  }
23532
24417
  const session = this.currentTinyCloudSession();
23533
24418
  if (!session) {
23534
- throw new import_sdk_core8.SessionExpiredError(/* @__PURE__ */ new Date(0));
24419
+ throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
23535
24420
  }
23536
24421
  const sessionExpiry = extractSiweExpiration(session.siwe);
23537
24422
  if (sessionExpiry !== void 0) {
23538
24423
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
23539
24424
  if (sessionExpiry.getTime() <= Date.now() + marginMs) {
23540
- throw new import_sdk_core8.SessionExpiredError(sessionExpiry);
24425
+ throw new import_sdk_core9.SessionExpiredError(sessionExpiry);
23541
24426
  }
23542
24427
  }
23543
24428
  const expanded = this.expandPermissionEntries(permissions);
@@ -23613,7 +24498,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23613
24498
  ...prepared,
23614
24499
  signature: signature2
23615
24500
  });
23616
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
24501
+ const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
23617
24502
  this.config.host,
23618
24503
  delegatedSession.delegationHeader
23619
24504
  );
@@ -23786,10 +24671,10 @@ var _TinyCloudNode = class _TinyCloudNode {
23786
24671
  throw new Error("Public space not enabled. Set enablePublicSpace: true in config.");
23787
24672
  }
23788
24673
  await this.auth.hostPublicSpace(publicSpaceId);
23789
- const kvActions = [import_sdk_core8.KV.PUT, import_sdk_core8.KV.GET, import_sdk_core8.KV.DEL, import_sdk_core8.KV.LIST, import_sdk_core8.KV.METADATA];
24674
+ const kvActions = [import_sdk_core9.KV.PUT, import_sdk_core9.KV.GET, import_sdk_core9.KV.DEL, import_sdk_core9.KV.LIST, import_sdk_core9.KV.METADATA];
23790
24675
  const abilities = { kv: { "": kvActions } };
23791
24676
  const now = /* @__PURE__ */ new Date();
23792
- const expiryMs = import_sdk_core8.EXPIRY.EPHEMERAL_MS;
24677
+ const expiryMs = import_sdk_core9.EXPIRY.EPHEMERAL_MS;
23793
24678
  const expirationTime = new Date(now.getTime() + expiryMs);
23794
24679
  const prepared = this.wasmBindings.prepareSession({
23795
24680
  abilities,
@@ -23807,7 +24692,7 @@ var _TinyCloudNode = class _TinyCloudNode {
23807
24692
  ...prepared,
23808
24693
  signature: signature2
23809
24694
  });
23810
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
24695
+ const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
23811
24696
  this.config.host,
23812
24697
  delegationSession.delegationHeader
23813
24698
  );
@@ -23837,8 +24722,8 @@ var _TinyCloudNode = class _TinyCloudNode {
23837
24722
  }]);
23838
24723
  }
23839
24724
  if (this._serviceContext) {
23840
- const publicKV = new import_sdk_core8.KVService({ prefix: "" });
23841
- const publicContext = this._serviceGraph.track(new import_sdk_core8.ServiceContext({
24725
+ const publicKV = new import_sdk_core9.KVService({ prefix: "" });
24726
+ const publicContext = this._serviceGraph.track(new import_sdk_core9.ServiceContext({
23842
24727
  invoke: this._serviceGraph.invoke,
23843
24728
  fetch: this._serviceGraph.fetch,
23844
24729
  hosts: this._serviceContext.hosts,
@@ -23990,14 +24875,14 @@ var _TinyCloudNode = class _TinyCloudNode {
23990
24875
  }
23991
24876
  const session = this.currentTinyCloudSession();
23992
24877
  if (!session) {
23993
- throw new import_sdk_core8.SessionExpiredError(/* @__PURE__ */ new Date(0));
24878
+ throw new import_sdk_core9.SessionExpiredError(/* @__PURE__ */ new Date(0));
23994
24879
  }
23995
24880
  const sessionExpiry = extractSiweExpiration(session.siwe);
23996
24881
  if (sessionExpiry !== void 0) {
23997
24882
  const now2 = Date.now();
23998
24883
  const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
23999
24884
  if (sessionExpiry.getTime() <= now2 + marginMs) {
24000
- throw new import_sdk_core8.SessionExpiredError(sessionExpiry);
24885
+ throw new import_sdk_core9.SessionExpiredError(sessionExpiry);
24001
24886
  }
24002
24887
  }
24003
24888
  if (!Array.isArray(permissions) || permissions.length === 0) {
@@ -24027,31 +24912,31 @@ var _TinyCloudNode = class _TinyCloudNode {
24027
24912
  );
24028
24913
  return { delegation: delegation2, prompted: true };
24029
24914
  }
24030
- const granted = this.projectSignedRecapCapabilities(session.siwe);
24031
- const { subset, missing } = this.signedCapabilitySubset(expandedEntries, granted);
24032
- if (!subset) {
24033
- const runtimeOperations = this.permissionEntriesToOperations(expandedEntries, session);
24034
- const runtimeGrant = this.findGrantForOperations(
24035
- runtimeOperations,
24036
- { excludePrimary: true }
24037
- );
24038
- if (runtimeGrant) {
24039
- const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
24040
- if (runtimeGrant.expiresAt.getTime() <= Date.now() + marginMs) {
24041
- throw new import_sdk_core8.SessionExpiredError(runtimeGrant.expiresAt);
24042
- }
24043
- const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
24044
- const delegation2 = await this.createDelegationViaRuntimeGrant(
24045
- did,
24046
- expandedEntries,
24047
- runtimeExpiration,
24048
- runtimeGrant,
24049
- runtimeOperations,
24050
- onPrepared
24051
- );
24052
- return { delegation: delegation2, prompted: false };
24915
+ const plan = this.planDerivation(
24916
+ expandedEntries,
24917
+ session,
24918
+ effectiveExpiration,
24919
+ Date.now()
24920
+ );
24921
+ if ("refused" in plan) {
24922
+ if (plan.refused === "SESSION_EXPIRING") {
24923
+ throw new import_sdk_core9.SessionExpiredError(plan.expiredAt ?? sessionExpiry ?? /* @__PURE__ */ new Date(0));
24053
24924
  }
24054
- throw new import_sdk_core8.PermissionNotInManifestError(missing, granted);
24925
+ if (plan.refused === "CAVEATED_AUTHORITY") {
24926
+ throw new import_sdk_core9.CaveatedDelegationUnsupportedError(plan.caveated ?? []);
24927
+ }
24928
+ throw new import_sdk_core9.PermissionNotInManifestError(plan.missing ?? [], plan.granted ?? []);
24929
+ }
24930
+ if (plan.path === "runtime") {
24931
+ const delegation2 = await this.createDelegationViaRuntimeGrant(
24932
+ did,
24933
+ expandedEntries,
24934
+ plan.effectiveExpiration,
24935
+ plan.grant,
24936
+ plan.operations,
24937
+ onPrepared
24938
+ );
24939
+ return { delegation: delegation2, prompted: false };
24055
24940
  }
24056
24941
  const delegation = await this.createDelegationViaWasmPath(
24057
24942
  did,
@@ -24062,6 +24947,149 @@ var _TinyCloudNode = class _TinyCloudNode {
24062
24947
  );
24063
24948
  return { delegation, prompted: false };
24064
24949
  }
24950
+ /**
24951
+ * What `delegateTo` would select for `entries`, without signing or any
24952
+ * network call (TC-858 plan v3 §4.3): the session path when the signed
24953
+ * recap covers every entry, the runtime-grant path otherwise, or a
24954
+ * refusal. A refusal of `CAVEATED_AUTHORITY` means coverage exists only
24955
+ * through caveated branches, which the action-only WASM child-delegation
24956
+ * boundary cannot preserve — replication never derives authority through
24957
+ * them. `expiredAt`/`missing`/`granted`/`caveated` carry the payload
24958
+ * `delegateTo` turns back into its typed errors.
24959
+ * @internal
24960
+ */
24961
+ planDerivation(expandedEntries, session, effectiveExpiration, nowMs) {
24962
+ const caveatedRequest = expandedEntries.filter(
24963
+ (entry) => !(0, import_sdk_core9.recapCaveatsEqual)(entry.caveats, void 0)
24964
+ );
24965
+ if (caveatedRequest.length > 0) {
24966
+ return { refused: "CAVEATED_AUTHORITY", caveated: caveatedRequest };
24967
+ }
24968
+ const granted = this.projectSignedRecapCapabilities(session.siwe);
24969
+ const { subset, missing } = this.signedCapabilitySubset(expandedEntries, granted);
24970
+ if (subset) {
24971
+ return {
24972
+ path: "session",
24973
+ parentCid: session.delegationCid,
24974
+ expiresAt: effectiveExpiration.getTime(),
24975
+ effectiveExpiration
24976
+ };
24977
+ }
24978
+ const runtimeOperations = this.permissionEntriesToOperations(expandedEntries, session);
24979
+ const runtimeGrant = this.findGrantForOperations(
24980
+ runtimeOperations,
24981
+ { excludePrimary: true }
24982
+ );
24983
+ if (runtimeGrant) {
24984
+ const marginMs = _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS;
24985
+ if (runtimeGrant.expiresAt.getTime() <= nowMs + marginMs) {
24986
+ return { refused: "SESSION_EXPIRING", expiredAt: runtimeGrant.expiresAt };
24987
+ }
24988
+ const caveated = this.caveatedRuntimeGrantEntries(
24989
+ expandedEntries,
24990
+ runtimeOperations,
24991
+ runtimeGrant
24992
+ );
24993
+ if (caveated.length > 0) {
24994
+ return { refused: "CAVEATED_AUTHORITY", caveated };
24995
+ }
24996
+ const runtimeExpiration = runtimeGrant.expiresAt < effectiveExpiration ? runtimeGrant.expiresAt : effectiveExpiration;
24997
+ return {
24998
+ path: "runtime",
24999
+ parentCid: runtimeGrant.session.delegationCid,
25000
+ expiresAt: runtimeExpiration.getTime(),
25001
+ effectiveExpiration: runtimeExpiration,
25002
+ grant: runtimeGrant,
25003
+ operations: runtimeOperations
25004
+ };
25005
+ }
25006
+ const relaxedGranted = granted.map((entry) => ({ ...entry, caveats: void 0 }));
25007
+ const relaxedRequested = expandedEntries.map((entry) => ({ ...entry, caveats: void 0 }));
25008
+ const relaxed = this.signedCapabilitySubset(relaxedRequested, relaxedGranted);
25009
+ if (relaxed.subset) {
25010
+ return {
25011
+ refused: "CAVEATED_AUTHORITY",
25012
+ caveated: missing.map((entry) => ({ ...entry, caveats: [{ via: "session-recap" }] }))
25013
+ };
25014
+ }
25015
+ return { refused: "NOT_COVERED", missing, granted };
25016
+ }
25017
+ /**
25018
+ * The plan `delegateTo(device, entries)` would follow, as a pure lookup:
25019
+ * no WASM sign and no `POST /delegate`. Backs
25020
+ * `ReplicationAuthority.plan` (and `mint` inside it) so a predicted
25021
+ * parent and expiry can never disagree with what a mint would use (§4.3,
25022
+ * §4.4). Session expiry inside the 60 s margin refuses with
25023
+ * `SESSION_EXPIRING`; the same check delegateTo performs.
25024
+ * @internal
25025
+ */
25026
+ planDelegation(entries, options) {
25027
+ if (!Array.isArray(entries) || entries.length === 0) {
25028
+ throw new Error("planDelegation requires a non-empty permissions array");
25029
+ }
25030
+ const session = this.currentTinyCloudSession();
25031
+ if (!session) {
25032
+ return { refused: "SESSION_EXPIRING", expiredAt: /* @__PURE__ */ new Date(0) };
25033
+ }
25034
+ const nowMs = Date.now();
25035
+ const sessionExpiry = extractSiweExpiration(session.siwe);
25036
+ if (sessionExpiry !== void 0 && sessionExpiry.getTime() <= nowMs + _TinyCloudNode.SESSION_EXPIRY_SAFETY_MARGIN_MS) {
25037
+ return { refused: "SESSION_EXPIRING", expiredAt: sessionExpiry };
25038
+ }
25039
+ const expandedEntries = this.expandPermissionEntries(entries);
25040
+ const expiryMs = resolveExpiryMs(options?.expiry);
25041
+ const expirationTime = new Date(nowMs + expiryMs);
25042
+ const effectiveExpiration = sessionExpiry !== void 0 && sessionExpiry < expirationTime ? sessionExpiry : expirationTime;
25043
+ return this.planDerivation(expandedEntries, session, effectiveExpiration, nowMs);
25044
+ }
25045
+ /**
25046
+ * The replication entries this node's sign-in request carries for the
25047
+ * current replication config and the signed-in or restored address: the
25048
+ * output of the same augmentation step `resolveSignInCapabilities` runs,
25049
+ * with the unrestricted-get and secrets gates applied (§4.1, §4.6).
25050
+ * Empty when replication is off or no address is known. Pure.
25051
+ */
25052
+ replicationSignInEntries() {
25053
+ if (this.config.replication?.enabled !== true) return [];
25054
+ const auth = this.auth;
25055
+ if (auth === void 0 || typeof auth.replicationSignInEntries !== "function") {
25056
+ return [];
25057
+ }
25058
+ return auth.replicationSignInEntries();
25059
+ }
25060
+ async replicationAuthority() {
25061
+ const { createReplicationAuthority: createReplicationAuthority2 } = await getNodeReplicationLoaders().authority();
25062
+ return createReplicationAuthority2({
25063
+ replicationSession: () => this.currentTinyCloudSession() ?? this.replicationDelegateSession,
25064
+ siweExpiration: (siwe) => extractSiweExpiration(siwe),
25065
+ planDelegation: (entries, options) => this.planDelegation(entries, options),
25066
+ mintDelegation: async (deviceDid, entries) => {
25067
+ const result = await this.delegateTo((0, import_sdk_core9.principalDid)(deviceDid), entries);
25068
+ return {
25069
+ ucan: result.delegation.delegationHeader.Authorization,
25070
+ expiresAt: result.delegation.expiry.getTime()
25071
+ };
25072
+ }
25073
+ });
25074
+ }
25075
+ async bindReplicationRuntime(context, session, kv, principal) {
25076
+ if (!this.replicationRuntime) return;
25077
+ const identityPrincipal = principal ?? (this._address === void 0 ? void 0 : (0, import_sdk_core9.pkhDid)(this._address, this._chainId));
25078
+ if (identityPrincipal === void 0) return;
25079
+ const runtime = await this.replicationRuntime;
25080
+ const authority = await this.replicationAuthority();
25081
+ await runtime.bind({
25082
+ context,
25083
+ session,
25084
+ principal: identityPrincipal,
25085
+ authority,
25086
+ primaryKV: [{ space: session.spaceId, kv }]
25087
+ });
25088
+ }
25089
+ /** Stable control facade for this node's optional replication runtime. */
25090
+ get replication() {
25091
+ return this.replicationControl;
25092
+ }
24065
25093
  /**
24066
25094
  * Materialize one manifest-declared delegation using the current session key.
24067
25095
  * Delivery is intentionally out of band; callers decide how to transmit the
@@ -24135,7 +25163,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24135
25163
  const spaceId = resolvedSpaces.size === 1 ? [...resolvedSpaces][0] : session.spaceId;
24136
25164
  const abilities = {};
24137
25165
  for (const entry of entries) {
24138
- const shortService = import_sdk_core8.SERVICE_LONG_TO_SHORT[entry.service];
25166
+ const shortService = import_sdk_core9.SERVICE_LONG_TO_SHORT[entry.service];
24139
25167
  if (shortService === void 0) {
24140
25168
  throw new Error(
24141
25169
  `delegateTo: unknown service '${entry.service}' \u2014 no short-form mapping`
@@ -24192,7 +25220,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24192
25220
  if (onPrepared) {
24193
25221
  await onPrepared(delegation);
24194
25222
  }
24195
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
25223
+ const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
24196
25224
  this.config.host,
24197
25225
  delegationHeader
24198
25226
  );
@@ -24234,7 +25262,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24234
25262
  if (onPrepared) {
24235
25263
  await onPrepared(delegation);
24236
25264
  }
24237
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
25265
+ const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
24238
25266
  targetHost,
24239
25267
  delegationHeader
24240
25268
  );
@@ -24263,7 +25291,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24263
25291
  return this.wasmBindings.makeSpaceId(session.address, session.chainId, space);
24264
25292
  }
24265
25293
  expandPermissionEntries(permissions) {
24266
- return (0, import_sdk_core8.expandPermissionEntries)(permissions);
25294
+ return (0, import_sdk_core9.expandPermissionEntries)(permissions);
24267
25295
  }
24268
25296
  /**
24269
25297
  * The current WASM child-delegation APIs accept action-only maps. Refuse any
@@ -24271,10 +25299,10 @@ var _TinyCloudNode = class _TinyCloudNode {
24271
25299
  */
24272
25300
  assertDelegationCaveatsPreservable(entries) {
24273
25301
  const caveated = entries.filter(
24274
- (entry) => !(0, import_sdk_core8.recapCaveatsEqual)(entry.caveats, void 0)
25302
+ (entry) => !(0, import_sdk_core9.recapCaveatsEqual)(entry.caveats, void 0)
24275
25303
  );
24276
25304
  if (caveated.length > 0) {
24277
- throw new import_sdk_core8.CaveatedDelegationUnsupportedError(caveated);
25305
+ throw new import_sdk_core9.CaveatedDelegationUnsupportedError(caveated);
24278
25306
  }
24279
25307
  }
24280
25308
  /**
@@ -24284,6 +25312,18 @@ var _TinyCloudNode = class _TinyCloudNode {
24284
25312
  * it only accepts action maps, so reject the selected constrained branch.
24285
25313
  */
24286
25314
  assertRuntimeGrantCaveatsPreservable(entries, requestedOperations, grant) {
25315
+ const caveated = this.caveatedRuntimeGrantEntries(entries, requestedOperations, grant);
25316
+ if (caveated.length > 0) {
25317
+ throw new import_sdk_core9.CaveatedDelegationUnsupportedError(caveated);
25318
+ }
25319
+ }
25320
+ /**
25321
+ * The entries of `grant` that cover a requested operation while carrying
25322
+ * caveats — the branches {@link assertRuntimeGrantCaveatsPreservable}
25323
+ * rejects and {@link planDerivation} classifies as `CAVEATED_AUTHORITY`.
25324
+ * Shared so the pure plan and the mint path can't disagree.
25325
+ */
25326
+ caveatedRuntimeGrantEntries(entries, requestedOperations, grant) {
24287
25327
  let operationIndex = 0;
24288
25328
  const caveated = [];
24289
25329
  for (const entry of entries) {
@@ -24291,7 +25331,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24291
25331
  const requested = requestedOperations[operationIndex++];
24292
25332
  if (!requested) continue;
24293
25333
  const constrained = grant.operations.find(
24294
- (granted) => this.operationCovers(granted, requested) && !(0, import_sdk_core8.recapCaveatsEqual)(granted.caveats, void 0)
25334
+ (granted) => this.operationCovers(granted, requested) && !(0, import_sdk_core9.recapCaveatsEqual)(granted.caveats, void 0)
24295
25335
  );
24296
25336
  if (constrained) {
24297
25337
  caveated.push({
@@ -24302,15 +25342,13 @@ var _TinyCloudNode = class _TinyCloudNode {
24302
25342
  }
24303
25343
  }
24304
25344
  }
24305
- if (caveated.length > 0) {
24306
- throw new import_sdk_core8.CaveatedDelegationUnsupportedError(caveated);
24307
- }
25345
+ return caveated;
24308
25346
  }
24309
25347
  /** Reject caveated parent branches before action-only child signing. */
24310
25348
  assertPortableDelegationCaveatsPreservable(delegation) {
24311
25349
  const entries = [];
24312
25350
  const add3 = (service, space, path, actions, caveats) => {
24313
- if ((0, import_sdk_core8.recapCaveatsEqual)(caveats, void 0)) return;
25351
+ if ((0, import_sdk_core9.recapCaveatsEqual)(caveats, void 0)) return;
24314
25352
  entries.push({
24315
25353
  service: service.startsWith("tinycloud.") ? service : `tinycloud.${service}`,
24316
25354
  space,
@@ -24330,11 +25368,11 @@ var _TinyCloudNode = class _TinyCloudNode {
24330
25368
  add3(resource.service, resource.space, resource.path, resource.actions, resource.caveats);
24331
25369
  }
24332
25370
  if (entries.length > 0) {
24333
- throw new import_sdk_core8.CaveatedDelegationUnsupportedError(entries);
25371
+ throw new import_sdk_core9.CaveatedDelegationUnsupportedError(entries);
24334
25372
  }
24335
25373
  }
24336
25374
  shortServiceName(service) {
24337
- const short = import_sdk_core8.SERVICE_LONG_TO_SHORT[service];
25375
+ const short = import_sdk_core9.SERVICE_LONG_TO_SHORT[service];
24338
25376
  if (short === void 0) {
24339
25377
  throw new Error(
24340
25378
  `unknown service '${service}' \u2014 no short-form mapping`
@@ -24361,7 +25399,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24361
25399
  return abilities;
24362
25400
  }
24363
25401
  isEncryptionPermissionEntry(entry) {
24364
- return entry.service === import_sdk_core8.ENCRYPTION_PERMISSION_SERVICE && this.isEncryptionNetworkOperation("encryption", entry.path, entry.space);
25402
+ return entry.service === import_sdk_core9.ENCRYPTION_PERMISSION_SERVICE && this.isEncryptionNetworkOperation("encryption", entry.path, entry.space);
24365
25403
  }
24366
25404
  isRawRevocationPermissionEntry(entry) {
24367
25405
  return entry.service === "tinycloud.delegation" && entry.path === "" && entry.space?.startsWith("urn:cid:") === true && entry.actions.includes("tinycloud.delegation/revoke");
@@ -24409,7 +25447,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24409
25447
  const missing = requested.filter((entry) => {
24410
25448
  const raw = this.isEncryptionPermissionEntry(entry) || this.isRawRevocationPermissionEntry(entry);
24411
25449
  const comparable = raw && this.isEncryptionPermissionEntry(entry) ? { ...entry, space: "encryption" } : entry;
24412
- return !(0, import_sdk_core8.isCapabilitySubset)([comparable], raw ? rawGranted : spaceGranted).subset;
25450
+ return !(0, import_sdk_core9.isCapabilitySubset)([comparable], raw ? rawGranted : spaceGranted).subset;
24413
25451
  });
24414
25452
  return { subset: missing.length === 0, missing };
24415
25453
  }
@@ -24645,7 +25683,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24645
25683
  if (granted.service !== requested.service || !this.actionContains(granted.action, requested.action)) {
24646
25684
  return false;
24647
25685
  }
24648
- if (requested.caveats !== void 0 && !(0, import_sdk_core8.recapCaveatsEqual)(granted.caveats, requested.caveats)) {
25686
+ if (requested.caveats !== void 0 && !(0, import_sdk_core9.recapCaveatsEqual)(granted.caveats, requested.caveats)) {
24649
25687
  return false;
24650
25688
  }
24651
25689
  if (granted.resource !== void 0 || requested.resource !== void 0) {
@@ -24667,7 +25705,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24667
25705
  if (grantedAction === requestedAction) {
24668
25706
  return true;
24669
25707
  }
24670
- if ((0, import_sdk_core8.isExplicitOnlyAction)(requestedAction)) {
25708
+ if ((0, import_sdk_core9.isExplicitOnlyAction)(requestedAction)) {
24671
25709
  return false;
24672
25710
  }
24673
25711
  if (grantedAction.endsWith("/*")) {
@@ -24779,7 +25817,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24779
25817
  if (resolvedDelegateDID.endsWith(".eth") && this.config.ensResolver) {
24780
25818
  const address = await this.config.ensResolver.resolveAddress(resolvedDelegateDID);
24781
25819
  if (!address) throw new Error(`Could not resolve ENS name: ${resolvedDelegateDID}`);
24782
- resolvedDelegateDID = (0, import_sdk_core8.pkhDid)(address, 1);
25820
+ resolvedDelegateDID = (0, import_sdk_core9.pkhDid)(address, 1);
24783
25821
  }
24784
25822
  const entries = legacyParamsToPermissionEntries(
24785
25823
  params.actions,
@@ -24794,7 +25832,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24794
25832
  );
24795
25833
  return result.delegation;
24796
25834
  } catch (err) {
24797
- if (err instanceof import_sdk_core8.PermissionNotInManifestError) {
25835
+ if (err instanceof import_sdk_core9.PermissionNotInManifestError) {
24798
25836
  } else {
24799
25837
  throw err;
24800
25838
  }
@@ -24851,7 +25889,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24851
25889
  ...prepared,
24852
25890
  signature: signature2
24853
25891
  });
24854
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
25892
+ const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
24855
25893
  this.config.host,
24856
25894
  delegationSession.delegationHeader
24857
25895
  );
@@ -24876,12 +25914,12 @@ var _TinyCloudNode = class _TinyCloudNode {
24876
25914
  };
24877
25915
  const hasKvActions = params.actions.some((a) => a.startsWith("tinycloud.kv/"));
24878
25916
  if (hasKvActions && params.includePublicSpace !== false) {
24879
- const publicSpaceId = (0, import_sdk_core8.makePublicSpaceId)(
25917
+ const publicSpaceId = (0, import_sdk_core9.makePublicSpaceId)(
24880
25918
  this.wasmBindings.ensureEip55(session.address),
24881
25919
  session.chainId
24882
25920
  );
24883
25921
  const publicAbilities = {
24884
- kv: { "": [import_sdk_core8.KV.GET, import_sdk_core8.KV.PUT, import_sdk_core8.KV.METADATA] }
25922
+ kv: { "": [import_sdk_core9.KV.GET, import_sdk_core9.KV.PUT, import_sdk_core9.KV.METADATA] }
24885
25923
  };
24886
25924
  const publicPrepared = this.wasmBindings.prepareSession({
24887
25925
  abilities: publicAbilities,
@@ -24899,7 +25937,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24899
25937
  ...publicPrepared,
24900
25938
  signature: publicSignature
24901
25939
  });
24902
- const publicActivateResult = await (0, import_sdk_core8.activateSessionWithHost)(
25940
+ const publicActivateResult = await (0, import_sdk_core9.activateSessionWithHost)(
24903
25941
  this.config.host,
24904
25942
  publicSession.delegationHeader
24905
25943
  );
@@ -24909,7 +25947,7 @@ var _TinyCloudNode = class _TinyCloudNode {
24909
25947
  delegationHeader: publicSession.delegationHeader,
24910
25948
  spaceId: publicSpaceId,
24911
25949
  path: "",
24912
- actions: [import_sdk_core8.KV.GET, import_sdk_core8.KV.PUT, import_sdk_core8.KV.METADATA],
25950
+ actions: [import_sdk_core9.KV.GET, import_sdk_core9.KV.PUT, import_sdk_core9.KV.METADATA],
24913
25951
  disableSubDelegation: params.disableSubDelegation ?? false,
24914
25952
  expiry: expirationTime,
24915
25953
  delegateDID: params.delegateDID,
@@ -25004,7 +26042,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25004
26042
  ...prepared,
25005
26043
  signature: signature2
25006
26044
  });
25007
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
26045
+ const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
25008
26046
  targetHost,
25009
26047
  invokerSession.delegationHeader
25010
26048
  );
@@ -25124,7 +26162,7 @@ var _TinyCloudNode = class _TinyCloudNode {
25124
26162
  ...prepared,
25125
26163
  signature: signature2
25126
26164
  });
25127
- const activateResult = await (0, import_sdk_core8.activateSessionWithHost)(
26165
+ const activateResult = await (0, import_sdk_core9.activateSessionWithHost)(
25128
26166
  targetHost,
25129
26167
  subDelegationSession.delegationHeader
25130
26168
  );
@@ -25174,12 +26212,18 @@ TinyCloudNode.registerNodeDefaults({
25174
26212
  createSigner: (privateKey, chainId) => new PrivateKeySigner(privateKey, chainId)
25175
26213
  });
25176
26214
 
26215
+ // src/replication/node-loader.ts
26216
+ registerReplicationLoaders({
26217
+ runtime: () => Promise.resolve().then(() => (init_runtime(), runtime_exports)),
26218
+ authority: () => Promise.resolve().then(() => (init_authority(), authority_exports))
26219
+ });
26220
+
25177
26221
  // src/index.ts
25178
- var import_sdk_core10 = require("@tinycloud/sdk-core");
25179
- var import_sdk_core11 = require("@tinycloud/sdk-core");
26222
+ var import_sdk_core14 = require("@tinycloud/sdk-core");
26223
+ var import_sdk_core15 = require("@tinycloud/sdk-core");
25180
26224
 
25181
26225
  // src/storage/FileSessionStorage.ts
25182
- var import_sdk_core9 = require("@tinycloud/sdk-core");
26226
+ var import_sdk_core12 = require("@tinycloud/sdk-core");
25183
26227
  var import_fs = require("fs");
25184
26228
  var import_path = require("path");
25185
26229
  var FileSessionStorage = class {
@@ -25234,7 +26278,7 @@ var FileSessionStorage = class {
25234
26278
  try {
25235
26279
  const data = (0, import_fs.readFileSync)(filePath, "utf-8");
25236
26280
  const parsed = JSON.parse(data);
25237
- const validation = (0, import_sdk_core9.validatePersistedSessionData)(parsed);
26281
+ const validation = (0, import_sdk_core12.validatePersistedSessionData)(parsed);
25238
26282
  if (!validation.ok) {
25239
26283
  console.warn(`Invalid session data for ${address}:`, validation.error.message);
25240
26284
  (0, import_fs.unlinkSync)(filePath);
@@ -25343,10 +26387,6 @@ function wireOpenKeyAuthorize(openkey) {
25343
26387
  }
25344
26388
 
25345
26389
  // src/index.ts
25346
- var import_sdk_core12 = require("@tinycloud/sdk-core");
25347
- var import_sdk_core13 = require("@tinycloud/sdk-core");
25348
- var import_sdk_core14 = require("@tinycloud/sdk-core");
25349
- var import_sdk_core15 = require("@tinycloud/sdk-core");
25350
26390
  var import_sdk_core16 = require("@tinycloud/sdk-core");
25351
26391
  var import_sdk_core17 = require("@tinycloud/sdk-core");
25352
26392
  var import_sdk_core18 = require("@tinycloud/sdk-core");
@@ -25355,6 +26395,848 @@ var import_sdk_core20 = require("@tinycloud/sdk-core");
25355
26395
  var import_sdk_core21 = require("@tinycloud/sdk-core");
25356
26396
  var import_sdk_core22 = require("@tinycloud/sdk-core");
25357
26397
  var import_sdk_core23 = require("@tinycloud/sdk-core");
26398
+ var import_sdk_core24 = require("@tinycloud/sdk-core");
26399
+ var import_sdk_core25 = require("@tinycloud/sdk-core");
26400
+ var import_sdk_core26 = require("@tinycloud/sdk-core");
26401
+ var import_sdk_core27 = require("@tinycloud/sdk-core");
26402
+
26403
+ // src/replication/sqlite.ts
26404
+ var import_node_crypto2 = require("crypto");
26405
+ var import_promises = require("fs/promises");
26406
+ var import_node_path = require("path");
26407
+ var import_sdk_core13 = require("@tinycloud/sdk-core");
26408
+ var import_sdk_services4 = require("@tinycloud/sdk-services");
26409
+ init_authority();
26410
+ var ReplicaStorageError = class extends Error {
26411
+ constructor(code, message, options) {
26412
+ super(message);
26413
+ this.name = "ReplicaStorageError";
26414
+ this.code = code;
26415
+ this.cause = options?.cause;
26416
+ }
26417
+ };
26418
+ function storageError(code, action, error) {
26419
+ if (error instanceof ReplicaStorageError) return error;
26420
+ const detail = error instanceof Error ? error.message : String(error);
26421
+ return new ReplicaStorageError(code, `${action} failed: ${detail}`, { cause: error });
26422
+ }
26423
+ function isNotFound(error) {
26424
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
26425
+ }
26426
+ async function pathExists(path) {
26427
+ try {
26428
+ await (0, import_promises.stat)(path);
26429
+ return true;
26430
+ } catch (error) {
26431
+ if (isNotFound(error)) return false;
26432
+ throw storageError("STORAGE_ERROR", `Reading ${path}`, error);
26433
+ }
26434
+ }
26435
+ function principalOf(did) {
26436
+ return (0, import_sdk_core13.principalDid)(did);
26437
+ }
26438
+ var BASE32 = "abcdefghijklmnopqrstuvwxyz234567";
26439
+ function sha256Base32(material) {
26440
+ const digest = (0, import_node_crypto2.createHash)("sha256").update(material, "utf8").digest();
26441
+ let out = "";
26442
+ let buffer = 0;
26443
+ let bits = 0;
26444
+ for (const byte of digest) {
26445
+ buffer = buffer << 8 | byte;
26446
+ bits += 8;
26447
+ while (bits >= 5) {
26448
+ out += BASE32[buffer >>> bits - 5 & 31];
26449
+ bits -= 5;
26450
+ }
26451
+ }
26452
+ if (bits > 0) out += BASE32[buffer << 5 - bits & 31];
26453
+ return out.slice(0, 26);
26454
+ }
26455
+ function partitionDirOf(root, identity) {
26456
+ return (0, import_node_path.join)(root, sha256Base32((0, import_sdk_services4.replicationIdentityKey)(identity)));
26457
+ }
26458
+ function replicaHashOf(prefix, deviceDid) {
26459
+ return sha256Base32(`${prefix}
26460
+ ${principalOf(deviceDid)}`);
26461
+ }
26462
+ async function writeJsonAtomic(path, value, dirSync = fsyncDir) {
26463
+ const tmp = `${path}.${(0, import_node_crypto2.randomBytes)(6).toString("hex")}.tmp`;
26464
+ let handle;
26465
+ try {
26466
+ handle = await (0, import_promises.open)(tmp, "w", 384);
26467
+ await handle.writeFile(JSON.stringify(value), "utf8");
26468
+ await handle.sync();
26469
+ await handle.close();
26470
+ await (0, import_promises.rename)(tmp, path);
26471
+ await dirSync((0, import_node_path.dirname)(path));
26472
+ await (0, import_promises.chmod)(path, 384).catch(() => void 0);
26473
+ } catch (error) {
26474
+ try {
26475
+ await handle?.close();
26476
+ } catch {
26477
+ }
26478
+ await (0, import_promises.rm)(tmp, { force: true }).catch(() => void 0);
26479
+ throw storageError("STORAGE_ERROR", `Writing ${path}`, error);
26480
+ }
26481
+ }
26482
+ var DIR_SYNC_UNSUPPORTED = {
26483
+ ENOTSUP: true,
26484
+ ENOSYS: true,
26485
+ EINVAL: true,
26486
+ EISDIR: true,
26487
+ EPERM: true
26488
+ };
26489
+ async function fsyncDir(dir) {
26490
+ let handle;
26491
+ try {
26492
+ handle = await (0, import_promises.open)(dir, "r");
26493
+ await handle.sync();
26494
+ } catch (error) {
26495
+ const code = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
26496
+ if (typeof code === "string" && DIR_SYNC_UNSUPPORTED[code] === true) return;
26497
+ throw storageError("STORAGE_ERROR", `Syncing ${dir}`, error);
26498
+ } finally {
26499
+ await handle?.close().catch(() => void 0);
26500
+ }
26501
+ }
26502
+ async function readJsonFile(path) {
26503
+ try {
26504
+ return JSON.parse(await (0, import_promises.readFile)(path, "utf8"));
26505
+ } catch (error) {
26506
+ if (isNotFound(error)) return void 0;
26507
+ throw storageError("STORAGE_ERROR", `Reading ${path}`, error);
26508
+ }
26509
+ }
26510
+ function identityRecordOf(value) {
26511
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
26512
+ return void 0;
26513
+ }
26514
+ if (!("host" in value) || !("space" in value) || !("principal" in value) || typeof value.host !== "string" || typeof value.space !== "string" || typeof value.principal !== "string") {
26515
+ return void 0;
26516
+ }
26517
+ return { host: value.host, space: value.space, principal: value.principal };
26518
+ }
26519
+ function deviceRecordOf(value) {
26520
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
26521
+ return void 0;
26522
+ }
26523
+ if (!("did" in value) || !("jwk" in value) || typeof value.did !== "string" || value.jwk === null || typeof value.jwk !== "object") {
26524
+ return void 0;
26525
+ }
26526
+ return { did: value.did, jwk: value.jwk };
26527
+ }
26528
+ function sameIdentity(a, b) {
26529
+ try {
26530
+ const left = (0, import_sdk_services4.canonicalReplicationIdentity)(a);
26531
+ const right = (0, import_sdk_services4.canonicalReplicationIdentity)(b);
26532
+ return left.host === right.host && left.space === right.space && left.principal === right.principal;
26533
+ } catch {
26534
+ return false;
26535
+ }
26536
+ }
26537
+ async function ensurePartitionIdentity(dir, identity, dirSync) {
26538
+ try {
26539
+ await (0, import_promises.mkdir)(dir, { recursive: true, mode: 448 });
26540
+ await (0, import_promises.chmod)(dir, 448);
26541
+ } catch (error) {
26542
+ throw storageError("STORAGE_ERROR", `Creating ${dir}`, error);
26543
+ }
26544
+ const file = (0, import_node_path.join)(dir, "identity.json");
26545
+ const existing = await readJsonFile(file);
26546
+ if (existing === void 0) {
26547
+ await writeJsonAtomic(file, { v: 1, ...(0, import_sdk_services4.canonicalReplicationIdentity)(identity) }, dirSync);
26548
+ return;
26549
+ }
26550
+ const record = identityRecordOf(existing);
26551
+ if (record === void 0 || !sameIdentity(record, identity)) {
26552
+ throw new ReplicaStorageError(
26553
+ "STORAGE_ERROR",
26554
+ `The partition at ${dir} belongs to a different identity.`
26555
+ );
26556
+ }
26557
+ }
26558
+ var PENDING_WRITE_LOCKS = /* @__PURE__ */ new Map();
26559
+ function serializePendingWrite(file, section) {
26560
+ const tail = PENDING_WRITE_LOCKS.get(file) ?? Promise.resolve();
26561
+ const entered = tail.then(section);
26562
+ const next = entered.then(
26563
+ () => void 0,
26564
+ () => void 0
26565
+ );
26566
+ PENDING_WRITE_LOCKS.set(file, next);
26567
+ void next.then(() => {
26568
+ if (PENDING_WRITE_LOCKS.get(file) === next) PENDING_WRITE_LOCKS.delete(file);
26569
+ });
26570
+ return entered;
26571
+ }
26572
+ function parsePendingState(text, file, identity) {
26573
+ let state;
26574
+ try {
26575
+ state = JSON.parse(text);
26576
+ } catch (error) {
26577
+ throw storageError("STORAGE_ERROR", `Parsing ${file}`, error);
26578
+ }
26579
+ if (state === null || typeof state !== "object" || !("v" in state) || state.v !== 2 || !("identity" in state) || !("committedEpoch" in state) || typeof state.committedEpoch !== "number" || !("seq" in state) || typeof state.seq !== "number" || !("records" in state) || !Array.isArray(state.records)) {
26580
+ throw new ReplicaStorageError("STORAGE_ERROR", `Pending-write state at ${file} is corrupt.`);
26581
+ }
26582
+ const storedIdentity = identityRecordOf(state.identity);
26583
+ if (storedIdentity === void 0 || !sameIdentity(storedIdentity, identity)) {
26584
+ throw new ReplicaStorageError("STORAGE_ERROR", `Pending-write state at ${file} belongs to a different identity.`);
26585
+ }
26586
+ return state;
26587
+ }
26588
+ var _dir, _guard, _dirSync, _file, _FilePendingWriteStore_instances, canonicalFile_fn;
26589
+ var FilePendingWriteStore = class {
26590
+ constructor(identity, dir, guard, dirSync) {
26591
+ __privateAdd(this, _FilePendingWriteStore_instances);
26592
+ this.durable = true;
26593
+ __privateAdd(this, _dir);
26594
+ __privateAdd(this, _guard);
26595
+ __privateAdd(this, _dirSync);
26596
+ __privateAdd(this, _file);
26597
+ this.identity = identity;
26598
+ __privateSet(this, _dir, dir);
26599
+ __privateSet(this, _guard, guard);
26600
+ __privateSet(this, _dirSync, dirSync);
26601
+ }
26602
+ async read() {
26603
+ const file = await __privateMethod(this, _FilePendingWriteStore_instances, canonicalFile_fn).call(this);
26604
+ let text;
26605
+ try {
26606
+ text = await (0, import_promises.readFile)(file, "utf8");
26607
+ } catch (error) {
26608
+ if (isNotFound(error)) {
26609
+ return { v: 2, identity: this.identity, committedEpoch: 0, seq: 0, records: [] };
26610
+ }
26611
+ throw storageError("STORAGE_ERROR", `Reading ${file}`, error);
26612
+ }
26613
+ return parsePendingState(text, file, this.identity);
26614
+ }
26615
+ async readExisting() {
26616
+ let file;
26617
+ try {
26618
+ file = (0, import_node_path.join)(await (0, import_promises.realpath)(__privateGet(this, _dir)), "pending.json");
26619
+ } catch (error) {
26620
+ if (isNotFound(error)) return void 0;
26621
+ throw storageError("STORAGE_ERROR", `Resolving pending-write state in ${__privateGet(this, _dir)}`, error);
26622
+ }
26623
+ try {
26624
+ const text = await (0, import_promises.readFile)(file, "utf8");
26625
+ return parsePendingState(text, file, this.identity);
26626
+ } catch (error) {
26627
+ if (isNotFound(error)) return void 0;
26628
+ if (error instanceof ReplicaStorageError) throw error;
26629
+ throw storageError("STORAGE_ERROR", `Reading ${file}`, error);
26630
+ }
26631
+ }
26632
+ async update(mutate) {
26633
+ const file = await __privateMethod(this, _FilePendingWriteStore_instances, canonicalFile_fn).call(this);
26634
+ return serializePendingWrite(file, async () => {
26635
+ let currentFile;
26636
+ try {
26637
+ currentFile = (0, import_node_path.join)(await (0, import_promises.realpath)((0, import_node_path.dirname)(file)), (0, import_node_path.basename)(file));
26638
+ } catch (error) {
26639
+ throw storageError("STORAGE_ERROR", "Resolving the open pending-write partition", error);
26640
+ }
26641
+ if (currentFile !== file) {
26642
+ throw new ReplicaStorageError(
26643
+ "STORAGE_ERROR",
26644
+ `The pending-write partition changed while open: ${(0, import_node_path.dirname)(file)}.`
26645
+ );
26646
+ }
26647
+ return __privateGet(this, _guard).call(this, async () => {
26648
+ const state = await this.read();
26649
+ const result = mutate(state);
26650
+ await writeJsonAtomic(file, state, __privateGet(this, _dirSync));
26651
+ return result;
26652
+ });
26653
+ });
26654
+ }
26655
+ };
26656
+ _dir = new WeakMap();
26657
+ _guard = new WeakMap();
26658
+ _dirSync = new WeakMap();
26659
+ _file = new WeakMap();
26660
+ _FilePendingWriteStore_instances = new WeakSet();
26661
+ canonicalFile_fn = async function() {
26662
+ __privateGet(this, _file) ?? __privateSet(this, _file, (async () => {
26663
+ await ensurePartitionIdentity(__privateGet(this, _dir), this.identity, __privateGet(this, _dirSync));
26664
+ const file = (0, import_node_path.join)(__privateGet(this, _dir), "pending.json");
26665
+ try {
26666
+ return (0, import_node_path.join)(await (0, import_promises.realpath)((0, import_node_path.dirname)(file)), (0, import_node_path.basename)(file));
26667
+ } catch (error) {
26668
+ throw storageError("STORAGE_ERROR", `Resolving ${file}`, error);
26669
+ }
26670
+ })());
26671
+ return __privateGet(this, _file);
26672
+ };
26673
+ async function loadOrCreateDevice(idDir, guard, createDevice, dirSync) {
26674
+ return guard(async () => {
26675
+ try {
26676
+ await (0, import_promises.mkdir)(idDir, { recursive: true, mode: 448 });
26677
+ await (0, import_promises.chmod)(idDir, 448);
26678
+ } catch (error) {
26679
+ throw storageError("STORAGE_ERROR", `Creating ${idDir}`, error);
26680
+ }
26681
+ const file = (0, import_node_path.join)(idDir, "device.jwk");
26682
+ const existing = await readJsonFile(file);
26683
+ if (existing !== void 0) {
26684
+ const device2 = deviceRecordOf(existing);
26685
+ if (device2 === void 0) {
26686
+ throw new ReplicaStorageError(
26687
+ "STORAGE_ERROR",
26688
+ `The replica device key at ${file} is unreadable; remove the partition or restore it.`
26689
+ );
26690
+ }
26691
+ return device2;
26692
+ }
26693
+ const device = await createDevice();
26694
+ await writeJsonAtomic(file, { did: device.did, jwk: device.jwk }, dirSync);
26695
+ return device;
26696
+ });
26697
+ }
26698
+ async function createDeviceKey() {
26699
+ const wasm = await import("@tinycloud/node-sdk-wasm");
26700
+ const manager = new wasm.TCWSessionManager();
26701
+ const keyId = manager.createSessionKey("replica-device") ?? "replica-device";
26702
+ const jwkText = manager.jwk(keyId);
26703
+ if (jwkText === null || jwkText === void 0) {
26704
+ throw new ReplicaStorageError(
26705
+ "STORAGE_ERROR",
26706
+ "The session manager returned no JWK for the replica device key."
26707
+ );
26708
+ }
26709
+ return { did: manager.getDID(keyId), jwk: JSON.parse(jwkText) };
26710
+ }
26711
+ var SYNC_LEASE_TTL_MS = 12e4;
26712
+ var FENCE_FILE = "fence.json";
26713
+ async function readFence(replicaDir) {
26714
+ const fence = await readJsonFile((0, import_node_path.join)(replicaDir, FENCE_FILE));
26715
+ return typeof fence === "object" && fence !== null && "syncedThroughEpoch" in fence && typeof fence.syncedThroughEpoch === "number" ? fence.syncedThroughEpoch : 0;
26716
+ }
26717
+ function newestGrantInfo(replica, record, pending, spec) {
26718
+ if (record === null) return null;
26719
+ const parsed = replica.parseUcanGrant(record.bytes);
26720
+ return {
26721
+ cid: record.cid,
26722
+ parentCid: parsed.prf[0] ?? null,
26723
+ expiresAt: record.expiresAt === null ? null : record.expiresAt * 1e3,
26724
+ state: pending !== null && record === pending ? "pending" : "active",
26725
+ unconstrained: ucanAttUnconstrainedFor(parsed.att, spec.space, spec.prefix)
26726
+ };
26727
+ }
26728
+ var _device, _store, _replicaDir, _replica, _guard2, _dirSync2, _generation, _ino, _transportOverride, _closed, _inFlight, _transportFactory, _SqliteReplicaHandle_instances, assertOpen_fn, assertLive_fn, transports_fn;
26729
+ var SqliteReplicaHandle = class {
26730
+ constructor(input) {
26731
+ __privateAdd(this, _SqliteReplicaHandle_instances);
26732
+ __privateAdd(this, _device);
26733
+ __privateAdd(this, _store);
26734
+ __privateAdd(this, _replicaDir);
26735
+ __privateAdd(this, _replica);
26736
+ __privateAdd(this, _guard2);
26737
+ __privateAdd(this, _dirSync2);
26738
+ /** The replica row generation this handle opened under — the durable fence a purge commits past (browser-parity wipe). */
26739
+ __privateAdd(this, _generation);
26740
+ /** The inode of `replica.db` at open — a directory recreated in place is a different replica. */
26741
+ __privateAdd(this, _ino);
26742
+ __privateAdd(this, _transportOverride);
26743
+ __privateAdd(this, _closed, false);
26744
+ __privateAdd(this, _inFlight, /* @__PURE__ */ new Set());
26745
+ __privateAdd(this, _transportFactory);
26746
+ this.spec = input.spec;
26747
+ __privateSet(this, _device, input.device);
26748
+ this.deviceDid = input.device.did;
26749
+ __privateSet(this, _store, input.store);
26750
+ __privateSet(this, _replicaDir, input.replicaDir);
26751
+ __privateSet(this, _replica, input.replica);
26752
+ __privateSet(this, _guard2, input.guard);
26753
+ __privateSet(this, _transportOverride, input.transportFor);
26754
+ __privateSet(this, _dirSync2, input.dirSync);
26755
+ __privateSet(this, _generation, input.generation);
26756
+ __privateSet(this, _ino, input.ino);
26757
+ }
26758
+ async get(key2) {
26759
+ await __privateMethod(this, _SqliteReplicaHandle_instances, assertLive_fn).call(this);
26760
+ const result = await new (__privateGet(this, _replica)).Replica({ store: __privateGet(this, _store) }).get(key2);
26761
+ const meta = {
26762
+ asOf: result.meta.asOf,
26763
+ coverage: result.meta.coverage,
26764
+ authority: result.meta.authority,
26765
+ syncedThroughEpoch: await readFence(__privateGet(this, _replicaDir))
26766
+ };
26767
+ switch (result.status) {
26768
+ case "present":
26769
+ return {
26770
+ status: "present",
26771
+ key: result.key,
26772
+ value: result.value,
26773
+ etag: result.etag,
26774
+ metadata: result.metadata,
26775
+ meta
26776
+ };
26777
+ case "content_missing":
26778
+ return {
26779
+ status: "content_missing",
26780
+ key: result.key,
26781
+ etag: result.etag,
26782
+ metadata: result.metadata,
26783
+ meta
26784
+ };
26785
+ default:
26786
+ return { status: result.status, key: result.key, meta };
26787
+ }
26788
+ }
26789
+ async list(options) {
26790
+ await __privateMethod(this, _SqliteReplicaHandle_instances, assertLive_fn).call(this);
26791
+ const result = await new (__privateGet(this, _replica)).Replica({ store: __privateGet(this, _store) }).list({
26792
+ prefix: options.prefix,
26793
+ ...options.after === void 0 ? {} : { after: options.after },
26794
+ ...options.limit === void 0 ? {} : { limit: options.limit }
26795
+ });
26796
+ return {
26797
+ keys: result.entries.map((entry) => entry.key),
26798
+ meta: {
26799
+ asOf: result.meta.asOf,
26800
+ coverage: result.meta.coverage,
26801
+ authority: result.meta.authority,
26802
+ syncedThroughEpoch: await readFence(__privateGet(this, _replicaDir))
26803
+ }
26804
+ };
26805
+ }
26806
+ /**
26807
+ * The newest installed grant — the pending one when a not-yet-promoted
26808
+ * install exists — with `parentCid` = signed `prf[0]` and `unconstrained`
26809
+ * computed from the signed `att` (replica's own grantCovers ignores
26810
+ * caveats, so the adapter computes it, §2.1). A constrained installed
26811
+ * grant is still reported (unconstrained: false) and never reused.
26812
+ */
26813
+ async grant() {
26814
+ await __privateMethod(this, _SqliteReplicaHandle_instances, assertLive_fn).call(this);
26815
+ const state = await __privateGet(this, _store).open();
26816
+ if (state === null) return null;
26817
+ return newestGrantInfo(
26818
+ __privateGet(this, _replica),
26819
+ state.pendingGrant ?? state.grant,
26820
+ state.pendingGrant,
26821
+ this.spec
26822
+ );
26823
+ }
26824
+ async installGrant(ucan) {
26825
+ await __privateMethod(this, _SqliteReplicaHandle_instances, assertLive_fn).call(this);
26826
+ const parsed = __privateGet(this, _replica).parseUcanGrant(ucan);
26827
+ const state = await __privateGet(this, _store).open();
26828
+ if (state === null) {
26829
+ throw new (__privateGet(this, _replica)).ReplicaError(
26830
+ __privateGet(this, _replica).ReplicaErrorCode.NOT_FOUND,
26831
+ "The replica has not been created."
26832
+ );
26833
+ }
26834
+ __privateGet(this, _replica).assertGrantInstallable(parsed, {
26835
+ deviceDid: principalOf(__privateGet(this, _device).did),
26836
+ space: this.spec.space,
26837
+ prefix: this.spec.prefix,
26838
+ now: Date.now()
26839
+ });
26840
+ if (!ucanAttUnconstrainedFor(parsed.att, this.spec.space, this.spec.prefix)) {
26841
+ throw new (__privateGet(this, _replica)).ReplicaError(
26842
+ __privateGet(this, _replica).ReplicaErrorCode.GRANT_NOT_COVERING,
26843
+ "The grant's get or sync coverage carries caveats; re-mint instead of installing it."
26844
+ );
26845
+ }
26846
+ await __privateGet(this, _store).installGrant(parsed);
26847
+ return newestGrantInfo(__privateGet(this, _replica), parsed, parsed, this.spec);
26848
+ }
26849
+ async sync(options) {
26850
+ await __privateMethod(this, _SqliteReplicaHandle_instances, assertLive_fn).call(this);
26851
+ const transportFor = await __privateMethod(this, _SqliteReplicaHandle_instances, transports_fn).call(this);
26852
+ const abort = new AbortController();
26853
+ options.signal.throwIfAborted();
26854
+ const onAbort = () => abort.abort(options.signal.reason);
26855
+ options.signal.addEventListener("abort", onAbort, { once: true });
26856
+ const engine = new (__privateGet(this, _replica)).Replica({
26857
+ store: __privateGet(this, _store),
26858
+ transportFor
26859
+ });
26860
+ const running = engine.sync({ signal: abort.signal });
26861
+ const registration = { promise: running, abort: () => abort.abort() };
26862
+ __privateGet(this, _inFlight).add(registration);
26863
+ try {
26864
+ const report = await running;
26865
+ await __privateGet(this, _guard2).call(this, () => writeJsonAtomic(
26866
+ (0, import_node_path.join)(__privateGet(this, _replicaDir), FENCE_FILE),
26867
+ { v: 1, syncedThroughEpoch: options.syncStartEpoch },
26868
+ __privateGet(this, _dirSync2)
26869
+ ));
26870
+ return {
26871
+ status: "synced",
26872
+ pages: report.pages,
26873
+ changes: report.changes,
26874
+ deleted: report.deleted,
26875
+ fetched: report.fetched,
26876
+ contentMissing: report.contentMissing,
26877
+ coverage: report.coverage,
26878
+ syncedThroughEpoch: options.syncStartEpoch
26879
+ };
26880
+ } catch (error) {
26881
+ if (__privateGet(this, _replica).isReplicaError(error, __privateGet(this, _replica).ReplicaErrorCode.BUSY)) {
26882
+ return { status: "busy" };
26883
+ }
26884
+ throw error;
26885
+ } finally {
26886
+ __privateGet(this, _inFlight).delete(registration);
26887
+ options.signal.removeEventListener("abort", onAbort);
26888
+ }
26889
+ }
26890
+ async status() {
26891
+ await __privateMethod(this, _SqliteReplicaHandle_instances, assertLive_fn).call(this);
26892
+ const engine = new (__privateGet(this, _replica)).Replica({ store: __privateGet(this, _store) });
26893
+ const status = await engine.status();
26894
+ const syncedThroughEpoch = await readFence(__privateGet(this, _replicaDir));
26895
+ const state = await __privateGet(this, _store).open();
26896
+ const grant = state === null ? null : newestGrantInfo(
26897
+ __privateGet(this, _replica),
26898
+ state.pendingGrant ?? state.grant,
26899
+ state.pendingGrant,
26900
+ this.spec
26901
+ );
26902
+ return {
26903
+ coverage: status.coverage,
26904
+ lastSyncAt: status.lastSyncAt,
26905
+ syncedThroughEpoch,
26906
+ authority: { state: status.authority.state, expiresAt: status.authority.expiresAt },
26907
+ grant,
26908
+ counts: status.counts,
26909
+ bytes: status.bytes,
26910
+ lastError: status.lastError
26911
+ };
26912
+ }
26913
+ async close() {
26914
+ if (__privateGet(this, _closed)) return;
26915
+ __privateSet(this, _closed, true);
26916
+ for (const sync of __privateGet(this, _inFlight)) sync.abort();
26917
+ await Promise.allSettled([...__privateGet(this, _inFlight)].map((sync) => sync.promise));
26918
+ await __privateGet(this, _store).close();
26919
+ }
26920
+ };
26921
+ _device = new WeakMap();
26922
+ _store = new WeakMap();
26923
+ _replicaDir = new WeakMap();
26924
+ _replica = new WeakMap();
26925
+ _guard2 = new WeakMap();
26926
+ _dirSync2 = new WeakMap();
26927
+ _generation = new WeakMap();
26928
+ _ino = new WeakMap();
26929
+ _transportOverride = new WeakMap();
26930
+ _closed = new WeakMap();
26931
+ _inFlight = new WeakMap();
26932
+ _transportFactory = new WeakMap();
26933
+ _SqliteReplicaHandle_instances = new WeakSet();
26934
+ assertOpen_fn = function() {
26935
+ if (__privateGet(this, _closed)) {
26936
+ throw new (__privateGet(this, _replica)).ReplicaError(
26937
+ __privateGet(this, _replica).ReplicaErrorCode.CLOSED,
26938
+ "The replica handle is closed."
26939
+ );
26940
+ }
26941
+ };
26942
+ assertLive_fn = async function() {
26943
+ __privateMethod(this, _SqliteReplicaHandle_instances, assertOpen_fn).call(this);
26944
+ try {
26945
+ const stats = await (0, import_promises.stat)((0, import_node_path.join)(__privateGet(this, _replicaDir), "replica.db"));
26946
+ if (__privateGet(this, _ino) !== void 0 && stats.ino !== __privateGet(this, _ino)) {
26947
+ throw new (__privateGet(this, _replica)).ReplicaError(
26948
+ __privateGet(this, _replica).ReplicaErrorCode.RESET_REQUIRED,
26949
+ "The replica was recreated; open it again to continue."
26950
+ );
26951
+ }
26952
+ } catch (error) {
26953
+ if (isNotFound(error)) {
26954
+ throw new (__privateGet(this, _replica)).ReplicaError(
26955
+ __privateGet(this, _replica).ReplicaErrorCode.RESET_REQUIRED,
26956
+ "The replica was purged; open it again to continue."
26957
+ );
26958
+ }
26959
+ throw error;
26960
+ }
26961
+ const state = await __privateGet(this, _store).open();
26962
+ if (state !== null && state.generation !== __privateGet(this, _generation)) {
26963
+ throw new (__privateGet(this, _replica)).ReplicaError(
26964
+ __privateGet(this, _replica).ReplicaErrorCode.RESET_REQUIRED,
26965
+ "The replica was purged or reopened; open it again to continue."
26966
+ );
26967
+ }
26968
+ };
26969
+ transports_fn = async function() {
26970
+ if (__privateGet(this, _transportOverride) !== void 0) {
26971
+ const override = __privateGet(this, _transportOverride);
26972
+ const spec = this.spec;
26973
+ const device = __privateGet(this, _device);
26974
+ return (grant) => override(grant, spec, device);
26975
+ }
26976
+ __privateGet(this, _transportFactory) ?? __privateSet(this, _transportFactory, (async () => {
26977
+ const wasm = await import("@tinycloud/node-sdk-wasm");
26978
+ const kvSyncTransport = __privateGet(this, _replica).kvSyncTransport;
26979
+ const spec = this.spec;
26980
+ const device = __privateGet(this, _device);
26981
+ const fetch2 = spec.fetch ?? globalThis.fetch.bind(globalThis);
26982
+ return (grant) => {
26983
+ const context = new import_sdk_core13.ServiceContext({
26984
+ invoke: wasm.invoke,
26985
+ invokeAny: wasm.invokeAny,
26986
+ fetch: fetch2,
26987
+ hosts: [spec.identity.host]
26988
+ });
26989
+ const kv = new import_sdk_core13.KVService({});
26990
+ kv.initialize(context);
26991
+ context.registerService("kv", kv);
26992
+ context.setSession({
26993
+ delegationHeader: { Authorization: new TextDecoder().decode(grant.bytes) },
26994
+ delegationCid: grant.cid,
26995
+ spaceId: spec.space,
26996
+ verificationMethod: device.did,
26997
+ jwk: device.jwk
26998
+ });
26999
+ return kvSyncTransport(kv);
27000
+ };
27001
+ })());
27002
+ return __privateGet(this, _transportFactory);
27003
+ };
27004
+ function createSqliteReplicaStorage(options) {
27005
+ const root = options.dir;
27006
+ const guard = options.guard ?? ((section) => section());
27007
+ const createDevice = options.createDevice ?? createDeviceKey;
27008
+ async function openHandle(spec) {
27009
+ const [replica, sqlite] = await Promise.all([
27010
+ // @ts-ignore — TS2307 when replica's dist is absent (CI builds node-sdk first).
27011
+ import("@tinycloud/replica"),
27012
+ // @ts-ignore — same as above.
27013
+ import("@tinycloud/replica/sqlite")
27014
+ ]);
27015
+ if ((0, import_sdk_services4.requiresSecretsOptIn)(spec.space, spec.prefix) && spec.allowSecrets !== true) {
27016
+ throw new replica.ReplicaError(
27017
+ replica.ReplicaErrorCode.SECRETS_OPT_IN_REQUIRED,
27018
+ `Replicating ${spec.space}/kv/${spec.prefix} copies secret material to disk; pass allowSecrets to opt in.`
27019
+ );
27020
+ }
27021
+ const idDir = partitionDirOf(root, spec.identity);
27022
+ await ensurePartitionIdentity(idDir, spec.identity, options.dirSync);
27023
+ const createdDevice = spec.device ?? await loadOrCreateDevice(idDir, guard, createDevice, options.dirSync);
27024
+ const device = { ...createdDevice, did: principalOf(createdDevice.did) };
27025
+ const replicaHash = replicaHashOf(spec.prefix, device.did);
27026
+ const replicaDir = (0, import_node_path.join)(idDir, "replicas", replicaHash);
27027
+ const store = await sqlite.SqliteReplicaStore.open(replicaDir, {
27028
+ create: true,
27029
+ guard
27030
+ });
27031
+ let generation;
27032
+ try {
27033
+ try {
27034
+ await store.init({
27035
+ name: spec.prefix.replace(/\/+$/, "") || "replica",
27036
+ replicaId: replicaHash,
27037
+ host: spec.identity.host,
27038
+ space: spec.space,
27039
+ prefix: spec.prefix,
27040
+ deviceDid: device.did,
27041
+ allowSecrets: spec.allowSecrets,
27042
+ localReadPolicy: "whileGrantValid",
27043
+ retentionGrantCid: null
27044
+ });
27045
+ } catch (error) {
27046
+ if (!replica.isReplicaError(error, replica.ReplicaErrorCode.CONFIG_MISMATCH)) {
27047
+ throw error;
27048
+ }
27049
+ }
27050
+ const state = await store.open();
27051
+ if (state === null) {
27052
+ throw new replica.ReplicaError(
27053
+ replica.ReplicaErrorCode.NOT_FOUND,
27054
+ "The replica row vanished during init."
27055
+ );
27056
+ }
27057
+ const config = state.config;
27058
+ if (config.host !== spec.identity.host || config.space !== spec.space || config.prefix !== spec.prefix) {
27059
+ throw new replica.ReplicaError(
27060
+ replica.ReplicaErrorCode.CONFIG_MISMATCH,
27061
+ `This replica follows ${config.host} ${config.space}/kv/${config.prefix}, not ${spec.identity.host} ${spec.space}/kv/${spec.prefix}.`
27062
+ );
27063
+ }
27064
+ if (principalOf(config.deviceDid) !== principalOf(device.did)) {
27065
+ throw new replica.ReplicaError(
27066
+ replica.ReplicaErrorCode.CONFIG_MISMATCH,
27067
+ "The stored replica belongs to a different device key; purge the partition to rekey."
27068
+ );
27069
+ }
27070
+ generation = state.generation;
27071
+ } catch (error) {
27072
+ await store.close().catch(() => void 0);
27073
+ throw error;
27074
+ }
27075
+ let ino;
27076
+ try {
27077
+ ino = (await (0, import_promises.stat)((0, import_node_path.join)(replicaDir, "replica.db"))).ino;
27078
+ } catch (error) {
27079
+ if (!isNotFound(error)) throw error;
27080
+ }
27081
+ return new SqliteReplicaHandle({
27082
+ spec,
27083
+ device,
27084
+ store,
27085
+ replicaDir,
27086
+ replica,
27087
+ guard,
27088
+ transportFor: options.transportFor,
27089
+ dirSync: options.dirSync,
27090
+ generation,
27091
+ ino
27092
+ });
27093
+ }
27094
+ async function inspectStatus(spec, { signal }) {
27095
+ const checkAbort = () => {
27096
+ if (signal.aborted) throw signal.reason ?? Object.assign(new Error("Replica status inspection was aborted"), { code: "ABORTED" });
27097
+ };
27098
+ checkAbort();
27099
+ const idDir = partitionDirOf(root, spec.identity);
27100
+ if (!await pathExists(idDir)) return void 0;
27101
+ checkAbort();
27102
+ const identityFile = (0, import_node_path.join)(idDir, "identity.json");
27103
+ const storedIdentity = identityRecordOf(await readJsonFile(identityFile));
27104
+ if (storedIdentity === void 0 || !sameIdentity(storedIdentity, spec.identity)) {
27105
+ throw new ReplicaStorageError("STORAGE_ERROR", `The partition at ${idDir} belongs to a different identity or has no identity record.`);
27106
+ }
27107
+ checkAbort();
27108
+ let device = spec.device;
27109
+ if (device === void 0) {
27110
+ const deviceFile = (0, import_node_path.join)(idDir, "device.jwk");
27111
+ const storedDevice = await readJsonFile(deviceFile);
27112
+ if (storedDevice === void 0) return void 0;
27113
+ device = deviceRecordOf(storedDevice);
27114
+ if (device === void 0) throw new ReplicaStorageError("STORAGE_ERROR", `The replica device key at ${deviceFile} is unreadable.`);
27115
+ }
27116
+ checkAbort();
27117
+ const replicaDir = (0, import_node_path.join)(idDir, "replicas", replicaHashOf(spec.prefix, device.did));
27118
+ if (!await pathExists(replicaDir)) return void 0;
27119
+ checkAbort();
27120
+ const [replica, sqlite] = await Promise.all([
27121
+ // @ts-ignore — TS2307 when replica's dist is absent (CI builds node-sdk first).
27122
+ import("@tinycloud/replica"),
27123
+ // @ts-ignore — same as above.
27124
+ import("@tinycloud/replica/sqlite")
27125
+ ]);
27126
+ checkAbort();
27127
+ const inspected = await sqlite.SqliteReplicaStore.inspect(replicaDir, { signal });
27128
+ checkAbort();
27129
+ if (inspected === null) return void 0;
27130
+ const { state, status } = inspected;
27131
+ if (state.config.host !== spec.identity.host || state.config.space !== spec.space || state.config.prefix !== spec.prefix || principalOf(state.config.deviceDid) !== principalOf(device.did)) {
27132
+ throw new ReplicaStorageError("STORAGE_ERROR", `The replica at ${replicaDir} does not match the requested identity, space, prefix, or device.`);
27133
+ }
27134
+ const syncedThroughEpoch = await readFence(replicaDir);
27135
+ checkAbort();
27136
+ return {
27137
+ coverage: status.coverage,
27138
+ lastSyncAt: status.lastSyncAt,
27139
+ syncedThroughEpoch,
27140
+ authority: { state: status.authority.state, expiresAt: status.authority.expiresAt },
27141
+ grant: newestGrantInfo(replica, state.pendingGrant ?? state.grant, state.pendingGrant, spec),
27142
+ counts: status.counts,
27143
+ bytes: status.bytes,
27144
+ lastError: status.lastError
27145
+ };
27146
+ }
27147
+ async function purgePartition(target) {
27148
+ const [replica, sqlite] = await Promise.all([
27149
+ // @ts-ignore — TS2307 when replica's dist is absent (CI builds node-sdk first).
27150
+ import("@tinycloud/replica"),
27151
+ // @ts-ignore — same as above.
27152
+ import("@tinycloud/replica/sqlite")
27153
+ ]);
27154
+ const idDir = partitionDirOf(root, target.identity);
27155
+ if (!await pathExists(idDir)) return;
27156
+ const deviceDids = [];
27157
+ const deviceFile = (0, import_node_path.join)(idDir, "device.jwk");
27158
+ const stored = await readJsonFile(deviceFile);
27159
+ if (stored !== void 0) {
27160
+ const device = deviceRecordOf(stored);
27161
+ if (device === void 0) {
27162
+ throw new ReplicaStorageError(
27163
+ "STORAGE_ERROR",
27164
+ `The replica device key at ${deviceFile} is unreadable.`
27165
+ );
27166
+ }
27167
+ deviceDids.push(device.did);
27168
+ }
27169
+ if (target.sessionDeviceDid !== void 0) deviceDids.push(target.sessionDeviceDid);
27170
+ const devices = [...new Map(deviceDids.map((did) => [principalOf(did), did])).values()];
27171
+ let firstError;
27172
+ for (const deviceDid of devices) {
27173
+ const replicaDir = (0, import_node_path.join)(idDir, "replicas", replicaHashOf(target.prefix, deviceDid));
27174
+ if (!await pathExists(replicaDir)) continue;
27175
+ try {
27176
+ let store;
27177
+ try {
27178
+ store = await sqlite.SqliteReplicaStore.open(replicaDir, { create: false, guard });
27179
+ } catch (error) {
27180
+ if (replica.isReplicaError(error, replica.ReplicaErrorCode.NOT_FOUND)) {
27181
+ await guard(() => (0, import_promises.rm)(replicaDir, { recursive: true, force: true }));
27182
+ continue;
27183
+ }
27184
+ throw error;
27185
+ }
27186
+ try {
27187
+ const state = await store.open();
27188
+ if (state === null) {
27189
+ await store.close().catch(() => void 0);
27190
+ await guard(() => (0, import_promises.rm)(replicaDir, { recursive: true, force: true }));
27191
+ continue;
27192
+ }
27193
+ const lease = await store.acquireSyncLease(SYNC_LEASE_TTL_MS);
27194
+ if (lease === null) {
27195
+ throw new replica.ReplicaError(
27196
+ replica.ReplicaErrorCode.BUSY,
27197
+ "Another process holds this replica's sync lease."
27198
+ );
27199
+ }
27200
+ try {
27201
+ if (state.revoked === null) {
27202
+ await store.reset(lease, "purged");
27203
+ }
27204
+ await store.destroy(lease);
27205
+ } finally {
27206
+ await store.releaseLease(lease).catch(() => void 0);
27207
+ }
27208
+ } finally {
27209
+ await store.close().catch(() => void 0);
27210
+ }
27211
+ } catch (error) {
27212
+ firstError ?? (firstError = error);
27213
+ }
27214
+ }
27215
+ if (firstError !== void 0) throw firstError;
27216
+ }
27217
+ return {
27218
+ kind: "sqlite",
27219
+ open: openHandle,
27220
+ inspectStatus,
27221
+ purge: purgePartition,
27222
+ // Always the durable partitioned file store (review): the runtime
27223
+ // must never fall back to volatile in-memory pending state — a
27224
+ // restart that lost ambiguous write records would serve stale data.
27225
+ // Without a guard the file store still durably serializes each update;
27226
+ // the guard only adds cross-process read-modify-write exclusion.
27227
+ pendingWrites(identity) {
27228
+ return new FilePendingWriteStore(
27229
+ identity,
27230
+ partitionDirOf(root, identity),
27231
+ guard,
27232
+ options.dirSync
27233
+ );
27234
+ }
27235
+ };
27236
+ }
27237
+ function sqliteReplicaStorage(options) {
27238
+ return createSqliteReplicaStorage(options);
27239
+ }
25358
27240
  // Annotate the CommonJS export names for ESM import in node:
25359
27241
  0 && (module.exports = {
25360
27242
  ACCEPTED_MARKER_VERSIONS,
@@ -25394,6 +27276,7 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
25394
27276
  IdentityParseError,
25395
27277
  InvalidRestoredSessionError,
25396
27278
  KVService,
27279
+ MAX_SECRET_SCOPE_LENGTH,
25397
27280
  ManifestValidationError,
25398
27281
  MemorySessionStorage,
25399
27282
  NETWORK_NAME_PATTERN,
@@ -25407,6 +27290,7 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
25407
27290
  RUNTIME_DELEGATION_REJECTIONS,
25408
27291
  RuntimeDelegationRejectedError,
25409
27292
  SECRET_NAME_RE,
27293
+ SECRET_SCOPE_RE,
25410
27294
  SQLAction,
25411
27295
  SQLService,
25412
27296
  STORAGE_FULL_MESSAGE,
@@ -25419,6 +27303,7 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
25419
27303
  Space,
25420
27304
  SpaceErrorCodes,
25421
27305
  SpaceService,
27306
+ TC832_RESERVED_SCOPES,
25422
27307
  TinyCloud,
25423
27308
  TinyCloudDebugLogger,
25424
27309
  TinyCloudNode,
@@ -25432,6 +27317,7 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
25432
27317
  activateCompactRuntimeDelegation,
25433
27318
  activateValidatedRuntimeDelegation,
25434
27319
  addressStorageKey,
27320
+ appSecretScope,
25435
27321
  buildCanonicalDecryptRequest,
25436
27322
  buildDecryptAttenuation,
25437
27323
  buildDecryptFacts,
@@ -25507,6 +27393,7 @@ var import_sdk_core23 = require("@tinycloud/sdk-core");
25507
27393
  resourceCapabilitiesToSpaceAbilitiesMap,
25508
27394
  serializeDelegation,
25509
27395
  signedCompactUcanExpiry,
27396
+ sqliteReplicaStorage,
25510
27397
  tinyCloudDebugLogger,
25511
27398
  validateEnvelope,
25512
27399
  validateManifest,