@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.
@@ -182,13 +182,13 @@ var IndexedDbMeta = class {
182
182
  return [transaction, transaction.objectStore(META_STORE)];
183
183
  }
184
184
  async get(paths) {
185
- const missing5 = paths.filter((path) => !this.cache.has(path));
186
- if (missing5.length > 0) {
185
+ const missing6 = paths.filter((path) => !this.cache.has(path));
186
+ if (missing6.length > 0) {
187
187
  this.settleRemoves();
188
188
  const generation = this.generation;
189
189
  const [transaction, store] = this.transaction("readonly");
190
190
  const found = /* @__PURE__ */ new Map();
191
- for (const path of missing5) {
191
+ for (const path of missing6) {
192
192
  const request3 = store.get(path);
193
193
  request3.onsuccess = () => void found.set(path, request3.result ?? null);
194
194
  }
@@ -1237,10 +1237,10 @@ var RemoteWatch = class {
1237
1237
  });
1238
1238
  }
1239
1239
  }
1240
- heldBy({ tab, holds: holds2, seq: seq2 }) {
1240
+ heldBy({ tab, holds: holds3, seq: seq2 }) {
1241
1241
  const from = tab;
1242
- const { add, drop } = holds2;
1243
- if (holds2?.instance !== void 0) this.instances.set(from, holds2.instance);
1242
+ const { add, drop } = holds3;
1243
+ if (holds3?.instance !== void 0) this.instances.set(from, holds3.instance);
1244
1244
  const held = this.peerHolds.get(from) ?? /* @__PURE__ */ new Map();
1245
1245
  for (const path of drop) held.delete(path);
1246
1246
  for (const [path, fid] of add) held.set(path, fid);
@@ -1524,11 +1524,11 @@ var META_OPS = ["get", "update", "move", "remove", "links", "under", "all"];
1524
1524
  var FILE_ID_TRIES = 3;
1525
1525
  function sidecar(meta) {
1526
1526
  const pathOf = ([first]) => [first, "/"].flat().find((p) => typeof p === "string");
1527
- const guarded2 = (op) => (...args) => meta[op].apply(meta, args).catch((err) => {
1527
+ const guarded3 = (op) => (...args) => meta[op].apply(meta, args).catch((err) => {
1528
1528
  throw translate(err, pathOf(args), "sidecar", false);
1529
1529
  });
1530
1530
  const names2 = meta.fresh ? [...META_OPS, "fresh"] : META_OPS;
1531
- const ops = Object.fromEntries(names2.map((op) => [op, guarded2(op)]));
1531
+ const ops = Object.fromEntries(names2.map((op) => [op, guarded3(op)]));
1532
1532
  const { updateMany } = meta;
1533
1533
  ops.updateMany = updateMany ? (changes) => updateMany.call(meta, changes).catch((err) => {
1534
1534
  throw translate(err, changes[0]?.path ?? "/", "sidecar", false);
@@ -3638,12 +3638,12 @@ var OpfsFs = class {
3638
3638
  if (!move) return false;
3639
3639
  for (let attempt = 0; ; attempt++) {
3640
3640
  this.others++;
3641
- const failed3 = await move.call(handle, dir, name2).then(
3641
+ const failed4 = await move.call(handle, dir, name2).then(
3642
3642
  () => void 0,
3643
3643
  (err) => ({ err })
3644
3644
  );
3645
- if (!failed3) return true;
3646
- const error = failed3.err?.name;
3645
+ if (!failed4) return true;
3646
+ const error = failed4.err?.name;
3647
3647
  if (handle.kind !== "file" || !LOCKED.has(error)) return false;
3648
3648
  const delay2 = SYNC_BACKOFF_MS[attempt];
3649
3649
  if (delay2 === void 0) throw fsError("EBUSY", name2);
@@ -6842,9 +6842,9 @@ var KernelSocket = class _KernelSocket {
6842
6842
  case SO_TYPE:
6843
6843
  return SOCK_STREAM;
6844
6844
  case SO_ERROR: {
6845
- const failed3 = this.failed;
6845
+ const failed4 = this.failed;
6846
6846
  this.failed = void 0;
6847
- return failed3 ? wasiErrno(failed3) : 0;
6847
+ return failed4 ? wasiErrno(failed4) : 0;
6848
6848
  }
6849
6849
  case SO_ACCEPTCONN:
6850
6850
  return this.state === "listening" ? 1 : 0;
@@ -6924,6 +6924,7 @@ var LoopbackNet = class {
6924
6924
  internal = /* @__PURE__ */ new Set();
6925
6925
  reserved = /* @__PURE__ */ new Set();
6926
6926
  facades = /* @__PURE__ */ new Map();
6927
+ proxyStamped;
6927
6928
  nextEphemeral = EPHEMERAL_FIRST;
6928
6929
  route;
6929
6930
  origins;
@@ -6998,9 +6999,15 @@ var LoopbackNet = class {
6998
6999
  this.kernelOnly(port, true);
6999
7000
  this.facades.set(port, name2);
7000
7001
  }
7001
- facadeAt(addr) {
7002
- if (addr.family !== "inet" || !isLoopback(canonicalHost(addr.host))) return void 0;
7003
- return this.facades.get(addr.port);
7002
+ stampProxy(port) {
7003
+ this.proxyStamped = port;
7004
+ }
7005
+ get originsStamped() {
7006
+ return this.proxyStamped !== void 0;
7007
+ }
7008
+ stampsPeers(addr) {
7009
+ if (addr.family !== "inet" || !isLoopback(canonicalHost(addr.host))) return false;
7010
+ return this.facades.has(addr.port) || this.proxyStamped === addr.port;
7004
7011
  }
7005
7012
  activate(addr, start2) {
7006
7013
  this.activators.set(keyOf(addr), start2);
@@ -7310,7 +7317,34 @@ function uploadsFor(peer) {
7310
7317
  });
7311
7318
  return { of, answer: (call) => pulls.get(call.nid)?.(call) };
7312
7319
  }
7313
- function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {}) {
7320
+ function headOf(nid, response) {
7321
+ return {
7322
+ net: "head",
7323
+ nid,
7324
+ ...response.url !== void 0 ? { url: response.url } : {},
7325
+ ...response.redirected !== void 0 ? { redirected: response.redirected } : {},
7326
+ ...response.redirects ? { redirects: response.redirects } : {},
7327
+ ...response.opaqueRedirect ? { opaqueRedirect: true } : {},
7328
+ status: response.status,
7329
+ statusText: response.statusText,
7330
+ headers: response.headers
7331
+ };
7332
+ }
7333
+ function requestOf(call, signal, uploads) {
7334
+ const { url, method, headers, streamed, body, redirect, nid } = call;
7335
+ return {
7336
+ url,
7337
+ method,
7338
+ headers,
7339
+ ...streamed ? { bodyStream: uploads.of(nid, signal) } : body ? { body } : {},
7340
+ ...redirect !== void 0 ? { redirect } : {},
7341
+ signal
7342
+ };
7343
+ }
7344
+ function serveTransport(peer, transport, {
7345
+ closeWaitMs = CLOSE_WAIT_MS2,
7346
+ attributed = false
7347
+ } = {}) {
7314
7348
  const open2 = /* @__PURE__ */ new Map();
7315
7349
  const fail2 = (nid, e) => {
7316
7350
  open2.delete(nid);
@@ -7330,27 +7364,17 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS2 } = {})
7330
7364
  const entry = { abort };
7331
7365
  open2.set(call.nid, entry);
7332
7366
  try {
7333
- const response = await transport.fetch({
7334
- url: call.url,
7335
- method: call.method,
7336
- headers: call.headers,
7337
- ...call.streamed ? { bodyStream: uploads.of(call.nid, abort.signal) } : call.body ? { body: call.body } : {},
7338
- signal: abort.signal
7339
- });
7367
+ const response = await transport.fetch(
7368
+ requestOf(call, abort.signal, uploads),
7369
+ attributed ? call.owner : void 0,
7370
+ attributed ? call.stamp : void 0
7371
+ );
7340
7372
  if (!open2.has(call.nid)) {
7341
7373
  await response.cancel();
7342
7374
  return;
7343
7375
  }
7344
7376
  open2.set(call.nid, { abort, body: response.body[Symbol.asyncIterator](), response });
7345
- peer.postMessage({
7346
- net: "head",
7347
- nid: call.nid,
7348
- ...response.redirected ? { url: response.url, redirected: true } : {},
7349
- ...response.redirects ? { redirects: response.redirects } : {},
7350
- status: response.status,
7351
- statusText: response.statusText,
7352
- headers: response.headers
7353
- });
7377
+ peer.postMessage(headOf(call.nid, response));
7354
7378
  } catch (e) {
7355
7379
  fail2(call.nid, e);
7356
7380
  }
@@ -8206,9 +8230,9 @@ function serveClient(port, host) {
8206
8230
  ended.resolve();
8207
8231
  }
8208
8232
  async function hello(message3) {
8209
- const refused3 = versionError(message3.protocol) ?? await hosts.requests.accept(host, message3);
8210
- if (refused3) {
8211
- send2({ hello: { protocol: PROTOCOL, error: refused3 } });
8233
+ const refused4 = versionError(message3.protocol) ?? await hosts.requests.accept(host, message3);
8234
+ if (refused4) {
8235
+ send2({ hello: { protocol: PROTOCOL, error: refused4 } });
8212
8236
  detach();
8213
8237
  return;
8214
8238
  }
@@ -8498,7 +8522,7 @@ function satisfies(version, range2) {
8498
8522
  }
8499
8523
 
8500
8524
  // src/version.ts
8501
- var KERNEL_VERSION = true ? "1.170.4" : "0.0.0-dev";
8525
+ var KERNEL_VERSION = true ? "1.172.0" : "0.0.0-dev";
8502
8526
  var OS_RELEASE = "6.0.0-slicc";
8503
8527
  function procVersion() {
8504
8528
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -8790,10 +8814,10 @@ async function tierPackages(fs, physical, roots, bins, kernel, global) {
8790
8814
  const own = commandsOf(pkg, manifest);
8791
8815
  const named = new Set(own.map((command) => command.name));
8792
8816
  const extra = bins ? await binCommandsOf(physical, pkg, manifest, named) : [];
8793
- const refused3 = engineRefusal(manifest, kernel);
8817
+ const refused4 = engineRefusal(manifest, kernel);
8794
8818
  const name2 = pkg.slice(root.length + 1);
8795
8819
  const dependency = direct?.has(name2) === false;
8796
- const marks = { ...refused3 ? { refused: refused3 } : {}, ...dependency ? { dependency } : {} };
8820
+ const marks = { ...refused4 ? { refused: refused4 } : {}, ...dependency ? { dependency } : {} };
8797
8821
  out.push({
8798
8822
  name: name2,
8799
8823
  pkg,
@@ -8825,7 +8849,7 @@ function winners(tier) {
8825
8849
  }
8826
8850
  return out;
8827
8851
  }
8828
- async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION, refused3, global = /* @__PURE__ */ new Set()) {
8852
+ async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, kernel = KERNEL_VERSION, refused4, global = /* @__PURE__ */ new Set()) {
8829
8853
  const found = /* @__PURE__ */ new Map();
8830
8854
  const physical = physicalResolver(fs);
8831
8855
  const tiers = (typeof modules === "string" ? [modules] : modules).map(
@@ -8839,7 +8863,7 @@ async function scanCommands(fs, modules, binsFrom = Number.POSITIVE_INFINITY, ke
8839
8863
  const dependencies = [];
8840
8864
  for (const [index, roots] of tiers.entries()) {
8841
8865
  const tier = await tierPackages(fs, physical, roots, index >= binsFrom, kernel, global);
8842
- if (refused3) refused3.push(...tier.flatMap((entry) => entry.commands.filter((c) => c.refused)));
8866
+ if (refused4) refused4.push(...tier.flatMap((entry) => entry.commands.filter((c) => c.refused)));
8843
8867
  await take(tier.filter((entry) => !entry.dependency));
8844
8868
  dependencies.push(tier.filter((entry) => entry.dependency));
8845
8869
  }
@@ -9155,32 +9179,32 @@ function nextFire(schedule, after, utc = false) {
9155
9179
  }
9156
9180
  return null;
9157
9181
  }
9158
- function missedFires(schedule, from, until, utc = false, cap = MISSED_CAP) {
9182
+ function missedFires(schedule, from, until2, utc = false, cap = MISSED_CAP) {
9159
9183
  let count2 = 0;
9160
9184
  let last = null;
9161
9185
  let at = from;
9162
9186
  while (count2 < cap) {
9163
9187
  at = nextFire(schedule, at, utc);
9164
- if (at === null || at > until) return { count: count2, last, more: false };
9188
+ if (at === null || at > until2) return { count: count2, last, more: false };
9165
9189
  last = at;
9166
9190
  count2++;
9167
9191
  }
9168
9192
  const next3 = nextFire(schedule, last, utc);
9169
- if (next3 === null || next3 > until) return { count: count2, last, more: false };
9170
- return { count: count2, last: latestFire(schedule, last, until, utc), more: true };
9193
+ if (next3 === null || next3 > until2) return { count: count2, last, more: false };
9194
+ return { count: count2, last: latestFire(schedule, last, until2, utc), more: true };
9171
9195
  }
9172
- function latestFire(schedule, from, until, utc = false) {
9196
+ function latestFire(schedule, from, until2, utc = false) {
9173
9197
  let found = from;
9174
9198
  for (let span = 6e4; ; span *= 2) {
9175
- const start2 = Math.max(from, until - span);
9199
+ const start2 = Math.max(from, until2 - span);
9176
9200
  const first = nextFire(schedule, start2, utc);
9177
- if (first !== null && first <= until) {
9201
+ if (first !== null && first <= until2) {
9178
9202
  found = first;
9179
9203
  break;
9180
9204
  }
9181
9205
  if (start2 === from) return from;
9182
9206
  }
9183
- for (let at = nextFire(schedule, found, utc); at !== null && at <= until; ) {
9207
+ for (let at = nextFire(schedule, found, utc); at !== null && at <= until2; ) {
9184
9208
  found = at;
9185
9209
  at = nextFire(schedule, at, utc);
9186
9210
  }
@@ -9892,12 +9916,12 @@ var UnlinkedKeeper = class {
9892
9916
  return this.locks;
9893
9917
  }
9894
9918
  async undoing(op, peers, sends, heard, shared2 = []) {
9895
- let failed3;
9919
+ let failed4;
9896
9920
  let out;
9897
9921
  try {
9898
9922
  out = await op();
9899
9923
  } catch (err) {
9900
- failed3 = err ?? new Error("failed");
9924
+ failed4 = err ?? new Error("failed");
9901
9925
  await this.rollBackAsides(sends, shared2);
9902
9926
  }
9903
9927
  const hiddenShared = new Set(shared2.map((one) => one.hidden));
@@ -9918,7 +9942,7 @@ var UnlinkedKeeper = class {
9918
9942
  const done5 = () => one.release().then(() => this.dropIfLast(one.hidden));
9919
9943
  void Promise.all(waits.map(({ told }) => told)).then(done5, done5);
9920
9944
  }
9921
- if (failed3 !== void 0) throw failed3;
9945
+ if (failed4 !== void 0) throw failed4;
9922
9946
  return out;
9923
9947
  }
9924
9948
  async rollBackAsides(sends, shared2) {
@@ -10065,7 +10089,7 @@ var UnlinkedKeeper = class {
10065
10089
  // src/cron/clock.ts
10066
10090
  var systemCronClock = {
10067
10091
  now: () => Date.now(),
10068
- sleep(until, signal) {
10092
+ sleep(until2, signal) {
10069
10093
  if (signal.aborted) return Promise.resolve();
10070
10094
  return new Promise((resolve2) => {
10071
10095
  const done5 = () => {
@@ -10073,7 +10097,7 @@ var systemCronClock = {
10073
10097
  signal.removeEventListener("abort", done5);
10074
10098
  resolve2();
10075
10099
  };
10076
- const timer = setTimeout(done5, Math.max(0, until - Date.now()));
10100
+ const timer = setTimeout(done5, Math.max(0, until2 - Date.now()));
10077
10101
  timer.unref?.();
10078
10102
  signal.addEventListener("abort", done5, { once: true });
10079
10103
  });
@@ -10177,15 +10201,15 @@ var CronService = class {
10177
10201
  async pass() {
10178
10202
  if (this.wake.signal.aborted) this.wake = new AbortController();
10179
10203
  const wake = this.wake;
10180
- let until;
10204
+ let until2;
10181
10205
  try {
10182
- until = await this.tick();
10206
+ until2 = await this.tick();
10183
10207
  } catch (err) {
10184
10208
  await this.error(`cron: ${messageOf(err)}`);
10185
- until = this.clock.now() + WAKE_MS;
10209
+ until2 = this.clock.now() + WAKE_MS;
10186
10210
  }
10187
10211
  if (this.stopping.signal.aborted) return;
10188
- await this.clock.sleep(until, wake.signal);
10212
+ await this.clock.sleep(until2, wake.signal);
10189
10213
  }
10190
10214
  async provision() {
10191
10215
  const { fs, owners } = this.host;
@@ -10402,14 +10426,17 @@ var PLACEHOLDER_REFUSED = "refused: this request has a sealed placeholder in its
10402
10426
  var PlaceholderRefused = class extends Error {
10403
10427
  status = 403;
10404
10428
  code = "EACCES";
10405
- constructor() {
10406
- super(PLACEHOLDER_REFUSED);
10429
+ constructor(reason = PLACEHOLDER_REFUSED) {
10430
+ super(reason);
10407
10431
  }
10408
10432
  };
10409
- function carries(text) {
10433
+ function holds2(text, known) {
10434
+ return PLACEHOLDER.test(text) || known.some((placeholder) => text.includes(placeholder));
10435
+ }
10436
+ function carries(text, known) {
10410
10437
  let layer = text;
10411
10438
  for (let i = 0; i < PERCENT_LAYERS; i++) {
10412
- if (PLACEHOLDER.test(layer)) return true;
10439
+ if (holds2(layer, known)) return true;
10413
10440
  const next3 = layer.replace(
10414
10441
  ESCAPE,
10415
10442
  (_, hex4) => String.fromCharCode(Number.parseInt(hex4, 16))
@@ -10417,35 +10444,36 @@ function carries(text) {
10417
10444
  if (next3 === layer) return false;
10418
10445
  layer = next3;
10419
10446
  }
10420
- return PLACEHOLDER.test(layer);
10447
+ return holds2(layer, known);
10421
10448
  }
10422
- function basicCarries(value2) {
10449
+ function basicCarries(value2, known) {
10423
10450
  const credential = BASIC.exec(value2)?.[1];
10424
10451
  if (credential === void 0) return false;
10425
10452
  const letters = credential.replace(/[^A-Za-z0-9+/_-]/g, "").replaceAll("-", "+").replaceAll("_", "/");
10426
10453
  for (let shift = 0; shift < BASE64_GROUP; shift++) {
10427
10454
  const part = letters.slice(shift);
10428
10455
  const whole = part.length % BASE64_GROUP === 1 ? part.slice(0, -1) : part;
10429
- if (carries(atob(whole))) return true;
10456
+ if (carries(atob(whole), known)) return true;
10430
10457
  }
10431
10458
  return false;
10432
10459
  }
10433
- function headersCarry(headers) {
10460
+ function headersCarry(headers, known) {
10434
10461
  return headers.some(
10435
- ([name2, value2]) => carries(name2.toLowerCase()) || carries(value2) || basicCarries(value2)
10462
+ ([name2, value2]) => carries(name2, known) || carries(name2.toLowerCase(), known) || carries(value2, known) || basicCarries(value2, known)
10436
10463
  );
10437
10464
  }
10438
- function urlCarries(url) {
10439
- return carries(url) || URL.canParse(url) && carries(new URL(url).href);
10465
+ function urlCarries(url, known) {
10466
+ return carries(url, known) || URL.canParse(url) && carries(new URL(url).href, known);
10440
10467
  }
10441
- function refuse(request3) {
10442
- if (urlCarries(request3.url) || headersCarry(request3.headers)) throw new PlaceholderRefused();
10468
+ function detected(request3, known) {
10469
+ return urlCarries(request3.url, known) || headersCarry(request3.headers, known);
10443
10470
  }
10444
- function refuseSocket(request3) {
10445
- refuse(request3);
10446
- if (request3.protocols.some(carries)) throw new PlaceholderRefused();
10471
+ function refuseSocket(request3, known) {
10472
+ if (detected(request3, known) || request3.protocols.some((p) => carries(p, known))) {
10473
+ throw new PlaceholderRefused();
10474
+ }
10447
10475
  }
10448
- function placeholderFloor(inner) {
10476
+ function placeholderFloor(inner, { known = () => [], fill: fill2 } = {}) {
10449
10477
  const open2 = inner.websocket?.bind(inner);
10450
10478
  return {
10451
10479
  get traits() {
@@ -10453,13 +10481,14 @@ function placeholderFloor(inner) {
10453
10481
  },
10454
10482
  ...open2 ? {
10455
10483
  websocket: async (request3) => {
10456
- refuseSocket(request3);
10484
+ refuseSocket(request3, known());
10457
10485
  return open2(request3);
10458
10486
  }
10459
10487
  } : {},
10460
- async fetch(request3, owner) {
10461
- refuse(request3);
10462
- return inner.fetch(request3, owner);
10488
+ async fetch(request3, owner, stamp) {
10489
+ if (!detected(request3, known())) return inner.fetch(request3, owner, stamp);
10490
+ if (!fill2 || !stamp) throw new PlaceholderRefused();
10491
+ return fill2(request3, stamp);
10463
10492
  }
10464
10493
  };
10465
10494
  }
@@ -10632,14 +10661,14 @@ function tunnelTarget(req) {
10632
10661
  }
10633
10662
  return { host, port };
10634
10663
  }
10635
- async function watchHangup(conn, abort, until) {
10636
- while (!until.aborted && !abort.signal.aborted) {
10664
+ async function watchHangup(conn, abort, until2) {
10665
+ while (!until2.aborted && !abort.signal.aborted) {
10637
10666
  if (conn.poll().hangup) {
10638
10667
  abort.abort(new KernelError("EPIPE"));
10639
10668
  return;
10640
10669
  }
10641
10670
  try {
10642
- await conn.changed(until);
10671
+ await conn.changed(until2);
10643
10672
  } catch {
10644
10673
  return;
10645
10674
  }
@@ -10830,7 +10859,7 @@ var RealmProxy = class {
10830
10859
  const waiting = new AbortController();
10831
10860
  void watchHangup(ctx.socket, abort, waiting.signal);
10832
10861
  try {
10833
- response = await this.upstream(req, url, body, abort.signal, ctx.socket.peerCred?.pid);
10862
+ response = await this.upstream(req, url, body, abort.signal, ctx.socket);
10834
10863
  } finally {
10835
10864
  waiting.abort();
10836
10865
  }
@@ -10857,7 +10886,7 @@ var RealmProxy = class {
10857
10886
  await conn.write(latin1Bytes("HTTP/1.1 100 Continue\r\n\r\n"), this.stop.signal);
10858
10887
  }
10859
10888
  }
10860
- async upstream(req, url, body, signal, owner) {
10889
+ async upstream(req, url, body, signal, socket) {
10861
10890
  const sent = BODILESS_METHODS.has(req.method) ? void 0 : body;
10862
10891
  try {
10863
10892
  const fetching = this.options.transport.fetch(
@@ -10868,7 +10897,8 @@ var RealmProxy = class {
10868
10897
  ...sent instanceof Uint8Array ? { body: sent } : sent ? { bodyStream: sent } : {},
10869
10898
  signal
10870
10899
  },
10871
- owner
10900
+ socket.peerCred?.pid,
10901
+ socket.peerStamp
10872
10902
  );
10873
10903
  return await untilAborted(fetching, signal);
10874
10904
  } catch (e) {
@@ -10912,8 +10942,8 @@ var RealmProxy = class {
10912
10942
  }
10913
10943
  async connect(conn, incoming, req, idle2) {
10914
10944
  const target = tunnelTarget(req);
10915
- const refused3 = target.port === 443 ? await this.tunnelReady(target) : void 0;
10916
- if (refused3) throw refused3;
10945
+ const refused4 = target.port === 443 ? await this.tunnelReady(target) : void 0;
10946
+ if (refused4) throw refused4;
10917
10947
  await conn.write(latin1Bytes("HTTP/1.1 200 Connection Established\r\n\r\n"), this.stop.signal);
10918
10948
  try {
10919
10949
  const first = await incoming.peek(this.stop.signal);
@@ -11185,7 +11215,7 @@ async function relay(socket, conn) {
11185
11215
  // src/fs/attest.ts
11186
11216
  var ATTEST_MAX = 1024 * 1024;
11187
11217
  var UNOWNED = 1e3;
11188
- function refuse2(code, path, why) {
11218
+ function refuse(code, path, why) {
11189
11219
  throw Object.assign(new Error(`attest ${path}: ${why}`), { code });
11190
11220
  }
11191
11221
  function chainOf(path) {
@@ -11227,39 +11257,49 @@ async function trustedParents(fs, path, o) {
11227
11257
  const parents = [];
11228
11258
  for (const dir of chainOf(path).slice(0, -1)) {
11229
11259
  const st = await fs.lstat(dir);
11230
- if (st.isSymbolicLink) refuse2("EACCES", path, `${dir} is a symlink`);
11231
- if (!st.isDirectory) refuse2("ENOTDIR", path, `${dir} is not a directory`);
11260
+ if (st.isSymbolicLink) refuse("EACCES", path, `${dir} is a symlink`);
11261
+ if (!st.isDirectory) refuse("ENOTDIR", path, `${dir} is not a directory`);
11232
11262
  const perm = owned(dir, st);
11233
11263
  if (o.users !== "off" && (perm.uid !== 0 || (perm.mode & 18) !== 0)) {
11234
- refuse2("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
11264
+ refuse("EACCES", path, `${dir} is not root-owned or is writable by group or others`);
11235
11265
  }
11236
11266
  parents.push(perm);
11237
11267
  }
11238
11268
  return parents;
11239
11269
  }
11270
+ function missing3(e) {
11271
+ return e?.code === "ENOENT";
11272
+ }
11240
11273
  async function attest(fs, asked, o) {
11274
+ if (o.absent !== void 0 && o.absent !== "allow") {
11275
+ refuse("EINVAL", String(asked), "absent takes only allow");
11276
+ }
11241
11277
  if (typeof asked !== "string" || !asked.startsWith("/")) {
11242
- refuse2("EINVAL", String(asked), "not an absolute path");
11278
+ refuse("EINVAL", String(asked), "not an absolute path");
11243
11279
  }
11244
11280
  const path = normalizePath(asked);
11245
11281
  const mount = o.mounts.find((target) => {
11246
11282
  const at = normalizePath(target);
11247
11283
  return at === "/" || under2(path, at);
11248
11284
  });
11249
- if (mount !== void 0) refuse2("EACCES", path, `under the mount ${mount}`);
11285
+ if (mount !== void 0) refuse("EACCES", path, `under the mount ${mount}`);
11250
11286
  const parents = await trustedParents(fs, path, o);
11251
11287
  for (let tries = 0; ; tries++) {
11252
- const before = await fs.lstat(path);
11253
- if (before.isSymbolicLink) refuse2("EACCES", path, "is a symlink");
11288
+ const before = await fs.lstat(path).catch((e) => {
11289
+ if (o.absent === "allow" && missing3(e)) return void 0;
11290
+ throw e;
11291
+ });
11292
+ if (!before) return { path, absent: true, users: o.users, onRootFs: true, parents };
11293
+ if (before.isSymbolicLink) refuse("EACCES", path, "is a symlink");
11254
11294
  if (!before.isFile)
11255
- refuse2(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
11256
- if (before.size > ATTEST_MAX) refuse2("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
11295
+ refuse(before.isDirectory ? "EISDIR" : "EINVAL", path, "is not a regular file");
11296
+ if (before.size > ATTEST_MAX) refuse("EFBIG", path, `is over ${ATTEST_MAX} bytes`);
11257
11297
  const bytes = (await fs.readFileBuffer(path)).slice();
11258
11298
  const after = await fs.lstat(path);
11259
11299
  if (unchanged(before, after, bytes)) {
11260
11300
  return attested(path, after, bytes, await sha2562(bytes), o, parents);
11261
11301
  }
11262
- if (tries >= 1) refuse2("EAGAIN", path, "changed while it was read");
11302
+ if (tries >= 1) refuse("EAGAIN", path, "changed while it was read");
11263
11303
  }
11264
11304
  }
11265
11305
  var WATCH_DEBOUNCE_MS = 50;
@@ -11318,7 +11358,7 @@ var S_IFREG2 = 32768;
11318
11358
  var COMMAND = /^\/(?:usr\/)?bin\/([^/]+)$/;
11319
11359
  var MAX_LINKS6 = 40;
11320
11360
  var BIN_ENTRY = /\/bin\/[^/]+$/;
11321
- function missing3(err) {
11361
+ function missing4(err) {
11322
11362
  return err?.code === "ENOENT";
11323
11363
  }
11324
11364
  function synthetic(directory, path) {
@@ -11422,7 +11462,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
11422
11462
  }
11423
11463
  async function entryTarget(path) {
11424
11464
  if (!BIN_ENTRY.test(path) || !(await virtual(path))?.isFile) return void 0;
11425
- if (!await fs.lstat(path).then(() => false, missing3)) return void 0;
11465
+ if (!await fs.lstat(path).then(() => false, missing4)) return void 0;
11426
11466
  const target = await targetOf2(path);
11427
11467
  return target?.path === path ? void 0 : target;
11428
11468
  }
@@ -11434,11 +11474,11 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
11434
11474
  return target?.path;
11435
11475
  }
11436
11476
  const absent2 = (err) => {
11437
- if (missing3(err)) return EMPTY2;
11477
+ if (missing4(err)) return EMPTY2;
11438
11478
  throw err;
11439
11479
  };
11440
11480
  async function content(path, err) {
11441
- if (!missing3(err) || !(await linked2(path))?.isFile) throw err;
11481
+ if (!missing4(err) || !(await linked2(path))?.isFile) throw err;
11442
11482
  const target = await redirected2(path);
11443
11483
  return target === void 0 ? EMPTY2 : fs.readFileBuffer(target).catch(absent2);
11444
11484
  }
@@ -11447,7 +11487,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
11447
11487
  try {
11448
11488
  return await real(path);
11449
11489
  } catch (err) {
11450
- const found = missing3(err) ? await linked2(path) : void 0;
11490
+ const found = missing4(err) ? await linked2(path) : void 0;
11451
11491
  if (found) return found;
11452
11492
  throw err;
11453
11493
  }
@@ -11472,7 +11512,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
11472
11512
  const extra = await children3(path);
11473
11513
  if (!extra) return fs.readdir(path);
11474
11514
  const real = await fs.readdir(path).catch((err) => {
11475
- if (missing3(err)) return [];
11515
+ if (missing4(err)) return [];
11476
11516
  throw err;
11477
11517
  });
11478
11518
  return [.../* @__PURE__ */ new Set([...real, ...extra])].sort();
@@ -11481,7 +11521,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
11481
11521
  const extra = await children3(path);
11482
11522
  if (!extra) return fs.readdirStat(path);
11483
11523
  const real = await fs.readdirStat(path).catch((err) => {
11484
- if (missing3(err)) return [];
11524
+ if (missing4(err)) return [];
11485
11525
  throw err;
11486
11526
  });
11487
11527
  const seen = new Set(real.map(([name2]) => name2));
@@ -11515,7 +11555,7 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
11515
11555
  ...ranged2 ? {
11516
11556
  ...ranged2,
11517
11557
  pread: (path, offset, length2, version) => ranged2.pread(path, offset, length2, version).catch(async (err) => {
11518
- const target = missing3(err) ? await redirected2(path) : void 0;
11558
+ const target = missing4(err) ? await redirected2(path) : void 0;
11519
11559
  if (target === void 0) throw err;
11520
11560
  return ranged2.pread(target, offset, length2).catch(absent2);
11521
11561
  })
@@ -11546,7 +11586,7 @@ var S_IFREG3 = 32768;
11546
11586
  var MAX_HOPS2 = 40;
11547
11587
  var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
11548
11588
  var baseOf2 = (path) => path.slice(path.lastIndexOf("/") + 1);
11549
- function missing4(err) {
11589
+ function missing5(err) {
11550
11590
  return err?.code === "ENOENT";
11551
11591
  }
11552
11592
  function statOf(path, bytes) {
@@ -11599,11 +11639,11 @@ function withEtcFiles(fs, files) {
11599
11639
  const text = files.get(path)?.();
11600
11640
  return text === void 0 ? void 0 : new TextEncoder().encode(text);
11601
11641
  };
11602
- const absent2 = (path) => fs.lstat(path).then(() => false, missing4);
11642
+ const absent2 = (path) => fs.lstat(path).then(() => false, missing5);
11603
11643
  const follow2 = linkFollower(fs, files);
11604
11644
  const listedAbsent = async (path) => files.has(path) && await absent2(path) ? bytesOf2(path) : void 0;
11605
11645
  const fallback = (path, make) => async (err) => {
11606
- const at = missing4(err) ? await follow2(path) : void 0;
11646
+ const at = missing5(err) ? await follow2(path) : void 0;
11607
11647
  const bytes = at === void 0 ? void 0 : await listedAbsent(at);
11608
11648
  if (bytes === void 0 || at === void 0) throw err;
11609
11649
  return make(bytes, at);
@@ -13418,8 +13458,8 @@ var DriverConnection = class _DriverConnection {
13418
13458
  } finally {
13419
13459
  clearTimeout(timer);
13420
13460
  }
13421
- const refused3 = driverVersionError(hello.protocol);
13422
- if (refused3) throw errnoError("EPROTO", refused3);
13461
+ const refused4 = driverVersionError(hello.protocol);
13462
+ if (refused4) throw errnoError("EPROTO", refused4);
13423
13463
  if (hello.error) throw errnoError(hello.errno ?? "EIO", hello.error);
13424
13464
  return new _DriverConnection(port, hello.capabilities ?? {}, waiting, timeoutMs, options);
13425
13465
  }
@@ -13503,29 +13543,29 @@ var HeldSet = class extends Set {
13503
13543
  this.idle = idle2;
13504
13544
  this.moved = moved2;
13505
13545
  }
13506
- add(holds2) {
13507
- holds2.onIdle = this.idle;
13508
- holds2.onMoved = this.moved;
13509
- return super.add(holds2);
13546
+ add(holds3) {
13547
+ holds3.onIdle = this.idle;
13548
+ holds3.onMoved = this.moved;
13549
+ return super.add(holds3);
13510
13550
  }
13511
13551
  doubt(paths, over) {
13512
- for (const holds2 of this) {
13513
- for (const path of paths) holds2.doubt(path, true);
13514
- if (over !== void 0) holds2.doubt(over);
13552
+ for (const holds3 of this) {
13553
+ for (const path of paths) holds3.doubt(path, true);
13554
+ if (over !== void 0) holds3.doubt(over);
13515
13555
  }
13516
13556
  }
13517
13557
  async bindIds(id2) {
13518
- for (const holds2 of [...this]) await holds2.bindIds(id2);
13558
+ for (const holds3 of [...this]) await holds3.bindIds(id2);
13519
13559
  }
13520
13560
  heldIds() {
13521
13561
  const out = /* @__PURE__ */ new Map();
13522
- for (const holds2 of this) for (const [path, fid] of holds2.heldIds()) out.set(path, fid);
13562
+ for (const holds3 of this) for (const [path, fid] of holds3.heldIds()) out.set(path, fid);
13523
13563
  return [...out];
13524
13564
  }
13525
- delete(holds2) {
13526
- const removed = super.delete(holds2);
13527
- for (const path of /* @__PURE__ */ new Set([...holds2.keys(), ...holds2.opens.keys()])) this.idle(path);
13528
- holds2.releaseAll();
13565
+ delete(holds3) {
13566
+ const removed = super.delete(holds3);
13567
+ for (const path of /* @__PURE__ */ new Set([...holds3.keys(), ...holds3.opens.keys()])) this.idle(path);
13568
+ holds3.releaseAll();
13529
13569
  return removed;
13530
13570
  }
13531
13571
  };
@@ -15443,8 +15483,8 @@ async function guarded(entry, path, req) {
15443
15483
  return { paths };
15444
15484
  } catch (err) {
15445
15485
  const refusal2 = err.code === "EACCES";
15446
- const refused3 = req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
15447
- return { refused: refused3 };
15486
+ const refused4 = req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
15487
+ return { refused: refused4 };
15448
15488
  }
15449
15489
  }
15450
15490
  async function copyOp(entry, path, req) {
@@ -15640,13 +15680,13 @@ async function created2(entry, req) {
15640
15680
  return seen === void 0 ? looked : json2({ ...looked.json, seen });
15641
15681
  }
15642
15682
  var DENIED = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
15643
- async function rmPermitted(entry, path, req, refused3) {
15683
+ async function rmPermitted(entry, path, req, refused4) {
15644
15684
  const st = await entry.fs.lstat(path).catch(() => void 0);
15645
- if (!st?.isDirectory) return refused3;
15685
+ if (!st?.isDirectory) return refused4;
15646
15686
  const unlisted = await guarded(entry, path, { ...req, op: "readdir" });
15647
15687
  if ("refused" in unlisted) return unlisted.refused;
15648
15688
  const names2 = await entry.fs.readdir(path).catch(() => void 0);
15649
- if (!names2) return refused3;
15689
+ if (!names2) return refused4;
15650
15690
  let first;
15651
15691
  for (const name2 of names2) {
15652
15692
  const child = await dispatchOne(entry, {
@@ -15697,14 +15737,14 @@ async function newDevName(entry, path, req) {
15697
15737
  const named = NAMING.has(req.op);
15698
15738
  if (!named && !CREATIONS.has(req.op)) return void 0;
15699
15739
  const target = named ? entry.fs.resolvePath(entry.cwd, req.arg2 ?? "") : path;
15700
- const refused3 = devCreation(target, entry.cred?.());
15701
- if (!refused3) return void 0;
15740
+ const refused4 = devCreation(target, entry.cred?.());
15741
+ if (!refused4) return void 0;
15702
15742
  const there = await entry.fs.lstat(target).then(
15703
15743
  () => true,
15704
15744
  () => false
15705
15745
  );
15706
15746
  if (there) return void 0;
15707
- return { ok: false, errno: refused3, message: `${target}: no new names in /dev or /proc` };
15747
+ return { ok: false, errno: refused4, message: `${target}: no new names in /dev or /proc` };
15708
15748
  }
15709
15749
  var MISS_OPS = /* @__PURE__ */ new Set(["stat", "lstat"]);
15710
15750
  async function linkFree(fs, path) {
@@ -16416,9 +16456,9 @@ var SYS_TREE = {
16416
16456
  `,
16417
16457
  slicc_file_ids: (listing) => `${listing.fileIds ?? 0}
16418
16458
  `,
16419
- slicc_peer_holds: ({ holds: holds2 }) => `${holds2?.mine ?? 0} ${holds2?.peers ?? 0} ${holds2?.sent ?? 0}
16459
+ slicc_peer_holds: ({ holds: holds3 }) => `${holds3?.mine ?? 0} ${holds3?.peers ?? 0} ${holds3?.sent ?? 0}
16420
16460
  `,
16421
- slicc_peer_held: ({ holds: holds2 }) => (holds2?.held ?? []).map((path) => `${path}
16461
+ slicc_peer_held: ({ holds: holds3 }) => (holds3?.held ?? []).map((path) => `${path}
16422
16462
  `).join(""),
16423
16463
  slicc_rename_acks: (listing) => {
16424
16464
  const samples = [...listing.renameAcks?.ackMs ?? []].sort((a, b) => a - b);
@@ -17159,11 +17199,11 @@ var EpollFile = class _EpollFile {
17159
17199
  const round = new AbortController();
17160
17200
  const stop = () => round.abort();
17161
17201
  signal.addEventListener("abort", stop, { once: true });
17162
- let failed3 = false;
17202
+ let failed4 = false;
17163
17203
  try {
17164
17204
  await file.changed(round.signal);
17165
17205
  } catch {
17166
- failed3 = true;
17206
+ failed4 = true;
17167
17207
  } finally {
17168
17208
  round.abort();
17169
17209
  signal.removeEventListener("abort", stop);
@@ -17171,7 +17211,7 @@ var EpollFile = class _EpollFile {
17171
17211
  if (signal.aborted) return;
17172
17212
  reg.gen++;
17173
17213
  this.changes.wake();
17174
- if (failed3) await pause(RETRY_MS, signal);
17214
+ if (failed4) await pause(RETRY_MS, signal);
17175
17215
  }
17176
17216
  }
17177
17217
  };
@@ -17807,8 +17847,8 @@ var KernelLoopback = class {
17807
17847
  );
17808
17848
  } catch (err) {
17809
17849
  socket.close();
17810
- const refused3 = err instanceof KernelError && err.code === "ECONNREFUSED";
17811
- throw refused3 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
17850
+ const refused4 = err instanceof KernelError && err.code === "ECONNREFUSED";
17851
+ throw refused4 ? errno2("ECONNREFUSED", `nothing listens on the kernel's port ${port}`) : err;
17812
17852
  }
17813
17853
  signal.addEventListener("abort", () => socket.close(), { once: true });
17814
17854
  return socket;
@@ -18152,11 +18192,11 @@ function ipv6(host) {
18152
18192
  const back = halves.length === 2 ? groups(halves[1]) : [];
18153
18193
  if (![...head, ...back].every((g) => /^[0-9A-Fa-f]{1,4}$/.test(g))) return void 0;
18154
18194
  const words2 = [...head, ...back].map((g) => Number.parseInt(g, 16));
18155
- const missing5 = 8 - words2.length - tail2.length;
18156
- if (halves.length === 2 ? missing5 < 1 : missing5 !== 0) return void 0;
18195
+ const missing6 = 8 - words2.length - tail2.length;
18196
+ if (halves.length === 2 ? missing6 < 1 : missing6 !== 0) return void 0;
18157
18197
  const all = [
18158
18198
  ...head.map((g) => Number.parseInt(g, 16)),
18159
- ...new Array(halves.length === 2 ? missing5 : 0).fill(0),
18199
+ ...new Array(halves.length === 2 ? missing6 : 0).fill(0),
18160
18200
  ...back.map((g) => Number.parseInt(g, 16)),
18161
18201
  ...tail2
18162
18202
  ];
@@ -19201,10 +19241,12 @@ var HttpHandles = class {
19201
19241
  ws;
19202
19242
  owner;
19203
19243
  local;
19204
- constructor(transport, owner, local2) {
19244
+ stamp;
19245
+ constructor(transport, owner, local2, stamp) {
19205
19246
  this.transport = transport;
19206
19247
  this.owner = owner;
19207
19248
  this.local = local2;
19249
+ this.stamp = stamp;
19208
19250
  this.ws = new WsHandles(transport, () => ++this.nextHandle, local2);
19209
19251
  }
19210
19252
  syscall(req) {
@@ -19280,7 +19322,7 @@ var HttpHandles = class {
19280
19322
  ...entry.upload ? { bodyStream: entry.upload } : req.body ? { body: req.body } : {},
19281
19323
  signal: entry.abort.signal
19282
19324
  };
19283
- const response = port === void 0 ? await this.transport.fetch(request3, this.owner) : await this.local.fetch(request3, port);
19325
+ const response = port === void 0 ? await this.transport.fetch(request3, this.owner, await this.stamp?.()) : await this.local.fetch(request3, port);
19284
19326
  entry.body = response.body[Symbol.asyncIterator]();
19285
19327
  entry.cancel = () => response.cancel();
19286
19328
  if (!this.open.has(handle)) await entry.cancel().catch(() => void 0);
@@ -19302,8 +19344,8 @@ var HttpHandles = class {
19302
19344
  if (text === NO_TRANSPORT || typeof status !== "number" || status === 502) {
19303
19345
  const code = codeOf2(e);
19304
19346
  const errno3 = text === NO_TRANSPORT ? "ENETUNREACH" : code !== "EIO" ? code : "ECONNREFUSED";
19305
- const failed3 = e.detail === "transport";
19306
- return { ok: false, errno: errno3, message: text, ...failed3 ? { detail: "transport" } : {} };
19347
+ const failed4 = e.detail === "transport";
19348
+ return { ok: false, errno: errno3, message: text, ...failed4 ? { detail: "transport" } : {} };
19307
19349
  }
19308
19350
  entry.body = once(new TextEncoder().encode(text))[Symbol.asyncIterator]();
19309
19351
  return this.headOf(handle, req.url, {
@@ -21210,7 +21252,7 @@ function pass(c, input, final) {
21210
21252
  const partials = [];
21211
21253
  scanMain(c, input, best, partials);
21212
21254
  scanWrapped(c, input, best, partials);
21213
- const holds2 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
21255
+ const holds3 = final ? [] : [...new Set(partials)].sort((a, b) => a - b);
21214
21256
  const starts = [...best.keys()].sort((a, b) => a - b);
21215
21257
  const parts2 = [];
21216
21258
  const hits = /* @__PURE__ */ new Map();
@@ -21220,8 +21262,8 @@ function pass(c, input, final) {
21220
21262
  let h = 0;
21221
21263
  for (; ; ) {
21222
21264
  while (s < starts.length && starts[s] < pos) s++;
21223
- while (h < holds2.length && holds2[h] < pos) h++;
21224
- const hold = h < holds2.length ? holds2[h] : Infinity;
21265
+ while (h < holds3.length && holds3[h] < pos) h++;
21266
+ const hold = h < holds3.length ? holds3[h] : Infinity;
21225
21267
  const next3 = s < starts.length ? starts[s] : Infinity;
21226
21268
  if (hold <= next3) {
21227
21269
  cut = Math.min(hold, input.length);
@@ -21323,23 +21365,23 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
21323
21365
  let pending = 0;
21324
21366
  let busy = false;
21325
21367
  let timer;
21326
- let failed3;
21368
+ let failed4;
21327
21369
  const waiters = /* @__PURE__ */ new Set();
21328
21370
  const quiet2 = () => !busy && pending === 0;
21329
21371
  const wake = () => {
21330
21372
  for (const waiter of [...waiters]) waiter();
21331
21373
  };
21332
21374
  const raise = () => {
21333
- if (failed3 === void 0) return;
21334
- const err = failed3;
21335
- failed3 = void 0;
21375
+ if (failed4 === void 0) return;
21376
+ const err = failed4;
21377
+ failed4 = void 0;
21336
21378
  throw err;
21337
21379
  };
21338
21380
  const later = (bytes) => {
21339
21381
  if (bytes.length === 0) return;
21340
21382
  pending += 1;
21341
21383
  tail2 = tail2.then(() => writeAll3(file, bytes)).catch((err) => {
21342
- if (failed3 === void 0) failed3 = err;
21384
+ if (failed4 === void 0) failed4 = err;
21343
21385
  }).finally(() => {
21344
21386
  pending -= 1;
21345
21387
  if (quiet2()) wake();
@@ -24414,7 +24456,7 @@ async function connect(req, proc) {
24414
24456
  }
24415
24457
  const path = filePath(req.addr);
24416
24458
  const name2 = path !== void 0 ? await proc.names?.find(path) : void 0;
24417
- const stamp = proc.net.facadeAt(req.addr) && await proc.stamp?.();
24459
+ const stamp = proc.net.stampsPeers(req.addr) && await proc.stamp?.();
24418
24460
  const dialing = target.connect(req.addr, true, proc.cred?.(), stamp || void 0, true, name2);
24419
24461
  if (req.nonblock) {
24420
24462
  dialing?.catch(() => void 0);
@@ -24536,7 +24578,7 @@ async function secureConnect(req, proc) {
24536
24578
  delete req.clientCert;
24537
24579
  throw new KernelError("ENOTSUP");
24538
24580
  }
24539
- return { ...tlsOverTransport(req, proc), path: "transport", substitutes: true };
24581
+ return { ...await tlsOverTransport(req, proc), path: "transport", substitutes: true };
24540
24582
  }
24541
24583
  const socket = proc.net.socket("inet");
24542
24584
  const fd = proc.fds.install(new OpenFile(socket), 3);
@@ -24555,7 +24597,7 @@ async function uplinked(proc, host) {
24555
24597
  return false;
24556
24598
  }
24557
24599
  }
24558
- function tlsOverTransport(req, proc) {
24600
+ async function tlsOverTransport(req, proc) {
24559
24601
  if (req.ca) throw new KernelError("ENOTSUP");
24560
24602
  if (req.alpn && req.alpn.length > 0 && !req.alpn.includes("http/1.1")) {
24561
24603
  throw new KernelError("EPROTONOSUPPORT");
@@ -24568,7 +24610,9 @@ function tlsOverTransport(req, proc) {
24568
24610
  if (isLoopbackHost(servername) || isLoopbackHost(req.host)) throw new KernelError("ENOTSUP");
24569
24611
  const host = servername.includes(":") && !servername.startsWith("[") ? `[${servername}]` : servername;
24570
24612
  const origin = req.port === 443 ? `https://${host}` : `https://${host}:${req.port}`;
24613
+ const stamp = proc.net.originsStamped ? await proc.stamp?.() : void 0;
24571
24614
  const [mine, theirs] = KernelSocket.pair(proc.net, "inet", proc.cred?.());
24615
+ theirs.peerStamp = stamp;
24572
24616
  mine.peer = { family: "inet", host: req.host, port: req.port };
24573
24617
  try {
24574
24618
  proc.net.serveOrigin(theirs, origin);
@@ -27727,13 +27771,13 @@ function inherited(opts) {
27727
27771
  ...opts.cred ? { cred: opts.cred } : {}
27728
27772
  };
27729
27773
  }
27730
- function heldBy(process, holds2, replacements) {
27731
- process.keptPath = (path) => holds2.keptAt(path)?.hidden;
27732
- process.keptHandle = (handle) => holds2.keptFor(handle)?.hidden;
27733
- process.holdsHandle = (handle) => holds2.holdsHandle(handle);
27774
+ function heldBy(process, holds3, replacements) {
27775
+ process.keptPath = (path) => holds3.keptAt(path)?.hidden;
27776
+ process.keptHandle = (handle) => holds3.keptFor(handle)?.hidden;
27777
+ process.holdsHandle = (handle) => holds3.holdsHandle(handle);
27734
27778
  if (replacements) process.replacements = replacements;
27735
27779
  }
27736
- function holdingToken(opts, holds2, caller) {
27780
+ function holdingToken(opts, holds3, caller) {
27737
27781
  return mintSyncFsToken({
27738
27782
  ...opts.owners ? caller : { umask: caller.umask },
27739
27783
  ...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
@@ -27750,16 +27794,16 @@ function holdingToken(opts, holds2, caller) {
27750
27794
  ...opts.fileId ? { fileId: opts.fileId } : {},
27751
27795
  ...opts.announceHold ? { announceHold: opts.announceHold } : {},
27752
27796
  ...opts.renameSeq ? { renameSeq: opts.renameSeq } : {},
27753
- hold: (path, on, open2, real, handle, ino, fid) => holds2.hold(path, on, open2, real, handle, ino, fid),
27754
- boundIno: holds2.boundIno.bind(holds2),
27755
- trust: holds2.trust.bind(holds2),
27756
- keptFor: (handle) => holds2.keptFor(handle),
27757
- heldAt: (handle) => holds2.pathOf(handle),
27758
- unlinked: (path) => holds2.keptAt(path),
27759
- gate: (path, op) => opts.unlinkGate && holds2.holding(path) ? opts.unlinkGate.run(holds2.keyOf(path), op) : op(),
27760
- own: (path, op) => holds2.own(path, op),
27761
- revoked: (path) => holds2.isRevoked(path),
27762
- renamed: (from, to) => holds2.renamed(from, to)
27797
+ hold: (path, on, open2, real, handle, ino, fid) => holds3.hold(path, on, open2, real, handle, ino, fid),
27798
+ boundIno: holds3.boundIno.bind(holds3),
27799
+ trust: holds3.trust.bind(holds3),
27800
+ keptFor: (handle) => holds3.keptFor(handle),
27801
+ heldAt: (handle) => holds3.pathOf(handle),
27802
+ unlinked: (path) => holds3.keptAt(path),
27803
+ gate: (path, op) => opts.unlinkGate && holds3.holding(path) ? opts.unlinkGate.run(holds3.keyOf(path), op) : op(),
27804
+ own: (path, op) => holds3.own(path, op),
27805
+ revoked: (path) => holds3.isRevoked(path),
27806
+ renamed: (from, to) => holds3.renamed(from, to)
27763
27807
  });
27764
27808
  }
27765
27809
  function linksOf(opts) {
@@ -27916,15 +27960,15 @@ function spawnWasmProcess(opts) {
27916
27960
  )
27917
27961
  );
27918
27962
  publishStops(process, header4);
27919
- const holds2 = new HeldPaths();
27920
- opts.held?.add(holds2);
27921
- const token = holdingToken(opts, holds2, {
27963
+ const holds3 = new HeldPaths();
27964
+ opts.held?.add(holds3);
27965
+ const token = holdingToken(opts, holds3, {
27922
27966
  cred: () => process.cred,
27923
27967
  umask: () => process.umask,
27924
27968
  created: created4,
27925
- holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds2.keeps(path) || await process.holds(path))
27969
+ holdsKept: async (path) => path.includes(`/${UNLINKED_DIR}/`) && (holds3.keeps(path) || await process.holds(path))
27926
27970
  });
27927
- heldBy(process, holds2, opts.replacements);
27971
+ heldBy(process, holds3, opts.replacements);
27928
27972
  const worker = opts.createWorker();
27929
27973
  const dying = new Dying();
27930
27974
  const dispatch2 = (req, block) => dying.serve(
@@ -27956,7 +28000,7 @@ function spawnWasmProcess(opts) {
27956
28000
  responder.dispose();
27957
28001
  lane?.dispose();
27958
28002
  revokeSyncFsToken(token);
27959
- opts.held?.delete(holds2);
28003
+ opts.held?.delete(holds3);
27960
28004
  worker.terminate();
27961
28005
  settleExit(process.exit(), settle3, code);
27962
28006
  };
@@ -29035,6 +29079,236 @@ function enableDnsStub(net, stub) {
29035
29079
  });
29036
29080
  }
29037
29081
 
29082
+ // src/kernel/net/remote-transport.ts
29083
+ var TransportError = class extends Error {
29084
+ status;
29085
+ code;
29086
+ detail;
29087
+ constructor(message3, status, code, detail) {
29088
+ super(message3);
29089
+ this.status = status;
29090
+ this.code = code;
29091
+ this.detail = detail === "transport" ? detail : void 0;
29092
+ }
29093
+ };
29094
+ function unfollowed2(redirect) {
29095
+ return redirect !== void 0 && redirect !== "follow";
29096
+ }
29097
+ function honors(traits, redirect) {
29098
+ if (traits.redirectPolicy === true) return true;
29099
+ const hops = traits.redirectHops;
29100
+ const raw2 = traits.manualRedirects === true && (hops === void 0 || hops === false);
29101
+ return redirect === "manual" && raw2;
29102
+ }
29103
+ function refused3(message3) {
29104
+ return new TransportError(message3, 502, void 0, "transport");
29105
+ }
29106
+ var RemoteTransport = class {
29107
+ traits;
29108
+ port;
29109
+ waiting = /* @__PURE__ */ new Map();
29110
+ nextId = 0;
29111
+ sockets = /* @__PURE__ */ new Map();
29112
+ uploads = /* @__PURE__ */ new Map();
29113
+ failure;
29114
+ constructor(port, traits) {
29115
+ this.port = port;
29116
+ this.traits = traits;
29117
+ }
29118
+ receive(reply) {
29119
+ if (reply.net === "body-pull") {
29120
+ void this.pull(reply.nid);
29121
+ return;
29122
+ }
29123
+ const socket = this.sockets.get(reply.nid);
29124
+ if (socket && this.toSocket(reply, socket)) return;
29125
+ const waiter = this.waiting.get(reply.nid);
29126
+ if (!waiter) return;
29127
+ this.waiting.delete(reply.nid);
29128
+ if (reply.net === "error") {
29129
+ waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
29130
+ } else waiter.resolve(reply);
29131
+ }
29132
+ toSocket(reply, socket) {
29133
+ if (reply.net === "ws-message") socket.queue.push(reply.data);
29134
+ else if (reply.net === "ws-acked") socket.acked(reply.n);
29135
+ else if (reply.net === "ws-closed") {
29136
+ this.sockets.delete(reply.nid);
29137
+ socket.queue.end({ code: reply.code, reason: reply.reason });
29138
+ } else return false;
29139
+ return true;
29140
+ }
29141
+ async pull(nid) {
29142
+ const upload = this.uploads.get(nid);
29143
+ if (!upload) {
29144
+ this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
29145
+ return;
29146
+ }
29147
+ try {
29148
+ const next3 = await upload.next();
29149
+ if (next3.done) {
29150
+ this.uploads.delete(nid);
29151
+ this.port.postMessage({ net: "body-end", nid });
29152
+ } else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
29153
+ } catch (e) {
29154
+ this.uploads.delete(nid);
29155
+ this.port.postMessage({
29156
+ net: "body-error",
29157
+ nid,
29158
+ message: e instanceof Error ? e.message : String(e)
29159
+ });
29160
+ }
29161
+ }
29162
+ dropUpload(nid) {
29163
+ const upload = this.uploads.get(nid);
29164
+ this.uploads.delete(nid);
29165
+ void upload?.return?.().catch(() => void 0);
29166
+ }
29167
+ fail(error) {
29168
+ this.failure = error;
29169
+ for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
29170
+ for (const waiter of this.waiting.values()) waiter.reject(error);
29171
+ this.waiting.clear();
29172
+ for (const socket of this.sockets.values())
29173
+ socket.queue.end({ code: 1011, reason: error.message });
29174
+ this.sockets.clear();
29175
+ }
29176
+ ask(call) {
29177
+ if (this.failure) return Promise.reject(this.failure);
29178
+ return new Promise((resolve2, reject) => {
29179
+ this.waiting.set(call.nid, { resolve: resolve2, reject });
29180
+ this.port.postMessage(call);
29181
+ });
29182
+ }
29183
+ cancel(nid) {
29184
+ const waiter = this.waiting.get(nid);
29185
+ this.waiting.delete(nid);
29186
+ waiter?.reject(new TransportError("the request was cancelled"));
29187
+ this.port.postMessage({ net: "cancel", nid });
29188
+ }
29189
+ async fetch(request3, owner, stamp) {
29190
+ const nid = ++this.nextId;
29191
+ const { signal, redirect } = request3;
29192
+ signal.throwIfAborted();
29193
+ if (unfollowed2(redirect) && !honors(this.traits, redirect)) {
29194
+ throw refused3(`this transport cannot honor redirect: ${redirect}`);
29195
+ }
29196
+ let finished = false;
29197
+ const abort = () => {
29198
+ finished = true;
29199
+ this.dropUpload(nid);
29200
+ this.cancel(nid);
29201
+ };
29202
+ signal.addEventListener("abort", abort, { once: true });
29203
+ const finish = () => {
29204
+ this.dropUpload(nid);
29205
+ if (finished) return;
29206
+ finished = true;
29207
+ signal.removeEventListener("abort", abort);
29208
+ };
29209
+ if (request3.bodyStream) this.uploads.set(nid, request3.bodyStream[Symbol.asyncIterator]());
29210
+ let head;
29211
+ try {
29212
+ head = await this.ask({
29213
+ net: "fetch",
29214
+ nid,
29215
+ url: request3.url,
29216
+ method: request3.method,
29217
+ headers: request3.headers,
29218
+ ...request3.bodyStream ? { streamed: true } : request3.body ? { body: request3.body } : {},
29219
+ ...redirect !== void 0 ? { redirect } : {},
29220
+ ...owner !== void 0 ? { owner } : {},
29221
+ ...stamp ? { stamp } : {}
29222
+ });
29223
+ } catch (e) {
29224
+ finish();
29225
+ throw e;
29226
+ }
29227
+ const { status, statusText, headers, url, redirected: redirected2, redirects, opaqueRedirect } = head;
29228
+ const read = async () => {
29229
+ if (finished) return void 0;
29230
+ const reply = await this.ask({ net: "read", nid }).catch((e) => {
29231
+ finish();
29232
+ throw e;
29233
+ });
29234
+ if (reply.net === "chunk") return reply.bytes;
29235
+ finish();
29236
+ return void 0;
29237
+ };
29238
+ const cancel = async () => {
29239
+ if (finished) return;
29240
+ finish();
29241
+ this.cancel(nid);
29242
+ };
29243
+ if (unfollowed2(redirect) && (redirected2 || redirects?.length)) {
29244
+ await cancel();
29245
+ throw refused3(`this transport followed a redirect despite redirect: ${redirect}`);
29246
+ }
29247
+ return {
29248
+ ...url !== void 0 ? { url } : {},
29249
+ ...redirected2 !== void 0 ? { redirected: redirected2 } : {},
29250
+ ...redirects ? { redirects } : {},
29251
+ ...opaqueRedirect ? { opaqueRedirect } : {},
29252
+ status,
29253
+ statusText,
29254
+ headers,
29255
+ cancel,
29256
+ body: {
29257
+ [Symbol.asyncIterator]: () => ({
29258
+ next: async () => {
29259
+ const bytes = await read();
29260
+ return bytes ? { value: bytes, done: false } : { value: void 0, done: true };
29261
+ },
29262
+ return: async () => {
29263
+ await cancel();
29264
+ return { value: void 0, done: true };
29265
+ }
29266
+ })
29267
+ }
29268
+ };
29269
+ }
29270
+ async websocket(request3) {
29271
+ const nid = ++this.nextId;
29272
+ const { signal } = request3;
29273
+ signal.throwIfAborted();
29274
+ const abort = () => this.cancel(nid);
29275
+ signal.addEventListener("abort", abort, { once: true });
29276
+ let opened2;
29277
+ try {
29278
+ opened2 = await this.ask({
29279
+ net: "ws-open",
29280
+ nid,
29281
+ url: request3.url,
29282
+ protocols: request3.protocols,
29283
+ headers: request3.headers
29284
+ });
29285
+ } finally {
29286
+ signal.removeEventListener("abort", abort);
29287
+ }
29288
+ const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
29289
+ const queue = new MessageQueue(
29290
+ () => close(1e3, "a message is too big"),
29291
+ Number.POSITIVE_INFINITY,
29292
+ (n) => this.port.postMessage({ net: "ws-consumed", nid, n })
29293
+ );
29294
+ let unacked = 0;
29295
+ this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
29296
+ return {
29297
+ protocol: opened2.protocol,
29298
+ get buffered() {
29299
+ return unacked;
29300
+ },
29301
+ send: (data) => {
29302
+ unacked += payloadSize(data);
29303
+ this.port.postMessage({ net: "ws-send", nid, data });
29304
+ },
29305
+ messages: queue,
29306
+ close,
29307
+ closed: queue.closed
29308
+ };
29309
+ }
29310
+ };
29311
+
29038
29312
  // src/kernel/net/redirect-hops.ts
29039
29313
  var HELD_MS = 3e4;
29040
29314
  var HELD_MAX2 = 64;
@@ -29110,7 +29384,9 @@ function replayingHops(inner, heldMs = HELD_MS) {
29110
29384
  return { ...inner.traits, manualRedirects: true };
29111
29385
  },
29112
29386
  ...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
29113
- async fetch(request3, caller) {
29387
+ async fetch(request3, ...rest2) {
29388
+ if (unfollowed2(request3.redirect)) return inner.fetch(request3, ...rest2);
29389
+ const [caller] = rest2;
29114
29390
  const owner = caller ?? KERNEL;
29115
29391
  const key = keyOf3(owner, request3.method, request3.url);
29116
29392
  const waiting = held.get(key);
@@ -29120,7 +29396,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
29120
29396
  return replay(waiting);
29121
29397
  }
29122
29398
  if (waiting) drop(key);
29123
- const response = await inner.fetch(request3, caller);
29399
+ const response = await inner.fetch(request3, ...rest2);
29124
29400
  if (!response.redirects?.length) return response;
29125
29401
  return replay({
29126
29402
  owner,
@@ -29133,6 +29409,143 @@ function replayingHops(inner, heldMs = HELD_MS) {
29133
29409
  };
29134
29410
  }
29135
29411
 
29412
+ // src/kernel/net/sealed-fetch.ts
29413
+ var UNSAFE_FIELD = /[\r\n\0]/;
29414
+ function headerList(headers) {
29415
+ return Array.isArray(headers) && headers.every(
29416
+ (field4) => Array.isArray(field4) && field4.length === 2 && field4.every((text) => typeof text === "string" && !UNSAFE_FIELD.test(text))
29417
+ );
29418
+ }
29419
+ function sealedReplyValid(reply) {
29420
+ if (typeof reply !== "object" || reply === null) return false;
29421
+ const { redirects, redirected: redirected2, status, statusText, headers, url, body, cancel } = reply;
29422
+ 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";
29423
+ }
29424
+ function dropSealedReply(reply) {
29425
+ const { cancel } = reply ?? {};
29426
+ if (typeof cancel !== "function") return;
29427
+ void Promise.resolve().then(() => cancel.call(reply)).catch(() => void 0);
29428
+ }
29429
+ function failed2(reason) {
29430
+ const text = reason instanceof Error ? reason.message : String(reason);
29431
+ return new PlaceholderRefused(
29432
+ `refused: the request with a sealed placeholder was not completed: ${text}`
29433
+ );
29434
+ }
29435
+ var Stall = class {
29436
+ idle = new AbortController();
29437
+ ms;
29438
+ timer;
29439
+ signal;
29440
+ constructor(signals, ms) {
29441
+ this.ms = ms;
29442
+ this.signal = AbortSignal.any([...signals, this.idle.signal]);
29443
+ }
29444
+ arm() {
29445
+ clearTimeout(this.timer);
29446
+ this.timer = setTimeout(() => this.idle.abort("timeout"), this.ms);
29447
+ this.timer.unref?.();
29448
+ }
29449
+ touch() {
29450
+ if (this.timer !== void 0) this.arm();
29451
+ }
29452
+ rest() {
29453
+ clearTimeout(this.timer);
29454
+ this.timer = void 0;
29455
+ }
29456
+ };
29457
+ async function until(work, signal) {
29458
+ const stopped = Promise.withResolvers();
29459
+ const stop = () => stopped.reject(signal.reason);
29460
+ if (signal.aborted) stop();
29461
+ else signal.addEventListener("abort", stop, { once: true });
29462
+ try {
29463
+ return await Promise.race([work, stopped.promise]);
29464
+ } finally {
29465
+ signal.removeEventListener("abort", stop);
29466
+ }
29467
+ }
29468
+ async function* ticking(stream, stall) {
29469
+ for await (const chunk2 of stream) {
29470
+ stall.touch();
29471
+ yield chunk2;
29472
+ }
29473
+ }
29474
+ function sealedRequest(request3, stamp, stall) {
29475
+ const { method, url, headers, body, bodyStream } = request3;
29476
+ return {
29477
+ v: 1,
29478
+ caller: structuredClone(stamp),
29479
+ method,
29480
+ url,
29481
+ headers: headers.map(([name2, value2]) => [name2, value2]),
29482
+ redirect: "manual",
29483
+ ...bodyStream ? { bodyStream: ticking(bodyStream, stall) } : body ? { body } : {}
29484
+ };
29485
+ }
29486
+ function guarded2(reply, stall) {
29487
+ let finished = false;
29488
+ const cancel = async () => {
29489
+ stall.signal.removeEventListener("abort", dropped2);
29490
+ stall.rest();
29491
+ if (finished) return;
29492
+ finished = true;
29493
+ await reply.cancel().catch(() => void 0);
29494
+ };
29495
+ const dropped2 = () => void cancel();
29496
+ stall.signal.addEventListener("abort", dropped2, { once: true });
29497
+ const source = reply.body[Symbol.asyncIterator]();
29498
+ const body = (async function* () {
29499
+ try {
29500
+ for (; ; ) {
29501
+ stall.arm();
29502
+ const next3 = await until(source.next(), stall.signal);
29503
+ stall.rest();
29504
+ if (next3.done) {
29505
+ finished = true;
29506
+ return;
29507
+ }
29508
+ if (!(next3.value instanceof Uint8Array)) throw failed2("a body chunk is not bytes");
29509
+ if (next3.value.byteLength > 0) yield next3.value;
29510
+ }
29511
+ } finally {
29512
+ await cancel();
29513
+ }
29514
+ })();
29515
+ return {
29516
+ ...reply.url !== void 0 ? { url: reply.url } : {},
29517
+ status: reply.status,
29518
+ statusText: reply.statusText,
29519
+ headers: reply.headers,
29520
+ body,
29521
+ cancel
29522
+ };
29523
+ }
29524
+ function sealedFetcher(hook, stop, idleMs = BODY_IDLE_MS) {
29525
+ return async (request3, stamp) => {
29526
+ const stall = new Stall([request3.signal, stop], idleMs);
29527
+ const { signal } = stall;
29528
+ if (signal.aborted) throw failed2(signal.reason);
29529
+ stall.arm();
29530
+ const asked = Promise.resolve().then(() => {
29531
+ signal.throwIfAborted();
29532
+ return hook(sealedRequest(request3, stamp, stall), { signal });
29533
+ });
29534
+ let reply;
29535
+ try {
29536
+ reply = await until(asked, signal);
29537
+ } catch (e) {
29538
+ void asked.then(dropSealedReply, () => void 0);
29539
+ throw failed2(e);
29540
+ } finally {
29541
+ stall.rest();
29542
+ }
29543
+ if (sealedReplyValid(reply)) return guarded2(reply, stall);
29544
+ dropSealedReply(reply);
29545
+ throw failed2("the reply is not a scrubbed response");
29546
+ };
29547
+ }
29548
+
29136
29549
  // src/kernel/package-swaps.ts
29137
29550
  var SWAP_GAP_MS = 2e3;
29138
29551
  var STAGES = ["_tmp_", "_pacquet-stage_"];
@@ -29305,11 +29718,11 @@ var PackageLocks = class {
29305
29718
  if (!locks) return Promise.resolve(() => {
29306
29719
  });
29307
29720
  const { promise: held, resolve: release } = Promise.withResolvers();
29308
- return new Promise((granted2, failed3) => {
29721
+ return new Promise((granted2, failed4) => {
29309
29722
  locks.request(replacingLock(this.metadata, root), { mode: "exclusive" }, () => {
29310
29723
  granted2(() => release());
29311
29724
  return held;
29312
- }).catch(failed3);
29725
+ }).catch(failed4);
29313
29726
  });
29314
29727
  }
29315
29728
  };
@@ -29559,9 +29972,9 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
29559
29972
  let open2 = false;
29560
29973
  const reply = (message3, transfer = []) => port.postMessage(message3, transfer);
29561
29974
  async function hello(message3) {
29562
- const refused3 = driverVersionError(message3.protocol);
29563
- if (refused3) {
29564
- reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused3, errno: "EPROTO" } });
29975
+ const refused4 = driverVersionError(message3.protocol);
29976
+ if (refused4) {
29977
+ reply({ hello: { protocol: DRIVER_PROTOCOL, error: refused4, errno: "EPROTO" } });
29565
29978
  return;
29566
29979
  }
29567
29980
  try {
@@ -29911,22 +30324,22 @@ async function mountFstab(lines2, mount, signal, retries = FSTAB_RETRIES, discar
29911
30324
  );
29912
30325
  }
29913
30326
  async function mountLine({ line, spec, invalid }, mount, signal, retries, discard) {
29914
- let failed3 = invalid;
30327
+ let failed4 = invalid;
29915
30328
  for (let attempt = 0; !invalid && attempt <= retries.length && !signal.aborted; attempt++) {
29916
30329
  try {
29917
30330
  const entry = await mount(spec);
29918
30331
  if (!signal.aborted) return { line, target: spec.target, entry };
29919
30332
  discard(entry);
29920
- failed3 = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
30333
+ failed4 = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
29921
30334
  break;
29922
30335
  } catch (err) {
29923
- failed3 = err;
30336
+ failed4 = err;
29924
30337
  if (FINAL.has(codeOf6(err)) || attempt === retries.length) break;
29925
30338
  await wait(retries[attempt], signal);
29926
30339
  }
29927
30340
  }
29928
- const code = codeOf6(failed3);
29929
- return { line, target: spec.target, code, error: String(failed3?.message ?? code) };
30341
+ const code = codeOf6(failed4);
30342
+ return { line, target: spec.target, code, error: String(failed4?.message ?? code) };
29930
30343
  }
29931
30344
 
29932
30345
  // src/mount/hostfs.ts
@@ -31100,7 +31513,7 @@ var RULE = new RegExp(
31100
31513
  var TERM = /^[A-Za-z0-9._+-]+$/;
31101
31514
  var PLAIN3 = /^[A-Za-z0-9_@%+=:,./-]+$/;
31102
31515
  var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
31103
- function failed2(errno3, error) {
31516
+ function failed3(errno3, error) {
31104
31517
  return { error, errno: errno3 };
31105
31518
  }
31106
31519
  function unescaped(double) {
@@ -31279,10 +31692,10 @@ var Sudo = class {
31279
31692
  }
31280
31693
  async untrusted(path, cwd, word) {
31281
31694
  const files = this.o.backing ? await this.o.backing(path, cwd) : [];
31282
- if (!files) return failed2("ENOENT", `sudo: ${word}: command not found`);
31695
+ if (!files) return failed3("ENOENT", `sudo: ${word}: command not found`);
31283
31696
  for (const file of [path, ...files]) {
31284
31697
  if (!await this.trusted(file)) {
31285
- return failed2("EPERM", `sudo: ${file} must be root's, and writable by root only`);
31698
+ return failed3("EPERM", `sudo: ${file} must be root's, and writable by root only`);
31286
31699
  }
31287
31700
  }
31288
31701
  return void 0;
@@ -31299,7 +31712,7 @@ var Sudo = class {
31299
31712
  }
31300
31713
  async request(caller, call, signal) {
31301
31714
  const parsed2 = parseArgs(call.args);
31302
- if (typeof parsed2 === "string") return failed2("EINVAL", parsed2);
31715
+ if (typeof parsed2 === "string") return failed3("EINVAL", parsed2);
31303
31716
  if (this.o.mode !== "enforce") {
31304
31717
  const mode = this.o.mode;
31305
31718
  if (parsed2.list) return { list: `sudo: users are '${mode}': commands run as the caller
@@ -31308,9 +31721,9 @@ var Sudo = class {
31308
31721
  }
31309
31722
  const { cred } = caller;
31310
31723
  const self = await this.o.users.lookup(cred.ruid);
31311
- if (!self) return failed2("EPERM", `sudo: uid ${cred.ruid} is not in the passwd database`);
31724
+ if (!self) return failed3("EPERM", `sudo: uid ${cred.ruid} is not in the passwd database`);
31312
31725
  const target = await this.lookup(parsed2.user);
31313
- if (!target) return failed2("ENOENT", `sudo: unknown user ${parsed2.user}`);
31726
+ if (!target) return failed3("ENOENT", `sudo: unknown user ${parsed2.user}`);
31314
31727
  const root = cred.euid === 0;
31315
31728
  const rules = root ? [] : await this.policy();
31316
31729
  const applies = await this.applies(self, cred);
@@ -31318,13 +31731,13 @@ var Sudo = class {
31318
31731
  const [word = "", ...args] = parsed2.command;
31319
31732
  const cwd = await this.canonical(call.cwd);
31320
31733
  if (cwd === void 0 || !await this.reachable(cred, cwd)) {
31321
- return failed2(
31734
+ return failed3(
31322
31735
  "EACCES",
31323
31736
  `sudo: cannot run in ${call.cwd}: it isn't a directory you can enter`
31324
31737
  );
31325
31738
  }
31326
31739
  const path = await this.locate(word, cwd);
31327
- if (!path) return failed2("ENOENT", `sudo: ${word}: command not found`);
31740
+ if (!path) return failed3("ENOENT", `sudo: ${word}: command not found`);
31328
31741
  const untrusted2 = await this.untrusted(path, cwd, word);
31329
31742
  if (untrusted2) return untrusted2;
31330
31743
  const argv = [path, ...args];
@@ -31335,24 +31748,24 @@ var Sudo = class {
31335
31748
  if (root || matching.some((rule) => rule.nopasswd)) return grant();
31336
31749
  const quoted = argv.map(quoteWord).join(" ");
31337
31750
  if (matching.length === 0) {
31338
- return failed2(
31751
+ return failed3(
31339
31752
  "EPERM",
31340
31753
  `sudo: ${self.name} is not allowed to run ${quoted} as ${target.name}`
31341
31754
  );
31342
31755
  }
31343
- if (parsed2.nonInteractive) return failed2("EPERM", "sudo: a password is required");
31344
- if (this.pending.has(cred.ruid)) return failed2("EBUSY", "sudo: another request is pending");
31756
+ if (parsed2.nonInteractive) return failed3("EPERM", "sudo: a password is required");
31757
+ if (this.pending.has(cred.ruid)) return failed3("EBUSY", "sudo: another request is pending");
31345
31758
  this.pending.add(cred.ruid);
31346
31759
  try {
31347
31760
  const answer2 = await this.ask(caller, self, target, parsed2.command, path, cwd, signal);
31348
31761
  if (typeof answer2 !== "string") return answer2;
31349
31762
  if (await this.canonical(call.cwd) !== cwd || !await this.reachable(cred, cwd)) {
31350
- return failed2("EACCES", `sudo: ${call.cwd} changed while the request waited`);
31763
+ return failed3("EACCES", `sudo: ${call.cwd} changed while the request waited`);
31351
31764
  }
31352
31765
  const changed = await this.untrusted(path, cwd, word);
31353
31766
  if (changed) return changed;
31354
31767
  if (answer2 === "always" && !await this.remember(self, target, cwd, argv)) {
31355
- return failed2("EIO", "sudo: the rule could not be recorded");
31768
+ return failed3("EIO", "sudo: the rule could not be recorded");
31356
31769
  }
31357
31770
  return grant();
31358
31771
  } finally {
@@ -31369,7 +31782,7 @@ var Sudo = class {
31369
31782
  };
31370
31783
  }
31371
31784
  if (rules.length === 0) {
31372
- return failed2("EPERM", `User ${self.name} is not allowed to run sudo on ${host}.`);
31785
+ return failed3("EPERM", `User ${self.name} is not allowed to run sudo on ${host}.`);
31373
31786
  }
31374
31787
  const lines2 = rules.map(described).join("\n");
31375
31788
  return { list: `User ${self.name} may run the following commands on ${host}:
@@ -31378,7 +31791,7 @@ ${lines2}
31378
31791
  }
31379
31792
  async ask(caller, self, target, argv, path, cwd, requester) {
31380
31793
  const { approve } = this.o;
31381
- if (!approve || requester.aborted) return failed2("EACCES", "sudo: approval denied");
31794
+ if (!approve || requester.aborted) return failed3("EACCES", "sudo: approval denied");
31382
31795
  const createdAt = Date.now();
31383
31796
  const timeout = this.o.timeoutMs ?? SUDO_TIMEOUT_MS;
31384
31797
  const req = {
@@ -31408,9 +31821,9 @@ ${lines2}
31408
31821
  const answered2 = Promise.resolve().then(() => approve(req, { signal: control.signal })).catch(() => "deny");
31409
31822
  const answer2 = await Promise.race([answered2, aborted3]);
31410
31823
  if (answer2 === "aborted" || control.signal.aborted) {
31411
- return control.signal.reason === "expired" ? failed2("ETIMEDOUT", "sudo: the request expired") : failed2("EINTR", "sudo: the request was withdrawn");
31824
+ return control.signal.reason === "expired" ? failed3("ETIMEDOUT", "sudo: the request expired") : failed3("EINTR", "sudo: the request was withdrawn");
31412
31825
  }
31413
- return answer2 === "once" || answer2 === "always" ? answer2 : failed2("EACCES", "sudo: approval denied");
31826
+ return answer2 === "once" || answer2 === "always" ? answer2 : failed3("EACCES", "sudo: approval denied");
31414
31827
  } finally {
31415
31828
  clearTimeout(timer);
31416
31829
  requester.removeEventListener("abort", withdraw);
@@ -31701,13 +32114,13 @@ function interpreter(head) {
31701
32114
  function expandDefaults(defaults2, env) {
31702
32115
  const out = {};
31703
32116
  for (const [key, value2] of Object.entries(defaults2 ?? {})) {
31704
- let missing5 = false;
32117
+ let missing6 = false;
31705
32118
  const expanded = value2.replace(ENV_REFERENCE, (_, name2) => {
31706
32119
  const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
31707
- if (set3 === void 0) missing5 = true;
32120
+ if (set3 === void 0) missing6 = true;
31708
32121
  return set3 ?? "";
31709
32122
  });
31710
- if (!missing5) out[key] = expanded;
32123
+ if (!missing6) out[key] = expanded;
31711
32124
  }
31712
32125
  return out;
31713
32126
  }
@@ -31882,6 +32295,9 @@ var Launcher = class {
31882
32295
  usersMode;
31883
32296
  dac;
31884
32297
  sealed;
32298
+ fill;
32299
+ fills = new AbortController();
32300
+ placeholders = [];
31885
32301
  scrubs = /* @__PURE__ */ new Map();
31886
32302
  clipboard;
31887
32303
  embedder;
@@ -31963,7 +32379,7 @@ var Launcher = class {
31963
32379
  ...options.env
31964
32380
  };
31965
32381
  this.ca = kernelCa(options.caStore ?? memoryCaStore());
31966
- this.transport = placeholderFloor(replayingHops(options.transport ?? missingTransport()));
32382
+ this.transport = this.floored(options);
31967
32383
  this.announcedTraits = JSON.stringify(this.transport.traits);
31968
32384
  this.uplink = options.uplink;
31969
32385
  this.routes = new Routes(options.uplink?.traits.ipv6 === true);
@@ -32118,16 +32534,16 @@ var Launcher = class {
32118
32534
  if (!found) {
32119
32535
  found = this.swaps.settled().then(() => this.trustedAppended()).then(async (appended2) => {
32120
32536
  const tiers = await this.tiers(scope, appended2);
32121
- const refused3 = [];
32537
+ const refused4 = [];
32122
32538
  const commands = await scanCommands(
32123
32539
  this.scanned,
32124
32540
  tiers,
32125
32541
  tiers.length - appended2.length,
32126
32542
  void 0,
32127
- refused3,
32543
+ refused4,
32128
32544
  await this.globalRoots(scope)
32129
32545
  );
32130
- this.refusedOf.set(commands, refused3.map(refusing));
32546
+ this.refusedOf.set(commands, refused4.map(refusing));
32131
32547
  return commands;
32132
32548
  }).then(
32133
32549
  (commands) => this.refusals(commands).set(SUDO_COMMAND.name, SUDO_COMMAND).set(CRONTAB_COMMAND.name, CRONTAB_COMMAND)
@@ -32333,14 +32749,14 @@ var Launcher = class {
32333
32749
  return await this.commandAt(path, scope) ?? await this.refusedAt(path, name2, scope);
32334
32750
  }
32335
32751
  async refusedAt(path, name2, scope) {
32336
- const refused3 = this.refusedOf.get(await this.commands(scope)) ?? [];
32337
- if (refused3.length === 0) return void 0;
32752
+ const refused4 = this.refusedOf.get(await this.commands(scope)) ?? [];
32753
+ if (refused4.length === 0) return void 0;
32338
32754
  const st = await this.base.stat(path).catch(() => void 0);
32339
32755
  if (!st?.isFile) return void 0;
32340
32756
  const real = await physicalPathAsync(this.base, path).catch(() => path);
32341
32757
  const same3 = async (own) => own === path || await physicalPathAsync(this.base, own).catch(() => own) === real;
32342
32758
  const owners = [];
32343
- for (const c of refused3) {
32759
+ for (const c of refused4) {
32344
32760
  const origin = c.origin;
32345
32761
  for (const own of [origin.glue, origin.wasm, ...origin.variants ?? []]) {
32346
32762
  if (!await same3(own)) continue;
@@ -32350,11 +32766,11 @@ var Launcher = class {
32350
32766
  }
32351
32767
  const stem = name2.replace(/\.wasm$/, "");
32352
32768
  const named = owners.find((c) => c.name === name2) ?? owners.find((c) => c.name === stem);
32353
- return named ?? owners[0] ?? await this.refusedCopy(real, name2, refused3);
32769
+ return named ?? owners[0] ?? await this.refusedCopy(real, name2, refused4);
32354
32770
  }
32355
- async refusedCopy(real, name2, refused3) {
32771
+ async refusedCopy(real, name2, refused4) {
32356
32772
  const dir = real.slice(0, real.lastIndexOf("/"));
32357
- for (const c of refused3) {
32773
+ for (const c of refused4) {
32358
32774
  const origin = c.origin;
32359
32775
  if (origin.abi !== "emscripten" || origin.script || c.name !== name2) continue;
32360
32776
  const own = await physicalPathAsync(this.base, origin.glue).catch(() => origin.glue);
@@ -32562,12 +32978,12 @@ var Launcher = class {
32562
32978
  return void 0;
32563
32979
  }
32564
32980
  async planOne(req, { ppid, cred, scope }, catalogOnly = false) {
32565
- const refused3 = (err) => {
32981
+ const refused4 = (err) => {
32566
32982
  throw codeOf8(err) === "EACCES" ? new SpawnError("EACCES") : err;
32567
32983
  };
32568
- const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused3);
32984
+ const file = await this.execFile(req.file, req.cwd, this.execGuard(cred, ppid)).catch(refused4);
32569
32985
  const planned = await this.plan(file, req.argv, req.cwd, scope, req.argv0, catalogOnly);
32570
- await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused3);
32986
+ await this.mayExec(cred, { ...req, file, pid: ppid }, planned).catch(refused4);
32571
32987
  if (planned) return planned;
32572
32988
  throw new SpawnError(catalogOnly ? "ENOENT" : await this.unrunnable(file, req.cwd, scope));
32573
32989
  }
@@ -33025,6 +33441,19 @@ var Launcher = class {
33025
33441
  groupSession(pgid) {
33026
33442
  return this.jobs.sessionOf(pgid);
33027
33443
  }
33444
+ floored(options) {
33445
+ const { sealedFetch } = options;
33446
+ this.fill = sealedFetch && this.usersMode === "enforce" ? sealedFetcher(sealedFetch, this.fills.signal) : void 0;
33447
+ if (this.fill) this.net.stampProxy(REALM_PROXY_PORT);
33448
+ return placeholderFloor(replayingHops(options.transport ?? missingTransport()), {
33449
+ known: () => this.placeholders,
33450
+ ...this.fill ? { fill: this.fill } : {}
33451
+ });
33452
+ }
33453
+ httpFor(pid) {
33454
+ const stamp = this.fill ? () => this.liveStamp(pid) : void 0;
33455
+ return new HttpHandles(this.transport, pid, this.loopbackFor(pid), stamp);
33456
+ }
33028
33457
  loopbackFor(pid) {
33029
33458
  return new KernelLoopback(
33030
33459
  this.net,
@@ -33032,7 +33461,7 @@ var Launcher = class {
33032
33461
  const cred = this.credOf(pid);
33033
33462
  return { pid, uid: cred.euid, gid: cred.egid };
33034
33463
  },
33035
- () => this.connectorStamp(pid)
33464
+ () => this.liveStamp(pid)
33036
33465
  );
33037
33466
  }
33038
33467
  sourceCheck(pid, writer) {
@@ -33197,7 +33626,7 @@ var Launcher = class {
33197
33626
  jobs: this.jobs,
33198
33627
  ptys: this.ptys,
33199
33628
  net: this.net,
33200
- http: new HttpHandles(this.transport, pid, this.loopbackFor(pid)),
33629
+ http: this.httpFor(pid),
33201
33630
  locks: this.locks,
33202
33631
  fifos: this.fifos,
33203
33632
  sems: this.sems,
@@ -33512,6 +33941,19 @@ var Launcher = class {
33512
33941
  connectorStamp(pid) {
33513
33942
  return this.sealed.stamp(this.identityOf(pid), this.credOf(pid), this.tagsOf(pid));
33514
33943
  }
33944
+ async liveStamp(pid) {
33945
+ if (!this.creds.has(pid) || this.zombies.has(pid)) return void 0;
33946
+ return this.connectorStamp(pid);
33947
+ }
33948
+ setPlaceholders(list) {
33949
+ if (!Array.isArray(list) || !list.every((p) => typeof p === "string" && p !== "")) {
33950
+ throw fsError("EINVAL", "setPlaceholders takes a list of non-empty strings");
33951
+ }
33952
+ this.placeholders = [...list];
33953
+ }
33954
+ endFills() {
33955
+ this.fills.abort("terminated");
33956
+ }
33515
33957
  identityOf(pid) {
33516
33958
  const parent = this.jobs.shownParent(pid);
33517
33959
  const alive = parent !== void 0 && this.running(parent);
@@ -33634,7 +34076,7 @@ var Launcher = class {
33634
34076
  const at = normalizePath(path);
33635
34077
  this.unlinked.closed(at);
33636
34078
  this.writers?.unlinked.closed(at);
33637
- const holding = [...this.held].some((holds2) => holds2.holding(at)) || [...this.openFiles].some((open3) => open3.holdsAt(at));
34079
+ const holding = [...this.held].some((holds3) => holds3.holding(at)) || [...this.openFiles].some((open3) => open3.holdsAt(at));
33638
34080
  if (!holding) void this.rootFs.announceHolds?.([], [at], false);
33639
34081
  const open2 = [...this.openFiles].some((nodes) => nodes.writes(at)) || heldUnder(this.held, at);
33640
34082
  if (!open2) void this.mounts.commit(at).catch(() => void 0);
@@ -33797,8 +34239,9 @@ var Launcher = class {
33797
34239
  for (const root of roots) this.integrity.forget(root);
33798
34240
  this.resetCatalogs();
33799
34241
  }
33800
- attest(path) {
34242
+ attest(path, options = {}) {
33801
34243
  return attest(this.rootFs, path, {
34244
+ ...options,
33802
34245
  users: this.usersMode,
33803
34246
  mounts: this.mounts.list().map((entry) => entry.target).filter((target) => this.mounts.mounted(target) !== void 0)
33804
34247
  });
@@ -33855,8 +34298,8 @@ var Launcher = class {
33855
34298
  for (const name2 of names2 ?? []) {
33856
34299
  const path = joinName(real, name2);
33857
34300
  if (await this.base.hasOwner(path)) continue;
33858
- const failed3 = this.inUse(path) ? "busy" : await this.base.rm(path, { recursive: true, force: true }).catch(String);
33859
- if (failed3 === void 0) removed++;
34301
+ const failed4 = this.inUse(path) ? "busy" : await this.base.rm(path, { recursive: true, force: true }).catch(String);
34302
+ if (failed4 === void 0) removed++;
33860
34303
  else left++;
33861
34304
  }
33862
34305
  if (removed > 0) {
@@ -33951,7 +34394,7 @@ var Launcher = class {
33951
34394
  this.pnpmStale();
33952
34395
  if (!detach) return;
33953
34396
  for (const nodes of this.openFiles) nodes.revoke(at);
33954
- for (const holds2 of this.held) holds2.revoke(at);
34397
+ for (const holds3 of this.held) holds3.revoke(at);
33955
34398
  }
33956
34399
  unmountAll() {
33957
34400
  this.cron.stop();
@@ -34162,9 +34605,9 @@ var Launcher = class {
34162
34605
  }
34163
34606
  boundTo(path, hidden, fids) {
34164
34607
  const keeping = [...this.held].map(
34165
- (holds2) => [
34166
- holds2,
34167
- fids.flatMap((fid) => [...holds2.boundAt(path, fid), ...holds2.boundAt(hidden, fid)])
34608
+ (holds3) => [
34609
+ holds3,
34610
+ fids.flatMap((fid) => [...holds3.boundAt(path, fid), ...holds3.boundAt(hidden, fid)])
34168
34611
  ]
34169
34612
  ).filter(([, ids]) => ids.length > 0);
34170
34613
  const nodes = [...this.openFiles].filter(
@@ -34175,7 +34618,7 @@ var Launcher = class {
34175
34618
  (open2) => fids.some((fid) => open2.keepBound([hidden, path], fid, file))
34176
34619
  ).length;
34177
34620
  for (let i = kept; i < nodes.length; i++) file.release();
34178
- for (const [holds2, ids] of keeping) holds2.keepBound(ids, path, file);
34621
+ for (const [holds3, ids] of keeping) holds3.keepBound(ids, path, file);
34179
34622
  void this.rootFs.announceHolds?.([], [path, hidden], false);
34180
34623
  };
34181
34624
  return { keeping, nodes, keep: keep2 };
@@ -34335,7 +34778,7 @@ var Launcher = class {
34335
34778
  }
34336
34779
  moved(from, to, source) {
34337
34780
  this.renameLog.add(from, to);
34338
- for (const holds2 of this.held) holds2.renamed(from, to);
34781
+ for (const holds3 of this.held) holds3.renamed(from, to);
34339
34782
  if (source) return;
34340
34783
  for (const nodes of this.openFiles) nodes.renamed(from, to);
34341
34784
  this.watchers.moved(from, to);
@@ -34547,213 +34990,99 @@ function integrityAsker(port) {
34547
34990
  return { lookup: lookup2, answer: answer2 };
34548
34991
  }
34549
34992
 
34550
- // src/kernel/net/remote-transport.ts
34551
- var TransportError = class extends Error {
34552
- status;
34553
- code;
34554
- detail;
34555
- constructor(message3, status, code, detail) {
34556
- super(message3);
34557
- this.status = status;
34558
- this.code = code;
34559
- this.detail = detail === "transport" ? detail : void 0;
34560
- }
34561
- };
34562
- var RemoteTransport = class {
34563
- traits;
34564
- port;
34565
- waiting = /* @__PURE__ */ new Map();
34566
- nextId = 0;
34567
- sockets = /* @__PURE__ */ new Map();
34568
- uploads = /* @__PURE__ */ new Map();
34569
- failure;
34570
- constructor(port, traits) {
34571
- this.port = port;
34572
- this.traits = traits;
34573
- }
34574
- receive(reply) {
34575
- if (reply.net === "body-pull") {
34576
- void this.pull(reply.nid);
34577
- return;
34578
- }
34579
- const socket = this.sockets.get(reply.nid);
34580
- if (socket && this.toSocket(reply, socket)) return;
34581
- const waiter = this.waiting.get(reply.nid);
34582
- if (!waiter) return;
34583
- this.waiting.delete(reply.nid);
34584
- if (reply.net === "error") {
34585
- waiter.reject(new TransportError(reply.message, reply.status, reply.code, reply.detail));
34586
- } else waiter.resolve(reply);
34587
- }
34588
- toSocket(reply, socket) {
34589
- if (reply.net === "ws-message") socket.queue.push(reply.data);
34590
- else if (reply.net === "ws-acked") socket.acked(reply.n);
34591
- else if (reply.net === "ws-closed") {
34592
- this.sockets.delete(reply.nid);
34593
- socket.queue.end({ code: reply.code, reason: reply.reason });
34594
- } else return false;
34595
- return true;
34596
- }
34597
- async pull(nid) {
34598
- const upload = this.uploads.get(nid);
34599
- if (!upload) {
34600
- this.port.postMessage({ net: "body-error", nid, message: "the request body is gone" });
34601
- return;
34602
- }
34603
- try {
34604
- const next3 = await upload.next();
34605
- if (next3.done) {
34606
- this.uploads.delete(nid);
34607
- this.port.postMessage({ net: "body-end", nid });
34608
- } else this.port.postMessage({ net: "body-chunk", nid, bytes: next3.value });
34609
- } catch (e) {
34610
- this.uploads.delete(nid);
34611
- this.port.postMessage({
34612
- net: "body-error",
34613
- nid,
34614
- message: e instanceof Error ? e.message : String(e)
34615
- });
34616
- }
34617
- }
34618
- dropUpload(nid) {
34619
- const upload = this.uploads.get(nid);
34620
- this.uploads.delete(nid);
34993
+ // src/sealed-relay.ts
34994
+ function textOf(err) {
34995
+ return err instanceof Error ? err.message : String(err);
34996
+ }
34997
+ function sendBytes(port, bytes) {
34998
+ const copy = fresh(bytes);
34999
+ port.postMessage({ t: "chunk", bytes: copy }, [copy.buffer]);
35000
+ }
35001
+ function askFetch(port, req, signal) {
35002
+ signal.throwIfAborted();
35003
+ const { bodyStream, ...wire } = req;
35004
+ const { port1: near, port2: far } = new MessageChannel();
35005
+ const upload = bodyStream?.[Symbol.asyncIterator]();
35006
+ const head = Promise.withResolvers();
35007
+ let reading;
35008
+ let ended = false;
35009
+ const end = (failure2) => {
35010
+ if (ended) return;
35011
+ ended = true;
35012
+ signal.removeEventListener("abort", abort);
35013
+ near.close();
34621
35014
  void upload?.return?.().catch(() => void 0);
34622
- }
34623
- fail(error) {
34624
- this.failure = error;
34625
- for (const nid of [...this.uploads.keys()]) this.dropUpload(nid);
34626
- for (const waiter of this.waiting.values()) waiter.reject(error);
34627
- this.waiting.clear();
34628
- for (const socket of this.sockets.values())
34629
- socket.queue.end({ code: 1011, reason: error.message });
34630
- this.sockets.clear();
34631
- }
34632
- ask(call) {
34633
- if (this.failure) return Promise.reject(this.failure);
34634
- return new Promise((resolve2, reject) => {
34635
- this.waiting.set(call.nid, { resolve: resolve2, reject });
34636
- this.port.postMessage(call);
34637
- });
34638
- }
34639
- cancel(nid) {
34640
- const waiter = this.waiting.get(nid);
34641
- this.waiting.delete(nid);
34642
- waiter?.reject(new TransportError("the request was cancelled"));
34643
- this.port.postMessage({ net: "cancel", nid });
34644
- }
34645
- async fetch(request3) {
34646
- const nid = ++this.nextId;
34647
- const { signal } = request3;
34648
- signal.throwIfAborted();
34649
- let finished = false;
34650
- const abort = () => {
34651
- finished = true;
34652
- this.dropUpload(nid);
34653
- this.cancel(nid);
34654
- };
34655
- signal.addEventListener("abort", abort, { once: true });
34656
- const finish = () => {
34657
- this.dropUpload(nid);
34658
- if (finished) return;
34659
- finished = true;
34660
- signal.removeEventListener("abort", abort);
34661
- };
34662
- if (request3.bodyStream) this.uploads.set(nid, request3.bodyStream[Symbol.asyncIterator]());
34663
- let head;
35015
+ head.reject(failure2);
35016
+ reading?.reject(failure2);
35017
+ reading = void 0;
35018
+ };
35019
+ const abort = () => {
35020
+ near.postMessage({ t: "cancel", reason: String(signal.reason) });
35021
+ end(new Error(String(signal.reason)));
35022
+ };
35023
+ const pull = async () => {
34664
35024
  try {
34665
- head = await this.ask({
34666
- net: "fetch",
34667
- nid,
34668
- url: request3.url,
34669
- method: request3.method,
34670
- headers: request3.headers,
34671
- ...request3.bodyStream ? { streamed: true } : request3.body ? { body: request3.body } : {}
34672
- });
34673
- } catch (e) {
34674
- finish();
34675
- throw e;
35025
+ const next3 = await upload.next();
35026
+ if (ended) return;
35027
+ if (next3.done) near.postMessage({ t: "end" });
35028
+ else sendBytes(near, next3.value);
35029
+ } catch (err) {
35030
+ if (!ended) near.postMessage({ t: "error", message: textOf(err) });
34676
35031
  }
34677
- const { status, statusText, headers, url, redirected: redirected2, redirects } = head;
34678
- const read = async () => {
34679
- if (finished) return void 0;
34680
- const reply = await this.ask({ net: "read", nid }).catch((e) => {
34681
- finish();
34682
- throw e;
34683
- });
34684
- if (reply.net === "chunk") return reply.bytes;
34685
- finish();
34686
- return void 0;
35032
+ };
35033
+ const respond2 = (message3) => {
35034
+ const { status, statusText, headers, url } = message3;
35035
+ const body = {
35036
+ [Symbol.asyncIterator]: () => ({
35037
+ next: () => {
35038
+ if (ended) return Promise.resolve({ value: void 0, done: true });
35039
+ reading = Promise.withResolvers();
35040
+ near.postMessage({ t: "read" });
35041
+ return reading.promise;
35042
+ },
35043
+ return: async () => {
35044
+ await cancel();
35045
+ return { value: void 0, done: true };
35046
+ }
35047
+ })
34687
35048
  };
34688
35049
  const cancel = async () => {
34689
- if (finished) return;
34690
- finish();
34691
- this.cancel(nid);
35050
+ if (ended) return;
35051
+ near.postMessage({ t: "cancel", reason: "cancelled" });
35052
+ end(new Error("the request was cancelled"));
34692
35053
  };
34693
- return {
34694
- ...redirected2 ? { url, redirected: redirected2 } : {},
34695
- ...redirects ? { redirects } : {},
35054
+ head.resolve({
35055
+ ...url !== void 0 ? { url } : {},
34696
35056
  status,
34697
35057
  statusText,
34698
35058
  headers,
34699
- cancel,
34700
- body: {
34701
- [Symbol.asyncIterator]: () => ({
34702
- next: async () => {
34703
- const bytes = await read();
34704
- return bytes ? { value: bytes, done: false } : { value: void 0, done: true };
34705
- },
34706
- return: async () => {
34707
- await cancel();
34708
- return { value: void 0, done: true };
34709
- }
34710
- })
34711
- }
34712
- };
34713
- }
34714
- async websocket(request3) {
34715
- const nid = ++this.nextId;
34716
- const { signal } = request3;
34717
- signal.throwIfAborted();
34718
- const abort = () => this.cancel(nid);
34719
- signal.addEventListener("abort", abort, { once: true });
34720
- let opened2;
34721
- try {
34722
- opened2 = await this.ask({
34723
- net: "ws-open",
34724
- nid,
34725
- url: request3.url,
34726
- protocols: request3.protocols,
34727
- headers: request3.headers
34728
- });
34729
- } finally {
34730
- signal.removeEventListener("abort", abort);
34731
- }
34732
- const close = (code, reason) => this.port.postMessage({ net: "ws-close", nid, code, reason });
34733
- const queue = new MessageQueue(
34734
- () => close(1e3, "a message is too big"),
34735
- Number.POSITIVE_INFINITY,
34736
- (n) => this.port.postMessage({ net: "ws-consumed", nid, n })
34737
- );
34738
- let unacked = 0;
34739
- this.sockets.set(nid, { queue, acked: (n) => void (unacked -= n) });
34740
- return {
34741
- protocol: opened2.protocol,
34742
- get buffered() {
34743
- return unacked;
34744
- },
34745
- send: (data) => {
34746
- unacked += payloadSize(data);
34747
- this.port.postMessage({ net: "ws-send", nid, data });
34748
- },
34749
- messages: queue,
34750
- close,
34751
- closed: queue.closed
34752
- };
34753
- }
34754
- };
34755
-
34756
- // src/sealed-relay.ts
35059
+ body,
35060
+ cancel
35061
+ });
35062
+ };
35063
+ near.addEventListener("message", ({ data }) => {
35064
+ if (data.t === "pull") void pull();
35065
+ else if (data.t === "stop") void upload?.return?.().catch(() => void 0);
35066
+ else if (data.t === "head") respond2(data);
35067
+ else if (data.t === "chunk") {
35068
+ reading?.resolve({ value: data.bytes, done: false });
35069
+ reading = void 0;
35070
+ } else if (data.t === "end") {
35071
+ reading?.resolve({ value: void 0, done: true });
35072
+ reading = void 0;
35073
+ end(new Error("the response ended"));
35074
+ } else end(new Error(data.message));
35075
+ });
35076
+ near.addEventListener("close", () => end(new Error("the sealed fetch relay closed")));
35077
+ near.start();
35078
+ signal.addEventListener("abort", abort, { once: true });
35079
+ const ask = {
35080
+ req: { ...wire, ...upload ? { streamed: true } : {} },
35081
+ port: far
35082
+ };
35083
+ port.postMessage({ sealedFetch: ask }, [far]);
35084
+ return head.promise;
35085
+ }
34757
35086
  function sealedAsker(port) {
34758
35087
  const asks = /* @__PURE__ */ new Map();
34759
35088
  let next3 = 0;
@@ -34777,7 +35106,7 @@ function sealedAsker(port) {
34777
35106
  if (reply) waiting.resolve(reply);
34778
35107
  else waiting.reject(new Error(error ?? "no reply"));
34779
35108
  };
34780
- return { hook, answer: answer2 };
35109
+ return { hook, fetch: (req, { signal }) => askFetch(port, req, signal), answer: answer2 };
34781
35110
  }
34782
35111
 
34783
35112
  // src/serve.ts
@@ -34935,13 +35264,15 @@ function transferOf2(req, result) {
34935
35264
  if (result instanceof MessagePort) return [result];
34936
35265
  const bound3 = result?.port;
34937
35266
  if (req.op === "connect" && bound3 instanceof MessagePort) return [bound3];
34938
- if (req.op === "attest") return [result.bytes.buffer];
35267
+ if (req.op === "attest" && "bytes" in result) {
35268
+ return [result.bytes.buffer];
35269
+ }
34939
35270
  return void 0;
34940
35271
  }
34941
35272
  function attestOps(port) {
34942
35273
  const watches = /* @__PURE__ */ new Map();
34943
35274
  return async (l, req) => {
34944
- if (req.op === "attest") return l.attest(req.path);
35275
+ if (req.op === "attest") return l.attest(req.path, req.options);
34945
35276
  if (req.op === "chmod") return l.fs.chmod(req.path, modeOption(req.mode)).then(() => true);
34946
35277
  if (req.op === "integrity-revoke") return l.revokeIntegrity(req.path).then(() => true);
34947
35278
  if (req.op === "unwatch-files") {
@@ -34996,7 +35327,7 @@ async function connectClient(deps, { user, tag, bind: bind2 }) {
34996
35327
  });
34997
35328
  return unbind ? { port: port2, client } : port2;
34998
35329
  }
34999
- function hostOptions(req, port, sealed, clipboard, lookup2, requests) {
35330
+ function hostOptions(req, port, sealed, sealedFetch, clipboard, lookup2, requests) {
35000
35331
  return {
35001
35332
  cron: { lock: `slicc-kernel-cron:${req.metadata ?? META_DB}` },
35002
35333
  ...req.hostname !== void 0 ? { hostname: req.hostname } : {},
@@ -35005,6 +35336,7 @@ function hostOptions(req, port, sealed, clipboard, lookup2, requests) {
35005
35336
  ...req.denials ? { onDenial: (denial) => port.postMessage({ denial }) } : {},
35006
35337
  ...req.protect ? { protect: hostProtect(req.protect, lookup2) } : {},
35007
35338
  ...req.sealed ? { sealed } : {},
35339
+ ...req.sealedFetch ? { sealedFetch } : {},
35008
35340
  ...req.clipboard ? { clipboard } : {},
35009
35341
  ...req.requests ? { embedder: requests.hookFor(0, req.requests) } : {}
35010
35342
  };
@@ -35095,7 +35427,15 @@ function serveKernel(port, deps) {
35095
35427
  ...req.modules ? { modules: req.modules } : {},
35096
35428
  ...req.commands ? { commands: req.commands } : {},
35097
35429
  ...req.env ? { env: req.env } : {},
35098
- ...hostOptions(req, port, sealed.hook, clipboard.hook, integrity.lookup, requests),
35430
+ ...hostOptions(
35431
+ req,
35432
+ port,
35433
+ sealed.hook,
35434
+ sealed.fetch,
35435
+ clipboard.hook,
35436
+ integrity.lookup,
35437
+ requests
35438
+ ),
35099
35439
  ...req.approve ? { approve: approvals.ask } : {},
35100
35440
  ...net,
35101
35441
  ...media ? { media } : {},
@@ -35122,6 +35462,7 @@ function serveKernel(port, deps) {
35122
35462
  async function handle(req) {
35123
35463
  if (req.op === "init") return init(req);
35124
35464
  if (isAttestRequest(req)) return attestOp(await ready2(), req);
35465
+ if (req.op === "sealed-placeholders") return (await ready2()).setPlaceholders(req.list);
35125
35466
  if (req.op === "open-terminal") return terminal(req);
35126
35467
  if (req.op === "connect") return connect2(req.user, req.tag, req.requests);
35127
35468
  if (isUsersRequest(req)) return usersOp(await ready2(), req);