@ai-ecoverse/slicc-kernel 1.106.2 → 1.107.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
@@ -699,12 +699,12 @@ function userCred(uid, gid, groups = [gid]) {
699
699
  function copyCred(cred) {
700
700
  return { ...cred, groups: [...cred.groups] };
701
701
  }
702
- function id(value) {
703
- if (value === void 0 || value === -1 || value === 4294967295) return void 0;
704
- if (!Number.isInteger(value) || value < 0 || value > MAX_ID) {
705
- throw fsError("EINVAL", `not a user or group id: ${String(value)}`);
702
+ function id(value2) {
703
+ if (value2 === void 0 || value2 === -1 || value2 === 4294967295) return void 0;
704
+ if (!Number.isInteger(value2) || value2 < 0 || value2 > MAX_ID) {
705
+ throw fsError("EINVAL", `not a user or group id: ${String(value2)}`);
706
706
  }
707
- return value;
707
+ return value2;
708
708
  }
709
709
  function changeCred(cur, change) {
710
710
  if (typeof change !== "object" || change === null || Array.isArray(change)) {
@@ -715,10 +715,10 @@ function changeCred(cur, change) {
715
715
  for (const keys of [UIDS, GIDS]) {
716
716
  const own = keys.map((key) => cur[key]);
717
717
  for (const key of keys) {
718
- const value = id(change[key]);
719
- if (value === void 0) continue;
720
- if (!privileged && !own.includes(value)) throw fsError("EPERM", `${key} ${value}`);
721
- next3[key] = value;
718
+ const value2 = id(change[key]);
719
+ if (value2 === void 0) continue;
720
+ if (!privileged && !own.includes(value2)) throw fsError("EPERM", `${key} ${value2}`);
721
+ next3[key] = value2;
722
722
  }
723
723
  }
724
724
  if (change.groups !== void 0) {
@@ -1329,11 +1329,11 @@ function ipv6Groups(text) {
1329
1329
  } catch {
1330
1330
  return void 0;
1331
1331
  }
1332
- const [head, tail] = canonical.split("::");
1332
+ const [head, tail2] = canonical.split("::");
1333
1333
  const part = (s) => s ? s.split(":").map((h) => Number.parseInt(h, 16)) : [];
1334
1334
  const front = part(head);
1335
- const back = part(tail);
1336
- return tail === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
1335
+ const back = part(tail2);
1336
+ return tail2 === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
1337
1337
  }
1338
1338
  function toBits(values, width) {
1339
1339
  return values.reduce((acc, v) => acc << BigInt(width) | BigInt(v), 0n);
@@ -1815,8 +1815,8 @@ var KernelSocket = class _KernelSocket {
1815
1815
  }
1816
1816
  return this.options.get(`${level}:${name2}`) ?? 0;
1817
1817
  }
1818
- setOption(level, name2, value) {
1819
- this.options.set(`${level}:${name2}`, value);
1818
+ setOption(level, name2, value2) {
1819
+ this.options.set(`${level}:${name2}`, value2);
1820
1820
  }
1821
1821
  close() {
1822
1822
  const was = this.state;
@@ -2214,8 +2214,8 @@ var SENT_HEADERS_DROP = /* @__PURE__ */ new Set([
2214
2214
  ]);
2215
2215
  function headerRecord(headers) {
2216
2216
  const out = {};
2217
- for (const [name2, value] of headers) {
2218
- if (!SENT_HEADERS_DROP.has(name2.toLowerCase())) out[name2] = value;
2217
+ for (const [name2, value2] of headers) {
2218
+ if (!SENT_HEADERS_DROP.has(name2.toLowerCase())) out[name2] = value2;
2219
2219
  }
2220
2220
  return out;
2221
2221
  }
@@ -2306,9 +2306,9 @@ var NO_WEBSOCKET = "WebSocket not supported by this transport (fetchTransport ne
2306
2306
  var MAX_REQUEST_BODY = 64 * 1024 * 1024;
2307
2307
  function joinHeaders(headers) {
2308
2308
  const out = new Headers();
2309
- for (const [name2, value] of headers) {
2309
+ for (const [name2, value2] of headers) {
2310
2310
  try {
2311
- out.append(name2, value);
2311
+ out.append(name2, value2);
2312
2312
  } catch {
2313
2313
  }
2314
2314
  }
@@ -2387,8 +2387,8 @@ function fetchTransport(options = {}) {
2387
2387
  );
2388
2388
  }
2389
2389
  const headers2 = [];
2390
- response.headers.forEach((value, name2) => {
2391
- headers2.push([name2, value]);
2390
+ response.headers.forEach((value2, name2) => {
2391
+ headers2.push([name2, value2]);
2392
2392
  });
2393
2393
  const body = chunks(response.body, options.bodyIdleMs ?? BODY_IDLE_MS);
2394
2394
  return {
@@ -3449,9 +3449,9 @@ var PathMap = class {
3449
3449
  keys() {
3450
3450
  return this.values.keys();
3451
3451
  }
3452
- set(path, value) {
3452
+ set(path, value2) {
3453
3453
  if (!this.values.has(path)) this.link(path);
3454
- this.values.set(path, value);
3454
+ this.values.set(path, value2);
3455
3455
  return this;
3456
3456
  }
3457
3457
  delete(path) {
@@ -3933,8 +3933,8 @@ var ProtectedFs = class {
3933
3933
  for (let at = fs; at && at !== Object.prototype; at = Object.getPrototypeOf(at)) {
3934
3934
  for (const name2 of Object.getOwnPropertyNames(at)) {
3935
3935
  if (name2 === "constructor" || Object.hasOwn(view2, name2)) continue;
3936
- const value = fs[name2];
3937
- view2[name2] = typeof value === "function" ? value.bind(fs) : value;
3936
+ const value2 = fs[name2];
3937
+ view2[name2] = typeof value2 === "function" ? value2.bind(fs) : value2;
3938
3938
  }
3939
3939
  }
3940
3940
  return Object.assign(view2, own);
@@ -4064,8 +4064,8 @@ function view(target, overrides) {
4064
4064
  if (keys.has(prop)) return overrides[prop];
4065
4065
  return Reflect.get(t, prop, receiver);
4066
4066
  },
4067
- set(t, prop, value) {
4068
- return Reflect.set(t, prop, value);
4067
+ set(t, prop, value2) {
4068
+ return Reflect.set(t, prop, value2);
4069
4069
  },
4070
4070
  getPrototypeOf(t) {
4071
4071
  return Reflect.getPrototypeOf(t);
@@ -5273,12 +5273,12 @@ var PathGate = class {
5273
5273
  async acquire(path) {
5274
5274
  const prev = this.tails.get(path) ?? Promise.resolve();
5275
5275
  const { promise, resolve: resolve2 } = Promise.withResolvers();
5276
- const tail = prev.then(() => promise);
5277
- this.tails.set(path, tail);
5276
+ const tail2 = prev.then(() => promise);
5277
+ this.tails.set(path, tail2);
5278
5278
  await prev;
5279
5279
  return () => {
5280
5280
  resolve2();
5281
- if (this.tails.get(path) === tail) this.tails.delete(path);
5281
+ if (this.tails.get(path) === tail2) this.tails.delete(path);
5282
5282
  };
5283
5283
  }
5284
5284
  async run(path, op) {
@@ -5726,15 +5726,15 @@ function concat(chunks2, total = chunks2.reduce((n, c) => n + c.length, 0)) {
5726
5726
  }
5727
5727
  return out;
5728
5728
  }
5729
- function safeValue(value) {
5730
- return !/[\r\n\0]/.test(value);
5729
+ function safeValue(value2) {
5730
+ return !/[\r\n\0]/.test(value2);
5731
5731
  }
5732
5732
  function responseHead(status, reason, headers) {
5733
5733
  const phrase = /^[\t\x20-\x7e\x80-\xff]*$/.test(reason) ? reason : "";
5734
5734
  let head = `HTTP/1.1 ${status} ${phrase}\r
5735
5735
  `;
5736
- for (const [name2, value] of headers) {
5737
- if (TOKEN.test(name2) && safeValue(value)) head += `${name2}: ${value}\r
5736
+ for (const [name2, value2] of headers) {
5737
+ if (TOKEN.test(name2) && safeValue(value2)) head += `${name2}: ${value2}\r
5738
5738
  `;
5739
5739
  }
5740
5740
  return latin1Bytes(`${head}\r
@@ -6006,8 +6006,8 @@ Connection: close\r
6006
6006
  out.set(bytes, head.length);
6007
6007
  return out;
6008
6008
  }
6009
- function json(value) {
6010
- return respond(200, `${JSON.stringify(value, null, 2)}
6009
+ function json(value2) {
6010
+ return respond(200, `${JSON.stringify(value2, null, 2)}
6011
6011
  `, "application/json; charset=UTF-8");
6012
6012
  }
6013
6013
  var CdpFacade = class {
@@ -6405,9 +6405,9 @@ function comparator(token) {
6405
6405
  function set(text) {
6406
6406
  const trimmed = text.trim().replace(/(<=|>=|<|>|=|\^|~>?)\s+/g, "$1");
6407
6407
  if (trimmed === "") return ANY;
6408
- const range = /^(\S+)\s+-\s+(\S+)$/.exec(trimmed);
6409
- if (range) {
6410
- const [from, to] = [partial(range[1]), partial(range[2])];
6408
+ const range2 = /^(\S+)\s+-\s+(\S+)$/.exec(trimmed);
6409
+ if (range2) {
6410
+ const [from, to] = [partial(range2[1]), partial(range2[2])];
6411
6411
  return from && to ? hyphen(from, to) : void 0;
6412
6412
  }
6413
6413
  const out = [];
@@ -6426,16 +6426,16 @@ function holds(v, [op, w]) {
6426
6426
  if (op === ">=") return c >= 0;
6427
6427
  return c === 0;
6428
6428
  }
6429
- function satisfies(version, range) {
6429
+ function satisfies(version, range2) {
6430
6430
  const v = parseVersion(version);
6431
6431
  if (!v) return void 0;
6432
- const sets = range.split("||").map(set);
6432
+ const sets = range2.split("||").map(set);
6433
6433
  if (sets.some((s) => s === void 0)) return void 0;
6434
6434
  return sets.some((s) => s.every((c) => holds(v, c)));
6435
6435
  }
6436
6436
 
6437
6437
  // src/version.ts
6438
- var KERNEL_VERSION = true ? "1.106.2" : "0.0.0-dev";
6438
+ var KERNEL_VERSION = true ? "1.107.0" : "0.0.0-dev";
6439
6439
  var OS_RELEASE = "6.0.0-slicc";
6440
6440
  function procVersion() {
6441
6441
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -6459,19 +6459,19 @@ function inside(pkg, rel2) {
6459
6459
  function envOf(pkg, raw) {
6460
6460
  const env = {};
6461
6461
  if (!raw || typeof raw !== "object") return env;
6462
- for (const [key, value] of Object.entries(raw)) {
6462
+ for (const [key, value2] of Object.entries(raw)) {
6463
6463
  if (!ENV_KEY.test(key)) continue;
6464
- if (typeof value === "string") env[key] = value.replace(PACKAGE, pkg);
6465
- else if (value === null) env[key] = null;
6464
+ if (typeof value2 === "string") env[key] = value2.replace(PACKAGE, pkg);
6465
+ else if (value2 === null) env[key] = null;
6466
6466
  }
6467
6467
  return env;
6468
6468
  }
6469
6469
  function envFields(merged2) {
6470
6470
  const env = {};
6471
6471
  const unset = [];
6472
- for (const [key, value] of Object.entries(merged2)) {
6473
- if (value === null) unset.push(key);
6474
- else env[key] = value;
6472
+ for (const [key, value2] of Object.entries(merged2)) {
6473
+ if (value2 === null) unset.push(key);
6474
+ else env[key] = value2;
6475
6475
  }
6476
6476
  return {
6477
6477
  ...Object.keys(env).length > 0 ? { env } : {},
@@ -6550,9 +6550,9 @@ function commandsOf(pkg, manifest) {
6550
6550
  async function withPackagePaths(fs, pkg, command) {
6551
6551
  if (!command.env) return command;
6552
6552
  const env = {};
6553
- for (const [key, value] of Object.entries(command.env)) {
6554
- const path = !value.startsWith("/") && value.includes("/") && inside(pkg, value);
6555
- env[key] = path && await fs.exists(path) ? path : value;
6553
+ for (const [key, value2] of Object.entries(command.env)) {
6554
+ const path = !value2.startsWith("/") && value2.includes("/") && inside(pkg, value2);
6555
+ env[key] = path && await fs.exists(path) ? path : value2;
6556
6556
  }
6557
6557
  return { ...command, env };
6558
6558
  }
@@ -6603,7 +6603,7 @@ function physicalResolver(fs) {
6603
6603
  const known = /* @__PURE__ */ new Map();
6604
6604
  const pending = /* @__PURE__ */ new Set();
6605
6605
  let hops = 0;
6606
- const step = async (path) => {
6606
+ const step2 = async (path) => {
6607
6607
  if (path === "/") return { path, file: false };
6608
6608
  const slash = path.lastIndexOf("/");
6609
6609
  const parent = await resolve2(path.slice(0, slash) || "/");
@@ -6620,7 +6620,7 @@ function physicalResolver(fs) {
6620
6620
  let found = known.get(path);
6621
6621
  if (!found) {
6622
6622
  pending.add(path);
6623
- found = step(path).finally(() => pending.delete(path));
6623
+ found = step2(path).finally(() => pending.delete(path));
6624
6624
  known.set(path, found);
6625
6625
  }
6626
6626
  return found;
@@ -6655,15 +6655,15 @@ async function binCommandsOf(physical, pkg, manifest, taken) {
6655
6655
  }
6656
6656
  function engineRefusal(manifest, kernel) {
6657
6657
  const engines = manifest.engines;
6658
- const range = engines && typeof engines === "object" ? engines["slicc-kernel"] : void 0;
6658
+ const range2 = engines && typeof engines === "object" ? engines["slicc-kernel"] : void 0;
6659
6659
  const running = parseVersion(kernel);
6660
- if (typeof range !== "string" || !running || running.slice(0, 3).every((n) => n === 0)) {
6660
+ if (typeof range2 !== "string" || !running || running.slice(0, 3).every((n) => n === 0)) {
6661
6661
  return void 0;
6662
6662
  }
6663
- const fits = satisfies(kernel, range);
6663
+ const fits = satisfies(kernel, range2);
6664
6664
  if (fits) return void 0;
6665
6665
  const who = `${String(manifest.name ?? "?")}@${String(manifest.version ?? "?")}`;
6666
- return fits === false ? `${who} needs slicc-kernel ${range}; this kernel is ${kernel}` : `${who} has an engines.slicc-kernel range this kernel can't read: ${JSON.stringify(range)}`;
6666
+ return fits === false ? `${who} needs slicc-kernel ${range2}; this kernel is ${kernel}` : `${who} has an engines.slicc-kernel range this kernel can't read: ${JSON.stringify(range2)}`;
6667
6667
  }
6668
6668
  var PACKAGE_NAME = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
6669
6669
  function replacesOf(manifest) {
@@ -6794,6 +6794,573 @@ function binfmtOf(binfmts, path) {
6794
6794
  return best === void 0 ? void 0 : binfmts.get(best);
6795
6795
  }
6796
6796
 
6797
+ // src/cron/clock.ts
6798
+ var systemCronClock = {
6799
+ now: () => Date.now(),
6800
+ sleep(until, signal) {
6801
+ if (signal.aborted) return Promise.resolve();
6802
+ return new Promise((resolve2) => {
6803
+ const done4 = () => {
6804
+ clearTimeout(timer);
6805
+ signal.removeEventListener("abort", done4);
6806
+ resolve2();
6807
+ };
6808
+ const timer = setTimeout(done4, Math.max(0, until - Date.now()));
6809
+ timer.unref?.();
6810
+ signal.addEventListener("abort", done4, { once: true });
6811
+ });
6812
+ }
6813
+ };
6814
+
6815
+ // src/cron/schedule.ts
6816
+ var MISSED_CAP = 1e5;
6817
+ var MACROS = {
6818
+ "@yearly": "0 0 1 1 *",
6819
+ "@annually": "0 0 1 1 *",
6820
+ "@monthly": "0 0 1 * *",
6821
+ "@weekly": "0 0 * * 0",
6822
+ "@daily": "0 0 * * *",
6823
+ "@midnight": "0 0 * * *",
6824
+ "@hourly": "0 * * * *"
6825
+ };
6826
+ var MONTHS = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
6827
+ var WEEKDAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
6828
+ var FIELDS = [
6829
+ { name: "minute", min: 0, max: 59 },
6830
+ { name: "hour", min: 0, max: 23 },
6831
+ { name: "day of month", min: 1, max: 31 },
6832
+ { name: "month", min: 1, max: 12, names: MONTHS, offset: 1 },
6833
+ { name: "day of week", min: 0, max: 7, names: WEEKDAYS }
6834
+ ];
6835
+ function value(text, field4) {
6836
+ const named = field4.names?.indexOf(text.toLowerCase()) ?? -1;
6837
+ if (named >= 0) return named + (field4.offset ?? 0);
6838
+ if (!/^\d+$/.test(text)) throw new Error(`${field4.name}: "${text}" is not a number`);
6839
+ const number = Number(text);
6840
+ if (number < field4.min || number > field4.max)
6841
+ throw new Error(`${field4.name}: ${number} is outside ${field4.min}-${field4.max}`);
6842
+ return number;
6843
+ }
6844
+ function range(part, field4) {
6845
+ if (part === "*") return [field4.min, field4.max];
6846
+ const [from, to, extra] = part.split("-");
6847
+ if (extra !== void 0) throw new Error(`${field4.name}: "${part}" is not a range`);
6848
+ const start2 = value(from, field4);
6849
+ const end = to === void 0 ? start2 : value(to, field4);
6850
+ if (end < start2) throw new Error(`${field4.name}: range ${part} runs backwards`);
6851
+ return [start2, end];
6852
+ }
6853
+ function step(text, field4) {
6854
+ if (text === void 0) return 1;
6855
+ if (!/^\d+$/.test(text) || Number(text) === 0)
6856
+ throw new Error(`${field4.name}: step "${text}" must be a positive number`);
6857
+ return Number(text);
6858
+ }
6859
+ function field2(text, spec) {
6860
+ const out = /* @__PURE__ */ new Set();
6861
+ for (const part of text.split(",")) {
6862
+ if (part === "") throw new Error(`${spec.name}: empty list item`);
6863
+ const [base, every, extra] = part.split("/");
6864
+ if (extra !== void 0) throw new Error(`${spec.name}: "${part}" has two steps`);
6865
+ const [start2, end] = range(base, spec);
6866
+ const stride = step(every, spec);
6867
+ const last = every !== void 0 && !base.includes("-") ? spec.max : end;
6868
+ for (let n = start2; n <= last; n += stride) out.add(n);
6869
+ }
6870
+ return out;
6871
+ }
6872
+ function parseSchedule(expression) {
6873
+ const trimmed = expression.trim();
6874
+ const text = MACROS[trimmed.toLowerCase()] ?? trimmed;
6875
+ if (text.startsWith("@")) throw new Error(`unknown schedule ${trimmed}`);
6876
+ const parts2 = text.split(/\s+/);
6877
+ if (parts2.length !== 5)
6878
+ throw new Error(
6879
+ `"${trimmed}" needs 5 fields (minute hour day month weekday), not ${parts2.length}`
6880
+ );
6881
+ const [minutes, hours, days, months, weekdays] = parts2.map(
6882
+ (part, at) => field2(part, FIELDS[at])
6883
+ );
6884
+ if (weekdays.delete(7)) weekdays.add(0);
6885
+ return {
6886
+ minutes,
6887
+ hours,
6888
+ days,
6889
+ months,
6890
+ weekdays,
6891
+ anyDay: parts2[2].startsWith("*"),
6892
+ anyWeekday: parts2[4].startsWith("*")
6893
+ };
6894
+ }
6895
+ function parseWhen(expression) {
6896
+ if (expression.trim().toLowerCase() === "@reboot") return { reboot: true };
6897
+ return { reboot: false, schedule: parseSchedule(expression) };
6898
+ }
6899
+ var LOCAL = {
6900
+ year: (d) => d.getFullYear(),
6901
+ month: (d) => d.getMonth(),
6902
+ date: (d) => d.getDate(),
6903
+ day: (d) => d.getDay(),
6904
+ hours: (d) => d.getHours(),
6905
+ minutes: (d) => d.getMinutes(),
6906
+ setMonth: (d, month) => d.setMonth(month, 1),
6907
+ setDate: (d, date) => d.setDate(date),
6908
+ setHours: (d, hours) => d.setHours(hours, 0, 0, 0),
6909
+ setMinutes: (d, minutes) => d.setMinutes(minutes, 0, 0)
6910
+ };
6911
+ var UTC = {
6912
+ year: (d) => d.getUTCFullYear(),
6913
+ month: (d) => d.getUTCMonth(),
6914
+ date: (d) => d.getUTCDate(),
6915
+ day: (d) => d.getUTCDay(),
6916
+ hours: (d) => d.getUTCHours(),
6917
+ minutes: (d) => d.getUTCMinutes(),
6918
+ setMonth: (d, month) => d.setUTCMonth(month, 1),
6919
+ setDate: (d, date) => d.setUTCDate(date),
6920
+ setHours: (d, hours) => d.setUTCHours(hours, 0, 0, 0),
6921
+ setMinutes: (d, minutes) => d.setUTCMinutes(minutes, 0, 0)
6922
+ };
6923
+ function dayMatches(schedule, cal, date) {
6924
+ const day = schedule.days.has(cal.date(date));
6925
+ const weekday = schedule.weekdays.has(cal.day(date));
6926
+ if (schedule.anyDay || schedule.anyWeekday) return day && weekday;
6927
+ return day || weekday;
6928
+ }
6929
+ var LIMIT_YEARS = 8;
6930
+ function nextFire(schedule, after, utc = false) {
6931
+ const cal = utc ? UTC : LOCAL;
6932
+ const date = new Date(Math.floor(after / 6e4) * 6e4 + 6e4);
6933
+ const limit = cal.year(date) + LIMIT_YEARS;
6934
+ while (cal.year(date) <= limit) {
6935
+ if (!schedule.months.has(cal.month(date) + 1)) {
6936
+ cal.setMonth(date, cal.month(date) + 1);
6937
+ cal.setHours(date, 0);
6938
+ } else if (!dayMatches(schedule, cal, date)) {
6939
+ cal.setDate(date, cal.date(date) + 1);
6940
+ cal.setHours(date, 0);
6941
+ } else if (!schedule.hours.has(cal.hours(date))) {
6942
+ cal.setHours(date, cal.hours(date) + 1);
6943
+ } else if (!schedule.minutes.has(cal.minutes(date))) {
6944
+ cal.setMinutes(date, cal.minutes(date) + 1);
6945
+ } else return date.getTime();
6946
+ }
6947
+ return null;
6948
+ }
6949
+ function missedFires(schedule, from, until, utc = false, cap = MISSED_CAP) {
6950
+ let count2 = 0;
6951
+ let last = null;
6952
+ let at = from;
6953
+ while (count2 < cap) {
6954
+ at = nextFire(schedule, at, utc);
6955
+ if (at === null || at > until) return { count: count2, last, more: false };
6956
+ last = at;
6957
+ count2++;
6958
+ }
6959
+ const next3 = nextFire(schedule, last, utc);
6960
+ return { count: count2, last, more: next3 !== null && next3 <= until };
6961
+ }
6962
+
6963
+ // src/cron/table.ts
6964
+ var SYSTEM_CRONTAB = "/etc/crontab";
6965
+ var SPOOL_DIR = "/var/spool/cron/crontabs";
6966
+ var ENV_LINE = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;
6967
+ var NAME_LINE = /^#\s*name:\s*(.*?)\s*$/;
6968
+ var JOB_NAME = /^[A-Za-z0-9_][A-Za-z0-9_.-]*$/;
6969
+ var USER_NAME = /^[a-z_][a-z0-9_.-]*$/;
6970
+ function unquote(text) {
6971
+ const trimmed = text.trim();
6972
+ const quote = trimmed[0];
6973
+ if ((quote === '"' || quote === "'") && trimmed.length > 1 && trimmed.endsWith(quote))
6974
+ return trimmed.slice(1, -1);
6975
+ return trimmed;
6976
+ }
6977
+ function hashId(text) {
6978
+ let a = 2166136261;
6979
+ let b = 16777619;
6980
+ for (let i = 0; i < text.length; i++) {
6981
+ const c = text.charCodeAt(i);
6982
+ a = Math.imul(a ^ c, 16777619);
6983
+ b = Math.imul(b ^ c, 1540483477);
6984
+ }
6985
+ const hex3 = (n) => (n >>> 0).toString(16).padStart(8, "0");
6986
+ return hex3(a) + hex3(b);
6987
+ }
6988
+ function split2(text, count2) {
6989
+ const words2 = [];
6990
+ let rest2 = text;
6991
+ for (let i = 0; i < count2; i++) {
6992
+ const match = /^(\S+)\s+/.exec(rest2);
6993
+ if (!match) return void 0;
6994
+ words2.push(match[1]);
6995
+ rest2 = rest2.slice(match[0].length);
6996
+ }
6997
+ return [words2, rest2.trim()];
6998
+ }
6999
+ function jobOf(content, pending, ctx) {
7000
+ const fields = content.startsWith("@") ? 1 : 5;
7001
+ const parts2 = split2(content, fields + (ctx.system ? 1 : 0));
7002
+ if (!parts2 || parts2[1] === "") throw new Error("no command");
7003
+ const [words2, command] = parts2;
7004
+ const schedule = words2.slice(0, fields).join(" ");
7005
+ const when = parseWhen(schedule);
7006
+ const user = ctx.system ? words2[fields] : void 0;
7007
+ if (user !== void 0 && !USER_NAME.test(user)) throw new Error(`bad user name ${user}`);
7008
+ if (pending !== void 0 && !JOB_NAME.test(pending))
7009
+ throw new Error(`bad job name "${pending}"`);
7010
+ if (pending !== void 0 && ctx.names.has(pending))
7011
+ throw new Error(`job name ${pending} is taken`);
7012
+ const hashed = hashId(`${ctx.path}
7013
+ ${user ?? ""}
7014
+ ${schedule}
7015
+ ${command}`);
7016
+ let id2 = pending ?? hashed;
7017
+ for (let n = 2; pending === void 0 && ctx.names.has(id2); n++) id2 = `${hashed}.${n}`;
7018
+ ctx.names.add(id2);
7019
+ return {
7020
+ id: id2,
7021
+ ...pending !== void 0 ? { name: pending } : {},
7022
+ schedule,
7023
+ when,
7024
+ ...user !== void 0 ? { user } : {},
7025
+ command
7026
+ };
7027
+ }
7028
+ function parseCrontab(text, path, system = false) {
7029
+ const jobs = [];
7030
+ const errors = [];
7031
+ const env = {};
7032
+ const ctx = { path, system, names: /* @__PURE__ */ new Set() };
7033
+ let name2;
7034
+ for (const [index, raw] of text.split("\n").entries()) {
7035
+ const line = index + 1;
7036
+ const content = raw.trim();
7037
+ const named = NAME_LINE.exec(content);
7038
+ if (named) {
7039
+ name2 = named[1];
7040
+ continue;
7041
+ }
7042
+ const pending = name2;
7043
+ name2 = void 0;
7044
+ if (content === "" || content.startsWith("#")) continue;
7045
+ const assign = ENV_LINE.exec(content);
7046
+ if (assign) {
7047
+ env[assign[1]] = unquote(assign[2]);
7048
+ continue;
7049
+ }
7050
+ try {
7051
+ jobs.push({ line, ...jobOf(content, pending, ctx), env: { ...env } });
7052
+ } catch (err) {
7053
+ errors.push({ line, message: err.message });
7054
+ }
7055
+ }
7056
+ return { jobs, errors };
7057
+ }
7058
+
7059
+ // src/cron/service.ts
7060
+ var CRON_DIR = "/var/spool/cron";
7061
+ var STAMP_PATH = `${CRON_DIR}/stamp`;
7062
+ var LOG_DIR = "/var/log/cron";
7063
+ var ERR_LOG = `${LOG_DIR}/cron.err`;
7064
+ var LOG_CAP = 256 * 1024;
7065
+ var JOBS_PER_USER = 16;
7066
+ var WAKE_MS = 6e4;
7067
+ var BACK_JUMP_MS = 12e4;
7068
+ var DEFAULT_SHELL = "/bin/bash";
7069
+ var encoder = new TextEncoder();
7070
+ var EMPTY_STAMP = JSON.stringify({ jobs: {}, reboot: {} });
7071
+ var messageOf = (err) => err?.message ?? String(err);
7072
+ var keyOf2 = ({ source, job }) => `${source} ${job.id}`;
7073
+ function tail(bytes, cap = LOG_CAP) {
7074
+ return bytes.length > cap ? bytes.slice(bytes.length - cap) : bytes;
7075
+ }
7076
+ function concat2(parts2) {
7077
+ const out = new Uint8Array(parts2.reduce((n, part) => n + part.length, 0));
7078
+ let at = 0;
7079
+ for (const part of parts2) {
7080
+ out.set(part, at);
7081
+ at += part.length;
7082
+ }
7083
+ return out;
7084
+ }
7085
+ var Output = class {
7086
+ parts = [];
7087
+ size = 0;
7088
+ push(bytes) {
7089
+ this.parts.push(bytes.slice());
7090
+ this.size += bytes.length;
7091
+ if (this.size > LOG_CAP * 2) {
7092
+ const kept = tail(concat2(this.parts));
7093
+ this.parts = [kept];
7094
+ this.size = kept.length;
7095
+ }
7096
+ }
7097
+ bytes() {
7098
+ return tail(concat2(this.parts));
7099
+ }
7100
+ };
7101
+ function readStamp(text) {
7102
+ try {
7103
+ const parsed2 = JSON.parse(text ?? "");
7104
+ const jobs = parsed2.jobs && typeof parsed2.jobs === "object" ? parsed2.jobs : {};
7105
+ const reboot = parsed2.reboot && typeof parsed2.reboot === "object" ? parsed2.reboot : {};
7106
+ return { jobs: { ...jobs }, reboot: { ...reboot } };
7107
+ } catch {
7108
+ return { jobs: {}, reboot: {} };
7109
+ }
7110
+ }
7111
+ var CronService = class {
7112
+ host;
7113
+ clock;
7114
+ stopping = new AbortController();
7115
+ gate = new PathGate();
7116
+ running = /* @__PURE__ */ new Map();
7117
+ reported = /* @__PURE__ */ new Map();
7118
+ wake = new AbortController();
7119
+ started;
7120
+ rebooted = false;
7121
+ constructor(host) {
7122
+ this.host = host;
7123
+ this.clock = host.clock ?? systemCronClock;
7124
+ }
7125
+ start() {
7126
+ this.started ??= this.begin();
7127
+ return this.started;
7128
+ }
7129
+ stop() {
7130
+ this.stopping.abort();
7131
+ this.wake.abort();
7132
+ }
7133
+ async begin() {
7134
+ await this.host.ready?.().catch(() => void 0);
7135
+ if (this.stopping.signal.aborted) return;
7136
+ const { locks } = this.host;
7137
+ const fire = () => this.fire().catch((err) => {
7138
+ console.warn(`slicc-kernel cron: stopped: ${messageOf(err)}`);
7139
+ });
7140
+ if (!locks) return fire();
7141
+ await locks.request(this.host.lock, { signal: this.stopping.signal }, fire).catch(() => void 0);
7142
+ }
7143
+ poke = () => this.wake.abort();
7144
+ async fire() {
7145
+ await this.provision();
7146
+ const unwatch = await this.host.watch([SYSTEM_CRONTAB, SPOOL_DIR], this.poke);
7147
+ try {
7148
+ while (!this.stopping.signal.aborted) await this.pass();
7149
+ } finally {
7150
+ unwatch();
7151
+ }
7152
+ }
7153
+ async pass() {
7154
+ let until;
7155
+ try {
7156
+ until = await this.tick();
7157
+ } catch (err) {
7158
+ await this.error(`cron: ${messageOf(err)}`);
7159
+ until = this.clock.now() + WAKE_MS;
7160
+ }
7161
+ if (this.stopping.signal.aborted) return;
7162
+ if (this.wake.signal.aborted) this.wake = new AbortController();
7163
+ await this.clock.sleep(until, this.wake.signal);
7164
+ }
7165
+ async provision() {
7166
+ const { fs, owners } = this.host;
7167
+ for (const [dir, mode] of [
7168
+ [CRON_DIR, 493],
7169
+ [SPOOL_DIR, 448],
7170
+ [LOG_DIR, 493]
7171
+ ]) {
7172
+ if (await fs.exists(dir)) continue;
7173
+ await fs.mkdir(dir, { recursive: true });
7174
+ if (owners) await fs.chown?.(dir, { uid: 0, gid: 0, mode, follow: false });
7175
+ }
7176
+ }
7177
+ async tick() {
7178
+ const { fs } = this.host;
7179
+ const loaded = await this.load();
7180
+ const stamp = readStamp(await fs.readFile(STAMP_PATH).catch(() => void 0));
7181
+ const now = this.clock.now();
7182
+ const utc = this.clock.utc === true;
7183
+ const due2 = [];
7184
+ const keys = /* @__PURE__ */ new Set();
7185
+ let next3 = now + WAKE_MS;
7186
+ for (const entry of loaded) {
7187
+ const key = keyOf2(entry);
7188
+ keys.add(key);
7189
+ const { when } = entry.job;
7190
+ if (when.reboot) {
7191
+ if (this.rebooted || stamp.reboot[key] === this.host.bootId) continue;
7192
+ stamp.reboot[key] = this.host.bootId;
7193
+ due2.push({ entry, due: now, missed: 0 });
7194
+ continue;
7195
+ }
7196
+ const last = stamp.jobs[key];
7197
+ if (typeof last !== "number" || last > now + BACK_JUMP_MS) stamp.jobs[key] = now;
7198
+ else {
7199
+ const missed = missedFires(when.schedule, last, now, utc);
7200
+ if (missed.last !== null) {
7201
+ stamp.jobs[key] = now;
7202
+ due2.push({ entry, due: missed.last, missed: missed.count - 1 });
7203
+ }
7204
+ }
7205
+ const coming = nextFire(when.schedule, Math.max(now, stamp.jobs[key]), utc);
7206
+ if (coming !== null && coming < next3) next3 = coming;
7207
+ }
7208
+ this.rebooted = true;
7209
+ for (const map of [stamp.jobs, stamp.reboot])
7210
+ for (const key of Object.keys(map)) if (!keys.has(key)) delete map[key];
7211
+ await this.writeStamp(stamp);
7212
+ for (const each of due2) void this.spawn(each);
7213
+ return next3;
7214
+ }
7215
+ async writeStamp(stamp) {
7216
+ const { fs, owners } = this.host;
7217
+ const text = JSON.stringify(stamp);
7218
+ const old = await fs.readFile(STAMP_PATH).catch(() => void 0);
7219
+ if (old === text || old === void 0 && text === EMPTY_STAMP) return;
7220
+ const fresh2 = `${STAMP_PATH}.new`;
7221
+ const owner = owners ? { uid: 0, gid: 0, mode: 384 } : void 0;
7222
+ await fs.writeFile(fresh2, text, owner);
7223
+ await fs.rename(fresh2, STAMP_PATH);
7224
+ }
7225
+ async load() {
7226
+ const { fs } = this.host;
7227
+ const out = [];
7228
+ const system = await this.table(SYSTEM_CRONTAB, 0, true);
7229
+ for (const job of system?.jobs ?? []) {
7230
+ const account = await this.host.lookup(job.user);
7231
+ if (account) out.push({ source: "system", account, job });
7232
+ }
7233
+ const names = await fs.readdir(SPOOL_DIR).catch(() => []);
7234
+ for (const name2 of names.sort()) {
7235
+ if (name2.startsWith(".") || name2.endsWith("~") || name2.endsWith(".new")) continue;
7236
+ const path = `${SPOOL_DIR}/${name2}`;
7237
+ const account = await this.host.lookup(name2);
7238
+ if (!account) {
7239
+ await this.once(path, "no user", [`${path}: skipped: there is no user ${name2}`]);
7240
+ continue;
7241
+ }
7242
+ const table = await this.table(path, account.uid, false);
7243
+ for (const job of table?.jobs ?? []) out.push({ source: name2, account, job });
7244
+ }
7245
+ return out;
7246
+ }
7247
+ async table(path, uid, system) {
7248
+ const { fs, owners } = this.host;
7249
+ const st = await fs.lstat(path).catch(() => void 0);
7250
+ if (!st) {
7251
+ this.reported.delete(path);
7252
+ return void 0;
7253
+ }
7254
+ const trusted = st.isFile && (!owners || (st.uid === uid || st.uid === 0) && (st.mode & 18) === 0);
7255
+ if (!trusted) {
7256
+ const who = uid === 0 ? "root" : "its user or root";
7257
+ const why = `${path}: skipped: it must be a file of ${who}, writable by its owner only`;
7258
+ await this.once(path, "untrusted", [why]);
7259
+ return void 0;
7260
+ }
7261
+ const text = await fs.readFile(path).catch(() => "");
7262
+ const table = parseCrontab(text, path, system);
7263
+ const errors = table.errors.map(({ line, message: message3 }) => `${path}:${line}: ${message3}`);
7264
+ for (const job of table.jobs) {
7265
+ if (job.user !== void 0 && !await this.host.lookup(job.user))
7266
+ errors.push(`${path}:${job.line}: there is no user ${job.user}`);
7267
+ }
7268
+ await this.once(path, text, errors);
7269
+ return table;
7270
+ }
7271
+ async once(path, version, lines2) {
7272
+ if (this.reported.get(path) === version) return;
7273
+ this.reported.set(path, version);
7274
+ for (const line of lines2) await this.error(line);
7275
+ }
7276
+ async error(line) {
7277
+ if (this.stopping.signal.aborted) return;
7278
+ const stamp = new Date(this.clock.now()).toISOString();
7279
+ await this.append(ERR_LOG, encoder.encode(`${stamp} ${line}
7280
+ `), 0, 0).catch(() => void 0);
7281
+ }
7282
+ async append(path, bytes, uid, gid) {
7283
+ const { fs, owners } = this.host;
7284
+ await this.gate.run(path, async () => {
7285
+ const dir = path.slice(0, path.lastIndexOf("/"));
7286
+ if (!await fs.lstat(dir).catch(() => void 0)) {
7287
+ await fs.mkdir(dir, { recursive: true });
7288
+ if (owners) await fs.chown?.(dir, { uid: 0, gid: 0, mode: 493, follow: false });
7289
+ }
7290
+ const st = await fs.lstat(path).catch(() => void 0);
7291
+ if (owners) await this.trustLog(dir, path, st, uid);
7292
+ const old = st ? await fs.readFileBuffer(path) : void 0;
7293
+ const next3 = tail(old ? concat2([old, bytes]) : bytes);
7294
+ const owner = owners ? { uid, gid, mode: 384 } : void 0;
7295
+ await fs.writeFile(path, next3, old === void 0 ? owner : void 0);
7296
+ });
7297
+ }
7298
+ async trustLog(dir, path, st, uid) {
7299
+ const parent = await this.host.fs.lstat(dir);
7300
+ if (!parent.isDirectory || parent.isSymbolicLink || parent.uid !== 0)
7301
+ throw new Error(`${path} not written: ${dir} must be a directory of root`);
7302
+ if (st && (!st.isFile || st.isSymbolicLink || st.uid !== uid && st.uid !== 0))
7303
+ throw new Error(`${path} not written: it must be a file of uid ${uid} or root`);
7304
+ }
7305
+ logOf({ account, job }) {
7306
+ return normalizePath(`${LOG_DIR}/${account.name}/${job.id}.log`);
7307
+ }
7308
+ async spawn({ entry, due: due2, missed }) {
7309
+ const { account, job } = entry;
7310
+ const log = this.logOf(entry);
7311
+ const iso = new Date(due2).toISOString();
7312
+ const count2 = this.running.get(account.uid) ?? 0;
7313
+ if (count2 >= JOBS_PER_USER) {
7314
+ const why = `${JOBS_PER_USER} cron jobs of ${account.name} are running`;
7315
+ await this.append(
7316
+ log,
7317
+ encoder.encode(`--- ${iso} skipped: ${why} ---
7318
+ `),
7319
+ account.uid,
7320
+ account.gid
7321
+ ).catch((err) => this.error(messageOf(err)));
7322
+ await this.error(`${account.name}/${job.id}: run due ${iso} skipped: ${why}`);
7323
+ return;
7324
+ }
7325
+ this.running.set(account.uid, count2 + 1);
7326
+ const output = new Output();
7327
+ let ended;
7328
+ try {
7329
+ const cwd = await this.host.fs.exists(account.home) ? account.home : "/";
7330
+ const shell = job.env.SHELL ?? DEFAULT_SHELL;
7331
+ ended = await this.host.run({
7332
+ account,
7333
+ argv: [shell, "-c", job.command],
7334
+ cwd,
7335
+ env: {
7336
+ SHELL: shell,
7337
+ ...job.env,
7338
+ SLICC_CRON: "1",
7339
+ SLICC_CRON_JOB: job.id,
7340
+ SLICC_CRON_DUE: iso,
7341
+ SLICC_CRON_MISSED: String(missed)
7342
+ },
7343
+ output: (bytes) => output.push(bytes)
7344
+ });
7345
+ } catch (err) {
7346
+ output.push(encoder.encode(`cron: ${messageOf(err)}
7347
+ `));
7348
+ ended = { status: 127 };
7349
+ } finally {
7350
+ this.running.set(account.uid, (this.running.get(account.uid) ?? 1) - 1);
7351
+ }
7352
+ if (this.stopping.signal.aborted) return;
7353
+ const exit = ended.signal ? `signal=${ended.signal}` : `exit=${ended.status}`;
7354
+ const header4 = encoder.encode(`--- ${iso} ${exit} missed=${missed} ---
7355
+ `);
7356
+ const body = output.bytes();
7357
+ const newline = body.length > 0 && body[body.length - 1] !== 10 ? encoder.encode("\n") : new Uint8Array();
7358
+ await this.append(log, concat2([header4, body, newline]), account.uid, account.gid).catch(
7359
+ (err) => this.error(messageOf(err))
7360
+ );
7361
+ }
7362
+ };
7363
+
6797
7364
  // src/kernel/net/proxy-service.ts
6798
7365
  var SEND_BUFFER2 = 1024 * 1024;
6799
7366
  var TLS_HANDSHAKE = 22;
@@ -6858,12 +7425,12 @@ function localV4(a, b) {
6858
7425
  return a === 127 || a === 0 || a === 169 && b === 254;
6859
7426
  }
6860
7427
  function hextets(address) {
6861
- const [head, tail, extra] = address.split("::");
7428
+ const [head, tail2, extra] = address.split("::");
6862
7429
  if (extra !== void 0) return void 0;
6863
7430
  const part = (text) => text ? text.split(":").map((h) => Number.parseInt(h, 16)) : [];
6864
7431
  const front = part(head);
6865
- const back = part(tail);
6866
- const groups = tail === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
7432
+ const back = part(tail2);
7433
+ const groups = tail2 === void 0 ? front : [...front, ...new Array(8 - front.length - back.length).fill(0), ...back];
6867
7434
  return groups.length === 8 && groups.every((g) => g >= 0 && g <= 65535) ? groups : void 0;
6868
7435
  }
6869
7436
  function localV6(address) {
@@ -7989,12 +8556,12 @@ var FreshModules = class {
7989
8556
  return new Proxy(fs, {
7990
8557
  get(target, key, receiver) {
7991
8558
  if (Object.hasOwn(overrides, key)) return overrides[key];
7992
- const value = Reflect.get(target, key, receiver);
7993
- if (typeof value !== "function") return value;
7994
- let method = bound2.get(value);
8559
+ const value2 = Reflect.get(target, key, receiver);
8560
+ if (typeof value2 !== "function") return value2;
8561
+ let method = bound2.get(value2);
7995
8562
  if (method === void 0) {
7996
- method = value.bind(target);
7997
- bound2.set(value, method);
8563
+ method = value2.bind(target);
8564
+ bound2.set(value2, method);
7998
8565
  }
7999
8566
  return method;
8000
8567
  }
@@ -8189,8 +8756,8 @@ var FsWatchers = class {
8189
8756
  return new Proxy(fs, {
8190
8757
  get(target, key, receiver) {
8191
8758
  if (Object.hasOwn(overrides, key)) return overrides[key];
8192
- const value = Reflect.get(target, key, receiver);
8193
- return typeof value === "function" ? value.bind(target) : value;
8759
+ const value2 = Reflect.get(target, key, receiver);
8760
+ return typeof value2 === "function" ? value2.bind(target) : value2;
8194
8761
  }
8195
8762
  });
8196
8763
  }
@@ -8247,7 +8814,7 @@ function captureFile(onData, control) {
8247
8814
  close: () => control.ended()
8248
8815
  });
8249
8816
  }
8250
- function concat2(chunks2) {
8817
+ function concat3(chunks2) {
8251
8818
  const out = new Uint8Array(chunks2.reduce((n, c) => n + c.length, 0));
8252
8819
  let offset = 0;
8253
8820
  for (const chunk2 of chunks2) {
@@ -8417,14 +8984,14 @@ var ChildTable = class {
8417
8984
  if (!slots2 || !chunks2) return new Uint8Array(0);
8418
8985
  slots2.delete(slot2);
8419
8986
  if (slots2.size === 0) this.leftovers.delete(pid);
8420
- return concat2(chunks2);
8987
+ return concat3(chunks2);
8421
8988
  }
8422
8989
  };
8423
8990
 
8424
8991
  // src/kernel/clipboard.ts
8425
8992
  var CLIPBOARD_MAX_BYTES = 1024 * 1024;
8426
8993
  var CLIPBOARD_TIMEOUT_MS = 1e4;
8427
- var encoder = new TextEncoder();
8994
+ var encoder2 = new TextEncoder();
8428
8995
  var decoder = new TextDecoder("utf-8", { fatal: true });
8429
8996
  var READY = { readable: true, writable: true, hangup: false };
8430
8997
  function lineOf(err) {
@@ -8492,7 +9059,7 @@ var ClipboardChannel = class {
8492
9059
  const asked = this.broker.ask(async (hook) => {
8493
9060
  const text = await hook.read(stamp);
8494
9061
  if (typeof text !== "string") throw new KernelError("EIO", "the clipboard gave no text");
8495
- return encoder.encode(text);
9062
+ return encoder2.encode(text);
8496
9063
  });
8497
9064
  this.snapshot = asked;
8498
9065
  asked.then(
@@ -8602,12 +9169,12 @@ async function argvDigest(argv) {
8602
9169
  const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
8603
9170
  return [...hash].map((b) => b.toString(16).padStart(2, "0")).join("");
8604
9171
  }
8605
- function isStrings(value) {
8606
- return Array.isArray(value) && value.every((item) => typeof item === "string");
9172
+ function isStrings(value2) {
9173
+ return Array.isArray(value2) && value2.every((item) => typeof item === "string");
8607
9174
  }
8608
- function stringRecord(value) {
8609
- if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
8610
- const entries = Object.entries(value);
9175
+ function stringRecord(value2) {
9176
+ if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return void 0;
9177
+ const entries = Object.entries(value2);
8611
9178
  return entries.every(([, v]) => typeof v === "string") ? Object.fromEntries(entries) : void 0;
8612
9179
  }
8613
9180
  var TicketBook = class {
@@ -8767,14 +9334,14 @@ var DriverConnection = class _DriverConnection {
8767
9334
  var S_ISGID4 = 1024;
8768
9335
  var ID = /^\d{1,10}$/;
8769
9336
  var MAX_ID2 = 4294967294;
8770
- function idOption(value) {
8771
- return value === void 0 ? 0 : Number(value);
9337
+ function idOption(value2) {
9338
+ return value2 === void 0 ? 0 : Number(value2);
8772
9339
  }
8773
9340
  function checkIds(options) {
8774
9341
  for (const key of ["uid", "gid"]) {
8775
- const value = options[key];
8776
- if (value === void 0) continue;
8777
- if (!ID.test(value) || Number(value) > MAX_ID2) throw errnoError("EINVAL", `${key}=${value}`);
9342
+ const value2 = options[key];
9343
+ if (value2 === void 0) continue;
9344
+ if (!ID.test(value2) || Number(value2) > MAX_ID2) throw errnoError("EINVAL", `${key}=${value2}`);
8778
9345
  }
8779
9346
  }
8780
9347
  var MAX_LINKS7 = 40;
@@ -8988,7 +9555,7 @@ function statOf(attr2, path, mount) {
8988
9555
  } : {}
8989
9556
  };
8990
9557
  }
8991
- function concat3(chunks2, total) {
9558
+ function concat4(chunks2, total) {
8992
9559
  if (chunks2.length === 1 && chunks2[0]?.length === total) return chunks2[0];
8993
9560
  const out = new Uint8Array(total);
8994
9561
  let at = 0;
@@ -9495,7 +10062,7 @@ var MountFs = class _MountFs {
9495
10062
  } finally {
9496
10063
  await mount.conn.call({ op: "release", fh });
9497
10064
  }
9498
- return concat3(chunks2, total);
10065
+ return concat4(chunks2, total);
9499
10066
  }
9500
10067
  async writeFile(path, content, owner, redirects = 0) {
9501
10068
  const real = await this.follow(path, 0, true);
@@ -9590,7 +10157,7 @@ var MountFs = class _MountFs {
9590
10157
  } finally {
9591
10158
  await mount.conn.call({ op: "release", fh });
9592
10159
  }
9593
- return concat3(chunks2, total);
10160
+ return concat4(chunks2, total);
9594
10161
  }
9595
10162
  fits(mount, real, end) {
9596
10163
  if (mount.maxFile > 0 && end > mount.maxFile) {
@@ -10003,7 +10570,7 @@ var MountFs = class _MountFs {
10003
10570
  await mount.conn.call({
10004
10571
  op: "setattr",
10005
10572
  path: rel2,
10006
- ...Object.fromEntries(attrs.filter(([, value]) => value !== void 0))
10573
+ ...Object.fromEntries(attrs.filter(([, value2]) => value2 !== void 0))
10007
10574
  });
10008
10575
  }
10009
10576
  async chmod(path, mode, redirects = 0) {
@@ -10182,8 +10749,8 @@ async function storageUsage() {
10182
10749
  }
10183
10750
  var PLAIN_DIR_MODE = 493;
10184
10751
  var done = { ok: true, kind: "void" };
10185
- function json2(value) {
10186
- return { ok: true, kind: "json", json: value };
10752
+ function json2(value2) {
10753
+ return { ok: true, kind: "json", json: value2 };
10187
10754
  }
10188
10755
  function ownerFor2(entry, mode) {
10189
10756
  const cred = entry.cred?.();
@@ -10742,9 +11309,9 @@ function storeBlocked(header4, [low, high]) {
10742
11309
  }
10743
11310
  var anyBlocked = (mask) => mask !== void 0 && (mask[0] !== 0 || mask[1] !== 0);
10744
11311
  var U32 = 2 ** 32;
10745
- function storeU53(header4, lo, hi, value) {
10746
- Atomics.store(header4, hi, Math.floor(value / U32));
10747
- Atomics.store(header4, lo, value % U32 | 0);
11312
+ function storeU53(header4, lo, hi, value2) {
11313
+ Atomics.store(header4, hi, Math.floor(value2 / U32));
11314
+ Atomics.store(header4, lo, value2 % U32 | 0);
10748
11315
  }
10749
11316
  var SAB_STATE_READY = 2;
10750
11317
  var SAB_STATUS_BYTES = 1;
@@ -10755,20 +11322,20 @@ var SAB_DEFAULT_WINDOW_BYTES = 1024 * 1024;
10755
11322
  var SAB_MIN_BYTES = SAB_HEADER_BYTES + 4096;
10756
11323
  var SYNC_SAB_REQ_MSG = "sync-sab-req";
10757
11324
  var SYNC_SAB_NEXT_MSG = "sync-sab-next";
10758
- var encoder2 = new TextEncoder();
11325
+ var encoder3 = new TextEncoder();
10759
11326
  var decoder2 = new TextDecoder();
10760
11327
  function encodeSabResult(result) {
10761
11328
  if (!result.ok) {
10762
11329
  return {
10763
11330
  status: SAB_STATUS_ERRNO,
10764
- payload: encoder2.encode(JSON.stringify({ errno: result.errno, message: result.message }))
11331
+ payload: encoder3.encode(JSON.stringify({ errno: result.errno, message: result.message }))
10765
11332
  };
10766
11333
  }
10767
11334
  switch (result.kind) {
10768
11335
  case "bytes":
10769
11336
  return { status: SAB_STATUS_BYTES, payload: result.bytes };
10770
11337
  case "json":
10771
- return { status: SAB_STATUS_JSON, payload: encoder2.encode(JSON.stringify(result.json)) };
11338
+ return { status: SAB_STATUS_JSON, payload: encoder3.encode(JSON.stringify(result.json)) };
10772
11339
  default:
10773
11340
  return { status: SAB_STATUS_VOID, payload: new Uint8Array(0) };
10774
11341
  }
@@ -10876,14 +11443,14 @@ function attachSyncSabResponder(port, sab, token, opts) {
10876
11443
 
10877
11444
  // src/kernel/cpu-clock.ts
10878
11445
  var SYS_CAP_US = 2e4;
10879
- var LOCAL = SAB_CLOCK_OFFSET;
11446
+ var LOCAL2 = SAB_CLOCK_OFFSET;
10880
11447
  var BLOCKED = 0;
10881
11448
  var IDLE = 1;
10882
11449
  function epochMicros() {
10883
11450
  return Math.floor((performance.timeOrigin + performance.now()) * 1e3);
10884
11451
  }
10885
11452
  function slots(sab) {
10886
- return new BigInt64Array(sab, LOCAL, SAB_CLOCK_I64);
11453
+ return new BigInt64Array(sab, LOCAL2, SAB_CLOCK_I64);
10887
11454
  }
10888
11455
  var rawWait = Atomics.wait.bind(Atomics);
10889
11456
  function localIdle(sab, now) {
@@ -11272,14 +11839,14 @@ var KernelDgram = class {
11272
11839
  }
11273
11840
  return this.options.get(`${level}:${name2}`) ?? 0;
11274
11841
  }
11275
- setOption(level, name2, value) {
11276
- if (level === SOL_SOCKET2 && name2 === SO_BROADCAST && value !== 0) {
11842
+ setOption(level, name2, value2) {
11843
+ if (level === SOL_SOCKET2 && name2 === SO_BROADCAST && value2 !== 0) {
11277
11844
  throw new KernelError("EOPNOTSUPP");
11278
11845
  }
11279
11846
  if (level === IPPROTO_IP && name2 >= IP_MULTICAST_FIRST && name2 <= IP_MULTICAST_LAST) {
11280
11847
  throw new KernelError("ENOPROTOOPT");
11281
11848
  }
11282
- this.options.set(`${level}:${name2}`, value);
11849
+ this.options.set(`${level}:${name2}`, value2);
11283
11850
  }
11284
11851
  close() {
11285
11852
  if (this.closed) return;
@@ -11538,7 +12105,7 @@ var PATH_OPS = new Set(SYNC_FS_OPS);
11538
12105
  var EARLY_WHOLE_FILE = 64 * 1024;
11539
12106
 
11540
12107
  // src/process/process-fds.ts
11541
- var field2 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
12108
+ var field3 = (text) => (text || "none").replace(/[\s\\]/g, (c) => `\\${c.charCodeAt(0).toString(8).padStart(3, "0")}`);
11542
12109
  var pinnedRoot;
11543
12110
  var rootKind = () => globalThis.navigator?.storage ? "opfs" : "memory";
11544
12111
  function mountTable(mounts = []) {
@@ -11549,7 +12116,7 @@ function mountTable(mounts = []) {
11549
12116
  if (m.state !== "ok") options.push(m.state);
11550
12117
  const access2 = options.includes("ro") ? [] : ["rw"];
11551
12118
  lines2.push(
11552
- `${field2(m.source)} ${field2(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
12119
+ `${field3(m.source)} ${field3(m.target)} ${m.type} ${[...access2, ...options].join(",")} 0 0`
11553
12120
  );
11554
12121
  }
11555
12122
  return `${lines2.join("\n")}
@@ -11705,7 +12272,7 @@ function memoryInfo(source, used = 0) {
11705
12272
  ["SReclaimable", kb(0)],
11706
12273
  ["SwapTotal", kb(0)],
11707
12274
  ["SwapFree", kb(0)]
11708
- ].map(([key, value]) => `${`${key}:`.padEnd(16)}${value.padStart(12)}`).concat("").join("\n");
12275
+ ].map(([key, value2]) => `${`${key}:`.padEnd(16)}${value2.padStart(12)}`).concat("").join("\n");
11709
12276
  }
11710
12277
  function systemFile(name2, listing, now, memory) {
11711
12278
  if (name2 === "version") return procVersion();
@@ -11960,15 +12527,15 @@ async function procAlias(fs, path, follow2) {
11960
12527
  );
11961
12528
  if (!physical) return void 0;
11962
12529
  const walk2 = procWalk(path, follow2);
11963
- let step = walk2.next();
11964
- while (!step.done) {
11965
- const { at, check } = step.value;
12530
+ let step2 = walk2.next();
12531
+ while (!step2.done) {
12532
+ const { at, check } = step2.value;
11966
12533
  const link2 = await readlink.call(fs, at).catch(() => void 0);
11967
12534
  const isDir = (st) => st.isDirectory === true;
11968
12535
  const target = link2 ?? (check ? await lstat.call(fs, at).then(isDir, failed) : true);
11969
- step = walk2.next(target);
12536
+ step2 = walk2.next(target);
11970
12537
  }
11971
- return step.value;
12538
+ return step2.value;
11972
12539
  }
11973
12540
 
11974
12541
  // src/kernel/eventfd.ts
@@ -12014,23 +12581,23 @@ var EventFd = class _EventFd {
12014
12581
  blocked(signal);
12015
12582
  await this.changes.wait(signal);
12016
12583
  }
12017
- const value = this.semaphore ? 1n : this.count;
12018
- this.count -= value;
12584
+ const value2 = this.semaphore ? 1n : this.count;
12585
+ this.count -= value2;
12019
12586
  this.changes.wake();
12020
12587
  const out = new Uint8Array(_EventFd.SIZE);
12021
- new DataView(out.buffer).setBigUint64(0, value, true);
12588
+ new DataView(out.buffer).setBigUint64(0, value2, true);
12022
12589
  return out;
12023
12590
  }
12024
12591
  async write(bytes, signal) {
12025
12592
  if (bytes.length < _EventFd.SIZE) throw new KernelError("EINVAL");
12026
- const value = new DataView(bytes.buffer, bytes.byteOffset, _EventFd.SIZE).getBigUint64(0, true);
12027
- if (value > EVENTFD_MAX) throw new KernelError("EINVAL");
12028
- while (EVENTFD_MAX - this.count < value) {
12593
+ const value2 = new DataView(bytes.buffer, bytes.byteOffset, _EventFd.SIZE).getBigUint64(0, true);
12594
+ if (value2 > EVENTFD_MAX) throw new KernelError("EINVAL");
12595
+ while (EVENTFD_MAX - this.count < value2) {
12029
12596
  blocked(signal);
12030
12597
  await this.changes.wait(signal);
12031
12598
  }
12032
- this.count += value;
12033
- if (value > 0n) this.changes.wake();
12599
+ this.count += value2;
12600
+ if (value2 > 0n) this.changes.wake();
12034
12601
  return _EventFd.SIZE;
12035
12602
  }
12036
12603
  poll() {
@@ -12317,10 +12884,10 @@ var LockTable = class {
12317
12884
  }
12318
12885
  set(key, owner, kind, start2, end) {
12319
12886
  if (kind !== "unlock" && this.holder(key, owner, { key, kind, start: start2, end })) return false;
12320
- const range = { start: start2, end };
12887
+ const range2 = { start: start2, end };
12321
12888
  const kept = [];
12322
12889
  for (const lock of this.records.get(key) ?? []) {
12323
- if (lock.owner !== owner || !overlaps(lock, range)) kept.push(lock);
12890
+ if (lock.owner !== owner || !overlaps(lock, range2)) kept.push(lock);
12324
12891
  else {
12325
12892
  if (lock.start < start2) kept.push({ ...lock, end: start2 });
12326
12893
  if (lock.end > end) kept.push({ ...lock, start: end });
@@ -12331,13 +12898,13 @@ var LockTable = class {
12331
12898
  this.wake(key);
12332
12899
  return true;
12333
12900
  }
12334
- async wait(key, owner, kind, range, blocking) {
12335
- const want = { key, kind, ...range };
12901
+ async wait(key, owner, kind, range2, blocking) {
12902
+ const want = { key, kind, ...range2 };
12336
12903
  let signal;
12337
12904
  for (; ; ) {
12338
12905
  const holder = this.holder(key, owner, want);
12339
12906
  if (!holder) {
12340
- this.set(key, owner, kind, range.start, range.end);
12907
+ this.set(key, owner, kind, range2.start, range2.end);
12341
12908
  return;
12342
12909
  }
12343
12910
  if (this.waitsOn(holder.owner, owner)) throw new KernelError("EDEADLK");
@@ -12460,7 +13027,7 @@ var HOST_OPS = [
12460
13027
  "async-settle",
12461
13028
  "async-close"
12462
13029
  ];
12463
- var json3 = (value) => ({ ok: true, kind: "json", json: value });
13030
+ var json3 = (value2) => ({ ok: true, kind: "json", json: value2 });
12464
13031
  var done2 = { ok: true, kind: "void" };
12465
13032
  var KEPT_OPS = /* @__PURE__ */ new Set(["fd-write"]);
12466
13033
  var unknownSettled = false;
@@ -12490,9 +13057,9 @@ var AsyncOps = class {
12490
13057
  );
12491
13058
  return id2;
12492
13059
  }
12493
- resolve(value) {
13060
+ resolve(value2) {
12494
13061
  const id2 = this.hold();
12495
- this.complete(id2, json3(value));
13062
+ this.complete(id2, json3(value2));
12496
13063
  return id2;
12497
13064
  }
12498
13065
  hold() {
@@ -12637,19 +13204,19 @@ async function recordLock2(req, ctx) {
12637
13204
  locks.dropFile(await fileKey(target, "close"), owner);
12638
13205
  return done2;
12639
13206
  }
12640
- const range = lockRange(req.start, req.len);
13207
+ const range2 = lockRange(req.start, req.len);
12641
13208
  const key = await fileKey(target, req.kind, req.op === "lk-set" && req.fd !== void 0);
12642
13209
  if (req.op === "lk-get") {
12643
- const held = locks.holder(key, owner, { key, kind: req.kind, ...range });
13210
+ const held = locks.holder(key, owner, { key, kind: req.kind, ...range2 });
12644
13211
  if (!held) return json3(null);
12645
13212
  const len = held.end === Number.POSITIVE_INFINITY ? 0 : held.end - held.start;
12646
13213
  return json3({ kind: held.kind, pid: held.owner, start: held.start, len });
12647
13214
  }
12648
13215
  if (req.kind !== "unlock" && req.wait) {
12649
- await locks.wait(key, owner, req.kind, range, ctx.blocking);
13216
+ await locks.wait(key, owner, req.kind, range2, ctx.blocking);
12650
13217
  return done2;
12651
13218
  }
12652
- if (!locks.set(key, owner, req.kind, range.start, range.end)) throw new KernelError("EAGAIN");
13219
+ if (!locks.set(key, owner, req.kind, range2.start, range2.end)) throw new KernelError("EAGAIN");
12653
13220
  return done2;
12654
13221
  }
12655
13222
 
@@ -12682,15 +13249,16 @@ var MAX_UNREAD = 16 * 1024 * 1024;
12682
13249
  function errno(code, message3) {
12683
13250
  return Object.assign(new Error(`${code}: ${message3}`), { code });
12684
13251
  }
12685
- function requestHead(method, url, headers, extra) {
13252
+ function requestHead(method, url, headers, extra, first = []) {
12686
13253
  if (!TOKEN3.test(method)) throw errno("EINVAL", `method ${method}`);
12687
- const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `Host: ${url.host}`];
12688
- for (const [name2, value] of headers) {
13254
+ const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
13255
+ for (const [name2, value2] of first) lines2.push(`${name2}: ${value2}`);
13256
+ for (const [name2, value2] of headers) {
12689
13257
  if (OWN_HEADERS.has(name2.toLowerCase())) continue;
12690
- if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value)) throw errno("EINVAL", `header ${name2}`);
12691
- lines2.push(`${name2}: ${value}`);
13258
+ if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno("EINVAL", `header ${name2}`);
13259
+ lines2.push(`${name2}: ${value2}`);
12692
13260
  }
12693
- for (const [name2, value] of extra) lines2.push(`${name2}: ${value}`);
13261
+ for (const [name2, value2] of extra) lines2.push(`${name2}: ${value2}`);
12694
13262
  return latin1Bytes(`${lines2.join("\r\n")}\r
12695
13263
  \r
12696
13264
  `);
@@ -12799,8 +13367,8 @@ var KernelLoopback = class {
12799
13367
  async fetch(req, port) {
12800
13368
  const url = new URL(req.url);
12801
13369
  const body = req.body ?? (/^(POST|PUT|PATCH)$/i.test(req.method) ? new Uint8Array(0) : void 0);
12802
- const length2 = body ? [["Content-Length", String(body.length)]] : [];
12803
- const head = requestHead(req.method, url, req.headers, [...length2, ["Connection", "close"]]);
13370
+ const length2 = body ? [["content-length", String(body.length)]] : [];
13371
+ const head = requestHead(req.method, url, req.headers, length2, [["connection", "close"]]);
12804
13372
  const socket = await this.connect(url, port, req.signal);
12805
13373
  try {
12806
13374
  await writeAll2(socket, body ? concat([head, body]) : head, req.signal);
@@ -12893,7 +13461,7 @@ var LoopbackWebSocket = class {
12893
13461
  const queue = [];
12894
13462
  let wake;
12895
13463
  let ended = false;
12896
- void this.pump(new WsReader(incoming, void 0, true, true), (message3) => {
13464
+ void this.pump(incoming, (message3) => {
12897
13465
  queue.push(message3);
12898
13466
  this.unread += message3.length;
12899
13467
  wake?.();
@@ -12948,7 +13516,8 @@ var LoopbackWebSocket = class {
12948
13516
  this.pending -= bytes.length;
12949
13517
  })();
12950
13518
  }
12951
- async pump(reader, deliver) {
13519
+ async pump(incoming, deliver) {
13520
+ const reader = new WsReader(incoming, void 0, true, true);
12952
13521
  let close = { code: 1006, reason: "", wasClean: false };
12953
13522
  try {
12954
13523
  for (; ; ) {
@@ -12970,11 +13539,18 @@ var LoopbackWebSocket = class {
12970
13539
  } finally {
12971
13540
  const late = setTimeout(() => this.stop.abort(), CLOSE_WAIT_MS3);
12972
13541
  await this.writes;
13542
+ if (close.wasClean) await this.serverEnd(incoming);
12973
13543
  clearTimeout(late);
12974
13544
  this.socket.close();
12975
13545
  this.settle(close);
12976
13546
  }
12977
13547
  }
13548
+ async serverEnd(incoming) {
13549
+ try {
13550
+ while ((await incoming.some(64 * 1024, this.stop.signal)).length > 0) ;
13551
+ } catch {
13552
+ }
13553
+ }
12978
13554
  sendClose(code, reason) {
12979
13555
  if (this.sentClose) return;
12980
13556
  this.sentClose = true;
@@ -12998,7 +13574,7 @@ var LoopbackWebSocket = class {
12998
13574
  };
12999
13575
 
13000
13576
  // src/kernel/net/x509.ts
13001
- function concat4(parts2) {
13577
+ function concat5(parts2) {
13002
13578
  const out = new Uint8Array(parts2.reduce((n, p) => n + p.length, 0));
13003
13579
  let at = 0;
13004
13580
  for (const p of parts2) {
@@ -13014,8 +13590,8 @@ function length(n) {
13014
13590
  return Uint8Array.of(128 | bytes.length, ...bytes);
13015
13591
  }
13016
13592
  function tlv(tag, ...contents2) {
13017
- const body = concat4(contents2);
13018
- return concat4([Uint8Array.of(tag), length(body.length), body]);
13593
+ const body = concat5(contents2);
13594
+ return concat5([Uint8Array.of(tag), length(body.length), body]);
13019
13595
  }
13020
13596
  var seq = (...parts2) => tlv(48, ...parts2);
13021
13597
  var set2 = (...parts2) => tlv(49, ...parts2);
@@ -13026,7 +13602,7 @@ function integer(magnitude) {
13026
13602
  let start2 = 0;
13027
13603
  while (start2 < magnitude.length - 1 && magnitude[start2] === 0) start2++;
13028
13604
  const trimmed = magnitude.subarray(start2);
13029
- return tlv(2, trimmed[0] & 128 ? concat4([Uint8Array.of(0), trimmed]) : trimmed);
13605
+ return tlv(2, trimmed[0] & 128 ? concat5([Uint8Array.of(0), trimmed]) : trimmed);
13030
13606
  }
13031
13607
  function oid(dotted) {
13032
13608
  const [a, b, ...rest2] = dotted.split(".").map(Number);
@@ -13055,8 +13631,8 @@ function name(dn) {
13055
13631
  rdns.push(set2(seq(oid("2.5.4.3"), utf8(dn.commonName))));
13056
13632
  return seq(...rdns);
13057
13633
  }
13058
- function extension(id2, critical, value) {
13059
- return critical ? seq(oid(id2), TRUE, octets(value)) : seq(oid(id2), octets(value));
13634
+ function extension(id2, critical, value2) {
13635
+ return critical ? seq(oid(id2), TRUE, octets(value2)) : seq(oid(id2), octets(value2));
13060
13636
  }
13061
13637
  function children(der) {
13062
13638
  const out = [];
@@ -13113,11 +13689,11 @@ function ipv6(host) {
13113
13689
  if (!host.includes(":") || !/^[0-9A-Fa-f:.]+$/.test(host)) return void 0;
13114
13690
  const v4 = /(\d{1,3}(?:\.\d{1,3}){3})$/.exec(host);
13115
13691
  let text = host;
13116
- const tail = [];
13692
+ const tail2 = [];
13117
13693
  if (v4) {
13118
13694
  const bytes = ipv4(v4[1]);
13119
13695
  if (!bytes) return void 0;
13120
- tail.push(bytes[0] << 8 | bytes[1], bytes[2] << 8 | bytes[3]);
13696
+ tail2.push(bytes[0] << 8 | bytes[1], bytes[2] << 8 | bytes[3]);
13121
13697
  text = host.slice(0, -v4[1].length).replace(/:$/, host.endsWith(`::${v4[1]}`) ? ":" : "");
13122
13698
  }
13123
13699
  const halves = text.split("::");
@@ -13127,13 +13703,13 @@ function ipv6(host) {
13127
13703
  const back = halves.length === 2 ? groups(halves[1]) : [];
13128
13704
  if (![...head, ...back].every((g) => /^[0-9A-Fa-f]{1,4}$/.test(g))) return void 0;
13129
13705
  const words2 = [...head, ...back].map((g) => Number.parseInt(g, 16));
13130
- const missing4 = 8 - words2.length - tail.length;
13706
+ const missing4 = 8 - words2.length - tail2.length;
13131
13707
  if (halves.length === 2 ? missing4 < 1 : missing4 !== 0) return void 0;
13132
13708
  const all = [
13133
13709
  ...head.map((g) => Number.parseInt(g, 16)),
13134
13710
  ...new Array(halves.length === 2 ? missing4 : 0).fill(0),
13135
13711
  ...back.map((g) => Number.parseInt(g, 16)),
13136
- ...tail
13712
+ ...tail2
13137
13713
  ];
13138
13714
  return Uint8Array.from(all.flatMap((w) => [w >> 8, w & 255]));
13139
13715
  }
@@ -14123,11 +14699,11 @@ function waitFor(lookup4, signal) {
14123
14699
  reject(new KernelError("EINTR"));
14124
14700
  };
14125
14701
  signal?.addEventListener("abort", abort, { once: true });
14126
- void lookup4.work.then((value) => {
14702
+ void lookup4.work.then((value2) => {
14127
14703
  if (signal?.aborted) return;
14128
14704
  lookup4.waiters--;
14129
14705
  signal?.removeEventListener("abort", abort);
14130
- resolve2(value);
14706
+ resolve2(value2);
14131
14707
  });
14132
14708
  });
14133
14709
  }
@@ -14164,7 +14740,7 @@ function defaultTermios() {
14164
14740
  c_cc: cCc
14165
14741
  };
14166
14742
  }
14167
- var encoder3 = new TextEncoder();
14743
+ var encoder4 = new TextEncoder();
14168
14744
  function isContinuation(byte) {
14169
14745
  return (byte & 192) === 128;
14170
14746
  }
@@ -14287,7 +14863,7 @@ var KernelTty = class {
14287
14863
  this.line.push(byte);
14288
14864
  this.readable.push(Uint8Array.from(this.line));
14289
14865
  this.line = [];
14290
- if (echo) this.output(encoder3.encode("\n"));
14866
+ if (echo) this.output(encoder4.encode("\n"));
14291
14867
  } else {
14292
14868
  this.line.push(byte);
14293
14869
  if (echo) this.echo(byte);
@@ -14312,7 +14888,7 @@ var KernelTty = class {
14312
14888
  const utf83 = (this.termios.c_iflag & IUTF8) !== 0;
14313
14889
  const cells = utf83 ? dropped2.filter((b) => !isContinuation(b)).length : dropped2.length;
14314
14890
  if (cells > 0 && this.termios.c_lflag & ECHO) {
14315
- this.output(encoder3.encode("\b \b".repeat(cells)), false);
14891
+ this.output(encoder4.encode("\b \b".repeat(cells)), false);
14316
14892
  }
14317
14893
  }
14318
14894
  echo(byte) {
@@ -14564,7 +15140,7 @@ function terminalOf(ctx, fd) {
14564
15140
  if (!tty) throw new KernelError("ENOTTY");
14565
15141
  return tty;
14566
15142
  }
14567
- var json4 = (value) => ({ ok: true, kind: "json", json: value });
15143
+ var json4 = (value2) => ({ ok: true, kind: "json", json: value2 });
14568
15144
  var done3 = { ok: true, kind: "void" };
14569
15145
  function sizeKey(rows, cols) {
14570
15146
  return `${rows}x${cols}`;
@@ -14780,8 +15356,8 @@ var Semaphore = class {
14780
15356
  gid;
14781
15357
  mode;
14782
15358
  waiters = [];
14783
- constructor(value, uid, gid, mode) {
14784
- this.value = value;
15359
+ constructor(value2, uid, gid, mode) {
15360
+ this.value = value2;
14785
15361
  this.uid = uid;
14786
15362
  this.gid = gid;
14787
15363
  this.mode = mode;
@@ -15406,10 +15982,10 @@ var VfsNodes = class {
15406
15982
  async onEntry(path, op) {
15407
15983
  const key = await this.entryKey(path);
15408
15984
  const run2 = (this.entries.get(key) ?? Promise.resolve()).then(op);
15409
- const tail = run2.catch(() => void 0);
15410
- this.entries.set(key, tail);
15411
- void tail.then(() => {
15412
- if (this.entries.get(key) === tail) this.entries.delete(key);
15985
+ const tail2 = run2.catch(() => void 0);
15986
+ this.entries.set(key, tail2);
15987
+ void tail2.then(() => {
15988
+ if (this.entries.get(key) === tail2) this.entries.delete(key);
15413
15989
  });
15414
15990
  return run2;
15415
15991
  }
@@ -16034,11 +16610,11 @@ var MAX_READ = 1024 * 1024;
16034
16610
  var WRITE_ACCESS = 3;
16035
16611
  var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
16036
16612
  var DEFAULT_UMASK2 = 18;
16037
- function words(value) {
16038
- if (!Array.isArray(value) || !value.every((w) => typeof w === "string")) {
16613
+ function words(value2) {
16614
+ if (!Array.isArray(value2) || !value2.every((w) => typeof w === "string")) {
16039
16615
  throw new KernelError("EINVAL");
16040
16616
  }
16041
- return [...value];
16617
+ return [...value2];
16042
16618
  }
16043
16619
  var ESCAPES = { " ": "\\t", "\n": "\\n", "\r": "\\r" };
16044
16620
  function clipboardLine(text) {
@@ -18011,7 +18587,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
18011
18587
  clearTimeout(entry.timer);
18012
18588
  void entry.final.cancel().catch(() => void 0);
18013
18589
  };
18014
- const keyOf2 = (owner, method, url) => `${owner} ${method} ${url}`;
18590
+ const keyOf3 = (owner, method, url) => `${owner} ${method} ${url}`;
18015
18591
  const hold = (key, chain2) => {
18016
18592
  drop(key);
18017
18593
  const mine = [...held.keys()].filter((k) => held.get(k)?.owner === chain2.owner);
@@ -18030,7 +18606,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
18030
18606
  const method = followedWith(hop.status, chain2.method);
18031
18607
  const away = target.origin !== new URL(hop.url).origin;
18032
18608
  const print = away ? unauthorized(chain2.fingerprint) : chain2.fingerprint;
18033
- hold(keyOf2(chain2.owner, method, target.href), {
18609
+ hold(keyOf3(chain2.owner, method, target.href), {
18034
18610
  ...chain2,
18035
18611
  method,
18036
18612
  fingerprint: print,
@@ -18044,7 +18620,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
18044
18620
  },
18045
18621
  ...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
18046
18622
  async fetch(request, owner = KERNEL) {
18047
- const key = keyOf2(owner, request.method, request.url);
18623
+ const key = keyOf3(owner, request.method, request.url);
18048
18624
  const waiting = held.get(key);
18049
18625
  if (waiting && waiting.fingerprint === fingerprint(request.headers)) {
18050
18626
  held.delete(key);
@@ -18069,10 +18645,10 @@ function replayingHops(inner, heldMs = HELD_MS) {
18069
18645
  var FRAGMENT = 16;
18070
18646
  var MIN_VALUE = 8;
18071
18647
  var MIN_BASE64 = 8;
18072
- var encoder4 = new TextEncoder();
18648
+ var encoder5 = new TextEncoder();
18073
18649
  var STD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18074
18650
  function utf82(text) {
18075
- return encoder4.encode(text);
18651
+ return encoder5.encode(text);
18076
18652
  }
18077
18653
  function base642(bytes, padded = true) {
18078
18654
  let out = "";
@@ -18104,30 +18680,30 @@ function embedded(bytes, offset) {
18104
18680
  const last = Math.floor(8 * (offset + bytes.length) / 6);
18105
18681
  return encoded.slice(first, last);
18106
18682
  }
18107
- function unicode(value, upper) {
18683
+ function unicode(value2, upper) {
18108
18684
  let out = "";
18109
- for (let i = 0; i < value.length; i++) {
18110
- const unit = value.charCodeAt(i);
18685
+ for (let i = 0; i < value2.length; i++) {
18686
+ const unit = value2.charCodeAt(i);
18111
18687
  if (unit === 34) out += '\\"';
18112
18688
  else if (unit === 92) out += "\\\\";
18113
18689
  else if (unit < 32 || unit > 126) {
18114
18690
  const code = unit.toString(16).padStart(4, "0");
18115
18691
  out += `\\u${upper ? code.toUpperCase() : code}`;
18116
- } else out += value[i];
18692
+ } else out += value2[i];
18117
18693
  }
18118
18694
  return out;
18119
18695
  }
18120
- function percent(value) {
18696
+ function percent(value2) {
18121
18697
  let component;
18122
18698
  try {
18123
- component = encodeURIComponent(value);
18699
+ component = encodeURIComponent(value2);
18124
18700
  } catch {
18125
18701
  return [];
18126
18702
  }
18127
18703
  const lower = component.replace(/%[0-9A-F]{2}/g, (escape) => escape.toLowerCase());
18128
18704
  const plus = component.replace(/%20/g, "+");
18129
18705
  let form = "";
18130
- for (const byte of utf82(value)) {
18706
+ for (const byte of utf82(value2)) {
18131
18707
  const char = String.fromCharCode(byte);
18132
18708
  if (/[A-Za-z0-9*\-._]/.test(char)) form += char;
18133
18709
  else if (byte === 32) form += "+";
@@ -18135,8 +18711,8 @@ function percent(value) {
18135
18711
  }
18136
18712
  return [component, lower, plus, form];
18137
18713
  }
18138
- function html(value, apostrophe) {
18139
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, apostrophe);
18714
+ function html(value2, apostrophe) {
18715
+ return value2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, apostrophe);
18140
18716
  }
18141
18717
  function encodings(bytes) {
18142
18718
  const standard = [base642(bytes), base642(bytes, false)];
@@ -18146,9 +18722,9 @@ function encodings(bytes) {
18146
18722
  }
18147
18723
  return [...standard, ...standard.map(urlSafe)];
18148
18724
  }
18149
- function shapes(value) {
18150
- const raw = utf82(value);
18151
- const seen = /* @__PURE__ */ new Set([value]);
18725
+ function shapes(value2) {
18726
+ const raw = utf82(value2);
18727
+ const seen = /* @__PURE__ */ new Set([value2]);
18152
18728
  const out = [];
18153
18729
  if (raw.length < FRAGMENT) out.push({ bytes: raw, form: "raw" });
18154
18730
  for (let offset = 0; raw.length >= FRAGMENT && offset + FRAGMENT <= raw.length; offset++) {
@@ -18159,17 +18735,17 @@ function shapes(value) {
18159
18735
  seen.add(text);
18160
18736
  out.push({ bytes: utf82(text), form });
18161
18737
  };
18162
- const json5 = JSON.stringify(value).slice(1, -1);
18738
+ const json5 = JSON.stringify(value2).slice(1, -1);
18163
18739
  for (const text of [
18164
18740
  json5,
18165
18741
  json5.replace(/\//g, "\\/"),
18166
- unicode(value, false),
18167
- unicode(value, true)
18742
+ unicode(value2, false),
18743
+ unicode(value2, true)
18168
18744
  ]) {
18169
18745
  add(text, "json");
18170
18746
  }
18171
- for (const text of percent(value)) add(text, "percent");
18172
- for (const text of [html(value, "&#39;"), html(value, "&#x27;")]) add(text, "html");
18747
+ for (const text of percent(value2)) add(text, "percent");
18748
+ for (const text of [html(value2, "&#39;"), html(value2, "&#x27;")]) add(text, "html");
18173
18749
  for (const text of encodings(raw)) add(text, "base64");
18174
18750
  add(hex2(raw), "hex");
18175
18751
  add(hex2(raw).toUpperCase(), "hex");
@@ -18320,15 +18896,15 @@ function resolve(c, input, start2, end, source) {
18320
18896
  growing: false
18321
18897
  };
18322
18898
  }
18323
- const value = c.values[source.secret];
18899
+ const value2 = c.values[source.secret];
18324
18900
  let stop = end;
18325
18901
  let at = source.offset + FRAGMENT;
18326
- while (stop < input.length && at < value.length && input[stop] === value[at]) {
18902
+ while (stop < input.length && at < value2.length && input[stop] === value2[at]) {
18327
18903
  stop++;
18328
18904
  at++;
18329
18905
  }
18330
- const form = source.offset === 0 && at === value.length ? "raw" : "fragment";
18331
- const growing = stop === input.length && at < value.length;
18906
+ const form = source.offset === 0 && at === value2.length ? "raw" : "fragment";
18907
+ const growing = stop === input.length && at < value2.length;
18332
18908
  return { start: start2, end: stop, secret: source.secret, form, rank: RANK[form], growing };
18333
18909
  }
18334
18910
  function keep(best, candidate) {
@@ -18376,7 +18952,7 @@ function count(c, hits, candidate) {
18376
18952
  hit.count += 1;
18377
18953
  hits.set(key, hit);
18378
18954
  }
18379
- function concat5(parts2) {
18955
+ function concat6(parts2) {
18380
18956
  let length2 = 0;
18381
18957
  for (const part of parts2) length2 += part.length;
18382
18958
  const out = new Uint8Array(length2);
@@ -18418,7 +18994,7 @@ function pass(c, input, final) {
18418
18994
  pos = candidate.end;
18419
18995
  }
18420
18996
  parts2.push(input.subarray(pos, cut));
18421
- return { output: concat5(parts2), cut, hits };
18997
+ return { output: concat6(parts2), cut, hits };
18422
18998
  }
18423
18999
  function merge(into, from) {
18424
19000
  for (const [key, hit] of from) {
@@ -18461,7 +19037,7 @@ function compile(secrets, options = {}) {
18461
19037
  };
18462
19038
  return {
18463
19039
  push(chunk2) {
18464
- pending = concat5([pending, chunk2]);
19040
+ pending = concat6([pending, chunk2]);
18465
19041
  return run2(false);
18466
19042
  },
18467
19043
  idle() {
@@ -18481,9 +19057,9 @@ function compile(secrets, options = {}) {
18481
19057
  // src/kernel/scrub-file.ts
18482
19058
  var SCRUB_IDLE_MS = 50;
18483
19059
  var SCRUB_NONBLOCK_MAX = 64 * 1024;
18484
- var encoder5 = new TextEncoder();
19060
+ var encoder6 = new TextEncoder();
18485
19061
  function scrubberOf(secrets) {
18486
- const usable = secrets.filter((s) => encoder5.encode(s.value).length >= MIN_VALUE);
19062
+ const usable = secrets.filter((s) => encoder6.encode(s.value).length >= MIN_VALUE);
18487
19063
  return usable.length > 0 ? compile(usable, { idleMs: SCRUB_IDLE_MS }) : void 0;
18488
19064
  }
18489
19065
  async function writeAll3(file, bytes) {
@@ -18501,7 +19077,7 @@ function interrupted2(err) {
18501
19077
  function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
18502
19078
  const file = inner.file;
18503
19079
  const stream2 = scrubber.stream();
18504
- let tail = Promise.resolve();
19080
+ let tail2 = Promise.resolve();
18505
19081
  let pending = 0;
18506
19082
  let busy = false;
18507
19083
  let timer;
@@ -18520,7 +19096,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
18520
19096
  const later = (bytes) => {
18521
19097
  if (bytes.length === 0) return;
18522
19098
  pending += 1;
18523
- tail = tail.then(() => writeAll3(file, bytes)).catch((err) => {
19099
+ tail2 = tail2.then(() => writeAll3(file, bytes)).catch((err) => {
18524
19100
  if (failed3 === void 0) failed3 = err;
18525
19101
  }).finally(() => {
18526
19102
  pending -= 1;
@@ -18671,7 +19247,7 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
18671
19247
  "cancel",
18672
19248
  "materialize"
18673
19249
  ]);
18674
- var encoder6 = new TextEncoder();
19250
+ var encoder7 = new TextEncoder();
18675
19251
  var decoder3 = new TextDecoder("utf-8", { fatal: true });
18676
19252
  function parseSealed(bytes) {
18677
19253
  try {
@@ -18700,8 +19276,8 @@ function materializable(req) {
18700
19276
  function errorReply(code, message3) {
18701
19277
  return { v: 1, error: { code, message: message3 } };
18702
19278
  }
18703
- function isRecord(value) {
18704
- return typeof value === "object" && value !== null && !Array.isArray(value);
19279
+ function isRecord(value2) {
19280
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
18705
19281
  }
18706
19282
  function serialized(reply) {
18707
19283
  let plain2;
@@ -18752,7 +19328,7 @@ var SealedChannel = class {
18752
19328
  await this.broker.tickets.record(req, reply, caller.pid);
18753
19329
  if (this.inflight !== flight) return;
18754
19330
  this.inflight = void 0;
18755
- if (reply) this.reply = encoder6.encode(serialized(reply));
19331
+ if (reply) this.reply = encoder7.encode(serialized(reply));
18756
19332
  });
18757
19333
  this.inflight = flight;
18758
19334
  return length2;
@@ -19344,8 +19920,8 @@ function umountCall(target, flags2) {
19344
19920
  var FSTAB_PATH = "/etc/fstab";
19345
19921
  var FSTAB_RETRIES = [1e3, 4e3, 16e3];
19346
19922
  var FINAL = /* @__PURE__ */ new Set(["EINVAL", "EBUSY", "EPERM", "EACCES"]);
19347
- function unescape(field3) {
19348
- return field3.replace(
19923
+ function unescape(field4) {
19924
+ return field4.replace(
19349
19925
  /\\([0-7]{3})/g,
19350
19926
  (_, octal) => String.fromCharCode(Number.parseInt(octal, 8))
19351
19927
  );
@@ -19541,9 +20117,9 @@ var HostfsClient = class {
19541
20117
  let buffered = "";
19542
20118
  try {
19543
20119
  for (; ; ) {
19544
- const { done: done4, value } = await reader.read();
20120
+ const { done: done4, value: value2 } = await reader.read();
19545
20121
  if (done4) return;
19546
- buffered += decoder4.decode(value, { stream: true });
20122
+ buffered += decoder4.decode(value2, { stream: true });
19547
20123
  let end = buffered.indexOf("\n");
19548
20124
  while (end >= 0) {
19549
20125
  const line = buffered.slice(0, end).trim();
@@ -19805,10 +20381,10 @@ function timed(transport, ms) {
19805
20381
  reject(fsError2("ENOTCONN", why));
19806
20382
  }, ms);
19807
20383
  running.then(
19808
- (value) => {
20384
+ (value2) => {
19809
20385
  clearTimeout(timer);
19810
- if (expired) late?.(value);
19811
- resolve2(value);
20386
+ if (expired) late?.(value2);
20387
+ resolve2(value2);
19812
20388
  },
19813
20389
  (err) => {
19814
20390
  clearTimeout(timer);
@@ -20223,9 +20799,9 @@ var ChunkedBytes = class {
20223
20799
  if (size < this.size) {
20224
20800
  const keep2 = Math.ceil(size / CHUNK3);
20225
20801
  this.chunks.length = Math.min(this.chunks.length, keep2);
20226
- const tail = this.chunks[keep2 - 1];
20802
+ const tail2 = this.chunks[keep2 - 1];
20227
20803
  const from = size - (keep2 - 1) * CHUNK3;
20228
- if (tail && from < tail.length) tail.fill(0, from);
20804
+ if (tail2 && from < tail2.length) tail2.fill(0, from);
20229
20805
  }
20230
20806
  this.size = size;
20231
20807
  }
@@ -20240,8 +20816,8 @@ var ChunkedBytes = class {
20240
20816
  };
20241
20817
 
20242
20818
  // src/mount/tmpfs.ts
20243
- function idOption2(value) {
20244
- return value !== void 0 && /^\d+$/.test(value) ? Number(value) : 0;
20819
+ function idOption2(value2) {
20820
+ return value2 !== void 0 && /^\d+$/.test(value2) ? Number(value2) : 0;
20245
20821
  }
20246
20822
  function created2(ino, kind, mode, from, owner) {
20247
20823
  const now = Date.now();
@@ -20476,7 +21052,7 @@ function importedMemory(bytes) {
20476
21052
  const count2 = u32();
20477
21053
  for (let i = 0; i < count2; i++) {
20478
21054
  const module = name2();
20479
- const field3 = name2();
21055
+ const field4 = name2();
20480
21056
  const kind = bytes[at++];
20481
21057
  if (kind === 0) u32();
20482
21058
  else if (kind === 1) {
@@ -20484,7 +21060,7 @@ function importedMemory(bytes) {
20484
21060
  limits();
20485
21061
  } else if (kind === 2) {
20486
21062
  const l = limits();
20487
- return { module, name: field3, ...l };
21063
+ return { module, name: field4, ...l };
20488
21064
  } else if (kind === 3) at += 2;
20489
21065
  else if (kind === 4) {
20490
21066
  at++;
@@ -20575,12 +21151,12 @@ function readImports(r, types) {
20575
21151
  const foreign = {};
20576
21152
  for (let i = r.u32(); i > 0; i--) {
20577
21153
  const module = r.name();
20578
- const field3 = r.name();
21154
+ const field4 = r.name();
20579
21155
  const kind = r.byte();
20580
21156
  if (kind !== 0) skipImport(r, kind);
20581
21157
  else {
20582
21158
  const type = types[r.u32()] ?? "other";
20583
- if (!RESERVED_NAMESPACES.has(module)) (foreign[module] ??= {})[field3] = type;
21159
+ if (!RESERVED_NAMESPACES.has(module)) (foreign[module] ??= {})[field4] = type;
20584
21160
  }
20585
21161
  }
20586
21162
  return foreign;
@@ -21093,7 +21669,7 @@ var LAYOUT = [
21093
21669
  ];
21094
21670
  var LOAD_SAMPLE_MS = 5e3;
21095
21671
  var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
21096
- var encoder7 = new TextEncoder();
21672
+ var encoder8 = new TextEncoder();
21097
21673
  var USERS_MODES = ["off", "report", "enforce"];
21098
21674
  function usersMode(mode = "off") {
21099
21675
  if (USERS_MODES.includes(mode)) return mode;
@@ -21153,10 +21729,10 @@ function shebangCommand(words2) {
21153
21729
  const arg2 = words2.slice(1).join(" ");
21154
21730
  return { interp: words2[0], args: arg2 ? [arg2] : [] };
21155
21731
  }
21156
- const split2 = words2[1] === "-S";
21157
- const [interp, ...rest2] = words2.slice(split2 ? 2 : 1);
21732
+ const split3 = words2[1] === "-S";
21733
+ const [interp, ...rest2] = words2.slice(split3 ? 2 : 1);
21158
21734
  const arg = rest2.join(" ");
21159
- return { interp, args: split2 ? rest2 : arg ? [arg] : [] };
21735
+ return { interp, args: split3 ? rest2 : arg ? [arg] : [] };
21160
21736
  }
21161
21737
  function interpreter(head) {
21162
21738
  const words2 = shebang(head);
@@ -21167,9 +21743,9 @@ function interpreter(head) {
21167
21743
  }
21168
21744
  function expandDefaults(defaults, env) {
21169
21745
  const out = {};
21170
- for (const [key, value] of Object.entries(defaults ?? {})) {
21746
+ for (const [key, value2] of Object.entries(defaults ?? {})) {
21171
21747
  let missing4 = false;
21172
- const expanded = value.replace(ENV_REFERENCE, (_, name2) => {
21748
+ const expanded = value2.replace(ENV_REFERENCE, (_, name2) => {
21173
21749
  const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
21174
21750
  if (set3 === void 0) missing4 = true;
21175
21751
  return set3 ?? "";
@@ -21211,7 +21787,7 @@ function childHandle(handle) {
21211
21787
  onState: (listener) => handle.onState(listener)
21212
21788
  };
21213
21789
  }
21214
- function concat6(chunks2) {
21790
+ function concat7(chunks2) {
21215
21791
  const out = new Uint8Array(chunks2.reduce((n, chunk2) => n + chunk2.length, 0));
21216
21792
  let offset = 0;
21217
21793
  for (const chunk2 of chunks2) {
@@ -21316,6 +21892,8 @@ var Launcher = class {
21316
21892
  fileWatches;
21317
21893
  nextPid = 1e3;
21318
21894
  boot = Date.now();
21895
+ bootId = crypto.randomUUID();
21896
+ cron;
21319
21897
  terminals = 0;
21320
21898
  constructor(options) {
21321
21899
  this.usersMode = usersMode(options.users);
@@ -21446,6 +22024,7 @@ var Launcher = class {
21446
22024
  approve: options.approve,
21447
22025
  timeoutMs: options.sudoTimeoutMs
21448
22026
  });
22027
+ this.cron = this.cronService(options.cron);
21449
22028
  void this.unlinked.sweep("/");
21450
22029
  this.watchers.watch(
21451
22030
  [this.modulesDir, this.pnpmHome, ...this.appended],
@@ -21457,6 +22036,38 @@ var Launcher = class {
21457
22036
  this.resetCatalogs();
21458
22037
  });
21459
22038
  }
22039
+ cronService(options = {}) {
22040
+ return new CronService({
22041
+ fs: this.fs,
22042
+ owners: this.owners,
22043
+ lock: options.lock ?? "slicc-kernel-cron",
22044
+ bootId: this.bootId,
22045
+ ...options.clock ? { clock: options.clock } : {},
22046
+ locks: cronLocks(),
22047
+ ready: () => this.fstab,
22048
+ lookup: (name2) => this.users.lookup(name2),
22049
+ watch: async (paths, notify) => {
22050
+ const local = this.watchers.watch(paths, { recursive: true }, () => notify());
22051
+ const remote = await this.watchFiles(paths, notify);
22052
+ return () => {
22053
+ local();
22054
+ remote();
22055
+ };
22056
+ },
22057
+ run: async ({ account, argv, cwd, env, output }) => {
22058
+ const ended = await this.run(argv, {
22059
+ user: account,
22060
+ cwd,
22061
+ env,
22062
+ login: true,
22063
+ collect: false,
22064
+ onStdout: output,
22065
+ onStderr: output
22066
+ });
22067
+ return { status: ended.status, ...signalField(ended.signal) };
22068
+ }
22069
+ });
22070
+ }
21460
22071
  get owners() {
21461
22072
  return this.usersMode !== "off";
21462
22073
  }
@@ -21816,10 +22427,10 @@ var Launcher = class {
21816
22427
  if (!swap) throw new SpawnError("EACCES");
21817
22428
  const secrets = [];
21818
22429
  for (const [name2, placeholder] of Object.entries(swap.placeholders)) {
21819
- const value = swap.values[name2];
21820
- if (value === void 0 || env[name2] !== placeholder) continue;
21821
- env[name2] = value;
21822
- secrets.push({ name: name2, value, placeholder });
22430
+ const value2 = swap.values[name2];
22431
+ if (value2 === void 0 || env[name2] !== placeholder) continue;
22432
+ env[name2] = value2;
22433
+ secrets.push({ name: name2, value: value2, placeholder });
21823
22434
  }
21824
22435
  const scrub = scrubberOf(secrets);
21825
22436
  return { env, pid, cwd: booked.cwd, ...scrub ? { scrub } : {} };
@@ -21926,7 +22537,7 @@ var Launcher = class {
21926
22537
  if (hit !== void 0) return hit;
21927
22538
  const revocations = this.revocations;
21928
22539
  const loading2 = load();
21929
- const found = loading2.then(({ value }) => value);
22540
+ const found = loading2.then(({ value: value2 }) => value2);
21930
22541
  cache.set(key, found);
21931
22542
  const drop = () => {
21932
22543
  if (cache.get(key) === found) cache.delete(key);
@@ -22793,6 +23404,7 @@ var Launcher = class {
22793
23404
  for (const holds2 of this.held) holds2.revoke(at);
22794
23405
  }
22795
23406
  unmountAll() {
23407
+ this.cron.stop();
22796
23408
  this.booting.abort();
22797
23409
  const targets = this.mounts.list().map((m) => m.target);
22798
23410
  for (const target of targets.sort((a, b) => b.length - a.length)) this.umount(target, true);
@@ -22859,7 +23471,9 @@ var Launcher = class {
22859
23471
  if (this.owners) await this.stampLayout();
22860
23472
  if (this.owners) await this.sudoer.provision();
22861
23473
  await writeCaFile(this.base, this.ca).catch(() => void 0);
23474
+ await this.cron.provision().catch(() => void 0);
22862
23475
  this.fstab = this.mountFstab();
23476
+ void this.cron.start();
22863
23477
  }
22864
23478
  async mountFstab() {
22865
23479
  const text = await this.base.readFile(FSTAB_PATH).catch(() => "");
@@ -22881,9 +23495,9 @@ var Launcher = class {
22881
23495
  }
22882
23496
  );
22883
23497
  }
22884
- environment(cwd, extra, account) {
23498
+ environment(cwd, extra, account, login = false) {
22885
23499
  const env = {
22886
- ...this.env,
23500
+ ...login ? networkEnv(this.hostname) : this.env,
22887
23501
  ...userEnv(account, this.pnpmHome),
22888
23502
  PWD: cwd,
22889
23503
  ...extra
@@ -23035,7 +23649,7 @@ var Launcher = class {
23035
23649
  },
23036
23650
  account
23037
23651
  );
23038
- const report = (message3) => options.onData(encoder7.encode(`${message3}\r
23652
+ const report = (message3) => options.onData(encoder8.encode(`${message3}\r
23039
23653
  `));
23040
23654
  const handle = await this.launch(planned, {
23041
23655
  env,
@@ -23063,7 +23677,7 @@ var Launcher = class {
23063
23677
  tagOption(options.tag);
23064
23678
  const account = await this.account(options.user);
23065
23679
  const { cwd, file, planned } = await this.starting(argv, options.cwd, account, options.tag);
23066
- const env = this.environment(cwd, options.env, account);
23680
+ const env = this.environment(cwd, options.env, account, options.login);
23067
23681
  const out = [];
23068
23682
  const err = [];
23069
23683
  const keep2 = options.collect !== false;
@@ -23073,13 +23687,13 @@ var Launcher = class {
23073
23687
  };
23074
23688
  const stdout = collect(out, options.onStdout);
23075
23689
  const stderr = collect(err, options.onStderr);
23076
- const report = (message3) => stderr(encoder7.encode(`${message3}
23690
+ const report = (message3) => stderr(encoder8.encode(`${message3}
23077
23691
  `));
23078
23692
  if (!planned) {
23079
23693
  const directory = await this.directory(file, this.fs.resolvePath(cwd, file));
23080
23694
  report(`${file}: ${directory ? "Is a directory" : "command not found"}`);
23081
23695
  const status2 = directory ? NOT_EXECUTABLE : NOT_FOUND;
23082
- return { status: status2, stdout: concat6(out), stderr: concat6(err) };
23696
+ return { status: status2, stdout: concat7(out), stderr: concat7(err) };
23083
23697
  }
23084
23698
  const fds = new FdTable();
23085
23699
  fds.installAt(0, options.stdin ? bytesSource(options.stdin) : deviceFile("null"));
@@ -23097,9 +23711,12 @@ var Launcher = class {
23097
23711
  options.onStarted?.(handle.pid);
23098
23712
  const status = await handle.exited;
23099
23713
  const signal = handle.termsig();
23100
- return { status, ...signal ? { signal } : {}, stdout: concat6(out), stderr: concat6(err) };
23714
+ return { status, ...signal ? { signal } : {}, stdout: concat7(out), stderr: concat7(err) };
23101
23715
  }
23102
23716
  };
23717
+ function cronLocks() {
23718
+ return globalThis.navigator?.locks;
23719
+ }
23103
23720
 
23104
23721
  // src/node/loopback.ts
23105
23722
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -23139,10 +23756,10 @@ function hextets2(address) {
23139
23756
  const [a, b, c, d] = dotted.split(".").map(Number);
23140
23757
  text = `${address.slice(0, -dotted.length)}${(a << 8 | b).toString(16)}:${(c << 8 | d).toString(16)}`;
23141
23758
  }
23142
- const [head = "", tail] = text.split("::");
23759
+ const [head = "", tail2] = text.split("::");
23143
23760
  const part = (side) => side ? side.split(":").map((w) => Number.parseInt(w, 16)) : [];
23144
23761
  const left = part(head);
23145
- const right = tail === void 0 ? [] : part(tail);
23762
+ const right = tail2 === void 0 ? [] : part(tail2);
23146
23763
  const gap = Array(8 - left.length - right.length).fill(0);
23147
23764
  return [...left, ...gap, ...right];
23148
23765
  }
@@ -23870,7 +24487,7 @@ function dialStream(port, onClose) {
23870
24487
 
23871
24488
  // src/client/loopback-fetch.ts
23872
24489
  var OWN_HEADERS2 = /* @__PURE__ */ new Set(["host", "connection", "content-length", "transfer-encoding"]);
23873
- var encoder8 = new TextEncoder();
24490
+ var encoder9 = new TextEncoder();
23874
24491
  var latin12 = new TextDecoder("latin1");
23875
24492
  var ByteSource = class {
23876
24493
  buffered = new Uint8Array(0);
@@ -23879,16 +24496,16 @@ var ByteSource = class {
23879
24496
  this.reader = reader;
23880
24497
  }
23881
24498
  async more() {
23882
- const { done: done4, value } = await this.reader.read();
24499
+ const { done: done4, value: value2 } = await this.reader.read();
23883
24500
  if (done4) return false;
23884
- const joined3 = new Uint8Array(this.buffered.length + value.length);
24501
+ const joined3 = new Uint8Array(this.buffered.length + value2.length);
23885
24502
  joined3.set(this.buffered);
23886
- joined3.set(value, this.buffered.length);
24503
+ joined3.set(value2, this.buffered.length);
23887
24504
  this.buffered = joined3;
23888
24505
  return true;
23889
24506
  }
23890
24507
  async until(marker) {
23891
- const needle = encoder8.encode(marker);
24508
+ const needle = encoder9.encode(marker);
23892
24509
  for (; ; ) {
23893
24510
  const at = indexOf(this.buffered, needle);
23894
24511
  if (at >= 0) return this.take(at + needle.length);
@@ -23991,12 +24608,12 @@ async function requestBytes(request) {
23991
24608
  const url = new URL(request.url);
23992
24609
  const body = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
23993
24610
  const lines2 = [`${request.method} ${url.pathname}${url.search} HTTP/1.1`, `Host: ${url.host}`];
23994
- request.headers.forEach((value, name2) => {
23995
- if (!OWN_HEADERS2.has(name2)) lines2.push(`${name2}: ${value}`);
24611
+ request.headers.forEach((value2, name2) => {
24612
+ if (!OWN_HEADERS2.has(name2)) lines2.push(`${name2}: ${value2}`);
23996
24613
  });
23997
24614
  if (body) lines2.push(`Content-Length: ${body.length}`);
23998
24615
  lines2.push("Connection: close", "", "");
23999
- const head = encoder8.encode(lines2.join("\r\n"));
24616
+ const head = encoder9.encode(lines2.join("\r\n"));
24000
24617
  const out = new Uint8Array(head.length + (body?.length ?? 0));
24001
24618
  out.set(head);
24002
24619
  if (body) out.set(body, head.length);
@@ -24050,8 +24667,8 @@ var KernelCallError = class extends Error {
24050
24667
  this.code = code;
24051
24668
  }
24052
24669
  };
24053
- var encoder9 = new TextEncoder();
24054
- var bytesOf2 = (data) => typeof data === "string" ? encoder9.encode(data) : data;
24670
+ var encoder10 = new TextEncoder();
24671
+ var bytesOf2 = (data) => typeof data === "string" ? encoder10.encode(data) : data;
24055
24672
  var UNAVAILABLE = {
24056
24673
  manualRedirects: false,
24057
24674
  encodedBodies: false,
@@ -24071,7 +24688,7 @@ async function holdLock(locks) {
24071
24688
  await granted2.promise;
24072
24689
  return { name: name2, release: () => held.resolve() };
24073
24690
  }
24074
- function concat7(chunks2) {
24691
+ function concat8(chunks2) {
24075
24692
  const out = new Uint8Array(chunks2.reduce((n, c) => n + c.length, 0));
24076
24693
  let at = 0;
24077
24694
  for (const chunk2 of chunks2) {
@@ -24298,7 +24915,7 @@ async function runOn(channel, argv, opts) {
24298
24915
  onStderr: tee(2, onStderr)
24299
24916
  });
24300
24917
  const { status, signal } = await child.ended;
24301
- const text = (fd) => new TextDecoder().decode(concat7(chunks2[fd]));
24918
+ const text = (fd) => new TextDecoder().decode(concat8(chunks2[fd]));
24302
24919
  return {
24303
24920
  pid: child.pid,
24304
24921
  status,
@@ -24547,6 +25164,12 @@ function textOf(on) {
24547
25164
  const decoder4 = new TextDecoder();
24548
25165
  return (bytes) => on(decoder4.decode(bytes, { stream: true }));
24549
25166
  }
25167
+ var cronLocks2 = /* @__PURE__ */ new WeakMap();
25168
+ function cronLock(root) {
25169
+ let lock = cronLocks2.get(root);
25170
+ if (!lock) cronLocks2.set(root, lock = `slicc-kernel-cron:${crypto.randomUUID()}`);
25171
+ return lock;
25172
+ }
24550
25173
  async function createNodeKernel(options = {}) {
24551
25174
  const root = options.root ?? memoryRoot();
24552
25175
  const fs = new OpfsFs(root, void 0, void 0, { ranged: isMemoryRoot(root) });
@@ -24583,7 +25206,8 @@ async function createNodeKernel(options = {}) {
24583
25206
  ...options.protect ? { protect: options.protect } : {},
24584
25207
  ...options.sealed ? { sealed: options.sealed } : {},
24585
25208
  ...options.clipboard ? { clipboard: options.clipboard } : {},
24586
- ...options.approve ? { approve: options.approve } : {}
25209
+ ...options.approve ? { approve: options.approve } : {},
25210
+ cron: { lock: cronLock(root), ...options.cron?.clock ? { clock: options.cron.clock } : {} }
24587
25211
  });
24588
25212
  await launcher.prepare();
24589
25213
  const guard2 = (work) => new Promise((resolve2, reject) => {