@githolon/runtime 0.111.1 → 0.112.1

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.
@@ -2883,6 +2883,10 @@
2883
2883
  init_define_NOMOS_KERNEL_RELEASE();
2884
2884
  init_shims();
2885
2885
 
2886
+ // ../../platform-shells/browser/history_custody.ts
2887
+ init_define_NOMOS_KERNEL_RELEASE();
2888
+ init_shims();
2889
+
2886
2890
  // ../../node_modules/@bufbuild/protobuf/dist/esm/index.js
2887
2891
  init_define_NOMOS_KERNEL_RELEASE();
2888
2892
  init_shims();
@@ -7818,6 +7822,94 @@
7818
7822
  var DeviceRecoveryAdmissionStageSchema = /* @__PURE__ */ enumDesc(file_nomos_runtime_v2_correspondence_desk, 3);
7819
7823
  var DeviceRecoveryAdmissionStage = /* @__PURE__ */ tsEnum(DeviceRecoveryAdmissionStageSchema);
7820
7824
 
7825
+ // ../../platform-shells/browser/history_custody.ts
7826
+ function browserHistoryCustody(desk, discovery, providers, fetch2) {
7827
+ const origins = new Set(providers.map((provider) => new URL(provider).origin));
7828
+ return async (workspace, authToken) => {
7829
+ const placement = await discovery.discoverWorkspacePlacement(workspace);
7830
+ const leaseUrl = placement.custodyLeaseUrl;
7831
+ if (!leaseUrl || !origins.has(new URL(leaseUrl).origin)) throw new Error("History custody lease is not from a configured provider");
7832
+ const mediaType = "application/vnd.nomos.git-read-lease+protobuf";
7833
+ const response = await fetch2(leaseUrl, {
7834
+ headers: { Accept: mediaType, ...authToken ? { "x-nomos-auth": authToken } : {} },
7835
+ signal: AbortSignal.timeout(3e4)
7836
+ });
7837
+ if (!response.ok || response.headers.get("content-type")?.split(";")[0] !== mediaType) throw new Error(`History custody lease returned HTTP ${response.status} or an untyped response`);
7838
+ const lease = fromBinary(GitReadLeaseSchema, new Uint8Array(await response.arrayBuffer()));
7839
+ if (lease.formatVersion !== 1 || lease.workspace !== workspace || !lease.token || !/^https?:\/\//.test(lease.remote)) throw new Error("History custody lease does not identify this workspace and transport");
7840
+ return desk.deepenMain(workspace, { remote: lease.remote, headers: {
7841
+ Authorization: `Bearer ${lease.token}`,
7842
+ "x-nomos-artifacts-read-token": lease.token
7843
+ } });
7844
+ };
7845
+ }
7846
+
7847
+ // ../../platform-shells/browser/kernel_custody.ts
7848
+ init_define_NOMOS_KERNEL_RELEASE();
7849
+ init_shims();
7850
+ function browserKernelCustody(kernel, checkpoint, isCheckpointCurrent) {
7851
+ return {
7852
+ canRetainChanges: () => true,
7853
+ hasLocalCustody: (workspace) => kernel.branchHead(workspace, "main") !== void 0,
7854
+ openLocalCustody: async () => ({}),
7855
+ ledgerFor: () => {
7856
+ throw new Error("Browser Git custody is opened in place; there is no second local ledger");
7857
+ },
7858
+ async retainFrontier(effect) {
7859
+ await checkpoint();
7860
+ const retained = !!effect.head && kernel.branchHead(effect.workspace, effect.branch) === effect.head && effect.refs.every((ref) => kernel.branchHead(effect.workspace, ref.reference) === ref.oid) && isCheckpointCurrent();
7861
+ return create(FrontierRetainedSchema, {
7862
+ workspace: effect.workspace,
7863
+ branch: effect.branch,
7864
+ head: effect.head,
7865
+ retained,
7866
+ detail: retained ? "browser custody transaction committed" : "requested frontier differs from local custody",
7867
+ refs: retained ? effect.refs : []
7868
+ });
7869
+ },
7870
+ async persistBornCustody(effect) {
7871
+ await checkpoint();
7872
+ return create(PersistBornCustodyReceiptSchema, {
7873
+ children: effect.children.map((born) => {
7874
+ const workspace = born.child?.workspace ?? "";
7875
+ const head = born.child?.head ?? "";
7876
+ const persisted = !!workspace && !!head && kernel.branchHead(workspace, "main") === head && born.publication.every((item) => item.ref && kernel.branchHead(workspace, item.ref.reference) === item.ref.oid) && isCheckpointCurrent();
7877
+ return create(PersistedBornCustodySchema, {
7878
+ workspace,
7879
+ head,
7880
+ persisted,
7881
+ refs: persisted ? born.publication.map((item) => item.ref) : [],
7882
+ detail: persisted ? "born custody transaction committed" : "local custody does not contain the born frontier"
7883
+ });
7884
+ })
7885
+ });
7886
+ }
7887
+ };
7888
+ }
7889
+
7890
+ // ../../platform-shells/browser/runtime_fetch.ts
7891
+ init_define_NOMOS_KERNEL_RELEASE();
7892
+ init_shims();
7893
+ function browserRuntimeFetch(base, fetchImpl, caches) {
7894
+ const root = base.replace(/\/+$/, "");
7895
+ return async (input, init) => {
7896
+ const url = String(input);
7897
+ const bootArtifact = url === `${root}/v1/runtime/repository.xml` || url === `${root}/v1/runtime/nomos.law.usdz`;
7898
+ if (!bootArtifact || !caches) return fetchImpl(input, init);
7899
+ const cache = await caches.open("nomos-browser-boot-v1");
7900
+ let response;
7901
+ try {
7902
+ response = await fetchImpl(input, { ...init, signal: init?.signal ?? AbortSignal.timeout(15e3) });
7903
+ } catch (error) {
7904
+ const retained = await cache.match(url);
7905
+ if (retained) return retained;
7906
+ throw error;
7907
+ }
7908
+ if (response.ok) await cache.put(url, response.clone());
7909
+ return response;
7910
+ };
7911
+ }
7912
+
7821
7913
  // ../../adapter/proto/nomos/runtime/v2/runtime_pb.js
7822
7914
  init_define_NOMOS_KERNEL_RELEASE();
7823
7915
  init_shims();
@@ -9630,6 +9722,15 @@
9630
9722
  };
9631
9723
  return {
9632
9724
  preopen,
9725
+ snapshot() {
9726
+ const entries = [];
9727
+ const visit = (path, node) => {
9728
+ if (path !== "/work") entries.push({ path, ...node.data ? { bytes: node.data.slice() } : {} });
9729
+ for (const [name, child] of node.contents ?? []) visit(`${path}/${name}`, child);
9730
+ };
9731
+ visit("/work", preopen.dir);
9732
+ return entries;
9733
+ },
9633
9734
  files,
9634
9735
  fs: makeGitFs(
9635
9736
  preopen,
@@ -9815,8 +9916,7 @@
9815
9916
  if (response.outcome.case !== "custody" || response.outcome.value.operation.case !== "lawClosureInfo" || !response.outcome.value.operation.value.identity)
9816
9917
  throw new Error(`kernel refused USDA closure ${closureFile}`);
9817
9918
  };
9818
- async function createKernelMachine(source) {
9819
- const filesystem = memoryCustodyFilesystem();
9919
+ async function createKernelMachine(source, filesystem = memoryCustodyFilesystem(), onFilesystemMutation) {
9820
9920
  const machine = await createKernelMachineWithHost(source, (pushStderr) => {
9821
9921
  const wasi = new WASI(
9822
9922
  ["wasm_git_holon", "reactor"],
@@ -9830,6 +9930,30 @@
9830
9930
  ],
9831
9931
  { debug: false }
9832
9932
  );
9933
+ if (onFilesystemMutation) {
9934
+ const imports = wasi.wasiImport;
9935
+ for (const name of [
9936
+ "fd_write",
9937
+ "fd_pwrite",
9938
+ "fd_allocate",
9939
+ "fd_filestat_set_size",
9940
+ "path_open",
9941
+ "path_create_directory",
9942
+ "path_unlink_file",
9943
+ "path_remove_directory",
9944
+ "path_rename",
9945
+ "path_link",
9946
+ "path_symlink"
9947
+ ]) {
9948
+ const original = imports[name];
9949
+ if (!original) continue;
9950
+ imports[name] = (...args) => {
9951
+ const result = original(...args);
9952
+ if (result === 0 && !(name === "fd_write" && Number(args[0]) < 3) && !(name === "path_open" && (Number(args[4]) & 9) === 0)) onFilesystemMutation();
9953
+ return result;
9954
+ };
9955
+ }
9956
+ }
9833
9957
  return {
9834
9958
  filesystem,
9835
9959
  imports: unsignedWasiPointers(
@@ -10069,7 +10193,7 @@
10069
10193
  case: "resolveRef",
10070
10194
  value: create(ResolveRefRequestSchema, {
10071
10195
  repo: workspaceRepositoryPath(workspace),
10072
- reference: `refs/heads/${branch}`
10196
+ reference: branch.startsWith("refs/") ? branch : `refs/heads/${branch}`
10073
10197
  })
10074
10198
  }
10075
10199
  })
@@ -11056,7 +11180,6 @@
11056
11180
  return acquired;
11057
11181
  },
11058
11182
  deepenMain(workspace, ledger) {
11059
- if (ledger.operatorCustody !== true) return Promise.resolve({ changed: false, complete: true });
11060
11183
  return acquiring(workspace, ledger, "deepen-main", async () => {
11061
11184
  if (resolveRef(workspace, branchRef("main")) === void 0) {
11062
11185
  const acquired = await acquireMain(workspace, ledger);
@@ -11250,45 +11373,189 @@
11250
11373
  return desk;
11251
11374
  }
11252
11375
 
11253
- // ../src/runtime/peer_desk_store.ts
11376
+ // ../../platform-shells/browser/custody_store.ts
11254
11377
  init_define_NOMOS_KERNEL_RELEASE();
11255
11378
  init_shims();
11256
- var recordId = (namespace, key) => `${namespace.length}:${namespace}${key}`;
11257
- var copy = (record) => ({
11258
- ...record,
11259
- value: record.value.slice()
11260
- });
11261
- var _records;
11262
- var MemoryPeerDeskStore = class {
11263
- constructor() {
11379
+ var copyRecord = (record) => ({ ...record, value: record.value.slice() });
11380
+ var keyOf = (namespace, key) => JSON.stringify([namespace, key]);
11381
+ var _backend, _records, _revision, _committed, _queued, _failure, _closed;
11382
+ var _BrowserCustodyStore = class _BrowserCustodyStore {
11383
+ constructor(backend, snapshot) {
11384
+ __publicField(this, "filesystem", memoryCustodyFilesystem());
11385
+ __publicField(this, "replica");
11386
+ __publicField(this, "identity");
11387
+ __privateAdd(this, _backend);
11264
11388
  __privateAdd(this, _records, /* @__PURE__ */ new Map());
11389
+ __privateAdd(this, _revision, 0);
11390
+ __privateAdd(this, _committed, -1);
11391
+ __privateAdd(this, _queued);
11392
+ __privateAdd(this, _failure);
11393
+ __privateAdd(this, _closed, false);
11394
+ __publicField(this, "changed", () => {
11395
+ this.assertUsable();
11396
+ __privateWrapper(this, _revision)._++;
11397
+ void this.checkpoint().catch(() => {
11398
+ });
11399
+ });
11400
+ __privateSet(this, _backend, backend);
11401
+ if (snapshot && snapshot.format !== 1) throw new Error("Unsupported browser custody format; keep this site's data and update the application.");
11402
+ this.replica = snapshot?.replica ?? globalThis.crypto.getRandomValues(new BigUint64Array(1))[0] & (1n << 63n) - 1n;
11403
+ this.identity = snapshot?.identity ?? `browser-${globalThis.crypto.randomUUID()}`;
11404
+ for (const entry of snapshot?.files ?? []) {
11405
+ if (entry.bytes === void 0) this.filesystem.files.mkdir(entry.path);
11406
+ else this.filesystem.files.writeFile(entry.path, entry.bytes);
11407
+ }
11408
+ for (const record of snapshot?.records ?? []) __privateGet(this, _records).set(keyOf(record.namespace, record.key), copyRecord(record));
11409
+ for (const name of ["mkdir", "writeFile", "unlink"]) {
11410
+ const original = this.filesystem.files[name].bind(this.filesystem.files);
11411
+ this.filesystem.files[name] = (...args) => {
11412
+ this.assertUsable();
11413
+ const result = original(...args);
11414
+ this.changed();
11415
+ return result;
11416
+ };
11417
+ }
11418
+ const promises = this.filesystem.fs.promises;
11419
+ const mkdir = promises.mkdir.bind(promises);
11420
+ const writeFile = promises.writeFile.bind(promises);
11421
+ promises.mkdir = async (path) => {
11422
+ this.assertUsable();
11423
+ const result = await mkdir(path);
11424
+ this.changed();
11425
+ return result;
11426
+ };
11427
+ promises.writeFile = async (path, bytes) => {
11428
+ this.assertUsable();
11429
+ const result = await writeFile(path, bytes);
11430
+ this.changed();
11431
+ return result;
11432
+ };
11433
+ }
11434
+ static async open(backend) {
11435
+ try {
11436
+ return new _BrowserCustodyStore(backend, await backend.load());
11437
+ } catch (error) {
11438
+ backend.close();
11439
+ throw error;
11440
+ }
11441
+ }
11442
+ assertUsable() {
11443
+ if (__privateGet(this, _failure)) throw new Error("Browser custody could not be saved. Keep this tab open, free storage space, and reload only after recovery.", { cause: __privateGet(this, _failure) });
11444
+ if (__privateGet(this, _closed)) throw new Error("Browser custody is closed");
11265
11445
  }
11266
11446
  list(namespace) {
11267
- return [...__privateGet(this, _records).values()].filter((record) => record.namespace === namespace).sort((left, right) => left.key.localeCompare(right.key)).map(copy);
11447
+ this.assertUsable();
11448
+ return [...__privateGet(this, _records).values()].filter((record) => record.namespace === namespace).sort((a, b) => a.key.localeCompare(b.key)).map(copyRecord);
11268
11449
  }
11269
- compareExchange(namespace, key, expectedRevision, value) {
11270
- const id = recordId(namespace, key);
11450
+ compareExchange(namespace, key, expected, value) {
11451
+ this.assertUsable();
11452
+ const id = keyOf(namespace, key);
11271
11453
  const current = __privateGet(this, _records).get(id);
11272
- if (current?.revision !== expectedRevision) {
11273
- throw new Error(
11274
- `peer desk record '${namespace}/${key}' changed at revision ${current?.revision ?? "absent"}`
11275
- );
11276
- }
11277
- if (value === void 0) {
11278
- __privateGet(this, _records).delete(id);
11279
- return void 0;
11454
+ if (current?.revision !== expected) throw new Error(`peer desk record '${namespace}/${key}' changed at revision ${current?.revision ?? "absent"}`);
11455
+ const next = value === void 0 ? void 0 : { namespace, key, revision: (current?.revision ?? 0n) + 1n, value: value.slice() };
11456
+ if (next) __privateGet(this, _records).set(id, next);
11457
+ else __privateGet(this, _records).delete(id);
11458
+ this.changed();
11459
+ return next && copyRecord(next);
11460
+ }
11461
+ checkpoint() {
11462
+ this.assertUsable();
11463
+ if (!__privateGet(this, _queued)) {
11464
+ __privateSet(this, _queued, Promise.resolve().then(async () => {
11465
+ while (__privateGet(this, _committed) !== __privateGet(this, _revision)) {
11466
+ const revision = __privateGet(this, _revision);
11467
+ const snapshot = {
11468
+ format: 1,
11469
+ replica: this.replica,
11470
+ identity: this.identity,
11471
+ files: this.filesystem.snapshot(),
11472
+ records: [...__privateGet(this, _records).values()].map(copyRecord)
11473
+ };
11474
+ await __privateGet(this, _backend).commit(snapshot);
11475
+ __privateSet(this, _committed, revision);
11476
+ }
11477
+ }).catch((error) => {
11478
+ __privateSet(this, _failure, error);
11479
+ throw error;
11480
+ }).finally(() => {
11481
+ __privateSet(this, _queued, void 0);
11482
+ }));
11280
11483
  }
11281
- const next = Object.freeze({
11282
- namespace,
11283
- key,
11284
- revision: (current?.revision ?? 0n) + 1n,
11285
- value: value.slice()
11484
+ return __privateGet(this, _queued).then(() => {
11485
+ if (__privateGet(this, _committed) !== __privateGet(this, _revision)) return this.checkpoint();
11286
11486
  });
11287
- __privateGet(this, _records).set(id, next);
11288
- return copy(next);
11487
+ }
11488
+ isCheckpointCurrent() {
11489
+ return !__privateGet(this, _failure) && !__privateGet(this, _closed) && __privateGet(this, _committed) === __privateGet(this, _revision);
11490
+ }
11491
+ async close() {
11492
+ await this.checkpoint();
11493
+ __privateSet(this, _closed, true);
11494
+ __privateGet(this, _backend).close();
11289
11495
  }
11290
11496
  };
11497
+ _backend = new WeakMap();
11291
11498
  _records = new WeakMap();
11499
+ _revision = new WeakMap();
11500
+ _committed = new WeakMap();
11501
+ _queued = new WeakMap();
11502
+ _failure = new WeakMap();
11503
+ _closed = new WeakMap();
11504
+ var BrowserCustodyStore = _BrowserCustodyStore;
11505
+ async function openBrowserCustody(base) {
11506
+ if (!globalThis.indexedDB || !globalThis.navigator?.locks) throw new Error("Durable browser custody needs IndexedDB and Web Locks. Use a supported browser on HTTPS and allow site storage.");
11507
+ const name = `nomos-custody-v1:${base.replace(/\/+$/, "")}`;
11508
+ let release;
11509
+ let acquired;
11510
+ let refuse;
11511
+ const ready = new Promise((resolve, reject) => {
11512
+ acquired = resolve;
11513
+ refuse = reject;
11514
+ });
11515
+ const held = new Promise((resolve) => {
11516
+ release = resolve;
11517
+ });
11518
+ void navigator.locks.request(name, { ifAvailable: true }, async (lock) => {
11519
+ if (!lock) {
11520
+ refuse(new Error("This application's workspace is open in another tab. Close that tab and retry; your saved data is preserved."));
11521
+ return;
11522
+ }
11523
+ acquired();
11524
+ await held;
11525
+ }).catch(refuse);
11526
+ await ready;
11527
+ let db;
11528
+ try {
11529
+ db = await new Promise((resolve, reject) => {
11530
+ const request = indexedDB.open(name, 1);
11531
+ request.onupgradeneeded = () => request.result.createObjectStore("custody");
11532
+ request.onsuccess = () => resolve(request.result);
11533
+ request.onerror = () => reject(request.error);
11534
+ request.onblocked = () => reject(new Error("Browser custody upgrade is blocked by another tab. Close it and retry."));
11535
+ });
11536
+ } catch (error) {
11537
+ release();
11538
+ throw error;
11539
+ }
11540
+ return BrowserCustodyStore.open({
11541
+ load: () => new Promise((resolve, reject) => {
11542
+ const tx = db.transaction("custody", "readonly");
11543
+ const read = tx.objectStore("custody").get("current");
11544
+ tx.oncomplete = () => resolve(read.result);
11545
+ tx.onabort = () => reject(tx.error ?? new Error("Browser custody read aborted"));
11546
+ }),
11547
+ commit: (snapshot) => new Promise((resolve, reject) => {
11548
+ const tx = db.transaction("custody", "readwrite", { durability: "strict" });
11549
+ tx.objectStore("custody").put(snapshot, "current");
11550
+ tx.oncomplete = () => resolve();
11551
+ tx.onabort = () => reject(tx.error ?? new Error("Browser custody transaction aborted"));
11552
+ }),
11553
+ close: () => {
11554
+ db.close();
11555
+ release();
11556
+ }
11557
+ });
11558
+ }
11292
11559
 
11293
11560
  // ../../platform-shells/shared/peer_office_host.ts
11294
11561
  init_define_NOMOS_KERNEL_RELEASE();
@@ -13883,7 +14150,7 @@
13883
14150
  _material = new WeakMap();
13884
14151
 
13885
14152
  // ../src/runtime/credential_sessions.ts
13886
- var copy2 = (bytes) => bytes.slice();
14153
+ var copy = (bytes) => bytes.slice();
13887
14154
  var _bindings, _vault, _clock3, _contexts, _CredentialSessions_instances, refreshCapability_fn, applyProof_fn, authorSecret_fn;
13888
14155
  var CredentialSessions = class {
13889
14156
  constructor(bindings, vault, clock) {
@@ -13963,7 +14230,7 @@
13963
14230
  if (secret.byteLength !== 32) {
13964
14231
  throw new Error(`session '${session}' has a malformed enrolled-device signing capability`);
13965
14232
  }
13966
- return copy2(secret);
14233
+ return copy(secret);
13967
14234
  }
13968
14235
  /** Whether this office's shell declared it a custodian by supplying its admission workload key. */
13969
14236
  holdsOfficeAdmissionKey() {
@@ -13977,7 +14244,7 @@
13977
14244
  throw new Error("this office holds recipient custody but its shell supplied no admission workload key");
13978
14245
  }
13979
14246
  if (secret.byteLength !== 32) throw new Error("this office's admission workload key is malformed");
13980
- return copy2(secret);
14247
+ return copy(secret);
13981
14248
  }
13982
14249
  authToken(session) {
13983
14250
  const capability = __privateGet(this, _bindings).credentialCapabilityFor(session);
@@ -13986,13 +14253,13 @@
13986
14253
  /** Background replica work names the durable capability directly; it does
13987
14254
  * not manufacture an interaction session merely to reach the same vault. */
13988
14255
  authTokenForCapability(capability) {
13989
- return copy2(__privateGet(this, _vault).authToken(capability) ?? new Uint8Array());
14256
+ return copy(__privateGet(this, _vault).authToken(capability) ?? new Uint8Array());
13990
14257
  }
13991
14258
  /** Background replica recovery addresses the durable capability directly;
13992
14259
  * this is the same vault slot an interaction session would select. */
13993
14260
  authorSecretForCapabilityIfPresent(capability) {
13994
14261
  const secret = __privateGet(this, _vault).authorSecret(capability);
13995
- return secret === void 0 || secret.byteLength === 0 ? void 0 : copy2(secret);
14262
+ return secret === void 0 || secret.byteLength === 0 ? void 0 : copy(secret);
13996
14263
  }
13997
14264
  /** The enrolled-device secret the session's capability holds, if any; a device challenge derives from it. */
13998
14265
  authorSecretIfPresent(session) {
@@ -18233,7 +18500,7 @@
18233
18500
  // ../src/runtime/read_maintenance_desk.ts
18234
18501
  init_define_NOMOS_KERNEL_RELEASE();
18235
18502
  init_shims();
18236
- var _queries3, _sessions5, _trace6, _observer, _clock6, _pending, _sequence8, _revision, _ReadMaintenanceDesk_instances, schedule_fn, nextDelay_fn;
18503
+ var _queries3, _sessions5, _trace6, _observer, _clock6, _pending, _sequence8, _revision2, _ReadMaintenanceDesk_instances, schedule_fn, nextDelay_fn;
18237
18504
  var ReadMaintenanceDesk = class {
18238
18505
  constructor(queries, sessions, trace, clock, observer = {}) {
18239
18506
  __privateAdd(this, _ReadMaintenanceDesk_instances);
@@ -18244,7 +18511,7 @@
18244
18511
  __privateAdd(this, _clock6);
18245
18512
  __privateAdd(this, _pending, /* @__PURE__ */ new Map());
18246
18513
  __privateAdd(this, _sequence8, 0n);
18247
- __privateAdd(this, _revision, 0);
18514
+ __privateAdd(this, _revision2, 0);
18248
18515
  __privateSet(this, _queries3, queries);
18249
18516
  __privateSet(this, _sessions5, sessions);
18250
18517
  __privateSet(this, _trace6, trace);
@@ -18295,7 +18562,7 @@
18295
18562
  })
18296
18563
  });
18297
18564
  }
18298
- __privateSet(this, _revision, __privateGet(this, _revision) + 1);
18565
+ __privateSet(this, _revision2, __privateGet(this, _revision2) + 1);
18299
18566
  __privateGet(this, _observer).readReady?.(workspace);
18300
18567
  }
18301
18568
  /**
@@ -18396,7 +18663,7 @@
18396
18663
  const format = localCopyFormatRefusal(error);
18397
18664
  if (format !== void 0) {
18398
18665
  __privateGet(this, _pending).delete(workspace);
18399
- __privateSet(this, _revision, __privateGet(this, _revision) + 1);
18666
+ __privateSet(this, _revision2, __privateGet(this, _revision2) + 1);
18400
18667
  __privateGet(this, _observer).localCopyUnreadable?.(workspace, format);
18401
18668
  __privateGet(this, _trace6).emit(demand.session, {
18402
18669
  case: "maintenanceProgress",
@@ -18437,20 +18704,20 @@
18437
18704
  }
18438
18705
  /** Drop any demand for a workspace no maintenance can serve (an unreadable copy). */
18439
18706
  forget(workspace) {
18440
- if (__privateGet(this, _pending).delete(workspace)) __privateSet(this, _revision, __privateGet(this, _revision) + 1);
18707
+ if (__privateGet(this, _pending).delete(workspace)) __privateSet(this, _revision2, __privateGet(this, _revision2) + 1);
18441
18708
  }
18442
18709
  hasPending() {
18443
18710
  return __privateGet(this, _pending).size > 0;
18444
18711
  }
18445
18712
  get revision() {
18446
- return __privateGet(this, _revision);
18713
+ return __privateGet(this, _revision2);
18447
18714
  }
18448
18715
  pendingWorkspaces() {
18449
18716
  return new Set(__privateGet(this, _pending).keys());
18450
18717
  }
18451
18718
  clear() {
18452
18719
  __privateGet(this, _pending).clear();
18453
- __privateSet(this, _revision, __privateGet(this, _revision) + 1);
18720
+ __privateSet(this, _revision2, __privateGet(this, _revision2) + 1);
18454
18721
  }
18455
18722
  };
18456
18723
  _queries3 = new WeakMap();
@@ -18460,7 +18727,7 @@
18460
18727
  _clock6 = new WeakMap();
18461
18728
  _pending = new WeakMap();
18462
18729
  _sequence8 = new WeakMap();
18463
- _revision = new WeakMap();
18730
+ _revision2 = new WeakMap();
18464
18731
  _ReadMaintenanceDesk_instances = new WeakSet();
18465
18732
  schedule_fn = function(workspace, cause, session, command, awaited = false) {
18466
18733
  if (__privateGet(this, _observer).isLocalCopyUnreadable?.(workspace)) return;
@@ -18488,7 +18755,7 @@
18488
18755
  for (const [key, value] of entries.filter(([key2]) => key2 === workspace)) __privateGet(this, _pending).set(key, value);
18489
18756
  for (const [key, value] of entries.filter(([key2]) => key2 !== workspace)) __privateGet(this, _pending).set(key, value);
18490
18757
  }
18491
- __privateSet(this, _revision, __privateGet(this, _revision) + 1);
18758
+ __privateSet(this, _revision2, __privateGet(this, _revision2) + 1);
18492
18759
  if (!existing || existing.read?.cause !== read?.cause || existing.background?.cause !== background?.cause) {
18493
18760
  __privateGet(this, _trace6).emit(session ?? existing?.session, {
18494
18761
  case: "maintenanceProgress",
@@ -20817,10 +21084,11 @@
20817
21084
  failures: 0,
20818
21085
  origin,
20819
21086
  publisher: !binding.cloudBound,
20820
- published: !binding.cloudBound ? head : void 0
21087
+ published: !binding.cloudBound ? head : void 0,
21088
+ wasResident: this.kernel.isResident(binding.workspace) !== false
20821
21089
  };
20822
21090
  __privateGet(this, _links).set(binding.workspace, link);
20823
- __privateMethod(this, _LiveCorrespondenceDesk_instances, open_fn2).call(this, link);
21091
+ if (link.wasResident) __privateMethod(this, _LiveCorrespondenceDesk_instances, open_fn2).call(this, link);
20824
21092
  }
20825
21093
  changed(workspace) {
20826
21094
  const link = __privateGet(this, _links).get(workspace);
@@ -20934,9 +21202,11 @@
20934
21202
  let wake;
20935
21203
  for (const link of __privateGet(this, _links).values()) {
20936
21204
  if (this.kernel.isResident(link.binding.workspace) === false) {
20937
- this.disconnect(link.binding.workspace);
21205
+ if (link.wasResident) this.disconnect(link.binding.workspace);
21206
+ else wake = wake === void 0 || wake > 250n ? 250n : wake;
20938
21207
  continue;
20939
21208
  }
21209
+ link.wasResident = true;
20940
21210
  if (link.state === "opening" && now >= link.due) {
20941
21211
  __privateMethod(this, _LiveCorrespondenceDesk_instances, effect_fn).call(this, link, { case: "close", value: true });
20942
21212
  link.state = "closed";
@@ -21019,11 +21289,11 @@
21019
21289
  // ../src/runtime/peer_lifecycle.ts
21020
21290
  init_define_NOMOS_KERNEL_RELEASE();
21021
21291
  init_shims();
21022
- var _events3, _closed;
21292
+ var _events3, _closed2;
21023
21293
  var PeerLifecycle = class {
21024
21294
  constructor(events, runtimeVersion) {
21025
21295
  __privateAdd(this, _events3);
21026
- __privateAdd(this, _closed, false);
21296
+ __privateAdd(this, _closed2, false);
21027
21297
  __privateSet(this, _events3, events);
21028
21298
  __privateGet(this, _events3).emit(void 0, {
21029
21299
  case: "ready",
@@ -21037,21 +21307,21 @@
21037
21307
  });
21038
21308
  }
21039
21309
  assertAccepting(request) {
21040
- if (__privateGet(this, _closed) && request.command.case !== "closeRealm") {
21310
+ if (__privateGet(this, _closed2) && request.command.case !== "closeRealm") {
21041
21311
  throw new Error("Nomos peer runtime is closed");
21042
21312
  }
21043
21313
  }
21044
21314
  close() {
21045
- if (__privateGet(this, _closed)) return false;
21046
- __privateSet(this, _closed, true);
21315
+ if (__privateGet(this, _closed2)) return false;
21316
+ __privateSet(this, _closed2, true);
21047
21317
  return true;
21048
21318
  }
21049
21319
  get closed() {
21050
- return __privateGet(this, _closed);
21320
+ return __privateGet(this, _closed2);
21051
21321
  }
21052
21322
  };
21053
21323
  _events3 = new WeakMap();
21054
- _closed = new WeakMap();
21324
+ _closed2 = new WeakMap();
21055
21325
 
21056
21326
  // ../src/runtime/records_desk.ts
21057
21327
  init_define_NOMOS_KERNEL_RELEASE();
@@ -21541,6 +21811,46 @@
21541
21811
  init_define_NOMOS_KERNEL_RELEASE();
21542
21812
  init_shims();
21543
21813
 
21814
+ // ../src/runtime/peer_desk_store.ts
21815
+ init_define_NOMOS_KERNEL_RELEASE();
21816
+ init_shims();
21817
+ var recordId = (namespace, key) => `${namespace.length}:${namespace}${key}`;
21818
+ var copy2 = (record) => ({
21819
+ ...record,
21820
+ value: record.value.slice()
21821
+ });
21822
+ var _records2;
21823
+ var MemoryPeerDeskStore = class {
21824
+ constructor() {
21825
+ __privateAdd(this, _records2, /* @__PURE__ */ new Map());
21826
+ }
21827
+ list(namespace) {
21828
+ return [...__privateGet(this, _records2).values()].filter((record) => record.namespace === namespace).sort((left, right) => left.key.localeCompare(right.key)).map(copy2);
21829
+ }
21830
+ compareExchange(namespace, key, expectedRevision, value) {
21831
+ const id = recordId(namespace, key);
21832
+ const current = __privateGet(this, _records2).get(id);
21833
+ if (current?.revision !== expectedRevision) {
21834
+ throw new Error(
21835
+ `peer desk record '${namespace}/${key}' changed at revision ${current?.revision ?? "absent"}`
21836
+ );
21837
+ }
21838
+ if (value === void 0) {
21839
+ __privateGet(this, _records2).delete(id);
21840
+ return void 0;
21841
+ }
21842
+ const next = Object.freeze({
21843
+ namespace,
21844
+ key,
21845
+ revision: (current?.revision ?? 0n) + 1n,
21846
+ value: value.slice()
21847
+ });
21848
+ __privateGet(this, _records2).set(id, next);
21849
+ return copy2(next);
21850
+ }
21851
+ };
21852
+ _records2 = new WeakMap();
21853
+
21544
21854
  // ../src/runtime/correspondence_recovery.ts
21545
21855
  init_define_NOMOS_KERNEL_RELEASE();
21546
21856
  init_shims();
@@ -26967,7 +27277,7 @@
26967
27277
  }
26968
27278
  var INTERACTIVE_PEER_CLASSES = /* @__PURE__ */ new Set(["personal-device", "browser"]);
26969
27279
  var INTERACTION_FIRST_MILLIS = 15e3;
26970
- var _kernel25, _sessions14, _interactivePeer, _interaction, _trace13, _credentials7, _credentialRecovery, _deviceIdentity, _receivingGroup2, _modelAdoption, _deviceChallenges, _enrolledCapabilities, _custody4, _readability3, _origins5, _seat2, _custodyAdmission, _correspondence3, _birthCustody, _placement5, _access, _identity2, _custodianPlacement, _identityRecovery, _queries8, _application3, _compatibility2, _custodyVerification, _commandPreparation, _applicationReadiness, _authenticationReadiness, _lawPackages, _readMaintenance, _readResponses, _residency4, _residencyPins, _subscriptions5, _follows3, _replicaInventory, _placementDiscovery2, _live3, _records2, _historicQueries, _authoringPreflight, _recovery, _lifecycle, _maintenance2, _background2, _paperSlots, _retentionObserver, _admissionDurability, _historyAcquisition, _responses, _PeerOffice_instances, fenced_fn, handleRequest_fn, localCopyUnreadable_fn, probeLocalCopyFormat_fn, protectedResidents_fn, bindInteraction_fn, keepCustodianPlacement_fn, dispatchRequest_fn, historyCredentialCapability_fn, preferredCredentialCapability_fn, correspondenceResponse_fn, authenticationReadinessResponse_fn, completedKernelCall_fn, modelAdoptionResponse_fn, receivingGroupResponse_fn, deviceIdentityResponse_fn, deviceChallengeFor_fn, deviceChallengeForCapability_fn, credentialRecoveryResponse_fn, afterCredentialKernelCall_fn, acknowledgedWhenDurable_fn, admissionDurabilityResponse_fn, birthCustodyResponse_fn, identityResponse_fn, identityRecoveryResponse_fn, response_fn, failure_fn, custodyRequired_fn, kernelResidencyRequired_fn, candidateCustodyRequired_fn;
27280
+ var _kernel25, _sessions14, _interactivePeer, _interaction, _trace13, _credentials7, _credentialRecovery, _deviceIdentity, _receivingGroup2, _modelAdoption, _deviceChallenges, _enrolledCapabilities, _custody4, _readability3, _origins5, _seat2, _custodyAdmission, _correspondence3, _birthCustody, _placement5, _access, _identity2, _custodianPlacement, _identityRecovery, _queries8, _application3, _compatibility2, _custodyVerification, _commandPreparation, _applicationReadiness, _authenticationReadiness, _lawPackages, _readMaintenance, _readResponses, _residency4, _residencyPins, _subscriptions5, _follows3, _replicaInventory, _placementDiscovery2, _live3, _records3, _historicQueries, _authoringPreflight, _recovery, _lifecycle, _maintenance2, _background2, _paperSlots, _retentionObserver, _admissionDurability, _historyAcquisition, _responses, _PeerOffice_instances, fenced_fn, handleRequest_fn, localCopyUnreadable_fn, probeLocalCopyFormat_fn, protectedResidents_fn, bindInteraction_fn, keepCustodianPlacement_fn, dispatchRequest_fn, historyCredentialCapability_fn, preferredCredentialCapability_fn, correspondenceResponse_fn, authenticationReadinessResponse_fn, completedKernelCall_fn, modelAdoptionResponse_fn, receivingGroupResponse_fn, deviceIdentityResponse_fn, deviceChallengeFor_fn, deviceChallengeForCapability_fn, credentialRecoveryResponse_fn, afterCredentialKernelCall_fn, acknowledgedWhenDurable_fn, admissionDurabilityResponse_fn, birthCustodyResponse_fn, identityResponse_fn, identityRecoveryResponse_fn, response_fn, failure_fn, custodyRequired_fn, kernelResidencyRequired_fn, candidateCustodyRequired_fn;
26971
27281
  var PeerOffice = class {
26972
27282
  constructor(kernel, credentials, profile, observations, custodyStorage, peerDeskStore) {
26973
27283
  __privateAdd(this, _PeerOffice_instances);
@@ -27019,7 +27329,7 @@
27019
27329
  __privateAdd(this, _replicaInventory);
27020
27330
  __privateAdd(this, _placementDiscovery2);
27021
27331
  __privateAdd(this, _live3);
27022
- __privateAdd(this, _records2);
27332
+ __privateAdd(this, _records3);
27023
27333
  __privateAdd(this, _historicQueries);
27024
27334
  __privateAdd(this, _authoringPreflight);
27025
27335
  __privateAdd(this, _recovery);
@@ -27273,7 +27583,7 @@
27273
27583
  command.criterion === AuthenticationReadinessCriterion.BIRTH_EVIDENCE
27274
27584
  )
27275
27585
  ));
27276
- __privateSet(this, _records2, new RecordsDesk(
27586
+ __privateSet(this, _records3, new RecordsDesk(
27277
27587
  __privateGet(this, _kernel25),
27278
27588
  __privateGet(this, _queries8),
27279
27589
  __privateGet(this, _sessions14),
@@ -27727,7 +28037,7 @@
27727
28037
  _replicaInventory = new WeakMap();
27728
28038
  _placementDiscovery2 = new WeakMap();
27729
28039
  _live3 = new WeakMap();
27730
- _records2 = new WeakMap();
28040
+ _records3 = new WeakMap();
27731
28041
  _historicQueries = new WeakMap();
27732
28042
  _authoringPreflight = new WeakMap();
27733
28043
  _recovery = new WeakMap();
@@ -28100,29 +28410,29 @@
28100
28410
  case "listWorkspaceMoments":
28101
28411
  return __privateMethod(this, _PeerOffice_instances, response_fn).call(this, request, {
28102
28412
  case: "workspaceMoments",
28103
- value: __privateGet(this, _records2).moments(request, request.command.value)
28413
+ value: __privateGet(this, _records3).moments(request, request.command.value)
28104
28414
  });
28105
28415
  case "estimateWorkspaceTransfer":
28106
28416
  return __privateMethod(this, _PeerOffice_instances, response_fn).call(this, request, {
28107
28417
  case: "workspaceTransferEstimate",
28108
- value: __privateGet(this, _records2).transferEstimate(request, request.command.value)
28418
+ value: __privateGet(this, _records3).transferEstimate(request, request.command.value)
28109
28419
  });
28110
28420
  case "readWorkspaceGenesis":
28111
28421
  return __privateMethod(this, _PeerOffice_instances, response_fn).call(this, request, {
28112
28422
  case: "workspaceGenesis",
28113
- value: __privateGet(this, _records2).genesis(request, request.command.value)
28423
+ value: __privateGet(this, _records3).genesis(request, request.command.value)
28114
28424
  });
28115
28425
  case "listChildWorkspaces":
28116
28426
  return __privateMethod(this, _PeerOffice_instances, response_fn).call(this, request, {
28117
28427
  case: "childWorkspaces",
28118
- value: __privateGet(this, _records2).children(request, request.command.value)
28428
+ value: __privateGet(this, _records3).children(request, request.command.value)
28119
28429
  });
28120
28430
  // The kernel still answers this in its transitional value arm; the desk
28121
28431
  // decodes it once so no client infers a version status for itself.
28122
28432
  case "checkReferenceVersions":
28123
28433
  return __privateMethod(this, _PeerOffice_instances, response_fn).call(this, request, {
28124
28434
  case: "referenceVersions",
28125
- value: __privateGet(this, _records2).referenceVersions(request, request.command.value)
28435
+ value: __privateGet(this, _records3).referenceVersions(request, request.command.value)
28126
28436
  });
28127
28437
  // A naming answer, not a custody read: it binds no session and mounts
28128
28438
  // nothing, so a client can ask which workspace a keyed birth addresses
@@ -28937,7 +29247,7 @@
28937
29247
  });
28938
29248
  }
28939
29249
  };
28940
- async function drivePeerFrame(runner, initialFrame, fetchImpl = globalThis.fetch, custody, bornCustody, credentialRefresh, yieldWakeToCaller = false, deviceIdentity, lawPackage, yieldLocalReadToCaller = false, yieldHistoryToCaller = false) {
29250
+ async function drivePeerFrame(runner, initialFrame, fetchImpl = globalThis.fetch, custody, bornCustody, credentialRefresh, yieldWakeToCaller = false, deviceIdentity, lawPackage, yieldLocalReadToCaller = false, yieldHistoryToCaller = false, performExternalEffect) {
28941
29251
  const persistBornCustody = bornCustody ?? (custody?.persistBornCustody ? (effect) => custody.persistBornCustody(effect) : void 0);
28942
29252
  let responseFrame = runner.handleFrame(initialFrame);
28943
29253
  const satisfied = /* @__PURE__ */ new Set();
@@ -29073,12 +29383,10 @@
29073
29383
  if (pending.effect.case === "historyAcquisition" && (yieldHistoryToCaller || !custody?.advanceHistory)) {
29074
29384
  return responseFrame;
29075
29385
  }
29076
- if (pending.effect.case === "refreshCredential" && credentialRefresh === externalPeerEffect) return responseFrame;
29077
- if (pending.effect.case === "deviceIdentity" && deviceIdentity === externalPeerEffect) return responseFrame;
29078
- if (pending.effect.case === "lawPackage" && lawPackage === externalPeerEffect) return responseFrame;
29079
29386
  if (pending.effect.case === "wake" && yieldWakeToCaller) return responseFrame;
29080
- if (pending.effect.case === "consoleEnrolment") return responseFrame;
29081
- const receipt = pending.effect.case === "http" ? await executeHttpEffect(pending.effect.value, fetchImpl) : pending.effect.case === "gitFetch" ? await executeGitFetchWithAlongside(pending.effect.value, fetchImpl) : pending.effect.case === "gitPush" ? await executeGitPushEffect(pending.effect.value, fetchImpl) : pending.effect.case === "persistBornCustody" ? create(PeerEffectReceiptSchema, {
29387
+ const external = pending.effect.case === "refreshCredential" && credentialRefresh === externalPeerEffect || pending.effect.case === "deviceIdentity" && deviceIdentity === externalPeerEffect || pending.effect.case === "lawPackage" && lawPackage === externalPeerEffect || pending.effect.case === "consoleEnrolment";
29388
+ if (external && !performExternalEffect) return responseFrame;
29389
+ const receipt = external ? await performExternalEffect(pending) : pending.effect.case === "http" ? await executeHttpEffect(pending.effect.value, fetchImpl) : pending.effect.case === "gitFetch" ? await executeGitFetchWithAlongside(pending.effect.value, fetchImpl) : pending.effect.case === "gitPush" ? await executeGitPushEffect(pending.effect.value, fetchImpl) : pending.effect.case === "persistBornCustody" ? create(PeerEffectReceiptSchema, {
29082
29390
  effectId: pending.effect.value.effectId,
29083
29391
  outcome: {
29084
29392
  case: "bornCustodyPersisted",
@@ -29106,7 +29414,7 @@
29106
29414
  async function executeHistoryAcquisitionEffect(effect, custody) {
29107
29415
  try {
29108
29416
  if (!custody.advanceHistory) throw new Error("platform shell has no history acquisition capability");
29109
- const progress = await custody.advanceHistory(effect.workspace);
29417
+ const progress = await custody.advanceHistory(effect.workspace, effect.credentialCapability);
29110
29418
  return create(PeerEffectReceiptSchema, {
29111
29419
  effectId: effect.effectId,
29112
29420
  outcome: {
@@ -29339,7 +29647,7 @@
29339
29647
  };
29340
29648
  };
29341
29649
  function openPeerOfficeHost(kernel, shell, fetchImpl = globalThis.fetch, maintenanceSettled, postEvent2 = () => {
29342
- }, credentialRefresh, yieldWakeToCaller = false, deviceIdentity, lawPackage) {
29650
+ }, credentialRefresh, yieldWakeToCaller = false, deviceIdentity, lawPackage, performExternalEffect) {
29343
29651
  let runner;
29344
29652
  const configuredOrigins = new Set((shell.providerOrigins?.() ?? []).map((provider) => originOf(provider)).filter((origin) => origin !== void 0));
29345
29653
  const permittedSocket = (url) => {
@@ -29348,10 +29656,10 @@
29348
29656
  return origin !== void 0 && configuredOrigins.has(origin);
29349
29657
  };
29350
29658
  const sockets = socketEffects(
29351
- (frame) => drivePeerFrame(runner, frame, fetchImpl, shell.custodyPort(), void 0, void 0, false, deviceIdentity, lawPackage),
29659
+ (frame) => drivePeerFrame(runner, frame, fetchImpl, shell.custodyPort(), void 0, void 0, false, deviceIdentity, lawPackage, false, false, performExternalEffect),
29352
29660
  permittedSocket
29353
29661
  );
29354
- const credentials = credentialEffects((frame) => drivePeerFrame(runner, frame, fetchImpl, shell.custodyPort(), void 0, credentialRefresh, false, deviceIdentity, lawPackage), credentialRefresh);
29662
+ const credentials = credentialEffects((frame) => drivePeerFrame(runner, frame, fetchImpl, shell.custodyPort(), void 0, credentialRefresh, false, deviceIdentity, lawPackage, false, false, performExternalEffect), credentialRefresh);
29355
29663
  runner = createPeerOfficeFrameRunner(
29356
29664
  kernel,
29357
29665
  shell.credentials(),
@@ -29376,7 +29684,10 @@
29376
29684
  credentialRefresh,
29377
29685
  false,
29378
29686
  deviceIdentity,
29379
- lawPackage
29687
+ lawPackage,
29688
+ false,
29689
+ false,
29690
+ performExternalEffect
29380
29691
  );
29381
29692
  },
29382
29693
  shell.peerDeskStore()
@@ -29428,7 +29739,10 @@
29428
29739
  credentialRefresh,
29429
29740
  yieldWakeToCaller,
29430
29741
  deviceIdentity,
29431
- lawPackage
29742
+ lawPackage,
29743
+ false,
29744
+ false,
29745
+ performExternalEffect
29432
29746
  );
29433
29747
  },
29434
29748
  settleRetention: (withinMillis) => runner.settleRetention(withinMillis),
@@ -29537,6 +29851,7 @@
29537
29851
  // one constitutional genesis offer. WorkspaceAccessDesk decides whether
29538
29852
  // that exact request may proceed against the unborn kernel mount.
29539
29853
  async openCustody(workspace) {
29854
+ if (physical.openLocalCustody) return physical.openLocalCustody(workspace);
29540
29855
  await custody.acquireMain(workspace, await ledgerFor(workspace));
29541
29856
  return {};
29542
29857
  },
@@ -29552,7 +29867,12 @@
29552
29867
  },
29553
29868
  persistBornCustody: (effect) => physical.persistBornCustody(effect),
29554
29869
  retainFrontier: (effect) => physical.retainFrontier(effect),
29555
- ...physical.completeHistoryInLocalCustody ? {
29870
+ ...physical.advanceHistory ? {
29871
+ advanceHistory: (workspace, capability) => {
29872
+ const credential = capability ? __privateGet(this, _credentials8).authToken(capability) : authToken;
29873
+ return physical.advanceHistory(workspace, credential && new TextDecoder().decode(credential));
29874
+ }
29875
+ } : physical.completeHistoryInLocalCustody ? {
29556
29876
  // The kernel mounts a shallow working copy; the peer's own Git custody is deep.
29557
29877
  // One bounded slice per call; the Peer Office decides whether and when to take the next.
29558
29878
  async advanceHistory(workspace) {
@@ -34689,92 +35009,72 @@
34689
35009
  }
34690
35010
 
34691
35011
  // ../../platform-shells/browser/peer.ts
34692
- var randomReplica = () => {
34693
- const bytes = globalThis.crypto.getRandomValues(new Uint8Array(8));
34694
- let value = 0n;
34695
- for (const byte of bytes) value = value << 8n | BigInt(byte);
34696
- return value & (1n << 63n) - 1n;
34697
- };
34698
35012
  async function openBrowserPeer(options) {
34699
- const fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
34700
- const selected = await selectReleaseKernel({
34701
- base: options.base,
34702
- release: options.release,
34703
- fetchImpl: (input, init) => fetchImpl(input, init),
34704
- cache: options.kernelCache
34705
- });
34706
- const machine = await createKernelMachine({
34707
- wasmModule: await WebAssembly.compile(selected.wasm),
34708
- bootstrapLawUsdz: selected.bootstrapLaw,
34709
- nomosLawUsdz: selected.controllerLaw,
34710
- replica: options.replica ?? randomReplica(),
34711
- trustRootPublicKey: options.trustRootPublicKey
34712
- });
34713
- const kernel = kernelExecutionDesk(machine);
34714
- const custodyDesk = gitCustodyDesk(kernel, fetchImpl);
34715
- const kernelStore = {
34716
- // The current browser store is writable but session-local. This capability
34717
- // must not be presented as proof of persistence across browser restarts.
34718
- canRetainChanges: () => true,
34719
- hasLocalCustody: (workspace) => kernel.isResident(workspace),
34720
- retainFrontier: async (effect) => ({
34721
- $typeName: "nomos.runtime.v2.FrontierRetained",
34722
- workspace: effect.workspace,
34723
- branch: effect.branch,
34724
- head: effect.head,
34725
- retained: false,
34726
- detail: "browser peer has no durable local custody",
34727
- refs: []
34728
- }),
34729
- ledgerFor: (workspace) => {
34730
- throw new Error(`browser peer holds no ledger for '${workspace}' beside the custodian`);
34731
- },
34732
- // A born child already lives in the kernel's own Git store; persisting it means witnessing that.
34733
- persistBornCustody: async (effect) => create(PersistBornCustodyReceiptSchema, {
34734
- children: effect.children.map((born) => {
34735
- const workspace = born.child?.workspace ?? "";
34736
- const head = born.child?.head ?? "";
34737
- const persisted = workspace.length > 0 && head.length > 0 && kernel.branchHead(workspace, "main") === head && born.publication.every((item) => item.ref && kernel.branchHead(workspace, item.ref.reference) === item.ref.oid);
34738
- return create(PersistedBornCustodySchema, {
34739
- workspace,
34740
- head,
34741
- persisted,
34742
- refs: persisted ? born.publication.map((item) => item.ref) : [],
34743
- detail: persisted ? "born custody already persisted by the kernel's Git custody" : "the kernel's Git custody does not contain the born frontier"
34744
- });
34745
- })
34746
- })
34747
- };
34748
- const shell = new PeerPlatformShell(
34749
- custodyDesk,
34750
- withWorkspaceDiscovery(kernelStore, {
35013
+ const storage = options.custodyStore ?? await openBrowserCustody(options.base);
35014
+ try {
35015
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch.bind(globalThis);
35016
+ const selected = await selectReleaseKernel({
35017
+ base: options.base,
35018
+ release: options.release,
35019
+ fetchImpl: browserRuntimeFetch(options.base, fetchImpl, globalThis.caches),
35020
+ cache: options.kernelCache
35021
+ });
35022
+ const machine = await createKernelMachine({
35023
+ wasmModule: await WebAssembly.compile(selected.wasm),
35024
+ bootstrapLawUsdz: selected.bootstrapLaw,
35025
+ nomosLawUsdz: selected.controllerLaw,
35026
+ replica: options.replica ?? storage.replica,
35027
+ trustRootPublicKey: options.trustRootPublicKey
35028
+ }, storage.filesystem, storage.changed);
35029
+ const kernel = kernelExecutionDesk(machine);
35030
+ const custodyDesk = gitCustodyDesk(kernel, fetchImpl);
35031
+ const kernelStore = browserKernelCustody(kernel, () => storage.checkpoint(), () => storage.isCheckpointCurrent());
35032
+ const physical = withWorkspaceDiscovery(kernelStore, {
34751
35033
  providers: options.discoveryProviders ?? [options.base],
34752
35034
  fetch: (input, init) => fetchImpl(input, init)
34753
- }),
34754
- options.profile,
34755
- void 0,
34756
- // Deliberately explicit until the browser shell grows a durable adapter.
34757
- // Production native hosts cannot fall through to this implementation.
34758
- new MemoryPeerDeskStore()
34759
- );
34760
- const office = openPeerOfficeHost(
34761
- kernel,
34762
- shell,
34763
- fetchImpl,
34764
- void 0,
34765
- options.postEvent,
34766
- options.credentialRefresh,
34767
- false,
34768
- options.deviceIdentity,
34769
- options.lawPackage
34770
- );
34771
- return {
34772
- invoke: (frame) => office.invoke({
34773
- workspace: fromBinary(RuntimeRequestSchema, frame).target?.workspace,
34774
- requestBytes: frame
34775
- }),
34776
- close: () => office.close()
34777
- };
35035
+ });
35036
+ physical.advanceHistory = browserHistoryCustody(custodyDesk, physical.discovery, options.discoveryProviders ?? [options.base], fetchImpl);
35037
+ const shell = new PeerPlatformShell(
35038
+ custodyDesk,
35039
+ physical,
35040
+ { ...options.profile, identity: storage.identity },
35041
+ void 0,
35042
+ { list: (namespace) => storage.list(namespace), compareExchange: (...args) => storage.compareExchange(...args) }
35043
+ );
35044
+ const office = openPeerOfficeHost(
35045
+ kernel,
35046
+ shell,
35047
+ fetchImpl,
35048
+ void 0,
35049
+ options.postEvent,
35050
+ options.credentialRefresh,
35051
+ false,
35052
+ options.deviceIdentity,
35053
+ options.lawPackage,
35054
+ options.performExternalEffect
35055
+ );
35056
+ return {
35057
+ invoke: async (frame) => {
35058
+ storage.assertUsable();
35059
+ const result = await office.invoke({
35060
+ workspace: fromBinary(RuntimeRequestSchema, frame).target?.workspace,
35061
+ requestBytes: frame
35062
+ });
35063
+ await storage.checkpoint();
35064
+ return result;
35065
+ },
35066
+ close: async () => {
35067
+ await office.settleRetention();
35068
+ office.close();
35069
+ await storage.close();
35070
+ machine.dispose();
35071
+ }
35072
+ };
35073
+ } catch (error) {
35074
+ await storage.close().catch(() => {
35075
+ });
35076
+ throw error;
35077
+ }
34778
35078
  }
34779
35079
 
34780
35080
  // ../../platform-shells/browser/entry.ts
@@ -34848,6 +35148,12 @@
34848
35148
  }
34849
35149
  booting = (async () => {
34850
35150
  peer = await openBrowserPeer({
35151
+ performExternalEffect: async (pending) => {
35152
+ if (!window.__nomosPerformEffect) throw new Error("The browser host cannot perform background effects. Update the application and reload.");
35153
+ return fromBinary(PeerEffectReceiptSchema, frameFromBase64(await window.__nomosPerformEffect(
35154
+ frameToBase64(toBinary(CorrespondencePendingSchema, pending))
35155
+ )));
35156
+ },
34851
35157
  credentialRefresh: externalPeerEffect,
34852
35158
  // The embedding Dart/web application owns the device identity store
34853
35159
  // (IndexedDB through the Flutter key store); the page runner keeps none.