@ai-ecoverse/slicc-kernel 1.170.4 → 1.172.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.js CHANGED
@@ -2362,9 +2362,9 @@ var KernelSocket = class _KernelSocket {
2362
2362
  case SO_TYPE:
2363
2363
  return SOCK_STREAM;
2364
2364
  case SO_ERROR: {
2365
- const failed3 = this.failed;
2365
+ const failed5 = this.failed;
2366
2366
  this.failed = void 0;
2367
- return failed3 ? wasiErrno(failed3) : 0;
2367
+ return failed5 ? wasiErrno(failed5) : 0;
2368
2368
  }
2369
2369
  case SO_ACCEPTCONN:
2370
2370
  return this.state === "listening" ? 1 : 0;
@@ -2444,6 +2444,7 @@ var LoopbackNet = class {
2444
2444
  internal = /* @__PURE__ */ new Set();
2445
2445
  reserved = /* @__PURE__ */ new Set();
2446
2446
  facades = /* @__PURE__ */ new Map();
2447
+ proxyStamped;
2447
2448
  nextEphemeral = EPHEMERAL_FIRST;
2448
2449
  route;
2449
2450
  origins;
@@ -2518,9 +2519,15 @@ var LoopbackNet = class {
2518
2519
  this.kernelOnly(port, true);
2519
2520
  this.facades.set(port, name2);
2520
2521
  }
2521
- facadeAt(addr) {
2522
- if (addr.family !== "inet" || !isLoopback(canonicalHost(addr.host))) return void 0;
2523
- return this.facades.get(addr.port);
2522
+ stampProxy(port) {
2523
+ this.proxyStamped = port;
2524
+ }
2525
+ get originsStamped() {
2526
+ return this.proxyStamped !== void 0;
2527
+ }
2528
+ stampsPeers(addr) {
2529
+ if (addr.family !== "inet" || !isLoopback(canonicalHost(addr.host))) return false;
2530
+ return this.facades.has(addr.port) || this.proxyStamped === addr.port;
2524
2531
  }
2525
2532
  activate(addr, start2) {
2526
2533
  this.activators.set(keyOf(addr), start2);
@@ -3695,7 +3702,7 @@ function satisfies(version, range2) {
3695
3702
  }
3696
3703
 
3697
3704
  // src/version.ts
3698
- var KERNEL_VERSION = true ? "1.170.4" : "0.0.0-dev";
3705
+ var KERNEL_VERSION = true ? "1.172.0" : "0.0.0-dev";
3699
3706
  var OS_RELEASE = "6.0.0-slicc";
3700
3707
  function procVersion() {
3701
3708
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -3987,10 +3994,10 @@ async function tierPackages(fs, physical, roots, bins, kernel, global) {
3987
3994
  const own = commandsOf(pkg, manifest);
3988
3995
  const named = new Set(own.map((command) => command.name));
3989
3996
  const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
3990
- const refused3 = engineRefusal(manifest, kernel);
3997
+ const refused4 = engineRefusal(manifest, kernel);
3991
3998
  const name2 = pkg.slice(root.length + 1);
3992
3999
  const dependency = direct?.has(name2) === false;
3993
- const marks = { ...refused3 ? { refused: refused3 } : {}, ...dependency ? { dependency } : {} };
4000
+ const marks = { ...refused4 ? { refused: refused4 } : {}, ...dependency ? { dependency } : {} };
3994
4001
  out.push({
3995
4002
  name: name2,
3996
4003
  pkg,
@@ -4022,7 +4029,7 @@ function winners(tier) {
4022
4029
  }
4023
4030
  return out;
4024
4031
  }
4025
- async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION, refused3, global = /* @__PURE__ */ new Set()) {
4032
+ async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION, refused4, global = /* @__PURE__ */ new Set()) {
4026
4033
  const found = /* @__PURE__ */ new Map();
4027
4034
  const physical = physicalResolver(fs);
4028
4035
  const tiers = (typeof modules === "string" ? [modules] : modules).map(
@@ -4036,7 +4043,7 @@ async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, ke
4036
4043
  const dependencies = [];
4037
4044
  for (const [index, roots] of tiers.entries()) {
4038
4045
  const tier = await tierPackages(fs, physical, roots, index >= binsFrom, kernel, global);
4039
- if (refused3) refused3.push(...tier.flatMap((entry) => entry.commands.filter((c) => c.refused)));
4046
+ if (refused4) refused4.push(...tier.flatMap((entry) => entry.commands.filter((c) => c.refused)));
4040
4047
  await take(tier.filter((entry) => !entry.dependency));
4041
4048
  dependencies.push(tier.filter((entry) => entry.dependency));
4042
4049
  }
@@ -4352,32 +4359,32 @@ function nextFire(schedule, after, utc = false) {
4352
4359
  }
4353
4360
  return null;
4354
4361
  }
4355
- function missedFires(schedule, from, until, utc = false, cap = MISSED_CAP) {
4362
+ function missedFires(schedule, from, until2, utc = false, cap = MISSED_CAP) {
4356
4363
  let count2 = 0;
4357
4364
  let last = null;
4358
4365
  let at = from;
4359
4366
  while (count2 < cap) {
4360
4367
  at = nextFire(schedule, at, utc);
4361
- if (at === null || at > until) return { count: count2, last, more: false };
4368
+ if (at === null || at > until2) return { count: count2, last, more: false };
4362
4369
  last = at;
4363
4370
  count2++;
4364
4371
  }
4365
4372
  const next3 = nextFire(schedule, last, utc);
4366
- if (next3 === null || next3 > until) return { count: count2, last, more: false };
4367
- return { count: count2, last: latestFire(schedule, last, until, utc), more: true };
4373
+ if (next3 === null || next3 > until2) return { count: count2, last, more: false };
4374
+ return { count: count2, last: latestFire(schedule, last, until2, utc), more: true };
4368
4375
  }
4369
- function latestFire(schedule, from, until, utc = false) {
4376
+ function latestFire(schedule, from, until2, utc = false) {
4370
4377
  let found = from;
4371
4378
  for (let span = 6e4; ; span *= 2) {
4372
- const start2 = Math.max(from, until - span);
4379
+ const start2 = Math.max(from, until2 - span);
4373
4380
  const first = nextFire(schedule, start2, utc);
4374
- if (first !== null && first <= until) {
4381
+ if (first !== null && first <= until2) {
4375
4382
  found = first;
4376
4383
  break;
4377
4384
  }
4378
4385
  if (start2 === from) return from;
4379
4386
  }
4380
- for (let at = nextFire(schedule, found, utc); at !== null && at <= until; ) {
4387
+ for (let at = nextFire(schedule, found, utc); at !== null && at <= until2; ) {
4381
4388
  found = at;
4382
4389
  at = nextFire(schedule, at, utc);
4383
4390
  }
@@ -5102,12 +5109,12 @@ var UnlinkedKeeper = class {
5102
5109
  return this.locks;
5103
5110
  }
5104
5111
  async undoing(op, peers, sends, heard, shared2 = []) {
5105
- let failed3;
5112
+ let failed5;
5106
5113
  let out;
5107
5114
  try {
5108
5115
  out = await op();
5109
5116
  } catch (err) {
5110
- failed3 = err ?? new Error("failed");
5117
+ failed5 = err ?? new Error("failed");
5111
5118
  await this.rollBackAsides(sends, shared2);
5112
5119
  }
5113
5120
  const hiddenShared = new Set(shared2.map((one) => one.hidden));
@@ -5128,7 +5135,7 @@ var UnlinkedKeeper = class {
5128
5135
  const done4 = () => one.release().then(() => this.dropIfLast(one.hidden));
5129
5136
  void Promise.all(waits.map(({ told }) => told)).then(done4, done4);
5130
5137
  }
5131
- if (failed3 !== void 0) throw failed3;
5138
+ if (failed5 !== void 0) throw failed5;
5132
5139
  return out;
5133
5140
  }
5134
5141
  async rollBackAsides(sends, shared2) {
@@ -5275,7 +5282,7 @@ var UnlinkedKeeper = class {
5275
5282
  // src/cron/clock.ts
5276
5283
  var systemCronClock = {
5277
5284
  now: () => Date.now(),
5278
- sleep(until, signal) {
5285
+ sleep(until2, signal) {
5279
5286
  if (signal.aborted) return Promise.resolve();
5280
5287
  return new Promise((resolve2) => {
5281
5288
  const done4 = () => {
@@ -5283,7 +5290,7 @@ var systemCronClock = {
5283
5290
  signal.removeEventListener("abort", done4);
5284
5291
  resolve2();
5285
5292
  };
5286
- const timer = setTimeout(done4, Math.max(0, until - Date.now()));
5293
+ const timer = setTimeout(done4, Math.max(0, until2 - Date.now()));
5287
5294
  timer.unref?.();
5288
5295
  signal.addEventListener("abort", done4, { once: true });
5289
5296
  });
@@ -5387,15 +5394,15 @@ var CronService = class {
5387
5394
  async pass() {
5388
5395
  if (this.wake.signal.aborted) this.wake = new AbortController();
5389
5396
  const wake = this.wake;
5390
- let until;
5397
+ let until2;
5391
5398
  try {
5392
- until = await this.tick();
5399
+ until2 = await this.tick();
5393
5400
  } catch (err) {
5394
5401
  await this.error(`cron: ${messageOf(err)}`);
5395
- until = this.clock.now() + WAKE_MS;
5402
+ until2 = this.clock.now() + WAKE_MS;
5396
5403
  }
5397
5404
  if (this.stopping.signal.aborted) return;
5398
- await this.clock.sleep(until, wake.signal);
5405
+ await this.clock.sleep(until2, wake.signal);
5399
5406
  }
5400
5407
  async provision() {
5401
5408
  const { fs, owners } = this.host;
@@ -5612,14 +5619,17 @@ var PLACEHOLDER_REFUSED = "refused: this request has a sealed placeholder in its
5612
5619
  var PlaceholderRefused = class extends Error {
5613
5620
  status = 403;
5614
5621
  code = "EACCES";
5615
- constructor() {
5616
- super(PLACEHOLDER_REFUSED);
5622
+ constructor(reason = PLACEHOLDER_REFUSED) {
5623
+ super(reason);
5617
5624
  }
5618
5625
  };
5619
- function carries(text) {
5626
+ function holds2(text, known) {
5627
+ return PLACEHOLDER.test(text) || known.some((placeholder) => text.includes(placeholder));
5628
+ }
5629
+ function carries(text, known) {
5620
5630
  let layer = text;
5621
5631
  for (let i = 0; i < PERCENT_LAYERS; i++) {
5622
- if (PLACEHOLDER.test(layer)) return true;
5632
+ if (holds2(layer, known)) return true;
5623
5633
  const next3 = layer.replace(
5624
5634
  ESCAPE,
5625
5635
  (_, hex4) => String.fromCharCode(Number.parseInt(hex4, 16))
@@ -5627,35 +5637,36 @@ function carries(text) {
5627
5637
  if (next3 === layer) return false;
5628
5638
  layer = next3;
5629
5639
  }
5630
- return PLACEHOLDER.test(layer);
5640
+ return holds2(layer, known);
5631
5641
  }
5632
- function basicCarries(value2) {
5642
+ function basicCarries(value2, known) {
5633
5643
  const credential = BASIC.exec(value2)?.[1];
5634
5644
  if (credential === void 0) return false;
5635
5645
  const letters = credential.replace(/[^A-Za-z0-9+/_-]/g, "").replaceAll("-", "+").replaceAll("_", "/");
5636
5646
  for (let shift = 0; shift < BASE64_GROUP; shift++) {
5637
5647
  const part = letters.slice(shift);
5638
5648
  const whole = part.length % BASE64_GROUP === 1 ? part.slice(0, -1) : part;
5639
- if (carries(atob(whole))) return true;
5649
+ if (carries(atob(whole), known)) return true;
5640
5650
  }
5641
5651
  return false;
5642
5652
  }
5643
- function headersCarry(headers) {
5653
+ function headersCarry(headers, known) {
5644
5654
  return headers.some(
5645
- ([name2, value2]) => carries(name2.toLowerCase()) || carries(value2) || basicCarries(value2)
5655
+ ([name2, value2]) => carries(name2, known) || carries(name2.toLowerCase(), known) || carries(value2, known) || basicCarries(value2, known)
5646
5656
  );
5647
5657
  }
5648
- function urlCarries(url) {
5649
- return carries(url) || URL.canParse(url) && carries(new URL(url).href);
5658
+ function urlCarries(url, known) {
5659
+ return carries(url, known) || URL.canParse(url) && carries(new URL(url).href, known);
5650
5660
  }
5651
- function refuse(request) {
5652
- if (urlCarries(request.url) || headersCarry(request.headers)) throw new PlaceholderRefused();
5661
+ function detected(request, known) {
5662
+ return urlCarries(request.url, known) || headersCarry(request.headers, known);
5653
5663
  }
5654
- function refuseSocket(request) {
5655
- refuse(request);
5656
- if (request.protocols.some(carries)) throw new PlaceholderRefused();
5664
+ function refuseSocket(request, known) {
5665
+ if (detected(request, known) || request.protocols.some((p) => carries(p, known))) {
5666
+ throw new PlaceholderRefused();
5667
+ }
5657
5668
  }
5658
- function placeholderFloor(inner) {
5669
+ function placeholderFloor(inner, { known = () => [], fill: fill2 } = {}) {
5659
5670
  const open = inner.websocket?.bind(inner);
5660
5671
  return {
5661
5672
  get traits() {
@@ -5663,13 +5674,14 @@ function placeholderFloor(inner) {
5663
5674
  },
5664
5675
  ...open ? {
5665
5676
  websocket: async (request) => {
5666
- refuseSocket(request);
5677
+ refuseSocket(request, known());
5667
5678
  return open(request);
5668
5679
  }
5669
5680
  } : {},
5670
- async fetch(request, owner) {
5671
- refuse(request);
5672
- return inner.fetch(request, owner);
5681
+ async fetch(request, owner, stamp) {
5682
+ if (!detected(request, known())) return inner.fetch(request, owner, stamp);
5683
+ if (!fill2 || !stamp) throw new PlaceholderRefused();
5684
+ return fill2(request, stamp);
5673
5685
  }
5674
5686
  };
5675
5687
  }
@@ -5910,14 +5922,14 @@ function tunnelTarget(req) {
5910
5922
  }
5911
5923
  return { host, port };
5912
5924
  }
5913
- async function watchHangup(conn, abort, until) {
5914
- while (!until.aborted && !abort.signal.aborted) {
5925
+ async function watchHangup(conn, abort, until2) {
5926
+ while (!until2.aborted && !abort.signal.aborted) {
5915
5927
  if (conn.poll().hangup) {
5916
5928
  abort.abort(new KernelError("EPIPE"));
5917
5929
  return;
5918
5930
  }
5919
5931
  try {
5920
- await conn.changed(until);
5932
+ await conn.changed(until2);
5921
5933
  } catch {
5922
5934
  return;
5923
5935
  }
@@ -6108,7 +6120,7 @@ var RealmProxy = class {
6108
6120
  const waiting = new AbortController();
6109
6121
  void watchHangup(ctx.socket, abort, waiting.signal);
6110
6122
  try {
6111
- response = await this.upstream(req, url, body, abort.signal, ctx.socket.peerCred?.pid);
6123
+ response = await this.upstream(req, url, body, abort.signal, ctx.socket);
6112
6124
  } finally {
6113
6125
  waiting.abort();
6114
6126
  }
@@ -6135,7 +6147,7 @@ var RealmProxy = class {
6135
6147
  await conn.write(latin1Bytes("HTTP/1.1 100 Continue\r\n\r\n"), this.stop.signal);
6136
6148
  }
6137
6149
  }
6138
- async upstream(req, url, body, signal, owner) {
6150
+ async upstream(req, url, body, signal, socket) {
6139
6151
  const sent = BODILESS_METHODS.has(req.method) ? void 0 : body;
6140
6152
  try {
6141
6153
  const fetching = this.options.transport.fetch(
@@ -6146,7 +6158,8 @@ var RealmProxy = class {
6146
6158
  ...sent instanceof Uint8Array ? { body: sent } : sent ? { bodyStream: sent } : {},
6147
6159
  signal
6148
6160
  },
6149
- owner
6161
+ socket.peerCred?.pid,
6162
+ socket.peerStamp
6150
6163
  );
6151
6164
  return await untilAborted(fetching, signal);
6152
6165
  } catch (e) {
@@ -6190,8 +6203,8 @@ var RealmProxy = class {
6190
6203
  }
6191
6204
  async connect(conn, incoming, req, idle2) {
6192
6205
  const target = tunnelTarget(req);
6193
- const refused3 = target.port === 443 ? await this.tunnelReady(target) : void 0;
6194
- if (refused3) throw refused3;
6206
+ const refused4 = target.port === 443 ? await this.tunnelReady(target) : void 0;
6207
+ if (refused4) throw refused4;
6195
6208
  await conn.write(latin1Bytes("HTTP/1.1 200 Connection Established\r\n\r\n"), this.stop.signal);
6196
6209
  try {
6197
6210
  const first = await incoming.peek(this.stop.signal);
@@ -6463,7 +6476,7 @@ async function relay(socket, conn) {
6463
6476
  // src/fs/attest.ts
6464
6477
  var ATTEST_MAX = 1024 * 1024;
6465
6478
  var UNOWNED = 1e3;
6466
- function refuse2(code, path, why) {
6479
+ function refuse(code, path, why) {
6467
6480
  throw Object.assign(new Error(`attest ${path}: ${why}`), { code });
6468
6481
  }
6469
6482
  function chainOf(path) {
@@ -6505,39 +6518,49 @@ async function trustedParents(fs, path, o) {
6505
6518
  const parents = [];
6506
6519
  for (const dir of chainOf(path).slice(0, -1)) {
6507
6520
  const st = await fs.lstat(dir);
6508
- if (st.isSymbolicLink) refuse2("EACCES", path, `${dir} is a symlink`);
6509
- if (!st.isDirectory) refuse2("ENOTDIR", path, `${dir} is not a directory`);
6521
+ if (st.isSymbolicLink) refuse("EACCES", path, `${dir} is a symlink`);
6522
+ if (!st.isDirectory) refuse("ENOTDIR", path, `${dir} is not a directory`);
6510
6523
  const perm = owned(dir, st);
6511
6524
  if (o.users !== "off" && (perm.uid !== 0 || (perm.mode & 18) !== 0)) {
6512
- refuse2("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
6525
+ refuse("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
6513
6526
  }
6514
6527
  parents.push(perm);
6515
6528
  }
6516
6529
  return parents;
6517
6530
  }
6531
+ function missing(e) {
6532
+ return e?.code === "ENOENT";
6533
+ }
6518
6534
  async function attest(fs, asked, o) {
6535
+ if (o.absent !== void 0 && o.absent !== "allow") {
6536
+ refuse("EINVAL", String(asked), "absent takes only allow");
6537
+ }
6519
6538
  if (typeof asked !== "string" || !asked.startsWith("/")) {
6520
- refuse2("EINVAL", String(asked), "not an absolute path");
6539
+ refuse("EINVAL", String(asked), "not an absolute path");
6521
6540
  }
6522
6541
  const path = normalizePath(asked);
6523
6542
  const mount = o.mounts.find((target) => {
6524
6543
  const at = normalizePath(target);
6525
6544
  return at === "/" || under(path, at);
6526
6545
  });
6527
- if (mount !== void 0) refuse2("EACCES", path, `under the mount ${mount}`);
6546
+ if (mount !== void 0) refuse("EACCES", path, `under the mount ${mount}`);
6528
6547
  const parents = await trustedParents(fs, path, o);
6529
6548
  for (let tries = 0; ; tries++) {
6530
- const before = await fs.lstat(path);
6531
- if (before.isSymbolicLink) refuse2("EACCES", path, "is a symlink");
6549
+ const before = await fs.lstat(path).catch((e) => {
6550
+ if (o.absent === "allow" && missing(e)) return void 0;
6551
+ throw e;
6552
+ });
6553
+ if (!before) return { path, absent: true, users: o.users, onRootFs: true, parents };
6554
+ if (before.isSymbolicLink) refuse("EACCES", path, "is a symlink");
6532
6555
  if (!before.isFile)
6533
- refuse2(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
6534
- if (before.size > ATTEST_MAX) refuse2("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
6556
+ refuse(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
6557
+ if (before.size > ATTEST_MAX) refuse("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
6535
6558
  const bytes = (await fs.readFileBuffer(path)).slice();
6536
6559
  const after = await fs.lstat(path);
6537
6560
  if (unchanged(before, after, bytes)) {
6538
6561
  return attested(path, after, bytes, await sha256(bytes), o, parents);
6539
6562
  }
6540
- if (tries >= 1) refuse2("EAGAIN", path, "changed while it was read");
6563
+ if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
6541
6564
  }
6542
6565
  }
6543
6566
  var WATCH_DEBOUNCE_MS = 50;
@@ -6708,7 +6731,7 @@ var S_IFREG = 32768;
6708
6731
  var COMMAND = /^\/(?:usr\/)?bin\/([^/]+)$/;
6709
6732
  var MAX_LINKS3 = 40;
6710
6733
  var BIN_ENTRY = /\/bin\/[^/]+$/;
6711
- function missing(err) {
6734
+ function missing2(err) {
6712
6735
  return err?.code === "ENOENT";
6713
6736
  }
6714
6737
  function synthetic(directory, path) {
@@ -6812,7 +6835,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
6812
6835
  }
6813
6836
  async function entryTarget(path) {
6814
6837
  if (!BIN_ENTRY.test(path) || !(await virtual(path))?.isFile) return void 0;
6815
- if (!await fs.lstat(path).then(() => false, missing)) return void 0;
6838
+ if (!await fs.lstat(path).then(() => false, missing2)) return void 0;
6816
6839
  const target = await targetOf2(path);
6817
6840
  return target?.path === path ? void 0 : target;
6818
6841
  }
@@ -6824,11 +6847,11 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
6824
6847
  return target?.path;
6825
6848
  }
6826
6849
  const absent2 = (err) => {
6827
- if (missing(err)) return EMPTY2;
6850
+ if (missing2(err)) return EMPTY2;
6828
6851
  throw err;
6829
6852
  };
6830
6853
  async function content(path, err) {
6831
- if (!missing(err) || !(await linked2(path))?.isFile) throw err;
6854
+ if (!missing2(err) || !(await linked2(path))?.isFile) throw err;
6832
6855
  const target = await redirected2(path);
6833
6856
  return target === void 0 ? EMPTY2 : fs.readFileBuffer(target).catch(absent2);
6834
6857
  }
@@ -6837,7 +6860,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
6837
6860
  try {
6838
6861
  return await real(path);
6839
6862
  } catch (err) {
6840
- const found = missing(err) ? await linked2(path) : void 0;
6863
+ const found = missing2(err) ? await linked2(path) : void 0;
6841
6864
  if (found) return found;
6842
6865
  throw err;
6843
6866
  }
@@ -6862,7 +6885,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
6862
6885
  const extra = await children3(path);
6863
6886
  if (!extra) return fs.readdir(path);
6864
6887
  const real = await fs.readdir(path).catch((err) => {
6865
- if (missing(err)) return [];
6888
+ if (missing2(err)) return [];
6866
6889
  throw err;
6867
6890
  });
6868
6891
  return [.../* @__PURE__ */ new Set([...real, ...extra])].sort();
@@ -6871,7 +6894,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
6871
6894
  const extra = await children3(path);
6872
6895
  if (!extra) return fs.readdirStat(path);
6873
6896
  const real = await fs.readdirStat(path).catch((err) => {
6874
- if (missing(err)) return [];
6897
+ if (missing2(err)) return [];
6875
6898
  throw err;
6876
6899
  });
6877
6900
  const seen = new Set(real.map(([name2]) => name2));
@@ -6905,7 +6928,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
6905
6928
  ...ranged2 ? {
6906
6929
  ...ranged2,
6907
6930
  pread: (path, offset, length2, version) => ranged2.pread(path, offset, length2, version).catch(async (err) => {
6908
- const target = missing(err) ? await redirected2(path) : void 0;
6931
+ const target = missing2(err) ? await redirected2(path) : void 0;
6909
6932
  if (target === void 0) throw err;
6910
6933
  return ranged2.pread(target, offset, length2).catch(absent2);
6911
6934
  })
@@ -6936,7 +6959,7 @@ var S_IFREG2 = 32768;
6936
6959
  var MAX_HOPS2 = 40;
6937
6960
  var parentOf3 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
6938
6961
  var baseOf = (path) => path.slice(path.lastIndexOf("/") + 1);
6939
- function missing2(err) {
6962
+ function missing3(err) {
6940
6963
  return err?.code === "ENOENT";
6941
6964
  }
6942
6965
  function statOf(path, bytes) {
@@ -6989,11 +7012,11 @@ function withEtcFiles(fs, files) {
6989
7012
  const text = files.get(path)?.();
6990
7013
  return text === void 0 ? void 0 : new TextEncoder().encode(text);
6991
7014
  };
6992
- const absent2 = (path) => fs.lstat(path).then(() => false, missing2);
7015
+ const absent2 = (path) => fs.lstat(path).then(() => false, missing3);
6993
7016
  const follow2 = linkFollower(fs, files);
6994
7017
  const listedAbsent = async (path) => files.has(path) && await absent2(path) ? bytesOf5(path) : void 0;
6995
7018
  const fallback = (path, make) => async (err) => {
6996
- const at = missing2(err) ? await follow2(path) : void 0;
7019
+ const at = missing3(err) ? await follow2(path) : void 0;
6997
7020
  const bytes = at === void 0 ? void 0 : await listedAbsent(at);
6998
7021
  if (bytes === void 0 || at === void 0) throw err;
6999
7022
  return make(bytes, at);
@@ -7203,7 +7226,7 @@ var MAX_LINKS4 = 40;
7203
7226
  function partsOf(path) {
7204
7227
  return path.split("/").filter((p) => p !== "" && p !== ".");
7205
7228
  }
7206
- function missing3(err) {
7229
+ function missing4(err) {
7207
7230
  const code = err?.code;
7208
7231
  return code === "ENOENT" || code === "ENOTDIR";
7209
7232
  }
@@ -7222,7 +7245,7 @@ async function resolved(fs, path, follow2, hops = []) {
7222
7245
  }
7223
7246
  const at = `/${[...done4, part].join("/")}`;
7224
7247
  const st = await fs.lstat(at).catch((err) => {
7225
- if (missing3(err)) return void 0;
7248
+ if (missing4(err)) return void 0;
7226
7249
  throw err;
7227
7250
  });
7228
7251
  if (!st) {
@@ -9366,8 +9389,8 @@ var DriverConnection = class _DriverConnection {
9366
9389
  } finally {
9367
9390
  clearTimeout(timer);
9368
9391
  }
9369
- const refused3 = driverVersionError(hello.protocol);
9370
- if (refused3) throw errnoError("EPROTO", refused3);
9392
+ const refused4 = driverVersionError(hello.protocol);
9393
+ if (refused4) throw errnoError("EPROTO", refused4);
9371
9394
  if (hello.error) throw errnoError(hello.errno ?? "EIO", hello.error);
9372
9395
  return new _DriverConnection(port, hello.capabilities ?? {}, waiting, timeoutMs, options);
9373
9396
  }
@@ -9451,29 +9474,29 @@ var HeldSet = class extends Set {
9451
9474
  this.idle = idle2;
9452
9475
  this.moved = moved2;
9453
9476
  }
9454
- add(holds2) {
9455
- holds2.onIdle = this.idle;
9456
- holds2.onMoved = this.moved;
9457
- return super.add(holds2);
9477
+ add(holds3) {
9478
+ holds3.onIdle = this.idle;
9479
+ holds3.onMoved = this.moved;
9480
+ return super.add(holds3);
9458
9481
  }
9459
9482
  doubt(paths, over) {
9460
- for (const holds2 of this) {
9461
- for (const path of paths) holds2.doubt(path, true);
9462
- if (over !== void 0) holds2.doubt(over);
9483
+ for (const holds3 of this) {
9484
+ for (const path of paths) holds3.doubt(path, true);
9485
+ if (over !== void 0) holds3.doubt(over);
9463
9486
  }
9464
9487
  }
9465
9488
  async bindIds(id2) {
9466
- for (const holds2 of [...this]) await holds2.bindIds(id2);
9489
+ for (const holds3 of [...this]) await holds3.bindIds(id2);
9467
9490
  }
9468
9491
  heldIds() {
9469
9492
  const out = /* @__PURE__ */ new Map();
9470
- for (const holds2 of this) for (const [path, fid] of holds2.heldIds()) out.set(path, fid);
9493
+ for (const holds3 of this) for (const [path, fid] of holds3.heldIds()) out.set(path, fid);
9471
9494
  return [...out];
9472
9495
  }
9473
- delete(holds2) {
9474
- const removed = super.delete(holds2);
9475
- for (const path of /* @__PURE__ */ new Set([...holds2.keys(), ...holds2.opens.keys()])) this.idle(path);
9476
- holds2.releaseAll();
9496
+ delete(holds3) {
9497
+ const removed = super.delete(holds3);
9498
+ for (const path of /* @__PURE__ */ new Set([...holds3.keys(), ...holds3.opens.keys()])) this.idle(path);
9499
+ holds3.releaseAll();
9477
9500
  return removed;
9478
9501
  }
9479
9502
  };
@@ -11391,8 +11414,8 @@ async function guarded(entry, path, req) {
11391
11414
  return { paths };
11392
11415
  } catch (err) {
11393
11416
  const refusal3 = err.code === "EACCES";
11394
- const refused3 = req.op === "exists" && refusal3 ? json2(false) : toErrno(err);
11395
- return { refused: refused3 };
11417
+ const refused4 = req.op === "exists" && refusal3 ? json2(false) : toErrno(err);
11418
+ return { refused: refused4 };
11396
11419
  }
11397
11420
  }
11398
11421
  async function copyOp(entry, path, req) {
@@ -11588,13 +11611,13 @@ async function created(entry, req) {
11588
11611
  return seen === void 0 ? looked : json2({ ...looked.json, seen });
11589
11612
  }
11590
11613
  var DENIED = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
11591
- async function rmPermitted(entry, path, req, refused3) {
11614
+ async function rmPermitted(entry, path, req, refused4) {
11592
11615
  const st = await entry.fs.lstat(path).catch(() => void 0);
11593
- if (!st?.isDirectory) return refused3;
11616
+ if (!st?.isDirectory) return refused4;
11594
11617
  const unlisted = await guarded(entry, path, { ...req, op: "readdir" });
11595
11618
  if ("refused" in unlisted) return unlisted.refused;
11596
11619
  const names2 = await entry.fs.readdir(path).catch(() => void 0);
11597
- if (!names2) return refused3;
11620
+ if (!names2) return refused4;
11598
11621
  let first;
11599
11622
  for (const name2 of names2) {
11600
11623
  const child = await dispatchOne(entry, {
@@ -11645,14 +11668,14 @@ async function newDevName(entry, path, req) {
11645
11668
  const named = NAMING.has(req.op);
11646
11669
  if (!named && !CREATIONS.has(req.op)) return void 0;
11647
11670
  const target = named ? entry.fs.resolvePath(entry.cwd, req.arg2 ?? "") : path;
11648
- const refused3 = devCreation(target, entry.cred?.());
11649
- if (!refused3) return void 0;
11671
+ const refused4 = devCreation(target, entry.cred?.());
11672
+ if (!refused4) return void 0;
11650
11673
  const there = await entry.fs.lstat(target).then(
11651
11674
  () => true,
11652
11675
  () => false
11653
11676
  );
11654
11677
  if (there) return void 0;
11655
- return { ok: false, errno: refused3, message: `${target}: no new names in /dev or /proc` };
11678
+ return { ok: false, errno: refused4, message: `${target}: no new names in /dev or /proc` };
11656
11679
  }
11657
11680
  var MISS_OPS = /* @__PURE__ */ new Set(["stat", "lstat"]);
11658
11681
  async function linkFree(fs, path) {
@@ -12364,9 +12387,9 @@ var SYS_TREE = {
12364
12387
  `,
12365
12388
  slicc_file_ids: (listing) => `${listing.fileIds ?? 0}
12366
12389
  `,
12367
- slicc_peer_holds: ({ holds: holds2 }) => `${holds2?.mine ?? 0} ${holds2?.peers ?? 0} ${holds2?.sent ?? 0}
12390
+ slicc_peer_holds: ({ holds: holds3 }) => `${holds3?.mine ?? 0} ${holds3?.peers ?? 0} ${holds3?.sent ?? 0}
12368
12391
  `,
12369
- slicc_peer_held: ({ holds: holds2 }) => (holds2?.held ?? []).map((path) => `${path}
12392
+ slicc_peer_held: ({ holds: holds3 }) => (holds3?.held ?? []).map((path) => `${path}
12370
12393
  `).join(""),
12371
12394
  slicc_rename_acks: (listing) => {
12372
12395
  const samples = [...listing.renameAcks?.ackMs ?? []].sort((a, b) => a - b);
@@ -13107,11 +13130,11 @@ var EpollFile = class _EpollFile {
13107
13130
  const round = new AbortController();
13108
13131
  const stop = () => round.abort();
13109
13132
  signal.addEventListener("abort", stop, { once: true });
13110
- let failed3 = false;
13133
+ let failed5 = false;
13111
13134
  try {
13112
13135
  await file.changed(round.signal);
13113
13136
  } catch {
13114
- failed3 = true;
13137
+ failed5 = true;
13115
13138
  } finally {
13116
13139
  round.abort();
13117
13140
  signal.removeEventListener("abort", stop);
@@ -13119,7 +13142,7 @@ var EpollFile = class _EpollFile {
13119
13142
  if (signal.aborted) return;
13120
13143
  reg.gen++;
13121
13144
  this.changes.wake();
13122
- if (failed3) await pause(RETRY_MS, signal);
13145
+ if (failed5) await pause(RETRY_MS, signal);
13123
13146
  }
13124
13147
  }
13125
13148
  };
@@ -13755,8 +13778,8 @@ var KernelLoopback = class {
13755
13778
  );
13756
13779
  } catch (err) {
13757
13780
  socket.close();
13758
- const refused3 = err instanceof KernelError && err.code === "ECONNREFUSED";
13759
- throw refused3 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
13781
+ const refused4 = err instanceof KernelError && err.code === "ECONNREFUSED";
13782
+ throw refused4 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
13760
13783
  }
13761
13784
  signal.addEventListener("abort", () => socket.close(), { once: true });
13762
13785
  return socket;
@@ -14100,11 +14123,11 @@ function ipv6(host) {
14100
14123
  const back = halves.length === 2 ? groups(halves[1]) : [];
14101
14124
  if (![...head, ...back].every((g) => /^[0-9A-Fa-f]{1,4}$/.test(g))) return void 0;
14102
14125
  const words2 = [...head, ...back].map((g) => Number.parseInt(g, 16));
14103
- const missing5 = 8 - words2.length - tail2.length;
14104
- if (halves.length === 2 ? missing5 < 1 : missing5 !== 0) return void 0;
14126
+ const missing6 = 8 - words2.length - tail2.length;
14127
+ if (halves.length === 2 ? missing6 < 1 : missing6 !== 0) return void 0;
14105
14128
  const all = [
14106
14129
  ...head.map((g) => Number.parseInt(g, 16)),
14107
- ...new Array(halves.length === 2 ? missing5 : 0).fill(0),
14130
+ ...new Array(halves.length === 2 ? missing6 : 0).fill(0),
14108
14131
  ...back.map((g) => Number.parseInt(g, 16)),
14109
14132
  ...tail2
14110
14133
  ];
@@ -15101,10 +15124,12 @@ var HttpHandles = class {
15101
15124
  ws;
15102
15125
  owner;
15103
15126
  local;
15104
- constructor(transport, owner, local2) {
15127
+ stamp;
15128
+ constructor(transport, owner, local2, stamp) {
15105
15129
  this.transport = transport;
15106
15130
  this.owner = owner;
15107
15131
  this.local = local2;
15132
+ this.stamp = stamp;
15108
15133
  this.ws = new WsHandles(transport, () => ++this.nextHandle, local2);
15109
15134
  }
15110
15135
  syscall(req) {
@@ -15180,7 +15205,7 @@ var HttpHandles = class {
15180
15205
  ...entry.upload ? { bodyStream: entry.upload } : req.body ? { body: req.body } : {},
15181
15206
  signal: entry.abort.signal
15182
15207
  };
15183
- const response = port === void 0 ? await this.transport.fetch(request, this.owner) : await this.local.fetch(request, port);
15208
+ const response = port === void 0 ? await this.transport.fetch(request, this.owner, await this.stamp?.()) : await this.local.fetch(request, port);
15184
15209
  entry.body = response.body[Symbol.asyncIterator]();
15185
15210
  entry.cancel = () => response.cancel();
15186
15211
  if (!this.open.has(handle)) await entry.cancel().catch(() => void 0);
@@ -15202,8 +15227,8 @@ var HttpHandles = class {
15202
15227
  if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
15203
15228
  const code = codeOf2(e);
15204
15229
  const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
15205
- const failed3 = e.detail === "transport";
15206
- return { ok: false, errno: errno3, message: text, ...failed3 ? { detail: "transport" } : {} };
15230
+ const failed5 = e.detail === "transport";
15231
+ return { ok: false, errno: errno3, message: text, ...failed5 ? { detail: "transport" } : {} };
15207
15232
  }
15208
15233
  entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
15209
15234
  return this.headOf(handle, req.url, {
@@ -16998,7 +17023,7 @@ function pass(c, input, final) {
16998
17023
  const partials = [];
16999
17024
  scanMain(c, input, best, partials);
17000
17025
  scanWrapped(c, input, best, partials);
17001
- const holds2 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
17026
+ const holds3 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
17002
17027
  const starts = [...best.keys()].sort((a, b) => a - b);
17003
17028
  const parts2 = [];
17004
17029
  const hits = /* @__PURE__ */ new Map();
@@ -17008,8 +17033,8 @@ function pass(c, input, final) {
17008
17033
  let h = 0;
17009
17034
  for (; ; ) {
17010
17035
  while (s < starts.length && starts[s] < pos) s++;
17011
- while (h < holds2.length && holds2[h] < pos) h++;
17012
- const hold = h < holds2.length ? holds2[h] : Infinity;
17036
+ while (h < holds3.length && holds3[h] < pos) h++;
17037
+ const hold = h < holds3.length ? holds3[h] : Infinity;
17013
17038
  const next3 = s < starts.length ? starts[s] : Infinity;
17014
17039
  if (hold <= next3) {
17015
17040
  cut = Math.min(hold, input.length);
@@ -17111,23 +17136,23 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
17111
17136
  let pending = 0;
17112
17137
  let busy = false;
17113
17138
  let timer;
17114
- let failed3;
17139
+ let failed5;
17115
17140
  const waiters = /* @__PURE__ */ new Set();
17116
17141
  const quiet3 = () => !busy && pending === 0;
17117
17142
  const wake = () => {
17118
17143
  for (const waiter of [...waiters]) waiter();
17119
17144
  };
17120
17145
  const raise = () => {
17121
- if (failed3 === void 0) return;
17122
- const err = failed3;
17123
- failed3 = void 0;
17146
+ if (failed5 === void 0) return;
17147
+ const err = failed5;
17148
+ failed5 = void 0;
17124
17149
  throw err;
17125
17150
  };
17126
17151
  const later = (bytes) => {
17127
17152
  if (bytes.length === 0) return;
17128
17153
  pending += 1;
17129
17154
  tail2 = tail2.then(() => writeAll2(file, bytes)).catch((err) => {
17130
- if (failed3 === void 0) failed3 = err;
17155
+ if (failed5 === void 0) failed5 = err;
17131
17156
  }).finally(() => {
17132
17157
  pending -= 1;
17133
17158
  if (quiet3()) wake();
@@ -20202,7 +20227,7 @@ async function connect(req, proc) {
20202
20227
  }
20203
20228
  const path = filePath(req.addr);
20204
20229
  const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
20205
- const stamp = proc.net.facadeAt(req.addr) && await proc.stamp?.();
20230
+ const stamp = proc.net.stampsPeers(req.addr) && await proc.stamp?.();
20206
20231
  const dialing = target.connect(req.addr, true, proc.cred?.(), stamp || void 0, true, name2);
20207
20232
  if (req.nonblock) {
20208
20233
  dialing?.catch(() => void 0);
@@ -20324,7 +20349,7 @@ async function secureConnect(req, proc) {
20324
20349
  delete req.clientCert;
20325
20350
  throw new KernelError("ENOTSUP");
20326
20351
  }
20327
- return { ...tlsOverTransport(req, proc), path: "transport", substitutes: true };
20352
+ return { ...await tlsOverTransport(req, proc), path: "transport", substitutes: true };
20328
20353
  }
20329
20354
  const socket = proc.net.socket("inet");
20330
20355
  const fd = proc.fds.install(new OpenFile(socket), 3);
@@ -20343,7 +20368,7 @@ async function uplinked(proc, host) {
20343
20368
  return false;
20344
20369
  }
20345
20370
  }
20346
- function tlsOverTransport(req, proc) {
20371
+ async function tlsOverTransport(req, proc) {
20347
20372
  if (req.ca) throw new KernelError("ENOTSUP");
20348
20373
  if (req.alpn && req.alpn.length > 0 && !req.alpn.includes("http/1.1")) {
20349
20374
  throw new KernelError("EPROTONOSUPPORT");
@@ -20356,7 +20381,9 @@ function tlsOverTransport(req, proc) {
20356
20381
  if (isLoopbackHost(servername) || isLoopbackHost(req.host)) throw new KernelError("ENOTSUP");
20357
20382
  const host = servername.includes(":") && !servername.startsWith("[") ? `[${servername}]` : servername;
20358
20383
  const origin = req.port === 443 ? `https://${host}` : `https://${host}:${req.port}`;
20384
+ const stamp = proc.net.originsStamped ? await proc.stamp?.() : void 0;
20359
20385
  const [mine, theirs] = KernelSocket.pair(proc.net, "inet", proc.cred?.());
20386
+ theirs.peerStamp = stamp;
20360
20387
  mine.peer = { family: "inet", host: req.host, port: req.port };
20361
20388
  try {
20362
20389
  proc.net.serveOrigin(theirs, origin);
@@ -23515,13 +23542,13 @@ function inherited(opts) {
23515
23542
  ...opts.cred ? { cred: opts.cred } : {}
23516
23543
  };
23517
23544
  }
23518
- function heldBy(process2, holds2, replacements) {
23519
- process2.keptPath = (path) => holds2.keptAt(path)?.hidden;
23520
- process2.keptHandle = (handle) => holds2.keptFor(handle)?.hidden;
23521
- process2.holdsHandle = (handle) => holds2.holdsHandle(handle);
23545
+ function heldBy(process2, holds3, replacements) {
23546
+ process2.keptPath = (path) => holds3.keptAt(path)?.hidden;
23547
+ process2.keptHandle = (handle) => holds3.keptFor(handle)?.hidden;
23548
+ process2.holdsHandle = (handle) => holds3.holdsHandle(handle);
23522
23549
  if (replacements) process2.replacements = replacements;
23523
23550
  }
23524
- function holdingToken(opts, holds2, caller) {
23551
+ function holdingToken(opts, holds3, caller) {
23525
23552
  return mintSyncFsToken({
23526
23553
  ...opts.owners ? caller : { umask: caller.umask },
23527
23554
  ...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
@@ -23538,16 +23565,16 @@ function holdingToken(opts, holds2, caller) {
23538
23565
  ...opts.fileId ? { fileId: opts.fileId } : {},
23539
23566
  ...opts.announceHold ? { announceHold: opts.announceHold } : {},
23540
23567
  ...opts.renameSeq ? { renameSeq: opts.renameSeq } : {},
23541
- hold: (path, on, open, real, handle, ino, fid) => holds2.hold(path, on, open, real, handle, ino, fid),
23542
- boundIno: holds2.boundIno.bind(holds2),
23543
- trust: holds2.trust.bind(holds2),
23544
- keptFor: (handle) => holds2.keptFor(handle),
23545
- heldAt: (handle) => holds2.pathOf(handle),
23546
- unlinked: (path) => holds2.keptAt(path),
23547
- gate: (path, op) => opts.unlinkGate && holds2.holding(path) ? opts.unlinkGate.run(holds2.keyOf(path), op) : op(),
23548
- own: (path, op) => holds2.own(path, op),
23549
- revoked: (path) => holds2.isRevoked(path),
23550
- renamed: (from, to) => holds2.renamed(from, to)
23568
+ hold: (path, on, open, real, handle, ino, fid) => holds3.hold(path, on, open, real, handle, ino, fid),
23569
+ boundIno: holds3.boundIno.bind(holds3),
23570
+ trust: holds3.trust.bind(holds3),
23571
+ keptFor: (handle) => holds3.keptFor(handle),
23572
+ heldAt: (handle) => holds3.pathOf(handle),
23573
+ unlinked: (path) => holds3.keptAt(path),
23574
+ gate: (path, op) => opts.unlinkGate && holds3.holding(path) ? opts.unlinkGate.run(holds3.keyOf(path), op) : op(),
23575
+ own: (path, op) => holds3.own(path, op),
23576
+ revoked: (path) => holds3.isRevoked(path),
23577
+ renamed: (from, to) => holds3.renamed(from, to)
23551
23578
  });
23552
23579
  }
23553
23580
  function linksOf(opts) {
@@ -23704,15 +23731,15 @@ function spawnWasmProcess(opts) {
23704
23731
  )
23705
23732
  );
23706
23733
  publishStops(process2, header5);
23707
- const holds2 = new HeldPaths();
23708
- opts.held?.add(holds2);
23709
- const token = holdingToken(opts, holds2, {
23734
+ const holds3 = new HeldPaths();
23735
+ opts.held?.add(holds3);
23736
+ const token = holdingToken(opts, holds3, {
23710
23737
  cred: () => process2.cred,
23711
23738
  umask: () => process2.umask,
23712
23739
  created: created4,
23713
- holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds2.keeps(path) || await process2.holds(path))
23740
+ holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds3.keeps(path) || await process2.holds(path))
23714
23741
  });
23715
- heldBy(process2, holds2, opts.replacements);
23742
+ heldBy(process2, holds3, opts.replacements);
23716
23743
  const worker = opts.createWorker();
23717
23744
  const dying = new Dying();
23718
23745
  const dispatch2 = (req, block) => dying.serve(
@@ -23744,7 +23771,7 @@ function spawnWasmProcess(opts) {
23744
23771
  responder.dispose();
23745
23772
  lane?.dispose();
23746
23773
  revokeSyncFsToken(token);
23747
- opts.held?.delete(holds2);
23774
+ opts.held?.delete(holds3);
23748
23775
  worker.terminate();
23749
23776
  settleExit(process2.exit(), settle, code);
23750
23777
  };
@@ -24310,10 +24337,10 @@ var RemoteWatch = class {
24310
24337
  });
24311
24338
  }
24312
24339
  }
24313
- heldBy({ tab, holds: holds2, seq: seq2 }) {
24340
+ heldBy({ tab, holds: holds3, seq: seq2 }) {
24314
24341
  const from = tab;
24315
- const { add, drop } = holds2;
24316
- if (holds2?.instance !== void 0) this.instances.set(from, holds2.instance);
24342
+ const { add, drop } = holds3;
24343
+ if (holds3?.instance !== void 0) this.instances.set(from, holds3.instance);
24317
24344
  const held = this.peerHolds.get(from) ?? /* @__PURE__ */ new Map();
24318
24345
  for (const path of drop) held.delete(path);
24319
24346
  for (const [path, fid] of add) held.set(path, fid);
@@ -25258,6 +25285,236 @@ function enableDnsStub(net, stub) {
25258
25285
  });
25259
25286
  }
25260
25287
 
25288
+ // src/kernel/net/remote-transport.ts
25289
+ var TransportError = class extends Error {
25290
+ status;
25291
+ code;
25292
+ detail;
25293
+ constructor(message3, status, code, detail) {
25294
+ super(message3);
25295
+ this.status = status;
25296
+ this.code = code;
25297
+ this.detail = detail === "transport" ? detail : void 0;
25298
+ }
25299
+ };
25300
+ function unfollowed2(redirect) {
25301
+ return redirect !== void 0 && redirect !== "follow";
25302
+ }
25303
+ function honors(traits, redirect) {
25304
+ if (traits.redirectPolicy === true) return true;
25305
+ const hops = traits.redirectHops;
25306
+ const raw2 = traits.manualRedirects === true && (hops === void 0 || hops === false);
25307
+ return redirect === "manual" && raw2;
25308
+ }
25309
+ function refused3(message3) {
25310
+ return new TransportError(message3, 502, void 0, "transport");
25311
+ }
25312
+ var RemoteTransport = class {
25313
+ traits;
25314
+ port;
25315
+ waiting = /* @__PURE__ */ new Map();
25316
+ nextId = 0;
25317
+ sockets = /* @__PURE__ */ new Map();
25318
+ uploads = /* @__PURE__ */ new Map();
25319
+ failure;
25320
+ constructor(port, traits) {
25321
+ this.port = port;
25322
+ this.traits = traits;
25323
+ }
25324
+ receive(reply) {
25325
+ if (reply.net === "body-pull") {
25326
+ void this.pull(reply.nid);
25327
+ return;
25328
+ }
25329
+ const socket = this.sockets.get(reply.nid);
25330
+ if (socket && this.toSocket(reply, socket)) return;
25331
+ const waiter = this.waiting.get(reply.nid);
25332
+ if (!waiter) return;
25333
+ this.waiting.delete(reply.nid);
25334
+ if (reply.net === "error") {
25335
+ waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
25336
+ } else waiter.resolve(reply);
25337
+ }
25338
+ toSocket(reply, socket) {
25339
+ if (reply.net === "ws-message") socket.queue.push(reply.data);
25340
+ else if (reply.net === "ws-acked") socket.acked(reply.n);
25341
+ else if (reply.net === "ws-closed") {
25342
+ this.sockets.delete(reply.nid);
25343
+ socket.queue.end({ code: reply.code, reason: reply.reason });
25344
+ } else return false;
25345
+ return true;
25346
+ }
25347
+ async pull(nid) {
25348
+ const upload = this.uploads.get(nid);
25349
+ if (!upload) {
25350
+ this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
25351
+ return;
25352
+ }
25353
+ try {
25354
+ const next3 = await upload.next();
25355
+ if (next3.done) {
25356
+ this.uploads.delete(nid);
25357
+ this.port.postMessage({ net: "body-end", nid });
25358
+ } else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
25359
+ } catch (e) {
25360
+ this.uploads.delete(nid);
25361
+ this.port.postMessage({
25362
+ net: "body-error",
25363
+ nid,
25364
+ message: e instanceof Error ? e.message : String(e)
25365
+ });
25366
+ }
25367
+ }
25368
+ dropUpload(nid) {
25369
+ const upload = this.uploads.get(nid);
25370
+ this.uploads.delete(nid);
25371
+ void upload?.return?.().catch(() => void 0);
25372
+ }
25373
+ fail(error) {
25374
+ this.failure = error;
25375
+ for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
25376
+ for (const waiter of this.waiting.values()) waiter.reject(error);
25377
+ this.waiting.clear();
25378
+ for (const socket of this.sockets.values())
25379
+ socket.queue.end({ code: 1011, reason: error.message });
25380
+ this.sockets.clear();
25381
+ }
25382
+ ask(call) {
25383
+ if (this.failure) return Promise.reject(this.failure);
25384
+ return new Promise((resolve2, reject) => {
25385
+ this.waiting.set(call.nid, { resolve: resolve2, reject });
25386
+ this.port.postMessage(call);
25387
+ });
25388
+ }
25389
+ cancel(nid) {
25390
+ const waiter = this.waiting.get(nid);
25391
+ this.waiting.delete(nid);
25392
+ waiter?.reject(new TransportError("the request was cancelled"));
25393
+ this.port.postMessage({ net: "cancel", nid });
25394
+ }
25395
+ async fetch(request, owner, stamp) {
25396
+ const nid = ++this.nextId;
25397
+ const { signal, redirect } = request;
25398
+ signal.throwIfAborted();
25399
+ if (unfollowed2(redirect) && !honors(this.traits, redirect)) {
25400
+ throw refused3(`this transport cannot honor redirect: ${redirect}`);
25401
+ }
25402
+ let finished = false;
25403
+ const abort = () => {
25404
+ finished = true;
25405
+ this.dropUpload(nid);
25406
+ this.cancel(nid);
25407
+ };
25408
+ signal.addEventListener("abort", abort, { once: true });
25409
+ const finish = () => {
25410
+ this.dropUpload(nid);
25411
+ if (finished) return;
25412
+ finished = true;
25413
+ signal.removeEventListener("abort", abort);
25414
+ };
25415
+ if (request.bodyStream) this.uploads.set(nid, request.bodyStream[Symbol.asyncIterator]());
25416
+ let head;
25417
+ try {
25418
+ head = await this.ask({
25419
+ net: "fetch",
25420
+ nid,
25421
+ url: request.url,
25422
+ method: request.method,
25423
+ headers: request.headers,
25424
+ ...request.bodyStream ? { streamed: true } : request.body ? { body: request.body } : {},
25425
+ ...redirect !== void 0 ? { redirect } : {},
25426
+ ...owner !== void 0 ? { owner } : {},
25427
+ ...stamp ? { stamp } : {}
25428
+ });
25429
+ } catch (e) {
25430
+ finish();
25431
+ throw e;
25432
+ }
25433
+ const { status, statusText, headers, url, redirected: redirected2, redirects, opaqueRedirect } = head;
25434
+ const read = async () => {
25435
+ if (finished) return void 0;
25436
+ const reply = await this.ask({ net: "read", nid }).catch((e) => {
25437
+ finish();
25438
+ throw e;
25439
+ });
25440
+ if (reply.net === "chunk") return reply.bytes;
25441
+ finish();
25442
+ return void 0;
25443
+ };
25444
+ const cancel = async () => {
25445
+ if (finished) return;
25446
+ finish();
25447
+ this.cancel(nid);
25448
+ };
25449
+ if (unfollowed2(redirect) && (redirected2 || redirects?.length)) {
25450
+ await cancel();
25451
+ throw refused3(`this transport followed a redirect despite redirect: ${redirect}`);
25452
+ }
25453
+ return {
25454
+ ...url !== void 0 ? { url } : {},
25455
+ ...redirected2 !== void 0 ? { redirected: redirected2 } : {},
25456
+ ...redirects ? { redirects } : {},
25457
+ ...opaqueRedirect ? { opaqueRedirect } : {},
25458
+ status,
25459
+ statusText,
25460
+ headers,
25461
+ cancel,
25462
+ body: {
25463
+ [Symbol.asyncIterator]: () => ({
25464
+ next: async () => {
25465
+ const bytes = await read();
25466
+ return bytes ? { value: bytes, done: false } : { value: void 0, done: true };
25467
+ },
25468
+ return: async () => {
25469
+ await cancel();
25470
+ return { value: void 0, done: true };
25471
+ }
25472
+ })
25473
+ }
25474
+ };
25475
+ }
25476
+ async websocket(request) {
25477
+ const nid = ++this.nextId;
25478
+ const { signal } = request;
25479
+ signal.throwIfAborted();
25480
+ const abort = () => this.cancel(nid);
25481
+ signal.addEventListener("abort", abort, { once: true });
25482
+ let opened2;
25483
+ try {
25484
+ opened2 = await this.ask({
25485
+ net: "ws-open",
25486
+ nid,
25487
+ url: request.url,
25488
+ protocols: request.protocols,
25489
+ headers: request.headers
25490
+ });
25491
+ } finally {
25492
+ signal.removeEventListener("abort", abort);
25493
+ }
25494
+ const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
25495
+ const queue = new MessageQueue(
25496
+ () => close(1e3, "a message is too big"),
25497
+ Number.POSITIVE_INFINITY,
25498
+ (n) => this.port.postMessage({ net: "ws-consumed", nid, n })
25499
+ );
25500
+ let unacked = 0;
25501
+ this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
25502
+ return {
25503
+ protocol: opened2.protocol,
25504
+ get buffered() {
25505
+ return unacked;
25506
+ },
25507
+ send: (data) => {
25508
+ unacked += payloadSize(data);
25509
+ this.port.postMessage({ net: "ws-send", nid, data });
25510
+ },
25511
+ messages: queue,
25512
+ close,
25513
+ closed: queue.closed
25514
+ };
25515
+ }
25516
+ };
25517
+
25261
25518
  // src/kernel/net/redirect-hops.ts
25262
25519
  var HELD_MS = 3e4;
25263
25520
  var HELD_MAX2 = 64;
@@ -25333,7 +25590,9 @@ function replayingHops(inner, heldMs = HELD_MS) {
25333
25590
  return { ...inner.traits, manualRedirects: true };
25334
25591
  },
25335
25592
  ...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
25336
- async fetch(request, caller) {
25593
+ async fetch(request, ...rest2) {
25594
+ if (unfollowed2(request.redirect)) return inner.fetch(request, ...rest2);
25595
+ const [caller] = rest2;
25337
25596
  const owner = caller ?? KERNEL;
25338
25597
  const key = keyOf3(owner, request.method, request.url);
25339
25598
  const waiting = held.get(key);
@@ -25343,7 +25602,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
25343
25602
  return replay(waiting);
25344
25603
  }
25345
25604
  if (waiting) drop(key);
25346
- const response = await inner.fetch(request, caller);
25605
+ const response = await inner.fetch(request, ...rest2);
25347
25606
  if (!response.redirects?.length) return response;
25348
25607
  return replay({
25349
25608
  owner,
@@ -25356,6 +25615,173 @@ function replayingHops(inner, heldMs = HELD_MS) {
25356
25615
  };
25357
25616
  }
25358
25617
 
25618
+ // src/body-idle.ts
25619
+ var BODY_IDLE_MS = 5 * 60 * 1e3;
25620
+ function idleFailure(ms) {
25621
+ return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {
25622
+ code: "ETIMEDOUT"
25623
+ });
25624
+ }
25625
+ async function readWithin(reader, ms) {
25626
+ if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();
25627
+ let timer;
25628
+ const idle2 = new Promise((_, reject) => {
25629
+ timer = setTimeout(() => reject(idleFailure(ms)), ms);
25630
+ });
25631
+ try {
25632
+ return await Promise.race([reader.read(), idle2]);
25633
+ } finally {
25634
+ clearTimeout(timer);
25635
+ }
25636
+ }
25637
+
25638
+ // src/kernel/net/sealed-fetch.ts
25639
+ var SEALED_FETCH_VERSION = 1;
25640
+ var UNSAFE_FIELD = /[\r\n\0]/;
25641
+ function sealedHooks(option) {
25642
+ if (!option) return {};
25643
+ if (typeof option === "function") return { request: option };
25644
+ const { request, fetch: fetch2 } = option;
25645
+ if (typeof request !== "function" || fetch2 !== void 0 && typeof fetch2 !== "function") {
25646
+ throw new TypeError("sealed takes a function or { request, fetch? }");
25647
+ }
25648
+ return { request, ...fetch2 ? { fetch: fetch2 } : {} };
25649
+ }
25650
+ function headerList(headers) {
25651
+ return Array.isArray(headers) && headers.every(
25652
+ (field4) => Array.isArray(field4) && field4.length === 2 && field4.every((text) => typeof text === "string" && !UNSAFE_FIELD.test(text))
25653
+ );
25654
+ }
25655
+ function sealedReplyValid(reply) {
25656
+ if (typeof reply !== "object" || reply === null) return false;
25657
+ const { redirects, redirected: redirected2, status, statusText, headers, url, body, cancel } = reply;
25658
+ return redirects === void 0 && redirected2 !== true && Number.isInteger(status) && status >= 100 && status <= 599 && typeof statusText === "string" && !UNSAFE_FIELD.test(statusText) && headerList(headers) && (url === void 0 || typeof url === "string") && typeof body?.[Symbol.asyncIterator] === "function" && typeof cancel === "function";
25659
+ }
25660
+ function dropSealedReply(reply) {
25661
+ const { cancel } = reply ?? {};
25662
+ if (typeof cancel !== "function") return;
25663
+ void Promise.resolve().then(() => cancel.call(reply)).catch(() => void 0);
25664
+ }
25665
+ function failed2(reason) {
25666
+ const text = reason instanceof Error ? reason.message : String(reason);
25667
+ return new PlaceholderRefused(
25668
+ `refused: the request with a sealed placeholder was not completed: ${text}`
25669
+ );
25670
+ }
25671
+ var Stall = class {
25672
+ idle = new AbortController();
25673
+ ms;
25674
+ timer;
25675
+ signal;
25676
+ constructor(signals, ms) {
25677
+ this.ms = ms;
25678
+ this.signal = AbortSignal.any([...signals, this.idle.signal]);
25679
+ }
25680
+ arm() {
25681
+ clearTimeout(this.timer);
25682
+ this.timer = setTimeout(() => this.idle.abort("timeout"), this.ms);
25683
+ this.timer.unref?.();
25684
+ }
25685
+ touch() {
25686
+ if (this.timer !== void 0) this.arm();
25687
+ }
25688
+ rest() {
25689
+ clearTimeout(this.timer);
25690
+ this.timer = void 0;
25691
+ }
25692
+ };
25693
+ async function until(work, signal) {
25694
+ const stopped = Promise.withResolvers();
25695
+ const stop = () => stopped.reject(signal.reason);
25696
+ if (signal.aborted) stop();
25697
+ else signal.addEventListener("abort", stop, { once: true });
25698
+ try {
25699
+ return await Promise.race([work, stopped.promise]);
25700
+ } finally {
25701
+ signal.removeEventListener("abort", stop);
25702
+ }
25703
+ }
25704
+ async function* ticking(stream2, stall) {
25705
+ for await (const chunk2 of stream2) {
25706
+ stall.touch();
25707
+ yield chunk2;
25708
+ }
25709
+ }
25710
+ function sealedRequest(request, stamp, stall) {
25711
+ const { method, url, headers, body, bodyStream: bodyStream2 } = request;
25712
+ return {
25713
+ v: 1,
25714
+ caller: structuredClone(stamp),
25715
+ method,
25716
+ url,
25717
+ headers: headers.map(([name2, value2]) => [name2, value2]),
25718
+ redirect: "manual",
25719
+ ...bodyStream2 ? { bodyStream: ticking(bodyStream2, stall) } : body ? { body } : {}
25720
+ };
25721
+ }
25722
+ function guarded2(reply, stall) {
25723
+ let finished = false;
25724
+ const cancel = async () => {
25725
+ stall.signal.removeEventListener("abort", dropped2);
25726
+ stall.rest();
25727
+ if (finished) return;
25728
+ finished = true;
25729
+ await reply.cancel().catch(() => void 0);
25730
+ };
25731
+ const dropped2 = () => void cancel();
25732
+ stall.signal.addEventListener("abort", dropped2, { once: true });
25733
+ const source = reply.body[Symbol.asyncIterator]();
25734
+ const body = (async function* () {
25735
+ try {
25736
+ for (; ; ) {
25737
+ stall.arm();
25738
+ const next3 = await until(source.next(), stall.signal);
25739
+ stall.rest();
25740
+ if (next3.done) {
25741
+ finished = true;
25742
+ return;
25743
+ }
25744
+ if (!(next3.value instanceof Uint8Array)) throw failed2("a body chunk is not bytes");
25745
+ if (next3.value.byteLength > 0) yield next3.value;
25746
+ }
25747
+ } finally {
25748
+ await cancel();
25749
+ }
25750
+ })();
25751
+ return {
25752
+ ...reply.url !== void 0 ? { url: reply.url } : {},
25753
+ status: reply.status,
25754
+ statusText: reply.statusText,
25755
+ headers: reply.headers,
25756
+ body,
25757
+ cancel
25758
+ };
25759
+ }
25760
+ function sealedFetcher(hook, stop, idleMs = BODY_IDLE_MS) {
25761
+ return async (request, stamp) => {
25762
+ const stall = new Stall([request.signal, stop], idleMs);
25763
+ const { signal } = stall;
25764
+ if (signal.aborted) throw failed2(signal.reason);
25765
+ stall.arm();
25766
+ const asked = Promise.resolve().then(() => {
25767
+ signal.throwIfAborted();
25768
+ return hook(sealedRequest(request, stamp, stall), { signal });
25769
+ });
25770
+ let reply;
25771
+ try {
25772
+ reply = await until(asked, signal);
25773
+ } catch (e) {
25774
+ void asked.then(dropSealedReply, () => void 0);
25775
+ throw failed2(e);
25776
+ } finally {
25777
+ stall.rest();
25778
+ }
25779
+ if (sealedReplyValid(reply)) return guarded2(reply, stall);
25780
+ dropSealedReply(reply);
25781
+ throw failed2("the reply is not a scrubbed response");
25782
+ };
25783
+ }
25784
+
25359
25785
  // src/kernel/package-swaps.ts
25360
25786
  var SWAP_GAP_MS = 2e3;
25361
25787
  var STAGES = ["_tmp_", "_pacquet-stage_"];
@@ -25528,11 +25954,11 @@ var PackageLocks = class {
25528
25954
  if (!locks) return Promise.resolve(() => {
25529
25955
  });
25530
25956
  const { promise: held, resolve: release } = Promise.withResolvers();
25531
- return new Promise((granted2, failed3) => {
25957
+ return new Promise((granted2, failed5) => {
25532
25958
  locks.request(replacingLock(this.metadata, root), { mode: "exclusive" }, () => {
25533
25959
  granted2(() => release());
25534
25960
  return held;
25535
- }).catch(failed3);
25961
+ }).catch(failed5);
25536
25962
  });
25537
25963
  }
25538
25964
  };
@@ -25782,9 +26208,9 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
25782
26208
  let open = false;
25783
26209
  const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
25784
26210
  async function hello(message3) {
25785
- const refused3 = driverVersionError(message3.protocol);
25786
- if (refused3) {
25787
- reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused3, errno: "EPROTO" } });
26211
+ const refused4 = driverVersionError(message3.protocol);
26212
+ if (refused4) {
26213
+ reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused4, errno: "EPROTO" } });
25788
26214
  return;
25789
26215
  }
25790
26216
  try {
@@ -25916,11 +26342,11 @@ var META_OPS = ["get", "update", "move", "remove", "links", "under", "all"];
25916
26342
  var FILE_ID_TRIES = 3;
25917
26343
  function sidecar(meta) {
25918
26344
  const pathOf = ([first]) => [first, "/"].flat().find((p) => typeof p === "string");
25919
- const guarded3 = (op) => (...args) => meta[op].apply(meta, args).catch((err) => {
26345
+ const guarded4 = (op) => (...args) => meta[op].apply(meta, args).catch((err) => {
25920
26346
  throw translate(err, pathOf(args), "sidecar", false);
25921
26347
  });
25922
26348
  const names2 = meta.fresh ? [...META_OPS, "fresh"] : META_OPS;
25923
- const ops = Object.fromEntries(names2.map((op) => [op, guarded3(op)]));
26349
+ const ops = Object.fromEntries(names2.map((op) => [op, guarded4(op)]));
25924
26350
  const { updateMany } = meta;
25925
26351
  ops.updateMany = updateMany ? (changes) => updateMany.call(meta, changes).catch((err) => {
25926
26352
  throw translate(err, changes[0]?.path ?? "/", "sidecar", false);
@@ -25944,7 +26370,7 @@ function occupied(entry) {
25944
26370
  function vacatedAt(path) {
25945
26371
  return { path, ino: inodeOf(`${path}\0${crypto.randomUUID()}`), vacated: true };
25946
26372
  }
25947
- function missing4(err) {
26373
+ function missing5(err) {
25948
26374
  const code = err?.code;
25949
26375
  return code === "ENOENT" || code === "ENOTDIR";
25950
26376
  }
@@ -26187,7 +26613,7 @@ var OpfsFs = class {
26187
26613
  if (there) return (await this.meta.get([found.path]))[0]?.fid ?? fid;
26188
26614
  const gone = await this.locate(found.path, true).then(
26189
26615
  () => false,
26190
- (err) => missing4(err)
26616
+ (err) => missing5(err)
26191
26617
  );
26192
26618
  if (gone) {
26193
26619
  await this.meta.update(found.path, (now) => {
@@ -26630,7 +27056,7 @@ var OpfsFs = class {
26630
27056
  try {
26631
27057
  return await op();
26632
27058
  } catch (err) {
26633
- if (attempt >= REPLACED_ATTEMPTS || !missing4(err)) throw err;
27059
+ if (attempt >= REPLACED_ATTEMPTS || !missing5(err)) throw err;
26634
27060
  await this.replacing;
26635
27061
  if (this.replacements === seen) throw err;
26636
27062
  }
@@ -26642,7 +27068,7 @@ var OpfsFs = class {
26642
27068
  try {
26643
27069
  return { path: current, handle: await this.handle(current) };
26644
27070
  } catch (err) {
26645
- if (!missing4(err)) throw err;
27071
+ if (!missing5(err)) throw err;
26646
27072
  const link2 = await this.linkAlong(current);
26647
27073
  if (!link2) throw err;
26648
27074
  if (link2.path === current && !follow2) return { path: current, link: link2 };
@@ -26878,7 +27304,7 @@ var OpfsFs = class {
26878
27304
  return this.locate(path, true).then(
26879
27305
  () => true,
26880
27306
  (err) => {
26881
- if (missing4(err)) return false;
27307
+ if (missing5(err)) return false;
26882
27308
  throw err;
26883
27309
  }
26884
27310
  );
@@ -27175,7 +27601,7 @@ var OpfsFs = class {
27175
27601
  try {
27176
27602
  return [(await this.locate(path, true)).path, true];
27177
27603
  } catch (err) {
27178
- if (!missing4(err)) throw err;
27604
+ if (!missing5(err)) throw err;
27179
27605
  }
27180
27606
  const [entry] = await this.meta.get([path]);
27181
27607
  const wanted = entry?.link === void 0 ? path : resolvePath(parentOf9(path), entry.link);
@@ -27267,7 +27693,7 @@ var OpfsFs = class {
27267
27693
  try {
27268
27694
  found = await this.exactly(() => this.locate(path, true));
27269
27695
  } catch (err) {
27270
- if (!missing4(err)) throw err;
27696
+ if (!missing5(err)) throw err;
27271
27697
  }
27272
27698
  if (found) {
27273
27699
  const directory = found.handle?.kind === "directory";
@@ -27403,7 +27829,7 @@ var OpfsFs = class {
27403
27829
  const taken = await this.exactly(() => this.lstat(to)).then(
27404
27830
  () => true,
27405
27831
  (err) => {
27406
- if (missing4(err)) return false;
27832
+ if (missing5(err)) return false;
27407
27833
  throw err;
27408
27834
  }
27409
27835
  );
@@ -27435,7 +27861,7 @@ var OpfsFs = class {
27435
27861
  const sourceStat = await this.describe(source);
27436
27862
  if (sourceStat.isDirectory && within9(destination, source.path)) throw fsError("EINVAL", to);
27437
27863
  const target = await this.exactly(() => this.locate(destination, false)).catch((err) => {
27438
- if (missing4(err)) return null;
27864
+ if (missing5(err)) return null;
27439
27865
  throw err;
27440
27866
  });
27441
27867
  const targetStat = target && await this.describe(target);
@@ -28026,12 +28452,12 @@ var OpfsFs = class {
28026
28452
  if (!move) return false;
28027
28453
  for (let attempt = 0; ; attempt++) {
28028
28454
  this.others++;
28029
- const failed3 = await move.call(handle, dir, name2).then(
28455
+ const failed5 = await move.call(handle, dir, name2).then(
28030
28456
  () => void 0,
28031
28457
  (err) => ({ err })
28032
28458
  );
28033
- if (!failed3) return true;
28034
- const error = failed3.err?.name;
28459
+ if (!failed5) return true;
28460
+ const error = failed5.err?.name;
28035
28461
  if (handle.kind !== "file" || !LOCKED.has(error)) return false;
28036
28462
  const delay2 = SYNC_BACKOFF_MS[attempt];
28037
28463
  if (delay2 === void 0) throw fsError("EBUSY", name2);
@@ -28072,7 +28498,7 @@ var OpfsFs = class {
28072
28498
  this.refuse(at);
28073
28499
  if (await this.exactly(() => this.locate(at, false)).then(
28074
28500
  () => true,
28075
- (err) => !missing4(err)
28501
+ (err) => !missing5(err)
28076
28502
  )) {
28077
28503
  throw fsError("EEXIST", path);
28078
28504
  }
@@ -28594,22 +29020,22 @@ async function mountFstab(lines2, mount, signal, retries = FSTAB_RETRIES, discar
28594
29020
  );
28595
29021
  }
28596
29022
  async function mountLine({ line, spec, invalid }, mount, signal, retries, discard) {
28597
- let failed3 = invalid;
29023
+ let failed5 = invalid;
28598
29024
  for (let attempt = 0; !invalid && attempt <= retries.length && !signal.aborted; attempt++) {
28599
29025
  try {
28600
29026
  const entry = await mount(spec);
28601
29027
  if (!signal.aborted) return { line, target: spec.target, entry };
28602
29028
  discard(entry);
28603
- failed3 = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
29029
+ failed5 = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
28604
29030
  break;
28605
29031
  } catch (err) {
28606
- failed3 = err;
29032
+ failed5 = err;
28607
29033
  if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
28608
29034
  await wait(retries[attempt], signal);
28609
29035
  }
28610
29036
  }
28611
- const code = codeOf6(failed3);
28612
- return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
29037
+ const code = codeOf6(failed5);
29038
+ return { line, target: spec.target, code, error: String(failed5?.message ?? code) };
28613
29039
  }
28614
29040
 
28615
29041
  // src/mount/hostfs.ts
@@ -30211,7 +30637,7 @@ var RULE = new RegExp(
30211
30637
  var TERM = /^[A-Za-z0-9._+-]+$/;
30212
30638
  var PLAIN3 = /^[A-Za-z0-9_@%+=:,./-]+$/;
30213
30639
  var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
30214
- function failed2(errno3, error) {
30640
+ function failed3(errno3, error) {
30215
30641
  return { error, errno: errno3 };
30216
30642
  }
30217
30643
  function unescaped(double) {
@@ -30390,10 +30816,10 @@ var Sudo = class {
30390
30816
  }
30391
30817
  async untrusted(path, cwd, word) {
30392
30818
  const files = this.o.backing ? await this.o.backing(path, cwd) : [];
30393
- if (!files) return failed2("ENOENT", `sudo: ${word}: command not found`);
30819
+ if (!files) return failed3("ENOENT", `sudo: ${word}: command not found`);
30394
30820
  for (const file of [path, ...files]) {
30395
30821
  if (!await this.trusted(file)) {
30396
- return failed2("EPERM", `sudo: ${file} must be root's, and writable by root only`);
30822
+ return failed3("EPERM", `sudo: ${file} must be root's, and writable by root only`);
30397
30823
  }
30398
30824
  }
30399
30825
  return void 0;
@@ -30410,7 +30836,7 @@ var Sudo = class {
30410
30836
  }
30411
30837
  async request(caller, call, signal) {
30412
30838
  const parsed2 = parseArgs(call.args);
30413
- if (typeof parsed2 === "string") return failed2("EINVAL", parsed2);
30839
+ if (typeof parsed2 === "string") return failed3("EINVAL", parsed2);
30414
30840
  if (this.o.mode !== "enforce") {
30415
30841
  const mode = this.o.mode;
30416
30842
  if (parsed2.list) return { list: `sudo: users are '${mode}': commands run as the caller
@@ -30419,9 +30845,9 @@ var Sudo = class {
30419
30845
  }
30420
30846
  const { cred } = caller;
30421
30847
  const self = await this.o.users.lookup(cred.ruid);
30422
- if (!self) return failed2("EPERM", `sudo: uid ${cred.ruid} is not in the passwd database`);
30848
+ if (!self) return failed3("EPERM", `sudo: uid ${cred.ruid} is not in the passwd database`);
30423
30849
  const target = await this.lookup(parsed2.user);
30424
- if (!target) return failed2("ENOENT", `sudo: unknown user ${parsed2.user}`);
30850
+ if (!target) return failed3("ENOENT", `sudo: unknown user ${parsed2.user}`);
30425
30851
  const root = cred.euid === 0;
30426
30852
  const rules = root ? [] : await this.policy();
30427
30853
  const applies = await this.applies(self, cred);
@@ -30429,13 +30855,13 @@ var Sudo = class {
30429
30855
  const [word = "", ...args] = parsed2.command;
30430
30856
  const cwd = await this.canonical(call.cwd);
30431
30857
  if (cwd === void 0 || !await this.reachable(cred, cwd)) {
30432
- return failed2(
30858
+ return failed3(
30433
30859
  "EACCES",
30434
30860
  `sudo: cannot run in ${call.cwd}: it isn't a directory you can enter`
30435
30861
  );
30436
30862
  }
30437
30863
  const path = await this.locate(word, cwd);
30438
- if (!path) return failed2("ENOENT", `sudo: ${word}: command not found`);
30864
+ if (!path) return failed3("ENOENT", `sudo: ${word}: command not found`);
30439
30865
  const untrusted2 = await this.untrusted(path, cwd, word);
30440
30866
  if (untrusted2) return untrusted2;
30441
30867
  const argv = [path, ...args];
@@ -30446,24 +30872,24 @@ var Sudo = class {
30446
30872
  if (root || matching.some((rule) => rule.nopasswd)) return grant();
30447
30873
  const quoted = argv.map(quoteWord).join(" ");
30448
30874
  if (matching.length === 0) {
30449
- return failed2(
30875
+ return failed3(
30450
30876
  "EPERM",
30451
30877
  `sudo: ${self.name} is not allowed to run ${quoted} as ${target.name}`
30452
30878
  );
30453
30879
  }
30454
- if (parsed2.nonInteractive) return failed2("EPERM", "sudo: a password is required");
30455
- if (this.pending.has(cred.ruid)) return failed2("EBUSY", "sudo: another request is pending");
30880
+ if (parsed2.nonInteractive) return failed3("EPERM", "sudo: a password is required");
30881
+ if (this.pending.has(cred.ruid)) return failed3("EBUSY", "sudo: another request is pending");
30456
30882
  this.pending.add(cred.ruid);
30457
30883
  try {
30458
30884
  const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
30459
30885
  if (typeof answer2 !== "string") return answer2;
30460
30886
  if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
30461
- return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
30887
+ return failed3("EACCES", `sudo: ${call.cwd} changed while the request waited`);
30462
30888
  }
30463
30889
  const changed = await this.untrusted(path, cwd, word);
30464
30890
  if (changed) return changed;
30465
30891
  if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
30466
- return failed2("EIO", "sudo: the rule could not be recorded");
30892
+ return failed3("EIO", "sudo: the rule could not be recorded");
30467
30893
  }
30468
30894
  return grant();
30469
30895
  } finally {
@@ -30480,7 +30906,7 @@ var Sudo = class {
30480
30906
  };
30481
30907
  }
30482
30908
  if (rules.length === 0) {
30483
- return failed2("EPERM", `User ${self.name} is not allowed to run sudo on ${host}.`);
30909
+ return failed3("EPERM", `User ${self.name} is not allowed to run sudo on ${host}.`);
30484
30910
  }
30485
30911
  const lines2 = rules.map(described).join("\n");
30486
30912
  return { list: `User ${self.name} may run the following commands on ${host}:
@@ -30489,7 +30915,7 @@ ${lines2}
30489
30915
  }
30490
30916
  async ask(caller, self, target, argv, path, cwd, requester) {
30491
30917
  const { approve } = this.o;
30492
- if (!approve || requester.aborted) return failed2("EACCES", "sudo: approval denied");
30918
+ if (!approve || requester.aborted) return failed3("EACCES", "sudo: approval denied");
30493
30919
  const createdAt = Date.now();
30494
30920
  const timeout = this.o.timeoutMs ?? SUDO_TIMEOUT_MS;
30495
30921
  const req = {
@@ -30519,9 +30945,9 @@ ${lines2}
30519
30945
  const answered = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
30520
30946
  const answer2 = await Promise.race([answered, aborted3]);
30521
30947
  if (answer2 === "aborted" || control.signal.aborted) {
30522
- return control.signal.reason === "expired" ? failed2("ETIMEDOUT", "sudo: the request expired") : failed2("EINTR", "sudo: the request was withdrawn");
30948
+ return control.signal.reason === "expired" ? failed3("ETIMEDOUT", "sudo: the request expired") : failed3("EINTR", "sudo: the request was withdrawn");
30523
30949
  }
30524
- return answer2 === "once" || answer2 === "always" ? answer2 : failed2("EACCES", "sudo: approval denied");
30950
+ return answer2 === "once" || answer2 === "always" ? answer2 : failed3("EACCES", "sudo: approval denied");
30525
30951
  } finally {
30526
30952
  clearTimeout(timer);
30527
30953
  requester.removeEventListener("abort", withdraw);
@@ -30808,13 +31234,13 @@ function interpreter(head) {
30808
31234
  function expandDefaults(defaults2, env) {
30809
31235
  const out = {};
30810
31236
  for (const [key, value2] of Object.entries(defaults2 ?? {})) {
30811
- let missing5 = false;
31237
+ let missing6 = false;
30812
31238
  const expanded = value2.replace(ENV_REFERENCE, (_, name2) => {
30813
31239
  const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
30814
- if (set3 === void 0) missing5 = true;
31240
+ if (set3 === void 0) missing6 = true;
30815
31241
  return set3 ?? "";
30816
31242
  });
30817
- if (!missing5) out[key] = expanded;
31243
+ if (!missing6) out[key] = expanded;
30818
31244
  }
30819
31245
  return out;
30820
31246
  }
@@ -30989,6 +31415,9 @@ var Launcher = class {
30989
31415
  usersMode;
30990
31416
  dac;
30991
31417
  sealed;
31418
+ fill;
31419
+ fills = new AbortController();
31420
+ placeholders = [];
30992
31421
  scrubs = /* @__PURE__ */ new Map();
30993
31422
  clipboard;
30994
31423
  embedder;
@@ -31070,7 +31499,7 @@ var Launcher = class {
31070
31499
  ...options.env
31071
31500
  };
31072
31501
  this.ca = kernelCa(options.caStore ?? memoryCaStore());
31073
- this.transport = placeholderFloor(replayingHops(options.transport ?? missingTransport()));
31502
+ this.transport = this.floored(options);
31074
31503
  this.announcedTraits = JSON.stringify(this.transport.traits);
31075
31504
  this.uplink = options.uplink;
31076
31505
  this.routes = new Routes(options.uplink?.traits.ipv6 === true);
@@ -31225,16 +31654,16 @@ var Launcher = class {
31225
31654
  if (!found) {
31226
31655
  found = this.swaps.settled().then(() => this.trustedAppended()).then(async (appended2) => {
31227
31656
  const tiers = await this.tiers(scope, appended2);
31228
- const refused3 = [];
31657
+ const refused4 = [];
31229
31658
  const commands = await scanCommands(
31230
31659
  this.scanned,
31231
31660
  tiers,
31232
31661
  tiers.length - appended2.length,
31233
31662
  void 0,
31234
- refused3,
31663
+ refused4,
31235
31664
  await this.globalRoots(scope)
31236
31665
  );
31237
- this.refusedOf.set(commands, refused3.map(refusing));
31666
+ this.refusedOf.set(commands, refused4.map(refusing));
31238
31667
  return commands;
31239
31668
  }).then(
31240
31669
  (commands) => this.refusals(commands).set(SUDO_COMMAND.name, SUDO_COMMAND).set(CRONTAB_COMMAND.name, CRONTAB_COMMAND)
@@ -31440,14 +31869,14 @@ var Launcher = class {
31440
31869
  return await this.commandAt(path, scope) ?? await this.refusedAt(path, name2, scope);
31441
31870
  }
31442
31871
  async refusedAt(path, name2, scope) {
31443
- const refused3 = this.refusedOf.get(await this.commands(scope)) ?? [];
31444
- if (refused3.length === 0) return void 0;
31872
+ const refused4 = this.refusedOf.get(await this.commands(scope)) ?? [];
31873
+ if (refused4.length === 0) return void 0;
31445
31874
  const st = await this.base.stat(path).catch(() => void 0);
31446
31875
  if (!st?.isFile) return void 0;
31447
31876
  const real = await physicalPathAsync(this.base, path).catch(() => path);
31448
31877
  const same2 = async (own) => own === path || await physicalPathAsync(this.base, own).catch(() => own) === real;
31449
31878
  const owners = [];
31450
- for (const c of refused3) {
31879
+ for (const c of refused4) {
31451
31880
  const origin = c.origin;
31452
31881
  for (const own of [origin.glue, origin.wasm, ...origin.variants ?? []]) {
31453
31882
  if (!await same2(own)) continue;
@@ -31457,11 +31886,11 @@ var Launcher = class {
31457
31886
  }
31458
31887
  const stem = name2.replace(/\.wasm$/, "");
31459
31888
  const named = owners.find((c) => c.name === name2) ?? owners.find((c) => c.name === stem);
31460
- return named ?? owners[0] ?? await this.refusedCopy(real, name2, refused3);
31889
+ return named ?? owners[0] ?? await this.refusedCopy(real, name2, refused4);
31461
31890
  }
31462
- async refusedCopy(real, name2, refused3) {
31891
+ async refusedCopy(real, name2, refused4) {
31463
31892
  const dir = real.slice(0, real.lastIndexOf("/"));
31464
- for (const c of refused3) {
31893
+ for (const c of refused4) {
31465
31894
  const origin = c.origin;
31466
31895
  if (origin.abi !== "emscripten" || origin.script || c.name !== name2) continue;
31467
31896
  const own = await physicalPathAsync(this.base, origin.glue).catch(() => origin.glue);
@@ -31669,12 +32098,12 @@ var Launcher = class {
31669
32098
  return void 0;
31670
32099
  }
31671
32100
  async planOne(req, { ppid, cred, scope }, catalogOnly = false) {
31672
- const refused3 = (err) => {
32101
+ const refused4 = (err) => {
31673
32102
  throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
31674
32103
  };
31675
- const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
32104
+ const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused4);
31676
32105
  const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0, catalogOnly);
31677
- await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused3);
32106
+ await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused4);
31678
32107
  if (planned) return planned;
31679
32108
  throw new SpawnError(catalogOnly ? "ENOENT" : await this.unrunnable(file, req.cwd, scope));
31680
32109
  }
@@ -32132,6 +32561,19 @@ var Launcher = class {
32132
32561
  groupSession(pgid) {
32133
32562
  return this.jobs.sessionOf(pgid);
32134
32563
  }
32564
+ floored(options) {
32565
+ const { sealedFetch } = options;
32566
+ this.fill = sealedFetch && this.usersMode === "enforce" ? sealedFetcher(sealedFetch, this.fills.signal) : void 0;
32567
+ if (this.fill) this.net.stampProxy(REALM_PROXY_PORT);
32568
+ return placeholderFloor(replayingHops(options.transport ?? missingTransport()), {
32569
+ known: () => this.placeholders,
32570
+ ...this.fill ? { fill: this.fill } : {}
32571
+ });
32572
+ }
32573
+ httpFor(pid) {
32574
+ const stamp = this.fill ? () => this.liveStamp(pid) : void 0;
32575
+ return new HttpHandles(this.transport, pid, this.loopbackFor(pid), stamp);
32576
+ }
32135
32577
  loopbackFor(pid) {
32136
32578
  return new KernelLoopback(
32137
32579
  this.net,
@@ -32139,7 +32581,7 @@ var Launcher = class {
32139
32581
  const cred = this.credOf(pid);
32140
32582
  return { pid, uid: cred.euid, gid: cred.egid };
32141
32583
  },
32142
- () => this.connectorStamp(pid)
32584
+ () => this.liveStamp(pid)
32143
32585
  );
32144
32586
  }
32145
32587
  sourceCheck(pid, writer) {
@@ -32304,7 +32746,7 @@ var Launcher = class {
32304
32746
  jobs: this.jobs,
32305
32747
  ptys: this.ptys,
32306
32748
  net: this.net,
32307
- http: new HttpHandles(this.transport, pid, this.loopbackFor(pid)),
32749
+ http: this.httpFor(pid),
32308
32750
  locks: this.locks,
32309
32751
  fifos: this.fifos,
32310
32752
  sems: this.sems,
@@ -32619,6 +33061,19 @@ var Launcher = class {
32619
33061
  connectorStamp(pid) {
32620
33062
  return this.sealed.stamp(this.identityOf(pid), this.credOf(pid), this.tagsOf(pid));
32621
33063
  }
33064
+ async liveStamp(pid) {
33065
+ if (!this.creds.has(pid) || this.zombies.has(pid)) return void 0;
33066
+ return this.connectorStamp(pid);
33067
+ }
33068
+ setPlaceholders(list) {
33069
+ if (!Array.isArray(list) || !list.every((p) => typeof p === "string" && p !== "")) {
33070
+ throw fsError("EINVAL", "setPlaceholders takes a list of non-empty strings");
33071
+ }
33072
+ this.placeholders = [...list];
33073
+ }
33074
+ endFills() {
33075
+ this.fills.abort("terminated");
33076
+ }
32622
33077
  identityOf(pid) {
32623
33078
  const parent = this.jobs.shownParent(pid);
32624
33079
  const alive = parent !== void 0 && this.running(parent);
@@ -32741,7 +33196,7 @@ var Launcher = class {
32741
33196
  const at = normalizePath(path);
32742
33197
  this.unlinked.closed(at);
32743
33198
  this.writers?.unlinked.closed(at);
32744
- const holding = [...this.held].some((holds2) => holds2.holding(at)) || [...this.openFiles].some((open2) => open2.holdsAt(at));
33199
+ const holding = [...this.held].some((holds3) => holds3.holding(at)) || [...this.openFiles].some((open2) => open2.holdsAt(at));
32745
33200
  if (!holding) void this.rootFs.announceHolds?.([], [at], false);
32746
33201
  const open = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
32747
33202
  if (!open) void this.mounts.commit(at).catch(() => void 0);
@@ -32904,8 +33359,9 @@ var Launcher = class {
32904
33359
  for (const root of roots) this.integrity.forget(root);
32905
33360
  this.resetCatalogs();
32906
33361
  }
32907
- attest(path) {
33362
+ attest(path, options = {}) {
32908
33363
  return attest(this.rootFs, path, {
33364
+ ...options,
32909
33365
  users: this.usersMode,
32910
33366
  mounts: this.mounts.list().map((entry) => entry.target).filter((target) => this.mounts.mounted(target) !== void 0)
32911
33367
  });
@@ -32962,8 +33418,8 @@ var Launcher = class {
32962
33418
  for (const name2 of names2 ?? []) {
32963
33419
  const path = joinName(real, name2);
32964
33420
  if (await this.base.hasOwner(path)) continue;
32965
- const failed3 = this.inUse(path) ? "busy" : await this.base.rm(path, { recursive: true, force: true }).catch(String);
32966
- if (failed3 === void 0) removed++;
33421
+ const failed5 = this.inUse(path) ? "busy" : await this.base.rm(path, { recursive: true, force: true }).catch(String);
33422
+ if (failed5 === void 0) removed++;
32967
33423
  else left++;
32968
33424
  }
32969
33425
  if (removed > 0) {
@@ -33058,7 +33514,7 @@ var Launcher = class {
33058
33514
  this.pnpmStale();
33059
33515
  if (!detach) return;
33060
33516
  for (const nodes of this.openFiles) nodes.revoke(at);
33061
- for (const holds2 of this.held) holds2.revoke(at);
33517
+ for (const holds3 of this.held) holds3.revoke(at);
33062
33518
  }
33063
33519
  unmountAll() {
33064
33520
  this.cron.stop();
@@ -33269,9 +33725,9 @@ var Launcher = class {
33269
33725
  }
33270
33726
  boundTo(path, hidden, fids) {
33271
33727
  const keeping = [...this.held].map(
33272
- (holds2) => [
33273
- holds2,
33274
- fids.flatMap((fid) => [...holds2.boundAt(path, fid), ...holds2.boundAt(hidden, fid)])
33728
+ (holds3) => [
33729
+ holds3,
33730
+ fids.flatMap((fid) => [...holds3.boundAt(path, fid), ...holds3.boundAt(hidden, fid)])
33275
33731
  ]
33276
33732
  ).filter(([, ids]) => ids.length > 0);
33277
33733
  const nodes = [...this.openFiles].filter(
@@ -33282,7 +33738,7 @@ var Launcher = class {
33282
33738
  (open) => fids.some((fid) => open.keepBound([hidden, path], fid, file))
33283
33739
  ).length;
33284
33740
  for (let i = kept; i < nodes.length; i++) file.release();
33285
- for (const [holds2, ids] of keeping) holds2.keepBound(ids, path, file);
33741
+ for (const [holds3, ids] of keeping) holds3.keepBound(ids, path, file);
33286
33742
  void this.rootFs.announceHolds?.([], [path, hidden], false);
33287
33743
  };
33288
33744
  return { keeping, nodes, keep: keep2 };
@@ -33442,7 +33898,7 @@ var Launcher = class {
33442
33898
  }
33443
33899
  moved(from, to, source) {
33444
33900
  this.renameLog.add(from, to);
33445
- for (const holds2 of this.held) holds2.renamed(from, to);
33901
+ for (const holds3 of this.held) holds3.renamed(from, to);
33446
33902
  if (source) return;
33447
33903
  for (const nodes of this.openFiles) nodes.renamed(from, to);
33448
33904
  this.watchers.moved(from, to);
@@ -33587,26 +34043,6 @@ function codeOf8(err) {
33587
34043
  return err?.code;
33588
34044
  }
33589
34045
 
33590
- // src/body-idle.ts
33591
- var BODY_IDLE_MS = 5 * 60 * 1e3;
33592
- function idleFailure(ms) {
33593
- return Object.assign(new Error(`the response body sent no data for ${ms} ms`), {
33594
- code: "ETIMEDOUT"
33595
- });
33596
- }
33597
- async function readWithin(reader, ms) {
33598
- if (!(ms > 0 && ms < Number.POSITIVE_INFINITY)) return reader.read();
33599
- let timer;
33600
- const idle2 = new Promise((_, reject) => {
33601
- timer = setTimeout(() => reject(idleFailure(ms)), ms);
33602
- });
33603
- try {
33604
- return await Promise.race([reader.read(), idle2]);
33605
- } finally {
33606
- clearTimeout(timer);
33607
- }
33608
- }
33609
-
33610
34046
  // src/websocket-transport.ts
33611
34047
  var SENT_HEADERS_DROP = /* @__PURE__ */ new Set([
33612
34048
  "host",
@@ -33756,10 +34192,11 @@ function fetchTransport(options = {}) {
33756
34192
  const send2 = options.fetch ?? globalThis.fetch.bind(globalThis);
33757
34193
  const Socket = options.webSocket === true ? globalThis.WebSocket : options.webSocket || void 0;
33758
34194
  const headers = options.webSocketHeaders === true;
33759
- const redirect = options.redirect ?? "follow";
34195
+ const instance = options.redirect ?? "follow";
33760
34196
  return {
33761
34197
  traits: {
33762
- manualRedirects: redirect === "manual",
34198
+ manualRedirects: instance === "manual",
34199
+ redirectPolicy: true,
33763
34200
  encodedBodies: false,
33764
34201
  maxRequestBody: options.maxRequestBody ?? MAX_REQUEST_BODY,
33765
34202
  crossOrigin: "cors",
@@ -33775,7 +34212,7 @@ function fetchTransport(options = {}) {
33775
34212
  headers: joinHeaders(request.headers),
33776
34213
  ...requestBody(request),
33777
34214
  signal: request.signal,
33778
- redirect,
34215
+ redirect: request.redirect ?? instance,
33779
34216
  credentials: "omit",
33780
34217
  mode: "cors"
33781
34218
  });
@@ -33799,6 +34236,7 @@ function fetchTransport(options = {}) {
33799
34236
  const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);
33800
34237
  return {
33801
34238
  ...response.redirected ? { url: response.url, redirected: true } : {},
34239
+ ...response.type === "opaqueredirect" ? { opaqueRedirect: true } : {},
33802
34240
  status: response.status,
33803
34241
  statusText: response.statusText,
33804
34242
  headers: headers2,
@@ -33834,7 +34272,34 @@ function uploadsFor(peer) {
33834
34272
  });
33835
34273
  return { of, answer: (call) => pulls.get(call.nid)?.(call) };
33836
34274
  }
33837
- function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS3 } = {}) {
34275
+ function headOf(nid, response) {
34276
+ return {
34277
+ net: "head",
34278
+ nid,
34279
+ ...response.url !== void 0 ? { url: response.url } : {},
34280
+ ...response.redirected !== void 0 ? { redirected: response.redirected } : {},
34281
+ ...response.redirects ? { redirects: response.redirects } : {},
34282
+ ...response.opaqueRedirect ? { opaqueRedirect: true } : {},
34283
+ status: response.status,
34284
+ statusText: response.statusText,
34285
+ headers: response.headers
34286
+ };
34287
+ }
34288
+ function requestOf(call, signal, uploads) {
34289
+ const { url, method, headers, streamed, body, redirect, nid } = call;
34290
+ return {
34291
+ url,
34292
+ method,
34293
+ headers,
34294
+ ...streamed ? { bodyStream: uploads.of(nid, signal) } : body ? { body } : {},
34295
+ ...redirect !== void 0 ? { redirect } : {},
34296
+ signal
34297
+ };
34298
+ }
34299
+ function serveTransport(peer, transport, {
34300
+ closeWaitMs = CLOSE_WAIT_MS3,
34301
+ attributed = false
34302
+ } = {}) {
33838
34303
  const open = /* @__PURE__ */ new Map();
33839
34304
  const fail3 = (nid, e) => {
33840
34305
  open.delete(nid);
@@ -33854,27 +34319,17 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS3 } = {})
33854
34319
  const entry = { abort };
33855
34320
  open.set(call.nid, entry);
33856
34321
  try {
33857
- const response = await transport.fetch({
33858
- url: call.url,
33859
- method: call.method,
33860
- headers: call.headers,
33861
- ...call.streamed ? { bodyStream: uploads.of(call.nid, abort.signal) } : call.body ? { body: call.body } : {},
33862
- signal: abort.signal
33863
- });
34322
+ const response = await transport.fetch(
34323
+ requestOf(call, abort.signal, uploads),
34324
+ attributed ? call.owner : void 0,
34325
+ attributed ? call.stamp : void 0
34326
+ );
33864
34327
  if (!open.has(call.nid)) {
33865
34328
  await response.cancel();
33866
34329
  return;
33867
34330
  }
33868
34331
  open.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });
33869
- peer.postMessage({
33870
- net: "head",
33871
- nid: call.nid,
33872
- ...response.redirected ? { url: response.url, redirected: true } : {},
33873
- ...response.redirects ? { redirects: response.redirects } : {},
33874
- status: response.status,
33875
- statusText: response.statusText,
33876
- headers: response.headers
33877
- });
34332
+ peer.postMessage(headOf(call.nid, response));
33878
34333
  } catch (e) {
33879
34334
  fail3(call.nid, e);
33880
34335
  }
@@ -34374,9 +34829,9 @@ function serveClient(port, host) {
34374
34829
  ended.resolve();
34375
34830
  }
34376
34831
  async function hello(message3) {
34377
- const refused3 = versionError(message3.protocol) ?? await hosts.requests.accept(host, message3);
34378
- if (refused3) {
34379
- send2({ hello: { protocol: PROTOCOL, error: refused3 } });
34832
+ const refused4 = versionError(message3.protocol) ?? await hosts.requests.accept(host, message3);
34833
+ if (refused4) {
34834
+ send2({ hello: { protocol: PROTOCOL, error: refused4 } });
34380
34835
  detach();
34381
34836
  return;
34382
34837
  }
@@ -34520,6 +34975,60 @@ import { AsyncLocalStorage } from "node:async_hooks";
34520
34975
  import { subscribe } from "node:diagnostics_channel";
34521
34976
  import { lookup as lookup2 } from "node:dns/promises";
34522
34977
  import { isIP as isIP3 } from "node:net";
34978
+
34979
+ // src/node/follow.ts
34980
+ var MAX_REDIRECTS = 20;
34981
+ var REDIRECTS = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
34982
+ var BODY_HEADERS = /* @__PURE__ */ new Set([
34983
+ "content-encoding",
34984
+ "content-language",
34985
+ "content-length",
34986
+ "content-location",
34987
+ "content-type"
34988
+ ]);
34989
+ var CREDENTIALS = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2"]);
34990
+ function failed4(message3) {
34991
+ return Object.assign(new Error(message3), { status: 502, detail: "transport" });
34992
+ }
34993
+ function locationOf(headers) {
34994
+ return headers.find(([name2]) => name2.toLowerCase() === "location")?.[1];
34995
+ }
34996
+ function nextHop(hop, status, location) {
34997
+ if (!URL.canParse(location, hop.url)) throw failed4(`a bad redirect from ${hop.url}`);
34998
+ const next3 = new URL(location, hop.url);
34999
+ if (next3.protocol !== "http:" && next3.protocol !== "https:") {
35000
+ throw failed4(`a redirect from ${hop.url} to ${next3.protocol}`);
35001
+ }
35002
+ next3.hash = "";
35003
+ const toGet = (status === 301 || status === 302) && hop.method === "POST" || status === 303 && hop.method !== "GET" && hop.method !== "HEAD";
35004
+ if (hop.bodyStream && !toGet) throw failed4(`a ${status} redirect would resend a streamed body`);
35005
+ const crossOrigin = next3.origin !== new URL(hop.url).origin;
35006
+ const { body, bodyStream: bodyStream2, ...rest2 } = hop;
35007
+ return {
35008
+ ...rest2,
35009
+ ...body && !toGet ? { body } : {},
35010
+ url: next3.href,
35011
+ method: toGet ? "GET" : hop.method,
35012
+ headers: hop.headers.filter(
35013
+ ([name2]) => !(toGet && BODY_HEADERS.has(name2.toLowerCase())) && !(crossOrigin && CREDENTIALS.has(name2.toLowerCase()))
35014
+ )
35015
+ };
35016
+ }
35017
+ async function followRedirects(send2, request) {
35018
+ let hop = { ...request, redirect: "manual" };
35019
+ for (let hops = 0; ; hops++) {
35020
+ const response = await send2(hop);
35021
+ const location = locationOf(response.headers);
35022
+ if (!REDIRECTS.has(response.status) || location === void 0) {
35023
+ return hops > 0 ? { ...response, url: hop.url, redirected: true } : response;
35024
+ }
35025
+ await response.cancel();
35026
+ if (hops >= MAX_REDIRECTS) throw failed4(`too many redirects from ${request.url}`);
35027
+ hop = nextHop(hop, response.status, location);
35028
+ }
35029
+ }
35030
+
35031
+ // src/node/loopback.ts
34523
35032
  var DEVTOOLS_PORTS = [9222, 9223, 9224, 9225, 9226, 9227, 9228, 9229];
34524
35033
  var METADATA_V6 = [64768, 3778, 0, 0, 0, 0, 0, 596].join(":");
34525
35034
  var resolveHost = async (host) => (await lookup2(host, { all: true, verbatim: true })).map((a) => a.address);
@@ -34597,7 +35106,7 @@ async function checkDestination(target, policy, resolve2 = resolveHost) {
34597
35106
  throw refusal2(url, address, place);
34598
35107
  }
34599
35108
  }
34600
- function guarded2(check, signal) {
35109
+ function guarded3(check, signal) {
34601
35110
  if (!signal) return check;
34602
35111
  signal.throwIfAborted();
34603
35112
  let stop = () => {
@@ -34684,22 +35193,23 @@ function ensureSubscribed() {
34684
35193
  function guardedLoopback(transport, policy, resolve2) {
34685
35194
  ensureSubscribed();
34686
35195
  const open = transport.websocket?.bind(transport);
35196
+ const send2 = async (request, owner, stamp) => {
35197
+ await guarded3(checkDestination(request.url, policy, resolve2), request.signal);
35198
+ const entry = { policy };
35199
+ try {
35200
+ return await loopbackStore.run(entry, () => transport.fetch(request, owner, stamp));
35201
+ } catch (err) {
35202
+ throw entry.refused ?? err;
35203
+ }
35204
+ };
34687
35205
  return {
34688
35206
  get traits() {
34689
35207
  return transport.traits;
34690
35208
  },
34691
- fetch: async (request, owner) => {
34692
- await guarded2(checkDestination(request.url, policy, resolve2), request.signal);
34693
- const entry = { policy };
34694
- try {
34695
- return await loopbackStore.run(entry, () => transport.fetch(request, owner));
34696
- } catch (err) {
34697
- throw entry.refused ?? err;
34698
- }
34699
- },
35209
+ fetch: (request, owner, stamp) => request.redirect === "follow" ? followRedirects((hop) => send2(hop, owner, stamp), request) : send2(request, owner, stamp),
34700
35210
  ...open ? {
34701
35211
  websocket: async (request) => {
34702
- await guarded2(checkDestination(request.url, policy, resolve2), request.signal);
35212
+ await guarded3(checkDestination(request.url, policy, resolve2), request.signal);
34703
35213
  const entry = { policy };
34704
35214
  try {
34705
35215
  return await loopbackStore.run(entry, () => open(request));
@@ -35082,212 +35592,6 @@ function diagnosing(transport, check = byDefault) {
35082
35592
  };
35083
35593
  }
35084
35594
 
35085
- // src/kernel/net/remote-transport.ts
35086
- var TransportError = class extends Error {
35087
- status;
35088
- code;
35089
- detail;
35090
- constructor(message3, status, code, detail) {
35091
- super(message3);
35092
- this.status = status;
35093
- this.code = code;
35094
- this.detail = detail === "transport" ? detail : void 0;
35095
- }
35096
- };
35097
- var RemoteTransport = class {
35098
- traits;
35099
- port;
35100
- waiting = /* @__PURE__ */ new Map();
35101
- nextId = 0;
35102
- sockets = /* @__PURE__ */ new Map();
35103
- uploads = /* @__PURE__ */ new Map();
35104
- failure;
35105
- constructor(port, traits) {
35106
- this.port = port;
35107
- this.traits = traits;
35108
- }
35109
- receive(reply) {
35110
- if (reply.net === "body-pull") {
35111
- void this.pull(reply.nid);
35112
- return;
35113
- }
35114
- const socket = this.sockets.get(reply.nid);
35115
- if (socket && this.toSocket(reply, socket)) return;
35116
- const waiter = this.waiting.get(reply.nid);
35117
- if (!waiter) return;
35118
- this.waiting.delete(reply.nid);
35119
- if (reply.net === "error") {
35120
- waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
35121
- } else waiter.resolve(reply);
35122
- }
35123
- toSocket(reply, socket) {
35124
- if (reply.net === "ws-message") socket.queue.push(reply.data);
35125
- else if (reply.net === "ws-acked") socket.acked(reply.n);
35126
- else if (reply.net === "ws-closed") {
35127
- this.sockets.delete(reply.nid);
35128
- socket.queue.end({ code: reply.code, reason: reply.reason });
35129
- } else return false;
35130
- return true;
35131
- }
35132
- async pull(nid) {
35133
- const upload = this.uploads.get(nid);
35134
- if (!upload) {
35135
- this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
35136
- return;
35137
- }
35138
- try {
35139
- const next3 = await upload.next();
35140
- if (next3.done) {
35141
- this.uploads.delete(nid);
35142
- this.port.postMessage({ net: "body-end", nid });
35143
- } else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
35144
- } catch (e) {
35145
- this.uploads.delete(nid);
35146
- this.port.postMessage({
35147
- net: "body-error",
35148
- nid,
35149
- message: e instanceof Error ? e.message : String(e)
35150
- });
35151
- }
35152
- }
35153
- dropUpload(nid) {
35154
- const upload = this.uploads.get(nid);
35155
- this.uploads.delete(nid);
35156
- void upload?.return?.().catch(() => void 0);
35157
- }
35158
- fail(error) {
35159
- this.failure = error;
35160
- for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
35161
- for (const waiter of this.waiting.values()) waiter.reject(error);
35162
- this.waiting.clear();
35163
- for (const socket of this.sockets.values())
35164
- socket.queue.end({ code: 1011, reason: error.message });
35165
- this.sockets.clear();
35166
- }
35167
- ask(call) {
35168
- if (this.failure) return Promise.reject(this.failure);
35169
- return new Promise((resolve2, reject) => {
35170
- this.waiting.set(call.nid, { resolve: resolve2, reject });
35171
- this.port.postMessage(call);
35172
- });
35173
- }
35174
- cancel(nid) {
35175
- const waiter = this.waiting.get(nid);
35176
- this.waiting.delete(nid);
35177
- waiter?.reject(new TransportError("the request was cancelled"));
35178
- this.port.postMessage({ net: "cancel", nid });
35179
- }
35180
- async fetch(request) {
35181
- const nid = ++this.nextId;
35182
- const { signal } = request;
35183
- signal.throwIfAborted();
35184
- let finished = false;
35185
- const abort = () => {
35186
- finished = true;
35187
- this.dropUpload(nid);
35188
- this.cancel(nid);
35189
- };
35190
- signal.addEventListener("abort", abort, { once: true });
35191
- const finish = () => {
35192
- this.dropUpload(nid);
35193
- if (finished) return;
35194
- finished = true;
35195
- signal.removeEventListener("abort", abort);
35196
- };
35197
- if (request.bodyStream) this.uploads.set(nid, request.bodyStream[Symbol.asyncIterator]());
35198
- let head;
35199
- try {
35200
- head = await this.ask({
35201
- net: "fetch",
35202
- nid,
35203
- url: request.url,
35204
- method: request.method,
35205
- headers: request.headers,
35206
- ...request.bodyStream ? { streamed: true } : request.body ? { body: request.body } : {}
35207
- });
35208
- } catch (e) {
35209
- finish();
35210
- throw e;
35211
- }
35212
- const { status, statusText, headers, url, redirected: redirected2, redirects } = head;
35213
- const read = async () => {
35214
- if (finished) return void 0;
35215
- const reply = await this.ask({ net: "read", nid }).catch((e) => {
35216
- finish();
35217
- throw e;
35218
- });
35219
- if (reply.net === "chunk") return reply.bytes;
35220
- finish();
35221
- return void 0;
35222
- };
35223
- const cancel = async () => {
35224
- if (finished) return;
35225
- finish();
35226
- this.cancel(nid);
35227
- };
35228
- return {
35229
- ...redirected2 ? { url, redirected: redirected2 } : {},
35230
- ...redirects ? { redirects } : {},
35231
- status,
35232
- statusText,
35233
- headers,
35234
- cancel,
35235
- body: {
35236
- [Symbol.asyncIterator]: () => ({
35237
- next: async () => {
35238
- const bytes = await read();
35239
- return bytes ? { value: bytes, done: false } : { value: void 0, done: true };
35240
- },
35241
- return: async () => {
35242
- await cancel();
35243
- return { value: void 0, done: true };
35244
- }
35245
- })
35246
- }
35247
- };
35248
- }
35249
- async websocket(request) {
35250
- const nid = ++this.nextId;
35251
- const { signal } = request;
35252
- signal.throwIfAborted();
35253
- const abort = () => this.cancel(nid);
35254
- signal.addEventListener("abort", abort, { once: true });
35255
- let opened2;
35256
- try {
35257
- opened2 = await this.ask({
35258
- net: "ws-open",
35259
- nid,
35260
- url: request.url,
35261
- protocols: request.protocols,
35262
- headers: request.headers
35263
- });
35264
- } finally {
35265
- signal.removeEventListener("abort", abort);
35266
- }
35267
- const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
35268
- const queue = new MessageQueue(
35269
- () => close(1e3, "a message is too big"),
35270
- Number.POSITIVE_INFINITY,
35271
- (n) => this.port.postMessage({ net: "ws-consumed", nid, n })
35272
- );
35273
- let unacked = 0;
35274
- this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
35275
- return {
35276
- protocol: opened2.protocol,
35277
- get buffered() {
35278
- return unacked;
35279
- },
35280
- send: (data) => {
35281
- unacked += payloadSize(data);
35282
- this.port.postMessage({ net: "ws-send", nid, data });
35283
- },
35284
- messages: queue,
35285
- close,
35286
- closed: queue.closed
35287
- };
35288
- }
35289
- };
35290
-
35291
35595
  // src/serve.ts
35292
35596
  function signalNumber(name2) {
35293
35597
  const key = name2.slice(3);
@@ -35921,9 +36225,9 @@ async function greet(channel, lock, timeoutMs, requests) {
35921
36225
  } finally {
35922
36226
  clearTimeout(timer);
35923
36227
  }
35924
- const refused3 = hello.error ?? versionError(hello.protocol);
35925
- if (refused3) {
35926
- const error = new Error(refused3);
36228
+ const refused4 = hello.error ?? versionError(hello.protocol);
36229
+ if (refused4) {
36230
+ const error = new Error(refused4);
35927
36231
  channel.end(error);
35928
36232
  throw error;
35929
36233
  }
@@ -36289,6 +36593,7 @@ function checkedRequests(hook) {
36289
36593
  return { kinds, handle: (request) => hook.handle(request) };
36290
36594
  }
36291
36595
  async function createNodeKernel(options = {}) {
36596
+ const hooks = sealedHooks(options.sealed);
36292
36597
  const root = options.root ?? memoryRoot();
36293
36598
  const fs = new OpfsFs(root, void 0, void 0, { ranged: isMemoryRoot(root) });
36294
36599
  await fs.reconcile();
@@ -36327,7 +36632,8 @@ async function createNodeKernel(options = {}) {
36327
36632
  users: options.users === void 0 ? DEFAULT_USERS : options.users,
36328
36633
  ...options.onDenial ? { onDenial: options.onDenial } : {},
36329
36634
  ...options.protect ? { protect: options.protect } : {},
36330
- ...options.sealed ? { sealed: options.sealed } : {},
36635
+ ...hooks.request ? { sealed: hooks.request } : {},
36636
+ ...hooks.fetch ? { sealedFetch: hooks.fetch } : {},
36331
36637
  ...options.clipboard ? { clipboard: options.clipboard } : {},
36332
36638
  ...options.requests ? { embedder: checkedRequests(options.requests) } : {},
36333
36639
  ...options.approve ? { approve: options.approve } : {},
@@ -36403,6 +36709,8 @@ async function createNodeKernel(options = {}) {
36403
36709
  },
36404
36710
  chmod: async (path, mode) => launcher.fs.chmod(path, modeOption(mode)),
36405
36711
  integrity: { revoke: (path) => guard2(() => launcher.revokeIntegrity(path)) },
36712
+ sealed: { setPlaceholders: (list) => guard2(async () => launcher.setPlaceholders(list)) },
36713
+ attest: ((path, attestOptions) => guard2(() => launcher.attest(path, attestOptions))),
36406
36714
  readFile: async (path) => launcher.fs.readFileBuffer(path),
36407
36715
  mount: (spec) => guard2(() => launcher.mount(spec)),
36408
36716
  umount: (target) => guard2(async () => launcher.umount(target)),
@@ -36435,6 +36743,7 @@ async function createNodeKernel(options = {}) {
36435
36743
  for (const reject of [...pending]) reject(new Error(TERMINATED));
36436
36744
  for (const kill of [...live]) kill();
36437
36745
  launcher.cdp.close();
36746
+ launcher.endFills();
36438
36747
  launcher.unmountAll();
36439
36748
  dropCache(cache);
36440
36749
  }
@@ -36444,6 +36753,7 @@ export {
36444
36753
  KernelCallError,
36445
36754
  KernelGoneError,
36446
36755
  MAX_WARM_WORKERS,
36756
+ SEALED_FETCH_VERSION,
36447
36757
  WARM_IDLE_MS,
36448
36758
  attachKernel,
36449
36759
  createNodeKernel,