@ai-ecoverse/slicc-kernel 1.136.8 → 1.137.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.js CHANGED
@@ -1319,6 +1319,15 @@ function isHostname(name2) {
1319
1319
  function ownNames(hostname) {
1320
1320
  return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
1321
1321
  }
1322
+ function hostsFile(hostname = DEFAULT_HOSTNAME) {
1323
+ return [
1324
+ "127.0.0.1 localhost localhost.localdomain",
1325
+ "::1 localhost ip6-localhost",
1326
+ `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(" ")}`,
1327
+ `${HOST_LOOPBACK_ADDRESS.join(".")} ${HOST_LOOPBACK}`,
1328
+ ""
1329
+ ].join("\n");
1330
+ }
1322
1331
 
1323
1332
  // src/kernel/net/routes.ts
1324
1333
  var HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join(".");
@@ -2003,6 +2012,7 @@ var LOCAL_ONLY = new Routes();
2003
2012
  var LoopbackNet = class {
2004
2013
  bound = /* @__PURE__ */ new Map();
2005
2014
  dgrams = /* @__PURE__ */ new Map();
2015
+ dgramServices = /* @__PURE__ */ new Map();
2006
2016
  unixDgrams = /* @__PURE__ */ new Map();
2007
2017
  activators = /* @__PURE__ */ new Map();
2008
2018
  internal = /* @__PURE__ */ new Set();
@@ -2053,9 +2063,16 @@ var LoopbackNet = class {
2053
2063
  releaseDgram(addr, socket) {
2054
2064
  if (this.dgrams.get(addr.port) === socket) this.dgrams.delete(addr.port);
2055
2065
  }
2056
- deliverDgram(port, datagram2) {
2066
+ serveDgram(port, serve) {
2067
+ this.dgramServices.set(port, serve);
2068
+ }
2069
+ deliverDgram(port, datagram2, to) {
2057
2070
  const target = this.dgrams.get(port);
2058
- return target ? target.deliver(datagram2) : false;
2071
+ if (target) return target.deliver(datagram2);
2072
+ const service = this.dgramServices.get(port);
2073
+ if (!service) return false;
2074
+ service(datagram2, to ?? { family: "inet", host: "127.0.0.1", port });
2075
+ return true;
2059
2076
  }
2060
2077
  bindable(addr, kernel) {
2061
2078
  if (addr.host !== "0.0.0.0" && !isLoopback(addr.host)) {
@@ -5684,8 +5701,8 @@ var OpfsFs = class {
5684
5701
  renamingDirs = /* @__PURE__ */ new Set();
5685
5702
  intents = 0;
5686
5703
  async intend(rename, at = `${RENAMES}/${crypto.randomUUID()}`) {
5687
- const record = { ...rename, at: Date.now() * 1e3 + this.intents++ % 1e3 };
5688
- await this.meta.update(at, () => ({ path: at, rename: record }));
5704
+ const record2 = { ...rename, at: Date.now() * 1e3 + this.intents++ % 1e3 };
5705
+ await this.meta.update(at, () => ({ path: at, rename: record2 }));
5689
5706
  return at;
5690
5707
  }
5691
5708
  async rollBack(from, to, intents) {
@@ -7486,7 +7503,7 @@ function satisfies(version, range2) {
7486
7503
  }
7487
7504
 
7488
7505
  // src/version.ts
7489
- var KERNEL_VERSION = true ? "1.136.8" : "0.0.0-dev";
7506
+ var KERNEL_VERSION = true ? "1.137.0" : "0.0.0-dev";
7490
7507
  var OS_RELEASE = "6.0.0-slicc";
7491
7508
  function procVersion() {
7492
7509
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -8626,11 +8643,11 @@ var CronService = class {
8626
8643
  }
8627
8644
  if (this.stopping.signal.aborted) return;
8628
8645
  const exit = ended.signal ? `signal=${ended.signal}` : `exit=${ended.status}`;
8629
- const header4 = encoder.encode(`--- ${iso} ${exit} missed=${missed} ---
8646
+ const header5 = encoder.encode(`--- ${iso} ${exit} missed=${missed} ---
8630
8647
  `);
8631
8648
  const body = output.bytes();
8632
8649
  const newline = body.length > 0 && body[body.length - 1] !== 10 ? encoder.encode("\n") : new Uint8Array();
8633
- await this.append(log, concat2([header4, body, newline]), account.uid, account.gid).catch(
8650
+ await this.append(log, concat2([header5, body, newline]), account.uid, account.gid).catch(
8634
8651
  (err) => this.error(messageOf(err))
8635
8652
  );
8636
8653
  }
@@ -9438,8 +9455,8 @@ var FileWatches = class {
9438
9455
  live = /* @__PURE__ */ new Set();
9439
9456
  local;
9440
9457
  remote;
9441
- constructor(local, remote) {
9442
- this.local = local;
9458
+ constructor(local2, remote) {
9459
+ this.local = local2;
9443
9460
  this.remote = remote;
9444
9461
  }
9445
9462
  announce() {
@@ -13159,18 +13176,18 @@ var SAB_I_ASYNC = 14;
13159
13176
  var SAB_I_STOP = 15;
13160
13177
  var SAB_I_BLOCKED = 16;
13161
13178
  var SAB_I_BLOCKED_HI = 17;
13162
- function loadBlocked(header4) {
13163
- return [Atomics.load(header4, SAB_I_BLOCKED), Atomics.load(header4, SAB_I_BLOCKED_HI)];
13179
+ function loadBlocked(header5) {
13180
+ return [Atomics.load(header5, SAB_I_BLOCKED), Atomics.load(header5, SAB_I_BLOCKED_HI)];
13164
13181
  }
13165
- function storeBlocked(header4, [low, high]) {
13166
- Atomics.store(header4, SAB_I_BLOCKED_HI, high);
13167
- Atomics.store(header4, SAB_I_BLOCKED, low);
13182
+ function storeBlocked(header5, [low, high]) {
13183
+ Atomics.store(header5, SAB_I_BLOCKED_HI, high);
13184
+ Atomics.store(header5, SAB_I_BLOCKED, low);
13168
13185
  }
13169
13186
  var anyBlocked = (mask) => mask !== void 0 && (mask[0] !== 0 || mask[1] !== 0);
13170
13187
  var U32 = 2 ** 32;
13171
- function storeU53(header4, lo, hi, value2) {
13172
- Atomics.store(header4, hi, Math.floor(value2 / U32));
13173
- Atomics.store(header4, lo, value2 % U32 | 0);
13188
+ function storeU53(header5, lo, hi, value2) {
13189
+ Atomics.store(header5, hi, Math.floor(value2 / U32));
13190
+ Atomics.store(header5, lo, value2 % U32 | 0);
13174
13191
  }
13175
13192
  var SAB_STATE_READY = 2;
13176
13193
  var SAB_STATUS_BYTES = 1;
@@ -13219,7 +13236,7 @@ function sabViews(sab) {
13219
13236
  var PENDING_TTL_MS = SYNC_FS_REQUEST_TIMEOUT_MS + 5e3;
13220
13237
  function attachSyncSabResponder(port, sab, token, opts) {
13221
13238
  const views = sabViews(sab);
13222
- const { header: header4, window } = views;
13239
+ const { header: header5, window } = views;
13223
13240
  const pending = /* @__PURE__ */ new Map();
13224
13241
  let disposed = false;
13225
13242
  const { dispatch: dispatch2 } = opts;
@@ -13230,20 +13247,20 @@ function attachSyncSabResponder(port, sab, token, opts) {
13230
13247
  pending.delete(id2);
13231
13248
  }
13232
13249
  function publish(id2, entry, offset) {
13233
- if (Atomics.load(header4, SAB_I_REQ) !== id2) {
13250
+ if (Atomics.load(header5, SAB_I_REQ) !== id2) {
13234
13251
  drop(id2);
13235
13252
  return;
13236
13253
  }
13237
13254
  const chunk2 = Math.min(window.byteLength, entry.payload.byteLength - offset);
13238
13255
  if (chunk2 > 0) window.set(entry.payload.subarray(offset, offset + chunk2));
13239
- Atomics.store(header4, SAB_I_STATUS, entry.status);
13240
- storeU53(header4, SAB_I_TOTAL, SAB_I_TOTAL_HI, entry.payload.byteLength);
13241
- Atomics.store(header4, SAB_I_CHUNK, chunk2);
13242
- storeU53(header4, SAB_I_OFFSET, SAB_I_OFFSET_HI, offset);
13243
- Atomics.store(header4, SAB_I_SEQ, id2);
13244
- Atomics.store(header4, SAB_I_STATE, SAB_STATE_READY);
13245
- Atomics.add(header4, SAB_I_PUB, 1);
13246
- Atomics.notify(header4, SAB_I_PUB);
13256
+ Atomics.store(header5, SAB_I_STATUS, entry.status);
13257
+ storeU53(header5, SAB_I_TOTAL, SAB_I_TOTAL_HI, entry.payload.byteLength);
13258
+ Atomics.store(header5, SAB_I_CHUNK, chunk2);
13259
+ storeU53(header5, SAB_I_OFFSET, SAB_I_OFFSET_HI, offset);
13260
+ Atomics.store(header5, SAB_I_SEQ, id2);
13261
+ Atomics.store(header5, SAB_I_STATE, SAB_STATE_READY);
13262
+ Atomics.add(header5, SAB_I_PUB, 1);
13263
+ Atomics.notify(header5, SAB_I_PUB);
13247
13264
  if (offset + chunk2 >= entry.payload.byteLength) drop(id2);
13248
13265
  else if (entry.timer) {
13249
13266
  clearTimeout(entry.timer);
@@ -13458,6 +13475,15 @@ var ProcessClocks = class {
13458
13475
  }
13459
13476
  };
13460
13477
 
13478
+ // src/kernel/proc-info.ts
13479
+ function mayTrace(viewer, target) {
13480
+ const by = viewer?.cred;
13481
+ const of = target.cred;
13482
+ if (!by || !of || by.euid === 0) return true;
13483
+ const uid = of.ruid === by.euid && of.euid === by.euid && of.suid === by.euid;
13484
+ return uid && of.rgid === by.egid && of.egid === by.egid && of.sgid === by.egid;
13485
+ }
13486
+
13461
13487
  // src/fs/pages.ts
13462
13488
  var PAGE = 64 * 1024;
13463
13489
  var READAHEAD = 1024 * 1024;
@@ -14013,7 +14039,16 @@ var ProcTree = class {
14013
14039
  if (!/^[1-9]\d*$/.test(top) || !this.alive(Number(top))) return void 0;
14014
14040
  if (leaf === "task") return this.task(Number(top), rest2);
14015
14041
  if (rest2.length > 0) return void 0;
14016
- if (leaf === void 0) return { kind: "dir", names: () => [...PID_NAMES, "task"] };
14042
+ if (leaf === void 0) {
14043
+ const exe = () => this.info(Number(top))?.exe === void 0 ? [] : ["exe"];
14044
+ return { kind: "dir", names: () => [...PID_NAMES, ...exe(), "task"] };
14045
+ }
14046
+ if (leaf === "exe") {
14047
+ const info = this.info(Number(top));
14048
+ if (info?.exe === void 0) return void 0;
14049
+ const denied2 = !mayTrace(this.ownInfo(), info);
14050
+ return { kind: "link", target: info.exe, ...denied2 ? { denied: denied2 } : {} };
14051
+ }
14017
14052
  if (!PID_NAMES.includes(leaf)) return void 0;
14018
14053
  return {
14019
14054
  kind: "file",
@@ -14025,6 +14060,10 @@ var ProcTree = class {
14025
14060
  }
14026
14061
  };
14027
14062
  }
14063
+ ownInfo() {
14064
+ const processes2 = this.listing().processes;
14065
+ return processes2.find((p) => p.tid === this.pid) ?? processes2.find((p) => p.pid === this.pid);
14066
+ }
14028
14067
  info(pid) {
14029
14068
  return this.listing().processes.find((p) => p.pid === pid);
14030
14069
  }
@@ -14088,6 +14127,7 @@ var ProcTree = class {
14088
14127
  readlink(path) {
14089
14128
  const node = this.find(path, false);
14090
14129
  if (node.kind !== "link") throw syncError("EINVAL", path);
14130
+ if (node.denied) throw syncError("EACCES", path);
14091
14131
  return node.target;
14092
14132
  }
14093
14133
  exists(path) {
@@ -15492,8 +15532,8 @@ function sameCert(a, b) {
15492
15532
  if (!a || !b) return a === b;
15493
15533
  return a.cert.length === b.cert.length && a.cert.every((byte, i) => byte === b.cert[i]);
15494
15534
  }
15495
- function winner(current, expected, record) {
15496
- return sameCert(current, expected) ? record : current;
15535
+ function winner(current, expected, record2) {
15536
+ return sameCert(current, expected) ? record2 : current;
15497
15537
  }
15498
15538
  var DAY = 24 * 60 * 60 * 1e3;
15499
15539
  var CA_LIFETIME = 3650 * DAY;
@@ -15510,14 +15550,14 @@ function validLeafName(host) {
15510
15550
  }
15511
15551
  var RealmCa = class _RealmCa {
15512
15552
  record;
15513
- constructor(record) {
15514
- this.record = record;
15553
+ constructor(record2) {
15554
+ this.record = record2;
15515
15555
  }
15516
15556
  static async open(owner, store, now = Date.now()) {
15517
15557
  const stored = await store.get(owner).catch(() => void 0);
15518
15558
  if (stored && stored.notAfter - now > CA_RENEW_BEFORE) return new _RealmCa(stored);
15519
- const record = await _RealmCa.create(owner, now);
15520
- return new _RealmCa(await store.swap(owner, stored, record));
15559
+ const record2 = await _RealmCa.create(owner, now);
15560
+ return new _RealmCa(await store.swap(owner, stored, record2));
15521
15561
  }
15522
15562
  static async create(owner, now) {
15523
15563
  const pair = await crypto.subtle.generateKey(ECDSA, false, ["sign", "verify"]);
@@ -16047,8 +16087,8 @@ function memoryCaStore() {
16047
16087
  const records = /* @__PURE__ */ new Map();
16048
16088
  return {
16049
16089
  get: async (owner) => records.get(owner),
16050
- swap: async (owner, expected, record) => {
16051
- const kept = winner(records.get(owner), expected, record);
16090
+ swap: async (owner, expected, record2) => {
16091
+ const kept = winner(records.get(owner), expected, record2);
16052
16092
  records.set(owner, kept);
16053
16093
  return kept;
16054
16094
  }
@@ -16175,10 +16215,10 @@ var WsHandles = class {
16175
16215
  open = /* @__PURE__ */ new Map();
16176
16216
  next;
16177
16217
  local;
16178
- constructor(transport, next3, local) {
16218
+ constructor(transport, next3, local2) {
16179
16219
  this.transport = transport;
16180
16220
  this.next = next3;
16181
- this.local = local;
16221
+ this.local = local2;
16182
16222
  }
16183
16223
  owns(handle) {
16184
16224
  return this.open.has(handle);
@@ -16207,8 +16247,8 @@ var WsHandles = class {
16207
16247
  return { ok: true, kind: "json", json: handle };
16208
16248
  }
16209
16249
  async connect(handle, req, entry) {
16210
- const { transport, local } = this;
16211
- const port = local?.port(req.url);
16250
+ const { transport, local: local2 } = this;
16251
+ const port = local2?.port(req.url);
16212
16252
  const open = { protocols: req.protocols, headers: req.headers, signal: entry.abort.signal };
16213
16253
  if (port === void 0 && (!transport.traits.websocket || !transport.websocket)) {
16214
16254
  return fail("ENOTSUP", NO_WEBSOCKET2);
@@ -16218,7 +16258,7 @@ var WsHandles = class {
16218
16258
  socket = port === void 0 ? await transport.websocket({
16219
16259
  url: toHostLoopback(req.url),
16220
16260
  ...open
16221
- }) : await local.websocket({ url: req.url, ...open }, port);
16261
+ }) : await local2.websocket({ url: req.url, ...open }, port);
16222
16262
  } catch (e) {
16223
16263
  return fail(errnoOf(e), message(e));
16224
16264
  }
@@ -16349,11 +16389,11 @@ var HttpHandles = class {
16349
16389
  ws;
16350
16390
  owner;
16351
16391
  local;
16352
- constructor(transport, owner, local) {
16392
+ constructor(transport, owner, local2) {
16353
16393
  this.transport = transport;
16354
16394
  this.owner = owner;
16355
- this.local = local;
16356
- this.ws = new WsHandles(transport, () => ++this.nextHandle, local);
16395
+ this.local = local2;
16396
+ this.ws = new WsHandles(transport, () => ++this.nextHandle, local2);
16357
16397
  }
16358
16398
  syscall(req) {
16359
16399
  if (req.op.startsWith("net-ws-")) return this.ws.syscall(req);
@@ -16505,6 +16545,43 @@ var HttpHandles = class {
16505
16545
  }
16506
16546
  };
16507
16547
 
16548
+ // src/kernel/net/hosts-file.ts
16549
+ var HOSTS_PATH = "/etc/hosts";
16550
+ function parseHosts(text) {
16551
+ const table = /* @__PURE__ */ new Map();
16552
+ for (const raw2 of text.split("\n")) {
16553
+ const [address, ...names2] = raw2.replace(/#.*/, "").trim().split(/\s+/);
16554
+ if (!address || names2.length === 0) continue;
16555
+ if (ipv4Bytes(address) === void 0 && ipv6Groups(address) === void 0) continue;
16556
+ for (const name2 of names2) {
16557
+ const key = name2.toLowerCase().replace(/\.$/, "");
16558
+ const known = table.get(key) ?? [];
16559
+ if (!known.includes(address)) known.push(address);
16560
+ table.set(key, known);
16561
+ }
16562
+ }
16563
+ return table;
16564
+ }
16565
+ function hostsReader(fs, path = HOSTS_PATH) {
16566
+ let stamp = "";
16567
+ let table;
16568
+ return async () => {
16569
+ const st = await fs.stat(path).catch(() => void 0);
16570
+ if (!st?.isFile) {
16571
+ stamp = "";
16572
+ table = void 0;
16573
+ return void 0;
16574
+ }
16575
+ const now = `${st.ino}:${st.size}:${st.mtime.getTime()}`;
16576
+ if (now === stamp && table) return table;
16577
+ const text = await fs.readFile(path).catch(() => void 0);
16578
+ if (text === void 0) return void 0;
16579
+ stamp = now;
16580
+ table = parseHosts(text);
16581
+ return table;
16582
+ };
16583
+ }
16584
+
16508
16585
  // src/kernel/net/uplink.ts
16509
16586
  function carriesUdp(uplink) {
16510
16587
  return uplink.traits.udp === true && typeof uplink.udp === "function";
@@ -16540,6 +16617,7 @@ var Resolver = class {
16540
16617
  timeoutMs;
16541
16618
  log;
16542
16619
  own;
16620
+ builtin;
16543
16621
  cache = /* @__PURE__ */ new Map();
16544
16622
  pending = /* @__PURE__ */ new Map();
16545
16623
  hosts;
@@ -16550,6 +16628,7 @@ var Resolver = class {
16550
16628
  this.timeoutMs = options.timeoutMs ?? RESOLVE_TIMEOUT_MS;
16551
16629
  this.log = options.log ?? ((message3) => console.warn(message3));
16552
16630
  this.own = ownNames(options.hostname ?? DEFAULT_HOSTNAME);
16631
+ this.builtin = parseHosts(hostsFile(options.hostname ?? DEFAULT_HOSTNAME));
16553
16632
  this.hosts = options.hosts;
16554
16633
  }
16555
16634
  async fromFile(key, family) {
@@ -16559,18 +16638,34 @@ var Resolver = class {
16559
16638
  const v6 = listed.filter((a) => ipv4Bytes(a) === void 0);
16560
16639
  return family === 4 ? v4 : family === 6 ? v6 : [...v4, ...v6];
16561
16640
  }
16641
+ async known(name2) {
16642
+ const key = name2.toLowerCase().replace(/\.$/, "");
16643
+ if (ipv4Bytes(key) || ipv6Groups(key)) return false;
16644
+ if (hostsEntry(key, this.own) !== void 0) return true;
16645
+ return ((await this.hosts?.().catch(() => void 0))?.get(key)?.length ?? 0) > 0;
16646
+ }
16647
+ async reverse(address) {
16648
+ const v6 = ipv6Groups(address)?.join(":");
16649
+ const same2 = (a) => a === address || v6 !== void 0 && ipv6Groups(a)?.join(":") === v6;
16650
+ const file = await this.hosts?.().catch(() => void 0);
16651
+ for (const table of [file, this.builtin]) {
16652
+ for (const [name2, addresses] of table ?? []) if (addresses.some(same2)) return name2;
16653
+ }
16654
+ if (ipv4Bytes(address)?.[0] === 127) return "localhost";
16655
+ return void 0;
16656
+ }
16562
16657
  async resolve(name2, family, blocking) {
16563
16658
  const key = name2.toLowerCase().replace(/\.$/, "");
16564
- const local = hostsEntry(key, this.own);
16659
+ const local2 = hostsEntry(key, this.own);
16565
16660
  if (ipv6Groups(key)) {
16566
- const v4 = family !== 6 && local ? [local] : [];
16661
+ const v4 = family !== 6 && local2 ? [local2] : [];
16567
16662
  return family === 4 ? v4 : [...v4, key];
16568
16663
  }
16569
16664
  const listed = this.hosts ? await this.fromFile(key, family) : void 0;
16570
16665
  if (listed?.length) return listed;
16571
- if (local) {
16666
+ if (local2) {
16572
16667
  const six = loopbackName(key, this.own) ? ["::1"] : [];
16573
- return family === 6 ? six : family === 4 ? [local] : [local, ...six];
16668
+ return family === 6 ? six : family === 4 ? [local2] : [local2, ...six];
16574
16669
  }
16575
16670
  if (!this.uplink || key === "") return [];
16576
16671
  const asked = this.uplink.traits.ipv6 ? family : 4;
@@ -17609,14 +17704,15 @@ var KernelDgram = class {
17609
17704
  const max = familyOf(target.host) === 6 ? MAX_DATAGRAM_V6 : MAX_DATAGRAM_V4;
17610
17705
  if (bytes.length > max) throw new KernelError("EMSGSIZE");
17611
17706
  const where = this.route(target.host);
17612
- const local = this.bound();
17707
+ const local2 = this.bound();
17613
17708
  if (where === "uplink") return this.sendUp(bytes, target);
17614
17709
  const from = {
17615
17710
  family: "inet",
17616
- host: local.host === "0.0.0.0" ? "127.0.0.1" : local.host,
17617
- port: local.port
17711
+ host: local2.host === "0.0.0.0" ? "127.0.0.1" : local2.host,
17712
+ port: local2.port
17618
17713
  };
17619
- const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from });
17714
+ const dest = { family: "inet", host: canonicalHost(target.host), port: target.port };
17715
+ const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from }, dest);
17620
17716
  if (!delivered && this.peer && sameAddr(this.peer, target)) {
17621
17717
  this.pending = "ECONNREFUSED";
17622
17718
  this.changes.wake();
@@ -19213,8 +19309,8 @@ function clientFirstOf(message3) {
19213
19309
  return m ? { header: m[1], bare: m[2] } : void 0;
19214
19310
  }
19215
19311
  var latinBytes = (text) => Uint8Array.from(text, (c) => c.charCodeAt(0));
19216
- function channelOf(header4, binding) {
19217
- const head = latinBytes(header4);
19312
+ function channelOf(header5, binding) {
19313
+ const head = latinBytes(header5);
19218
19314
  const all = new Uint8Array(head.length + (binding?.length ?? 0));
19219
19315
  all.set(head);
19220
19316
  if (binding) all.set(binding, head.length);
@@ -19336,6 +19432,7 @@ function latin2(bytes) {
19336
19432
  var PgServer = class {
19337
19433
  binding;
19338
19434
  plus = false;
19435
+ touch;
19339
19436
  constructor(binding) {
19340
19437
  this.binding = binding;
19341
19438
  }
@@ -19357,6 +19454,7 @@ var PgServer = class {
19357
19454
  return message3;
19358
19455
  }
19359
19456
  mechanisms(message3) {
19457
+ if (this.touch !== true) return message3;
19360
19458
  this.sasl = true;
19361
19459
  const offered = latin2(message3.subarray(9)).split("\0").filter((n) => n !== "");
19362
19460
  this.plus = offered.includes(PLUS);
@@ -19437,8 +19535,8 @@ function frame3(type, body) {
19437
19535
  return out;
19438
19536
  }
19439
19537
  function pgLength(bytes, started) {
19440
- const header4 = started ? 5 : 4;
19441
- if (bytes.length < header4) return void 0;
19538
+ const header5 = started ? 5 : 4;
19539
+ if (bytes.length < header5) return void 0;
19442
19540
  const length2 = int32(bytes, started ? 1 : 0);
19443
19541
  return started ? 1 + length2 : length2;
19444
19542
  }
@@ -19466,16 +19564,16 @@ function initial(message3) {
19466
19564
  function int32Text(n) {
19467
19565
  return String.fromCharCode(n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255);
19468
19566
  }
19469
- function serverHeader(header4, server) {
19470
- if (header4 === "n,,") return header4;
19471
- if (header4 === "y,," && !server.plus) return header4;
19472
- if (header4 === END_POINT && server.binding) return header4;
19567
+ function serverHeader(header5, server) {
19568
+ if (header5 === "n,,") return header5;
19569
+ if (header5 === "y,," && !server.plus) return header5;
19570
+ if (header5 === END_POINT && server.binding) return header5;
19473
19571
  return server.plus && server.binding ? END_POINT : "n,,";
19474
19572
  }
19475
- function rewritten(first, header4) {
19573
+ function rewritten(first, header5) {
19476
19574
  const parsed2 = clientFirstOf(first.data);
19477
- if (!parsed2 || parsed2.header === header4) return first;
19478
- return { mechanism: header4 === END_POINT ? PLUS : PLAIN, data: `${header4}${parsed2.bare}` };
19575
+ if (!parsed2 || parsed2.header === header5) return first;
19576
+ return { mechanism: header5 === END_POINT ? PLUS : PLAIN, data: `${header5}${parsed2.bare}` };
19479
19577
  }
19480
19578
  var PgClient = class {
19481
19579
  clientFirst;
@@ -19716,6 +19814,10 @@ var SessionWriter = class {
19716
19814
  this.proven ??= this.prove(protocol).catch(() => void 0);
19717
19815
  return this.proven;
19718
19816
  }
19817
+ async mayTouch() {
19818
+ if (this.s.verified) return true;
19819
+ return (await this.proof("pg"))?.anchor !== void 0;
19820
+ }
19719
19821
  async prove(protocol) {
19720
19822
  const s = this.s;
19721
19823
  if (s.anchoring) {
@@ -19765,7 +19867,10 @@ var SessionWriter = class {
19765
19867
  this.buffer.fill(0);
19766
19868
  this.buffer = joined4;
19767
19869
  if (this.mode === "sniff") this.mode = modeOf(latin12(joined4.subarray(0, 8))) ?? "sniff";
19768
- if (this.mode === "pg") this.sawPg = true;
19870
+ if (this.mode === "pg" && !this.sawPg) {
19871
+ this.sawPg = true;
19872
+ if (!this.s.verified) void this.proof("pg");
19873
+ }
19769
19874
  if (this.mode === "pass") await this.release();
19770
19875
  else if (this.mode === "http1") await this.http1();
19771
19876
  else if (this.mode === "smtp") await this.lines();
@@ -19945,6 +20050,7 @@ function sealedConn(conn, s) {
19945
20050
  for (; ; ) {
19946
20051
  const bytes = await conn.read();
19947
20052
  if (!bytes) return bytes;
20053
+ if (writer?.sawPg && pg.touch === void 0) pg.touch = await writer.mayTouch();
19948
20054
  const out = writer?.sawPg ? pg.filter(bytes) : bytes;
19949
20055
  if (pg.failed) {
19950
20056
  conn.close();
@@ -20592,8 +20698,8 @@ async function datagram(req, proc) {
20592
20698
  const ready2 = pollFile(dgram).readable;
20593
20699
  if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
20594
20700
  const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
20595
- const { bytes, from, truncated } = got;
20596
- return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated, ...from }) };
20701
+ const { bytes, from, truncated: truncated2 } = got;
20702
+ return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated: truncated2, ...from }) };
20597
20703
  }
20598
20704
  async function unixDatagram(req, dgram, proc) {
20599
20705
  if (req.op === "sock-sendto") {
@@ -20603,11 +20709,11 @@ async function unixDatagram(req, dgram, proc) {
20603
20709
  const ready2 = pollFile(dgram).readable;
20604
20710
  if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
20605
20711
  const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
20606
- const { bytes, from, truncated } = got;
20712
+ const { bytes, from, truncated: truncated2 } = got;
20607
20713
  return {
20608
20714
  ok: true,
20609
20715
  kind: "bytes",
20610
- bytes: encodeReceived({ bytes, truncated, host: from.path, port: 0, unix: true })
20716
+ bytes: encodeReceived({ bytes, truncated: truncated2, host: from.path, port: 0, unix: true })
20611
20717
  };
20612
20718
  }
20613
20719
  function domainOf(socket) {
@@ -23358,9 +23464,9 @@ var JsThreads = class {
23358
23464
  const { control, port } = msg;
23359
23465
  const tid = ++this.last;
23360
23466
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
23361
- const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
23467
+ const header5 = new Int32Array(sab, 0, SAB_HEADER_I32);
23362
23468
  const owned4 = new SharedArrayBuffer(4 * (1 + JS_THREAD_OWNED_FDS));
23363
- if (this.frozen) Atomics.store(header4, SAB_I_STOP, 1);
23469
+ if (this.frozen) Atomics.store(header5, SAB_I_STOP, 1);
23364
23470
  const clock = this.deps.clocks.thread(tid + 1, sab);
23365
23471
  let ended = false;
23366
23472
  const end = (code) => {
@@ -23368,7 +23474,7 @@ var JsThreads = class {
23368
23474
  ended = true;
23369
23475
  this.live.delete(tid);
23370
23476
  this.headers.delete(tid);
23371
- this.deps.wakes.delete(header4);
23477
+ this.deps.wakes.delete(header5);
23372
23478
  for (const [id2, token] of ops) {
23373
23479
  void this.deps.dispatch({ op: "async-cancel", id: id2, token });
23374
23480
  }
@@ -23418,8 +23524,8 @@ var JsThreads = class {
23418
23524
  control.addEventListener("message", onControl);
23419
23525
  control.start();
23420
23526
  this.live.set(tid, end);
23421
- this.headers.set(tid, header4);
23422
- this.deps.wakes.add(header4);
23527
+ this.headers.set(tid, header5);
23528
+ this.deps.wakes.add(header5);
23423
23529
  const init = {
23424
23530
  ...this.deps.init(sab, lane.lane),
23425
23531
  type: JS_THREAD_INIT,
@@ -23439,9 +23545,9 @@ var JsThreads = class {
23439
23545
  }
23440
23546
  stopped(stopped) {
23441
23547
  this.frozen = stopped;
23442
- for (const header4 of this.headers.values()) {
23443
- Atomics.store(header4, SAB_I_STOP, stopped ? 1 : 0);
23444
- Atomics.notify(header4, SAB_I_STOP);
23548
+ for (const header5 of this.headers.values()) {
23549
+ Atomics.store(header5, SAB_I_STOP, stopped ? 1 : 0);
23550
+ Atomics.notify(header5, SAB_I_STOP);
23445
23551
  }
23446
23552
  }
23447
23553
  close() {
@@ -23486,13 +23592,13 @@ var Dying = class {
23486
23592
  hard;
23487
23593
  busy = 0;
23488
23594
  finish;
23489
- start(code, sig, header4, process2, finish) {
23595
+ start(code, sig, header5, process2, finish) {
23490
23596
  if (this.ending) return;
23491
23597
  this.ending = { code, sig };
23492
23598
  this.finish = finish;
23493
23599
  this.hard = setTimeout(finish, KILL_HARD_MS);
23494
23600
  this.arm();
23495
- Atomics.store(header4, SAB_I_KILLED, code);
23601
+ Atomics.store(header5, SAB_I_KILLED, code);
23496
23602
  process2.die();
23497
23603
  }
23498
23604
  serve(req, work) {
@@ -23539,8 +23645,8 @@ function unblockedThread(threads, sig) {
23539
23645
  }
23540
23646
  return void 0;
23541
23647
  }
23542
- function unblocked(header4) {
23543
- return Atomics.load(header4, SAB_I_SIGNALS) & ~Atomics.load(header4, SAB_I_BLOCKED);
23648
+ function unblocked(header5) {
23649
+ return Atomics.load(header5, SAB_I_SIGNALS) & ~Atomics.load(header5, SAB_I_BLOCKED);
23544
23650
  }
23545
23651
  function threadCall(process2, req, cancelled, block) {
23546
23652
  return isWasmSyscall(req) ? process2.syscall(req, cancelled, block) : dispatchSyncFs(req);
@@ -23552,24 +23658,24 @@ function threadCancel(thread) {
23552
23658
  return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
23553
23659
  }
23554
23660
  var asyncFanout = /* @__PURE__ */ new WeakMap();
23555
- function notifiers(header4) {
23661
+ function notifiers(header5) {
23556
23662
  return {
23557
23663
  onPending(sig) {
23558
- Atomics.or(header4, SAB_I_SIGNALS, sigbit(sig));
23559
- Atomics.notify(header4, SAB_I_SIGNALS);
23664
+ Atomics.or(header5, SAB_I_SIGNALS, sigbit(sig));
23665
+ Atomics.notify(header5, SAB_I_SIGNALS);
23560
23666
  },
23561
23667
  onAsync() {
23562
- for (const at of [header4, ...asyncFanout.get(header4) ?? []]) {
23668
+ for (const at of [header5, ...asyncFanout.get(header5) ?? []]) {
23563
23669
  Atomics.add(at, SAB_I_ASYNC, 1);
23564
23670
  Atomics.notify(at, SAB_I_ASYNC);
23565
23671
  }
23566
23672
  }
23567
23673
  };
23568
23674
  }
23569
- function publishStops(process2, header4) {
23675
+ function publishStops(process2, header5) {
23570
23676
  process2.onState((state) => {
23571
- Atomics.store(header4, SAB_I_STOP, state === "stopped" ? 1 : 0);
23572
- Atomics.notify(header4, SAB_I_STOP);
23677
+ Atomics.store(header5, SAB_I_STOP, state === "stopped" ? 1 : 0);
23678
+ Atomics.notify(header5, SAB_I_STOP);
23573
23679
  });
23574
23680
  }
23575
23681
  function transferOf(opts, lane) {
@@ -23661,7 +23767,7 @@ function linksOf(opts) {
23661
23767
  function clipboardName(opts) {
23662
23768
  return opts.program.abi === "js" ? {} : { clipboardName: opts.argv0 };
23663
23769
  }
23664
- function processOptions(opts, header4, hooks, created4) {
23770
+ function processOptions(opts, header5, hooks, created4) {
23665
23771
  return {
23666
23772
  ...inherited(opts),
23667
23773
  ...opts.owners ? { owners: true } : {},
@@ -23700,16 +23806,16 @@ function processOptions(opts, header4, hooks, created4) {
23700
23806
  watches: opts.watches,
23701
23807
  onReap: opts.onReap,
23702
23808
  resolver: opts.resolver,
23703
- ...notifiers(header4),
23704
- onTimer: (which) => void Atomics.or(header4, SAB_I_TIMERS, 1 << which),
23705
- hasPending: () => unblocked(header4) !== 0 || Atomics.load(header4, SAB_I_TIMERS) !== 0,
23809
+ ...notifiers(header5),
23810
+ onTimer: (which) => void Atomics.or(header5, SAB_I_TIMERS, 1 << which),
23811
+ hasPending: () => unblocked(header5) !== 0 || Atomics.load(header5, SAB_I_TIMERS) !== 0,
23706
23812
  raise: hooks.raise,
23707
23813
  threadKill: hooks.threadKill,
23708
23814
  unblockedThread: hooks.unblockedThread,
23709
23815
  ...hooks.exitNow ? { exitNow: hooks.exitNow } : {},
23710
23816
  ...hooks.exitSignal ? { exitSignal: hooks.exitSignal } : {},
23711
- ...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header4, SAB_I_SIGNALS) } : {},
23712
- ...opts.program.abi === "wasi" ? { blockedBits: () => Atomics.load(header4, SAB_I_BLOCKED) } : {}
23817
+ ...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header5, SAB_I_SIGNALS) } : {},
23818
+ ...opts.program.abi === "wasi" ? { blockedBits: () => Atomics.load(header5, SAB_I_BLOCKED) } : {}
23713
23819
  };
23714
23820
  }
23715
23821
  function threadInit(opts, program, sab, cred, thread, main) {
@@ -23775,9 +23881,9 @@ async function crashReport(process2, onError, message3) {
23775
23881
  function spawnWasmProcess(opts) {
23776
23882
  const { promise: ready2, resolve: started } = readiness(opts.program.abi);
23777
23883
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
23778
- const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
23884
+ const header5 = new Int32Array(sab, 0, SAB_HEADER_I32);
23779
23885
  const blocked2 = opts.fork?.wasi?.blocked ?? opts.blocked;
23780
- if (blocked2 && anyBlocked(blocked2) && opts.program.abi === "wasi") storeBlocked(header4, blocked2);
23886
+ if (blocked2 && anyBlocked(blocked2) && opts.program.abi === "wasi") storeBlocked(header5, blocked2);
23781
23887
  const threadSignals = /* @__PURE__ */ new Map();
23782
23888
  const created4 = new Created();
23783
23889
  const process2 = new WasmProcess(
@@ -23785,7 +23891,7 @@ function spawnWasmProcess(opts) {
23785
23891
  opts.fds,
23786
23892
  processOptions(
23787
23893
  opts,
23788
- header4,
23894
+ header5,
23789
23895
  {
23790
23896
  raise: (sig, info) => signal(sig, info),
23791
23897
  threadKill: (tid, sig) => killThread(threadSignals.get(tid), process2.signalMasks().caught, sig),
@@ -23798,7 +23904,7 @@ function spawnWasmProcess(opts) {
23798
23904
  created4
23799
23905
  )
23800
23906
  );
23801
- publishStops(process2, header4);
23907
+ publishStops(process2, header5);
23802
23908
  const holds2 = new HeldPaths();
23803
23909
  opts.held?.add(holds2);
23804
23910
  const token = holdingToken(opts, holds2, {
@@ -23819,7 +23925,7 @@ function spawnWasmProcess(opts) {
23819
23925
  dispatch: clocks.timed(void 0, dispatch2)
23820
23926
  });
23821
23927
  const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
23822
- const jsThreads = jsThreadsOf(opts, process2, token, dispatch2, clocks, header4);
23928
+ const jsThreads = jsThreadsOf(opts, process2, token, dispatch2, clocks, header5);
23823
23929
  const { promise: exited, resolve: settle } = Promise.withResolvers();
23824
23930
  let done4 = false;
23825
23931
  const crash = new CrashSlot((message3) => crashReport(process2, opts.onError, message3));
@@ -23918,7 +24024,7 @@ function spawnWasmProcess(opts) {
23918
24024
  );
23919
24025
  const terminate = (code, sig) => {
23920
24026
  if (opts.program.abi !== "wasi" || done4) finish(code, sig);
23921
- else dying.start(code, sig, header4, process2, () => finish(code, sig));
24027
+ else dying.start(code, sig, header5, process2, () => finish(code, sig));
23922
24028
  };
23923
24029
  const signal = (sig, info) => {
23924
24030
  if (process2.signal(sig, info) === "terminate")
@@ -23933,16 +24039,16 @@ function spawnWasmProcess(opts) {
23933
24039
  signal,
23934
24040
  termsig: () => endedBy,
23935
24041
  onState: (listener) => process2.onState(listener),
23936
- memory: () => Atomics.load(header4, SAB_I_MEMORY) * 65536,
23937
- ...processViews(process2, opts, header4),
24042
+ memory: () => Atomics.load(header5, SAB_I_MEMORY) * 65536,
24043
+ ...processViews(process2, opts, header5),
23938
24044
  writesBack: () => opts.program.abi === "wasi" && !done4,
23939
24045
  ...clockViews(clocks)
23940
24046
  };
23941
24047
  }
23942
- function jsThreadsOf(opts, process2, token, dispatch2, clocks, header4) {
24048
+ function jsThreadsOf(opts, process2, token, dispatch2, clocks, header5) {
23943
24049
  if (opts.program.abi !== "js") return void 0;
23944
24050
  const wakes = /* @__PURE__ */ new Set();
23945
- asyncFanout.set(header4, wakes);
24051
+ asyncFanout.set(header5, wakes);
23946
24052
  const threads = new JsThreads({
23947
24053
  wakes,
23948
24054
  cap: jsThreadCap(opts.env),
@@ -23957,10 +24063,10 @@ function jsThreadsOf(opts, process2, token, dispatch2, clocks, header4) {
23957
24063
  process2.onState((state) => threads.stopped(state === "stopped"));
23958
24064
  return threads;
23959
24065
  }
23960
- function processViews(process2, opts, header4) {
24066
+ function processViews(process2, opts, header5) {
23961
24067
  return {
23962
24068
  ignoredSignals: (fork) => process2.inheritable(fork),
23963
- blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header4) : [0, 0],
24069
+ blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header5) : [0, 0],
23964
24070
  signalMasks: () => process2.signalMasks(),
23965
24071
  umask: () => process2.umask,
23966
24072
  cred: () => copyCred(process2.cred)
@@ -24518,42 +24624,398 @@ function isMessage(data) {
24518
24624
  return adopt !== null && Array.isArray(adopt.records) && Array.isArray(adopt.flocks);
24519
24625
  }
24520
24626
 
24521
- // src/kernel/net/hosts-file.ts
24522
- var HOSTS_PATH = "/etc/hosts";
24523
- function parseHosts(text) {
24524
- const table = /* @__PURE__ */ new Map();
24525
- for (const raw2 of text.split("\n")) {
24526
- const [address, ...names2] = raw2.replace(/#.*/, "").trim().split(/\s+/);
24527
- if (!address || names2.length === 0) continue;
24528
- if (ipv4Bytes(address) === void 0 && ipv6Groups(address) === void 0) continue;
24529
- for (const name2 of names2) {
24530
- const key = name2.toLowerCase().replace(/\.$/, "");
24531
- const known = table.get(key) ?? [];
24532
- if (!known.includes(address)) known.push(address);
24533
- table.set(key, known);
24627
+ // src/kernel/net/dns-stub.ts
24628
+ var DNS_PORT = 53;
24629
+ var DNS_STUB_ADDRESS = "127.0.0.53";
24630
+ var RESOLV_CONF_PATH = "/etc/resolv.conf";
24631
+ var RESOLV_CONF = `nameserver ${DNS_STUB_ADDRESS}
24632
+ options edns0
24633
+ `;
24634
+ var DNS_STUB_TTL = 30;
24635
+ var DNS_FORWARD_TIMEOUT_MS = 5e3;
24636
+ var DNS_TCP_IDLE_MS = 1e4;
24637
+ var DNS_TCP_MAX = 64;
24638
+ var DNS_UDP_INFLIGHT = 64;
24639
+ var TYPE_A = 1;
24640
+ var TYPE_PTR = 12;
24641
+ var TYPE_AAAA = 28;
24642
+ var TYPE_OPT = 41;
24643
+ var CLASS_IN = 1;
24644
+ var NOERROR = 0;
24645
+ var FORMERR = 1;
24646
+ var SERVFAIL = 2;
24647
+ var NXDOMAIN = 3;
24648
+ var NOTIMP = 4;
24649
+ var QR = 32768;
24650
+ var AA = 1024;
24651
+ var TC = 512;
24652
+ var RD = 256;
24653
+ var RA = 128;
24654
+ var CD = 16;
24655
+ var UDP_PLAIN = 512;
24656
+ var UDP_EDNS = 1232;
24657
+ var UDP_MAX = 4096;
24658
+ var DOH_MAX = 65535;
24659
+ var LOCAL_ZONES = ["localhost", "slicc.internal"];
24660
+ var MESSAGE = "application/dns-message";
24661
+ var u16 = (b, at) => b[at] << 8 | b[at + 1];
24662
+ function skipName(b, at) {
24663
+ let i = at;
24664
+ for (let hops = 0; hops < 128; hops++) {
24665
+ if (i >= b.length) return void 0;
24666
+ const len = b[i];
24667
+ if (len === 0) return i + 1;
24668
+ if ((len & 192) === 192) return i + 2 <= b.length ? i + 2 : void 0;
24669
+ if (len & 192) return void 0;
24670
+ i += len + 1;
24671
+ }
24672
+ return void 0;
24673
+ }
24674
+ function readName(b, at) {
24675
+ const labels = [];
24676
+ let i = at;
24677
+ let size = 0;
24678
+ for (; ; ) {
24679
+ if (i >= b.length) return void 0;
24680
+ const len = b[i];
24681
+ if (len === 0) break;
24682
+ if (len & 192) return void 0;
24683
+ size += len + 1;
24684
+ if (size > 254 || i + 1 + len > b.length) return void 0;
24685
+ labels.push(new TextDecoder().decode(b.subarray(i + 1, i + 1 + len)));
24686
+ i += len + 1;
24687
+ }
24688
+ return { name: labels.join(".").toLowerCase(), end: i + 1 };
24689
+ }
24690
+ function parseQuery(b) {
24691
+ if (b.length < 12) return void 0;
24692
+ const id2 = u16(b, 0);
24693
+ const flags2 = u16(b, 2);
24694
+ if (flags2 & QR) return void 0;
24695
+ if (flags2 >> 11 & 15) return { ok: false, id: id2, flags: flags2, rcode: NOTIMP };
24696
+ if (u16(b, 4) !== 1) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24697
+ const read = readName(b, 12);
24698
+ if (!read || read.end + 4 > b.length) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24699
+ const type = u16(b, read.end);
24700
+ const klass = u16(b, read.end + 2);
24701
+ const end = read.end + 4;
24702
+ let edns;
24703
+ let at = end;
24704
+ const records = u16(b, 6) + u16(b, 8) + u16(b, 10);
24705
+ for (let n = 0; n < records; n++) {
24706
+ const after = skipName(b, at);
24707
+ if (after === void 0 || after + 10 > b.length)
24708
+ return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24709
+ if (u16(b, after) === TYPE_OPT) edns = Math.max(UDP_PLAIN, u16(b, after + 2));
24710
+ at = after + 10 + u16(b, after + 8);
24711
+ if (at > b.length) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24712
+ }
24713
+ return { ok: true, question: { id: id2, flags: flags2, name: read.name, type, klass, end, edns } };
24714
+ }
24715
+ function encodeName(name2) {
24716
+ const out = [];
24717
+ for (const label of name2.split(".").filter(Boolean)) {
24718
+ const bytes = new TextEncoder().encode(label);
24719
+ out.push(bytes.length, ...bytes);
24720
+ }
24721
+ out.push(0);
24722
+ return out;
24723
+ }
24724
+ function header2(id2, flags2, counts) {
24725
+ const out = [id2 >> 8, id2 & 255, flags2 >> 8, flags2 & 255];
24726
+ for (const c of counts) out.push(c >> 8, c & 255);
24727
+ return out;
24728
+ }
24729
+ function opt() {
24730
+ return [0, 0, TYPE_OPT, UDP_EDNS >> 8, UDP_EDNS & 255, 0, 0, 0, 0, 0, 0];
24731
+ }
24732
+ function record(type, rdata) {
24733
+ const ttl = DNS_STUB_TTL;
24734
+ return [
24735
+ 192,
24736
+ 12,
24737
+ type >> 8,
24738
+ type & 255,
24739
+ 0,
24740
+ CLASS_IN,
24741
+ ttl >>> 24 & 255,
24742
+ ttl >>> 16 & 255,
24743
+ ttl >>> 8 & 255,
24744
+ ttl & 255,
24745
+ rdata.length >> 8,
24746
+ rdata.length & 255,
24747
+ ...rdata
24748
+ ];
24749
+ }
24750
+ function replyFlags(query, rcode, aa) {
24751
+ return QR | query & 30720 | (aa ? AA : 0) | query & RD | RA | query & CD | rcode;
24752
+ }
24753
+ function answers(reply, q) {
24754
+ if (reply.length < 12 || !(u16(reply, 2) & QR) || u16(reply, 4) !== 1) return false;
24755
+ const read = readName(reply, 12);
24756
+ if (!read || read.end + 4 > reply.length) return false;
24757
+ return read.name === q.name && u16(reply, read.end) === q.type && u16(reply, read.end + 2) === q.klass;
24758
+ }
24759
+ function errorReply(id2, flags2, rcode) {
24760
+ return new Uint8Array(header2(id2, replyFlags(flags2, rcode, false), [0, 0, 0, 0]));
24761
+ }
24762
+ function answerReply(query, q, rcode, answers2, aa) {
24763
+ const extra = q.edns !== void 0 ? [opt()] : [];
24764
+ return new Uint8Array([
24765
+ ...header2(q.id, replyFlags(q.flags, rcode, aa), [1, answers2.length, 0, extra.length]),
24766
+ ...query.subarray(12, q.end),
24767
+ ...answers2.flat(),
24768
+ ...extra.flat()
24769
+ ]);
24770
+ }
24771
+ function truncated(reply, q, query) {
24772
+ const limit = q.edns !== void 0 ? Math.min(q.edns, UDP_MAX) : UDP_PLAIN;
24773
+ if (reply.length <= limit) return reply;
24774
+ const flags2 = u16(reply, 2) | TC;
24775
+ const extra = q.edns !== void 0 ? [opt()] : [];
24776
+ return new Uint8Array([
24777
+ ...header2(q.id, flags2, [1, 0, 0, extra.length]),
24778
+ ...query.subarray(12, q.end),
24779
+ ...extra.flat()
24780
+ ]);
24781
+ }
24782
+ function ipv6Text(groups) {
24783
+ return groups.map((g) => g.toString(16)).join(":");
24784
+ }
24785
+ function reverseAddress(name2) {
24786
+ if (name2.endsWith(".in-addr.arpa")) {
24787
+ const parts2 = name2.slice(0, -".in-addr.arpa".length).split(".");
24788
+ if (parts2.length !== 4) return void 0;
24789
+ const text = parts2.reverse().join(".");
24790
+ return ipv4Bytes(text) ? text.split(".").map(Number).join(".") : void 0;
24791
+ }
24792
+ if (name2.endsWith(".ip6.arpa")) {
24793
+ const nibbles = name2.slice(0, -".ip6.arpa".length).split(".");
24794
+ if (nibbles.length !== 32 || !nibbles.every((n) => /^[0-9a-f]$/.test(n))) return void 0;
24795
+ const hex4 = nibbles.reverse().join("");
24796
+ const groups = Array.from(
24797
+ { length: 8 },
24798
+ (_, i) => Number.parseInt(hex4.slice(i * 4, i * 4 + 4), 16)
24799
+ );
24800
+ return ipv6Text(groups);
24801
+ }
24802
+ return void 0;
24803
+ }
24804
+ function local(name2) {
24805
+ return LOCAL_ZONES.some((zone) => name2 === zone || name2.endsWith(`.${zone}`));
24806
+ }
24807
+ function literal(name2) {
24808
+ return ipv4Bytes(name2) !== void 0 || ipv6Groups(name2) !== void 0;
24809
+ }
24810
+ function addressData(address, type) {
24811
+ if (type === TYPE_A) return ipv4Bytes(address);
24812
+ const groups = type === TYPE_AAAA ? ipv6Groups(address) : void 0;
24813
+ return groups?.flatMap((g) => [g >> 8, g & 255]);
24814
+ }
24815
+ var DnsStub = class {
24816
+ resolver;
24817
+ forwarder;
24818
+ timeoutMs;
24819
+ constructor(options) {
24820
+ this.resolver = options.resolver;
24821
+ this.forwarder = options.forward;
24822
+ this.timeoutMs = options.timeoutMs ?? DNS_FORWARD_TIMEOUT_MS;
24823
+ }
24824
+ async answer(query, udp) {
24825
+ const parsed2 = parseQuery(query);
24826
+ if (!parsed2) return void 0;
24827
+ if (!parsed2.ok) return errorReply(parsed2.id, parsed2.flags, parsed2.rcode);
24828
+ const q = parsed2.question;
24829
+ const reply = await this.reply(query, q).catch(
24830
+ () => answerReply(query, q, SERVFAIL, [], false)
24831
+ );
24832
+ return udp ? truncated(reply, q, query) : reply;
24833
+ }
24834
+ async reply(query, q) {
24835
+ if (q.klass !== CLASS_IN || literal(q.name)) return this.forward(query, q);
24836
+ if (q.type === TYPE_PTR) {
24837
+ const address = reverseAddress(q.name);
24838
+ const name2 = address !== void 0 ? await this.reverse(address) : void 0;
24839
+ if (name2 !== void 0)
24840
+ return answerReply(query, q, NOERROR, [record(TYPE_PTR, encodeName(name2))], true);
24841
+ return this.forward(query, q);
24842
+ }
24843
+ if (q.type === TYPE_A || q.type === TYPE_AAAA) {
24844
+ const addresses = q.name === "" ? [] : await this.lookup(q.name);
24845
+ const answers2 = addresses.flatMap((a) => {
24846
+ const data = addressData(a, q.type);
24847
+ return data ? [record(q.type, data)] : [];
24848
+ });
24849
+ if (answers2.length > 0 || local(q.name) || await this.known(q.name)) {
24850
+ const rcode = addresses.length > 0 ? NOERROR : NXDOMAIN;
24851
+ return answerReply(query, q, rcode, answers2, local(q.name));
24852
+ }
24853
+ return this.forward(query, q);
24854
+ }
24855
+ if (await this.known(q.name)) return answerReply(query, q, NOERROR, [], true);
24856
+ if (local(q.name)) {
24857
+ const there = (await this.lookup(q.name)).length > 0;
24858
+ return answerReply(query, q, there ? NOERROR : NXDOMAIN, [], true);
24534
24859
  }
24860
+ return this.forward(query, q);
24535
24861
  }
24536
- return table;
24862
+ lookup(name2) {
24863
+ return this.resolver.resolve(name2, 0).catch(() => []);
24864
+ }
24865
+ known(name2) {
24866
+ return this.resolver.known(name2).catch(() => false);
24867
+ }
24868
+ reverse(address) {
24869
+ return this.resolver.reverse(address).catch(() => void 0);
24870
+ }
24871
+ async forward(query, q) {
24872
+ if (!this.forwarder) return answerReply(query, q, SERVFAIL, [], false);
24873
+ const asked = query.slice();
24874
+ asked[0] = 0;
24875
+ asked[1] = 0;
24876
+ const got = await this.forwarder(asked, AbortSignal.timeout(this.timeoutMs)).catch(
24877
+ () => void 0
24878
+ );
24879
+ if (!got || !answers(got, q)) return answerReply(query, q, SERVFAIL, [], false);
24880
+ const reply = got.slice();
24881
+ reply[0] = q.id >> 8;
24882
+ reply[1] = q.id & 255;
24883
+ return reply;
24884
+ }
24885
+ };
24886
+ async function collect(body, max) {
24887
+ const parts2 = [];
24888
+ let size = 0;
24889
+ for await (const part of body) {
24890
+ size += part.length;
24891
+ if (size > max) return void 0;
24892
+ parts2.push(part);
24893
+ }
24894
+ const out = new Uint8Array(size);
24895
+ let at = 0;
24896
+ for (const part of parts2) {
24897
+ out.set(part, at);
24898
+ at += part.length;
24899
+ }
24900
+ return out;
24537
24901
  }
24538
- function hostsReader(fs, path = HOSTS_PATH) {
24539
- let stamp = "";
24540
- let table;
24541
- return async () => {
24542
- const st = await fs.stat(path).catch(() => void 0);
24543
- if (!st?.isFile) {
24544
- stamp = "";
24545
- table = void 0;
24902
+ function dohForward(transport, url) {
24903
+ return async (query, signal) => {
24904
+ const res = await transport.fetch({
24905
+ url,
24906
+ method: "POST",
24907
+ headers: [
24908
+ ["content-type", MESSAGE],
24909
+ ["accept", MESSAGE]
24910
+ ],
24911
+ body: query,
24912
+ signal
24913
+ });
24914
+ const type = res.headers.find(([k]) => k.toLowerCase() === "content-type")?.[1] ?? "";
24915
+ if (res.status !== 200 || type.split(";")[0].trim().toLowerCase() !== MESSAGE) {
24916
+ await res.cancel().catch(() => void 0);
24546
24917
  return void 0;
24547
24918
  }
24548
- const now = `${st.ino}:${st.size}:${st.mtime.getTime()}`;
24549
- if (now === stamp && table) return table;
24550
- const text = await fs.readFile(path).catch(() => void 0);
24551
- if (text === void 0) return void 0;
24552
- stamp = now;
24553
- table = parseHosts(text);
24554
- return table;
24919
+ return collect(res.body, DOH_MAX);
24555
24920
  };
24556
24921
  }
24922
+ function uplinkForward(uplink, server) {
24923
+ return async (query, signal) => {
24924
+ const conn = await uplink.dial({ network: "tcp", host: server, port: DNS_PORT, signal });
24925
+ const stop = () => conn.close();
24926
+ signal.addEventListener("abort", stop, { once: true });
24927
+ try {
24928
+ await conn.write(new Uint8Array([query.length >> 8, query.length & 255, ...query]));
24929
+ let got = new Uint8Array();
24930
+ for (; ; ) {
24931
+ if (got.length >= 2 && got.length >= 2 + u16(got, 0)) return got.slice(2, 2 + u16(got, 0));
24932
+ const piece = await conn.read();
24933
+ if (!piece) return void 0;
24934
+ const next3 = new Uint8Array(got.length + piece.length);
24935
+ next3.set(got);
24936
+ next3.set(piece, got.length);
24937
+ got = next3;
24938
+ }
24939
+ } finally {
24940
+ signal.removeEventListener("abort", stop);
24941
+ conn.close();
24942
+ }
24943
+ };
24944
+ }
24945
+ function dnsForward(uplink, transport, doh) {
24946
+ const server = uplink?.nameserver;
24947
+ if (uplink && server && (ipv4Bytes(server) || ipv6Groups(server)))
24948
+ return uplinkForward(uplink, server);
24949
+ return typeof doh === "string" ? dohForward(transport, doh) : void 0;
24950
+ }
24951
+ function kernelDnsStub(resolver, transport, uplink, doh) {
24952
+ return new DnsStub({ resolver, forward: dnsForward(uplink, transport, doh) });
24953
+ }
24954
+ async function readExactly(conn, size, signal) {
24955
+ const out = new Uint8Array(size);
24956
+ let at = 0;
24957
+ while (at < size) {
24958
+ const piece = await conn.read(size - at, signal);
24959
+ if (piece.length === 0) return void 0;
24960
+ out.set(piece, at);
24961
+ at += piece.length;
24962
+ }
24963
+ return out;
24964
+ }
24965
+ async function serveTcp(stub, conn) {
24966
+ try {
24967
+ for (; ; ) {
24968
+ const idle2 = AbortSignal.timeout(DNS_TCP_IDLE_MS);
24969
+ const size = await readExactly(conn, 2, idle2);
24970
+ if (!size) return;
24971
+ const query = await readExactly(conn, u16(size, 0), idle2);
24972
+ if (!query) return;
24973
+ const reply = await stub.answer(query, false);
24974
+ if (!reply) return;
24975
+ const framed = new Uint8Array([reply.length >> 8, reply.length & 255, ...reply]);
24976
+ const sent = await conn.write(framed, AbortSignal.timeout(DNS_TCP_IDLE_MS));
24977
+ if (sent < framed.length) return;
24978
+ }
24979
+ } catch {
24980
+ return;
24981
+ } finally {
24982
+ conn.close();
24983
+ }
24984
+ }
24985
+ function enableDnsStub(net, stub) {
24986
+ const at = { family: "inet", host: "127.0.0.1", port: DNS_PORT };
24987
+ net.reserve(DNS_PORT);
24988
+ net.kernelOnly(DNS_PORT, true);
24989
+ net.activate(at, () => {
24990
+ const listener = net.listen(at);
24991
+ const open = /* @__PURE__ */ new Set();
24992
+ void (async () => {
24993
+ for (; ; ) {
24994
+ const conn = await listener.accept().catch(() => void 0);
24995
+ if (!conn) return;
24996
+ if (open.size >= DNS_TCP_MAX) {
24997
+ conn.close();
24998
+ continue;
24999
+ }
25000
+ open.add(conn);
25001
+ void serveTcp(stub, conn).finally(() => open.delete(conn));
25002
+ }
25003
+ })();
25004
+ });
25005
+ let inflight = 0;
25006
+ net.serveDgram(DNS_PORT, (datagram2, to) => {
25007
+ if (inflight >= DNS_UDP_INFLIGHT) return;
25008
+ inflight++;
25009
+ void stub.answer(datagram2.bytes, true).then(
25010
+ (reply) => {
25011
+ if (!reply) return;
25012
+ const from = { family: "inet", host: to.host, port: DNS_PORT };
25013
+ net.deliverDgram(datagram2.from.port, { bytes: reply, from });
25014
+ },
25015
+ () => void 0
25016
+ ).finally(() => inflight--);
25017
+ });
25018
+ }
24557
25019
 
24558
25020
  // src/kernel/net/redirect-hops.ts
24559
25021
  var HELD_MS = 3e4;
@@ -24561,13 +25023,13 @@ var HELD_MAX = 64;
24561
25023
  var HELD_PER_OWNER = 8;
24562
25024
  var MATCHED = ["range", "if-none-match", "if-modified-since", "if-range", "accept-encoding"];
24563
25025
  var KERNEL = -1;
24564
- function header2(headers, name2) {
25026
+ function header3(headers, name2) {
24565
25027
  const values = headers.filter(([n]) => n.toLowerCase() === name2).map(([, v]) => v);
24566
25028
  return values.length > 0 ? values.join(", ") : void 0;
24567
25029
  }
24568
25030
  function fingerprint(headers) {
24569
- const fields = MATCHED.map((name2) => header2(headers, name2) ?? "");
24570
- return JSON.stringify([...fields, header2(headers, "authorization") !== void 0]);
25031
+ const fields = MATCHED.map((name2) => header3(headers, name2) ?? "");
25032
+ return JSON.stringify([...fields, header3(headers, "authorization") !== void 0]);
24571
25033
  }
24572
25034
  function unauthorized(print) {
24573
25035
  return JSON.stringify([...JSON.parse(print).slice(0, -1), false]);
@@ -24610,7 +25072,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
24610
25072
  };
24611
25073
  const replay = (chain2) => {
24612
25074
  const [hop, ...rest2] = chain2.hops;
24613
- const location = hop && header2(hop.headers, "location");
25075
+ const location = hop && header3(hop.headers, "location");
24614
25076
  if (!hop || location === void 0) return chain2.final;
24615
25077
  const target = new URL(location, hop.url);
24616
25078
  target.hash = "";
@@ -24735,7 +25197,7 @@ function materializable(req) {
24735
25197
  if (req.shellGrants !== true && !isStrings(req.names)) return false;
24736
25198
  return isStrings(req.argv) && typeof req.path === "string" && typeof req.cwd === "string";
24737
25199
  }
24738
- function errorReply(code, message3) {
25200
+ function errorReply2(code, message3) {
24739
25201
  return { v: 1, error: { code, message: message3 } };
24740
25202
  }
24741
25203
  function isRecord(value2) {
@@ -24747,9 +25209,9 @@ function serialized(reply) {
24747
25209
  const text = JSON.stringify(reply);
24748
25210
  plain3 = text === void 0 ? void 0 : JSON.parse(text);
24749
25211
  } catch (err) {
24750
- return JSON.stringify(errorReply("EIO", lineOf2(err)));
25212
+ return JSON.stringify(errorReply2("EIO", lineOf2(err)));
24751
25213
  }
24752
- if (!isRecord(plain3)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
25214
+ if (!isRecord(plain3)) return JSON.stringify(errorReply2("EIO", "the vault gave no reply"));
24753
25215
  const { v: _, ...rest2 } = plain3;
24754
25216
  return JSON.stringify({ v: 1, ...rest2 });
24755
25217
  }
@@ -24797,18 +25259,18 @@ var SealedChannel = class {
24797
25259
  }
24798
25260
  async answer(req, signal) {
24799
25261
  const hook = this.broker.hook;
24800
- if (!hook) return errorReply("ENOTCONN", "no vault is connected");
25262
+ if (!hook) return errorReply2("ENOTCONN", "no vault is connected");
24801
25263
  const stopped = new Promise((resolve2) => {
24802
25264
  signal.addEventListener("abort", () => resolve2(void 0), { once: true });
24803
25265
  });
24804
25266
  if (signal.aborted) return void 0;
24805
25267
  const asked = Promise.resolve().then(() => hook(req, { signal })).then(
24806
- (reply2) => isRecord(reply2) ? reply2 : errorReply("EIO", "the vault gave no reply"),
24807
- (err) => errorReply("EIO", lineOf2(err))
25268
+ (reply2) => isRecord(reply2) ? reply2 : errorReply2("EIO", "the vault gave no reply"),
25269
+ (err) => errorReply2("EIO", lineOf2(err))
24808
25270
  );
24809
25271
  const reply = await Promise.race([asked, stopped]);
24810
25272
  if (!signal.aborted) return reply;
24811
- return signal.reason === "timeout" ? errorReply("ETIMEDOUT", "the vault did not answer within 10 s") : void 0;
25273
+ return signal.reason === "timeout" ? errorReply2("ETIMEDOUT", "the vault did not answer within 10 s") : void 0;
24812
25274
  }
24813
25275
  drop() {
24814
25276
  this.reply?.fill(0);
@@ -27222,6 +27684,10 @@ function dataModuleUrl(source) {
27222
27684
  return { url: `data:text/javascript;base64,${btoa(binary2)}`, revoke: () => {
27223
27685
  } };
27224
27686
  }
27687
+ function describe(req, tty) {
27688
+ const exe = req.exe === void 0 ? {} : { exe: req.exe };
27689
+ return { argv: [req.argv0, ...req.args], tty, started: Date.now(), ...exe };
27690
+ }
27225
27691
  function linksOf2(req) {
27226
27692
  return req.links === void 0 ? {} : { links: req.links };
27227
27693
  }
@@ -27243,6 +27709,7 @@ var LAYOUT = [
27243
27709
  ["/etc", 493],
27244
27710
  [PASSWD, 420],
27245
27711
  [GROUP, 420],
27712
+ [RESOLV_CONF_PATH, 420],
27246
27713
  ["/usr", 493],
27247
27714
  ["/usr/local", 493]
27248
27715
  ];
@@ -27585,6 +28052,10 @@ var Launcher = class {
27585
28052
  roots: packageTlsRoots(this.verifiedFs(options.fs), this.modulesDir),
27586
28053
  ca: this.ca
27587
28054
  });
28055
+ enableDnsStub(
28056
+ this.net,
28057
+ kernelDnsStub(this.resolver, this.transport, options.uplink, options.doh)
28058
+ );
27588
28059
  enableCdp(this.net, this.cdp);
27589
28060
  this.facades.enable(this.net);
27590
28061
  const fs = this.commandFs(this.base);
@@ -27672,10 +28143,10 @@ var Launcher = class {
27672
28143
  ready: () => this.fstab,
27673
28144
  lookup: (name2) => this.users.lookup(name2),
27674
28145
  watch: async (paths, notify) => {
27675
- const local = this.watchers.watch(paths, { recursive: true }, () => notify());
28146
+ const local2 = this.watchers.watch(paths, { recursive: true }, () => notify());
27676
28147
  const remote = await this.watchFiles(paths, notify);
27677
28148
  return () => {
27678
- local();
28149
+ local2();
27679
28150
  remote();
27680
28151
  };
27681
28152
  },
@@ -27861,7 +28332,7 @@ var Launcher = class {
27861
28332
  abi: "wasi",
27862
28333
  glue,
27863
28334
  wasm: glue,
27864
- argv0: baseName2(argv0 || file).replace(/\.wasm$/, ""),
28335
+ argv0,
27865
28336
  ...asked
27866
28337
  };
27867
28338
  }
@@ -28403,7 +28874,18 @@ var Launcher = class {
28403
28874
  const handle = await this.admitted(
28404
28875
  program.abi !== "js",
28405
28876
  req.fds,
28406
- (fds, quietOom) => this.start({ ...req, fds, quietOom, cwd, program, argv0: target.argv0, args, env, cwdSlot })
28877
+ (fds, quietOom) => this.start({
28878
+ ...req,
28879
+ fds,
28880
+ quietOom,
28881
+ cwd,
28882
+ program,
28883
+ argv0: target.argv0,
28884
+ exe: target.copy ?? target.glue,
28885
+ args,
28886
+ env,
28887
+ cwdSlot
28888
+ })
28407
28889
  ).finally(() => this.cwds.release(cwdSlot));
28408
28890
  void handle.exited.finally(done4);
28409
28891
  return handle;
@@ -28595,11 +29077,7 @@ var Launcher = class {
28595
29077
  if (req.pgid !== void 0) this.jobs.join(pid, req.pgid);
28596
29078
  if (req.group === "lead") this.jobs.lead(pid);
28597
29079
  if (req.group === "session") this.jobs.setsid(pid);
28598
- this.described.set(pid, {
28599
- argv: [req.argv0, ...req.args],
28600
- tty: terminal?.name ?? null,
28601
- started: Date.now()
28602
- });
29080
+ this.described.set(pid, describe(req, terminal?.name ?? null));
28603
29081
  handle.onState(
28604
29082
  (state) => state === "stopped" ? this.stopped.add(pid) : this.stopped.delete(pid)
28605
29083
  );
@@ -29207,6 +29685,19 @@ var Launcher = class {
29207
29685
  inUse(path) {
29208
29686
  return [...this.openFiles].some((nodes) => nodes.holds(path)) || heldUnder(this.held, path);
29209
29687
  }
29688
+ async resolvConf() {
29689
+ if (isProtected(this.prefixes, RESOLV_CONF_PATH)) return;
29690
+ try {
29691
+ const there = await this.base.lstat(RESOLV_CONF_PATH).then(
29692
+ () => true,
29693
+ () => false
29694
+ );
29695
+ if (there) return;
29696
+ await this.base.writeFile(RESOLV_CONF_PATH, RESOLV_CONF);
29697
+ } catch {
29698
+ return;
29699
+ }
29700
+ }
29210
29701
  async stampLayout() {
29211
29702
  const layout = [
29212
29703
  ...LAYOUT,
@@ -29342,6 +29833,7 @@ var Launcher = class {
29342
29833
  await this.mountShm();
29343
29834
  await this.pnpmReady();
29344
29835
  await this.users.ensure();
29836
+ await this.resolvConf();
29345
29837
  if (this.owners) await this.stampLayout();
29346
29838
  if (this.owners) await this.sudoer.provision();
29347
29839
  await writeCaFile(this.base, this.ca).catch(() => void 0);
@@ -29580,12 +30072,12 @@ var Launcher = class {
29580
30072
  const out = [];
29581
30073
  const err = [];
29582
30074
  const keep2 = options.collect !== false;
29583
- const collect = (chunks2, tee) => (bytes) => {
30075
+ const collect2 = (chunks2, tee) => (bytes) => {
29584
30076
  if (keep2) chunks2.push(bytes);
29585
30077
  tee?.(bytes);
29586
30078
  };
29587
- const stdout = collect(out, options.onStdout);
29588
- const stderr = collect(err, options.onStderr);
30079
+ const stdout = collect2(out, options.onStdout);
30080
+ const stderr = collect2(err, options.onStderr);
29589
30081
  const report = (message3) => stderr(encoder10.encode(`${message3}
29590
30082
  `));
29591
30083
  if (!planned) {
@@ -30447,7 +30939,7 @@ function parseHead2(bytes) {
30447
30939
  }
30448
30940
  return { status: Number(match[1]), statusText: match[2] ?? "", headers };
30449
30941
  }
30450
- function header3(head, name2) {
30942
+ function header4(head, name2) {
30451
30943
  return head.headers.find(([key]) => key.toLowerCase() === name2)?.[1];
30452
30944
  }
30453
30945
  async function* chunked2(source) {
@@ -30476,8 +30968,8 @@ async function* untilClose2(source) {
30476
30968
  }
30477
30969
  function bodyOf2(source, head, method) {
30478
30970
  if (method === "HEAD" || head.status === 204 || head.status === 304) return void 0;
30479
- if (header3(head, "transfer-encoding")?.toLowerCase().includes("chunked")) return chunked2(source);
30480
- const length2 = header3(head, "content-length");
30971
+ if (header4(head, "transfer-encoding")?.toLowerCase().includes("chunked")) return chunked2(source);
30972
+ const length2 = header4(head, "content-length");
30481
30973
  if (length2 === void 0) return untilClose2(source);
30482
30974
  const size = Number(length2);
30483
30975
  if (!/^\d+$/.test(length2.trim()) || !Number.isSafeInteger(size)) {
@@ -31097,6 +31589,7 @@ async function createNodeKernel(options = {}) {
31097
31589
  ...options.env ? { env: options.env } : {},
31098
31590
  ...transport ? { transport } : {},
31099
31591
  ...options.network?.uplink ? { uplink: options.network.uplink } : {},
31592
+ ...options.network?.doh !== void 0 ? { doh: options.network.doh } : {},
31100
31593
  ...options.processMounts !== void 0 ? { processMounts: options.processMounts } : {},
31101
31594
  ...options.fstabRetries ? { fstabRetries: options.fstabRetries } : {},
31102
31595
  ...options.hostfs ? { hostfs: options.hostfs } : {},