@ai-ecoverse/slicc-kernel 1.106.3 → 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.3" : "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
 
@@ -12685,13 +13252,13 @@ function errno(code, message3) {
12685
13252
  function requestHead(method, url, headers, extra, first = []) {
12686
13253
  if (!TOKEN3.test(method)) throw errno("EINVAL", `method ${method}`);
12687
13254
  const lines2 = [`${method} ${url.pathname}${url.search} HTTP/1.1`, `host: ${url.host}`];
12688
- for (const [name2, value] of first) lines2.push(`${name2}: ${value}`);
12689
- for (const [name2, value] of headers) {
13255
+ for (const [name2, value2] of first) lines2.push(`${name2}: ${value2}`);
13256
+ for (const [name2, value2] of headers) {
12690
13257
  if (OWN_HEADERS.has(name2.toLowerCase())) continue;
12691
- if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value)) throw errno("EINVAL", `header ${name2}`);
12692
- lines2.push(`${name2}: ${value}`);
13258
+ if (!TOKEN3.test(name2) || !SAFE_VALUE.test(value2)) throw errno("EINVAL", `header ${name2}`);
13259
+ lines2.push(`${name2}: ${value2}`);
12693
13260
  }
12694
- for (const [name2, value] of extra) lines2.push(`${name2}: ${value}`);
13261
+ for (const [name2, value2] of extra) lines2.push(`${name2}: ${value2}`);
12695
13262
  return latin1Bytes(`${lines2.join("\r\n")}\r
12696
13263
  \r
12697
13264
  `);
@@ -13007,7 +13574,7 @@ var LoopbackWebSocket = class {
13007
13574
  };
13008
13575
 
13009
13576
  // src/kernel/net/x509.ts
13010
- function concat4(parts2) {
13577
+ function concat5(parts2) {
13011
13578
  const out = new Uint8Array(parts2.reduce((n, p) => n + p.length, 0));
13012
13579
  let at = 0;
13013
13580
  for (const p of parts2) {
@@ -13023,8 +13590,8 @@ function length(n) {
13023
13590
  return Uint8Array.of(128 | bytes.length, ...bytes);
13024
13591
  }
13025
13592
  function tlv(tag, ...contents2) {
13026
- const body = concat4(contents2);
13027
- return concat4([Uint8Array.of(tag), length(body.length), body]);
13593
+ const body = concat5(contents2);
13594
+ return concat5([Uint8Array.of(tag), length(body.length), body]);
13028
13595
  }
13029
13596
  var seq = (...parts2) => tlv(48, ...parts2);
13030
13597
  var set2 = (...parts2) => tlv(49, ...parts2);
@@ -13035,7 +13602,7 @@ function integer(magnitude) {
13035
13602
  let start2 = 0;
13036
13603
  while (start2 < magnitude.length - 1 && magnitude[start2] === 0) start2++;
13037
13604
  const trimmed = magnitude.subarray(start2);
13038
- 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);
13039
13606
  }
13040
13607
  function oid(dotted) {
13041
13608
  const [a, b, ...rest2] = dotted.split(".").map(Number);
@@ -13064,8 +13631,8 @@ function name(dn) {
13064
13631
  rdns.push(set2(seq(oid("2.5.4.3"), utf8(dn.commonName))));
13065
13632
  return seq(...rdns);
13066
13633
  }
13067
- function extension(id2, critical, value) {
13068
- 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));
13069
13636
  }
13070
13637
  function children(der) {
13071
13638
  const out = [];
@@ -13122,11 +13689,11 @@ function ipv6(host) {
13122
13689
  if (!host.includes(":") || !/^[0-9A-Fa-f:.]+$/.test(host)) return void 0;
13123
13690
  const v4 = /(\d{1,3}(?:\.\d{1,3}){3})$/.exec(host);
13124
13691
  let text = host;
13125
- const tail = [];
13692
+ const tail2 = [];
13126
13693
  if (v4) {
13127
13694
  const bytes = ipv4(v4[1]);
13128
13695
  if (!bytes) return void 0;
13129
- 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]);
13130
13697
  text = host.slice(0, -v4[1].length).replace(/:$/, host.endsWith(`::${v4[1]}`) ? ":" : "");
13131
13698
  }
13132
13699
  const halves = text.split("::");
@@ -13136,13 +13703,13 @@ function ipv6(host) {
13136
13703
  const back = halves.length === 2 ? groups(halves[1]) : [];
13137
13704
  if (![...head, ...back].every((g) => /^[0-9A-Fa-f]{1,4}$/.test(g))) return void 0;
13138
13705
  const words2 = [...head, ...back].map((g) => Number.parseInt(g, 16));
13139
- const missing4 = 8 - words2.length - tail.length;
13706
+ const missing4 = 8 - words2.length - tail2.length;
13140
13707
  if (halves.length === 2 ? missing4 < 1 : missing4 !== 0) return void 0;
13141
13708
  const all = [
13142
13709
  ...head.map((g) => Number.parseInt(g, 16)),
13143
13710
  ...new Array(halves.length === 2 ? missing4 : 0).fill(0),
13144
13711
  ...back.map((g) => Number.parseInt(g, 16)),
13145
- ...tail
13712
+ ...tail2
13146
13713
  ];
13147
13714
  return Uint8Array.from(all.flatMap((w) => [w >> 8, w & 255]));
13148
13715
  }
@@ -14132,11 +14699,11 @@ function waitFor(lookup4, signal) {
14132
14699
  reject(new KernelError("EINTR"));
14133
14700
  };
14134
14701
  signal?.addEventListener("abort", abort, { once: true });
14135
- void lookup4.work.then((value) => {
14702
+ void lookup4.work.then((value2) => {
14136
14703
  if (signal?.aborted) return;
14137
14704
  lookup4.waiters--;
14138
14705
  signal?.removeEventListener("abort", abort);
14139
- resolve2(value);
14706
+ resolve2(value2);
14140
14707
  });
14141
14708
  });
14142
14709
  }
@@ -14173,7 +14740,7 @@ function defaultTermios() {
14173
14740
  c_cc: cCc
14174
14741
  };
14175
14742
  }
14176
- var encoder3 = new TextEncoder();
14743
+ var encoder4 = new TextEncoder();
14177
14744
  function isContinuation(byte) {
14178
14745
  return (byte & 192) === 128;
14179
14746
  }
@@ -14296,7 +14863,7 @@ var KernelTty = class {
14296
14863
  this.line.push(byte);
14297
14864
  this.readable.push(Uint8Array.from(this.line));
14298
14865
  this.line = [];
14299
- if (echo) this.output(encoder3.encode("\n"));
14866
+ if (echo) this.output(encoder4.encode("\n"));
14300
14867
  } else {
14301
14868
  this.line.push(byte);
14302
14869
  if (echo) this.echo(byte);
@@ -14321,7 +14888,7 @@ var KernelTty = class {
14321
14888
  const utf83 = (this.termios.c_iflag & IUTF8) !== 0;
14322
14889
  const cells = utf83 ? dropped2.filter((b) => !isContinuation(b)).length : dropped2.length;
14323
14890
  if (cells > 0 && this.termios.c_lflag & ECHO) {
14324
- this.output(encoder3.encode("\b \b".repeat(cells)), false);
14891
+ this.output(encoder4.encode("\b \b".repeat(cells)), false);
14325
14892
  }
14326
14893
  }
14327
14894
  echo(byte) {
@@ -14573,7 +15140,7 @@ function terminalOf(ctx, fd) {
14573
15140
  if (!tty) throw new KernelError("ENOTTY");
14574
15141
  return tty;
14575
15142
  }
14576
- var json4 = (value) => ({ ok: true, kind: "json", json: value });
15143
+ var json4 = (value2) => ({ ok: true, kind: "json", json: value2 });
14577
15144
  var done3 = { ok: true, kind: "void" };
14578
15145
  function sizeKey(rows, cols) {
14579
15146
  return `${rows}x${cols}`;
@@ -14789,8 +15356,8 @@ var Semaphore = class {
14789
15356
  gid;
14790
15357
  mode;
14791
15358
  waiters = [];
14792
- constructor(value, uid, gid, mode) {
14793
- this.value = value;
15359
+ constructor(value2, uid, gid, mode) {
15360
+ this.value = value2;
14794
15361
  this.uid = uid;
14795
15362
  this.gid = gid;
14796
15363
  this.mode = mode;
@@ -15415,10 +15982,10 @@ var VfsNodes = class {
15415
15982
  async onEntry(path, op) {
15416
15983
  const key = await this.entryKey(path);
15417
15984
  const run2 = (this.entries.get(key) ?? Promise.resolve()).then(op);
15418
- const tail = run2.catch(() => void 0);
15419
- this.entries.set(key, tail);
15420
- void tail.then(() => {
15421
- 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);
15422
15989
  });
15423
15990
  return run2;
15424
15991
  }
@@ -16043,11 +16610,11 @@ var MAX_READ = 1024 * 1024;
16043
16610
  var WRITE_ACCESS = 3;
16044
16611
  var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
16045
16612
  var DEFAULT_UMASK2 = 18;
16046
- function words(value) {
16047
- 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")) {
16048
16615
  throw new KernelError("EINVAL");
16049
16616
  }
16050
- return [...value];
16617
+ return [...value2];
16051
16618
  }
16052
16619
  var ESCAPES = { " ": "\\t", "\n": "\\n", "\r": "\\r" };
16053
16620
  function clipboardLine(text) {
@@ -18020,7 +18587,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
18020
18587
  clearTimeout(entry.timer);
18021
18588
  void entry.final.cancel().catch(() => void 0);
18022
18589
  };
18023
- const keyOf2 = (owner, method, url) => `${owner} ${method} ${url}`;
18590
+ const keyOf3 = (owner, method, url) => `${owner} ${method} ${url}`;
18024
18591
  const hold = (key, chain2) => {
18025
18592
  drop(key);
18026
18593
  const mine = [...held.keys()].filter((k) => held.get(k)?.owner === chain2.owner);
@@ -18039,7 +18606,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
18039
18606
  const method = followedWith(hop.status, chain2.method);
18040
18607
  const away = target.origin !== new URL(hop.url).origin;
18041
18608
  const print = away ? unauthorized(chain2.fingerprint) : chain2.fingerprint;
18042
- hold(keyOf2(chain2.owner, method, target.href), {
18609
+ hold(keyOf3(chain2.owner, method, target.href), {
18043
18610
  ...chain2,
18044
18611
  method,
18045
18612
  fingerprint: print,
@@ -18053,7 +18620,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
18053
18620
  },
18054
18621
  ...inner.websocket ? { websocket: inner.websocket.bind(inner) } : {},
18055
18622
  async fetch(request, owner = KERNEL) {
18056
- const key = keyOf2(owner, request.method, request.url);
18623
+ const key = keyOf3(owner, request.method, request.url);
18057
18624
  const waiting = held.get(key);
18058
18625
  if (waiting && waiting.fingerprint === fingerprint(request.headers)) {
18059
18626
  held.delete(key);
@@ -18078,10 +18645,10 @@ function replayingHops(inner, heldMs = HELD_MS) {
18078
18645
  var FRAGMENT = 16;
18079
18646
  var MIN_VALUE = 8;
18080
18647
  var MIN_BASE64 = 8;
18081
- var encoder4 = new TextEncoder();
18648
+ var encoder5 = new TextEncoder();
18082
18649
  var STD = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18083
18650
  function utf82(text) {
18084
- return encoder4.encode(text);
18651
+ return encoder5.encode(text);
18085
18652
  }
18086
18653
  function base642(bytes, padded = true) {
18087
18654
  let out = "";
@@ -18113,30 +18680,30 @@ function embedded(bytes, offset) {
18113
18680
  const last = Math.floor(8 * (offset + bytes.length) / 6);
18114
18681
  return encoded.slice(first, last);
18115
18682
  }
18116
- function unicode(value, upper) {
18683
+ function unicode(value2, upper) {
18117
18684
  let out = "";
18118
- for (let i = 0; i < value.length; i++) {
18119
- const unit = value.charCodeAt(i);
18685
+ for (let i = 0; i < value2.length; i++) {
18686
+ const unit = value2.charCodeAt(i);
18120
18687
  if (unit === 34) out += '\\"';
18121
18688
  else if (unit === 92) out += "\\\\";
18122
18689
  else if (unit < 32 || unit > 126) {
18123
18690
  const code = unit.toString(16).padStart(4, "0");
18124
18691
  out += `\\u${upper ? code.toUpperCase() : code}`;
18125
- } else out += value[i];
18692
+ } else out += value2[i];
18126
18693
  }
18127
18694
  return out;
18128
18695
  }
18129
- function percent(value) {
18696
+ function percent(value2) {
18130
18697
  let component;
18131
18698
  try {
18132
- component = encodeURIComponent(value);
18699
+ component = encodeURIComponent(value2);
18133
18700
  } catch {
18134
18701
  return [];
18135
18702
  }
18136
18703
  const lower = component.replace(/%[0-9A-F]{2}/g, (escape) => escape.toLowerCase());
18137
18704
  const plus = component.replace(/%20/g, "+");
18138
18705
  let form = "";
18139
- for (const byte of utf82(value)) {
18706
+ for (const byte of utf82(value2)) {
18140
18707
  const char = String.fromCharCode(byte);
18141
18708
  if (/[A-Za-z0-9*\-._]/.test(char)) form += char;
18142
18709
  else if (byte === 32) form += "+";
@@ -18144,8 +18711,8 @@ function percent(value) {
18144
18711
  }
18145
18712
  return [component, lower, plus, form];
18146
18713
  }
18147
- function html(value, apostrophe) {
18148
- 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);
18149
18716
  }
18150
18717
  function encodings(bytes) {
18151
18718
  const standard = [base642(bytes), base642(bytes, false)];
@@ -18155,9 +18722,9 @@ function encodings(bytes) {
18155
18722
  }
18156
18723
  return [...standard, ...standard.map(urlSafe)];
18157
18724
  }
18158
- function shapes(value) {
18159
- const raw = utf82(value);
18160
- const seen = /* @__PURE__ */ new Set([value]);
18725
+ function shapes(value2) {
18726
+ const raw = utf82(value2);
18727
+ const seen = /* @__PURE__ */ new Set([value2]);
18161
18728
  const out = [];
18162
18729
  if (raw.length < FRAGMENT) out.push({ bytes: raw, form: "raw" });
18163
18730
  for (let offset = 0; raw.length >= FRAGMENT && offset + FRAGMENT <= raw.length; offset++) {
@@ -18168,17 +18735,17 @@ function shapes(value) {
18168
18735
  seen.add(text);
18169
18736
  out.push({ bytes: utf82(text), form });
18170
18737
  };
18171
- const json5 = JSON.stringify(value).slice(1, -1);
18738
+ const json5 = JSON.stringify(value2).slice(1, -1);
18172
18739
  for (const text of [
18173
18740
  json5,
18174
18741
  json5.replace(/\//g, "\\/"),
18175
- unicode(value, false),
18176
- unicode(value, true)
18742
+ unicode(value2, false),
18743
+ unicode(value2, true)
18177
18744
  ]) {
18178
18745
  add(text, "json");
18179
18746
  }
18180
- for (const text of percent(value)) add(text, "percent");
18181
- 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");
18182
18749
  for (const text of encodings(raw)) add(text, "base64");
18183
18750
  add(hex2(raw), "hex");
18184
18751
  add(hex2(raw).toUpperCase(), "hex");
@@ -18329,15 +18896,15 @@ function resolve(c, input, start2, end, source) {
18329
18896
  growing: false
18330
18897
  };
18331
18898
  }
18332
- const value = c.values[source.secret];
18899
+ const value2 = c.values[source.secret];
18333
18900
  let stop = end;
18334
18901
  let at = source.offset + FRAGMENT;
18335
- while (stop < input.length && at < value.length && input[stop] === value[at]) {
18902
+ while (stop < input.length && at < value2.length && input[stop] === value2[at]) {
18336
18903
  stop++;
18337
18904
  at++;
18338
18905
  }
18339
- const form = source.offset === 0 && at === value.length ? "raw" : "fragment";
18340
- 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;
18341
18908
  return { start: start2, end: stop, secret: source.secret, form, rank: RANK[form], growing };
18342
18909
  }
18343
18910
  function keep(best, candidate) {
@@ -18385,7 +18952,7 @@ function count(c, hits, candidate) {
18385
18952
  hit.count += 1;
18386
18953
  hits.set(key, hit);
18387
18954
  }
18388
- function concat5(parts2) {
18955
+ function concat6(parts2) {
18389
18956
  let length2 = 0;
18390
18957
  for (const part of parts2) length2 += part.length;
18391
18958
  const out = new Uint8Array(length2);
@@ -18427,7 +18994,7 @@ function pass(c, input, final) {
18427
18994
  pos = candidate.end;
18428
18995
  }
18429
18996
  parts2.push(input.subarray(pos, cut));
18430
- return { output: concat5(parts2), cut, hits };
18997
+ return { output: concat6(parts2), cut, hits };
18431
18998
  }
18432
18999
  function merge(into, from) {
18433
19000
  for (const [key, hit] of from) {
@@ -18470,7 +19037,7 @@ function compile(secrets, options = {}) {
18470
19037
  };
18471
19038
  return {
18472
19039
  push(chunk2) {
18473
- pending = concat5([pending, chunk2]);
19040
+ pending = concat6([pending, chunk2]);
18474
19041
  return run2(false);
18475
19042
  },
18476
19043
  idle() {
@@ -18490,9 +19057,9 @@ function compile(secrets, options = {}) {
18490
19057
  // src/kernel/scrub-file.ts
18491
19058
  var SCRUB_IDLE_MS = 50;
18492
19059
  var SCRUB_NONBLOCK_MAX = 64 * 1024;
18493
- var encoder5 = new TextEncoder();
19060
+ var encoder6 = new TextEncoder();
18494
19061
  function scrubberOf(secrets) {
18495
- 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);
18496
19063
  return usable.length > 0 ? compile(usable, { idleMs: SCRUB_IDLE_MS }) : void 0;
18497
19064
  }
18498
19065
  async function writeAll3(file, bytes) {
@@ -18510,7 +19077,7 @@ function interrupted2(err) {
18510
19077
  function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
18511
19078
  const file = inner.file;
18512
19079
  const stream2 = scrubber.stream();
18513
- let tail = Promise.resolve();
19080
+ let tail2 = Promise.resolve();
18514
19081
  let pending = 0;
18515
19082
  let busy = false;
18516
19083
  let timer;
@@ -18529,7 +19096,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
18529
19096
  const later = (bytes) => {
18530
19097
  if (bytes.length === 0) return;
18531
19098
  pending += 1;
18532
- tail = tail.then(() => writeAll3(file, bytes)).catch((err) => {
19099
+ tail2 = tail2.then(() => writeAll3(file, bytes)).catch((err) => {
18533
19100
  if (failed3 === void 0) failed3 = err;
18534
19101
  }).finally(() => {
18535
19102
  pending -= 1;
@@ -18680,7 +19247,7 @@ var SEALED_OPS = /* @__PURE__ */ new Set([
18680
19247
  "cancel",
18681
19248
  "materialize"
18682
19249
  ]);
18683
- var encoder6 = new TextEncoder();
19250
+ var encoder7 = new TextEncoder();
18684
19251
  var decoder3 = new TextDecoder("utf-8", { fatal: true });
18685
19252
  function parseSealed(bytes) {
18686
19253
  try {
@@ -18709,8 +19276,8 @@ function materializable(req) {
18709
19276
  function errorReply(code, message3) {
18710
19277
  return { v: 1, error: { code, message: message3 } };
18711
19278
  }
18712
- function isRecord(value) {
18713
- return typeof value === "object" && value !== null && !Array.isArray(value);
19279
+ function isRecord(value2) {
19280
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
18714
19281
  }
18715
19282
  function serialized(reply) {
18716
19283
  let plain2;
@@ -18761,7 +19328,7 @@ var SealedChannel = class {
18761
19328
  await this.broker.tickets.record(req, reply, caller.pid);
18762
19329
  if (this.inflight !== flight) return;
18763
19330
  this.inflight = void 0;
18764
- if (reply) this.reply = encoder6.encode(serialized(reply));
19331
+ if (reply) this.reply = encoder7.encode(serialized(reply));
18765
19332
  });
18766
19333
  this.inflight = flight;
18767
19334
  return length2;
@@ -19353,8 +19920,8 @@ function umountCall(target, flags2) {
19353
19920
  var FSTAB_PATH = "/etc/fstab";
19354
19921
  var FSTAB_RETRIES = [1e3, 4e3, 16e3];
19355
19922
  var FINAL = /* @__PURE__ */ new Set(["EINVAL", "EBUSY", "EPERM", "EACCES"]);
19356
- function unescape(field3) {
19357
- return field3.replace(
19923
+ function unescape(field4) {
19924
+ return field4.replace(
19358
19925
  /\\([0-7]{3})/g,
19359
19926
  (_, octal) => String.fromCharCode(Number.parseInt(octal, 8))
19360
19927
  );
@@ -19550,9 +20117,9 @@ var HostfsClient = class {
19550
20117
  let buffered = "";
19551
20118
  try {
19552
20119
  for (; ; ) {
19553
- const { done: done4, value } = await reader.read();
20120
+ const { done: done4, value: value2 } = await reader.read();
19554
20121
  if (done4) return;
19555
- buffered += decoder4.decode(value, { stream: true });
20122
+ buffered += decoder4.decode(value2, { stream: true });
19556
20123
  let end = buffered.indexOf("\n");
19557
20124
  while (end >= 0) {
19558
20125
  const line = buffered.slice(0, end).trim();
@@ -19814,10 +20381,10 @@ function timed(transport, ms) {
19814
20381
  reject(fsError2("ENOTCONN", why));
19815
20382
  }, ms);
19816
20383
  running.then(
19817
- (value) => {
20384
+ (value2) => {
19818
20385
  clearTimeout(timer);
19819
- if (expired) late?.(value);
19820
- resolve2(value);
20386
+ if (expired) late?.(value2);
20387
+ resolve2(value2);
19821
20388
  },
19822
20389
  (err) => {
19823
20390
  clearTimeout(timer);
@@ -20232,9 +20799,9 @@ var ChunkedBytes = class {
20232
20799
  if (size < this.size) {
20233
20800
  const keep2 = Math.ceil(size / CHUNK3);
20234
20801
  this.chunks.length = Math.min(this.chunks.length, keep2);
20235
- const tail = this.chunks[keep2 - 1];
20802
+ const tail2 = this.chunks[keep2 - 1];
20236
20803
  const from = size - (keep2 - 1) * CHUNK3;
20237
- if (tail && from < tail.length) tail.fill(0, from);
20804
+ if (tail2 && from < tail2.length) tail2.fill(0, from);
20238
20805
  }
20239
20806
  this.size = size;
20240
20807
  }
@@ -20249,8 +20816,8 @@ var ChunkedBytes = class {
20249
20816
  };
20250
20817
 
20251
20818
  // src/mount/tmpfs.ts
20252
- function idOption2(value) {
20253
- 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;
20254
20821
  }
20255
20822
  function created2(ino, kind, mode, from, owner) {
20256
20823
  const now = Date.now();
@@ -20485,7 +21052,7 @@ function importedMemory(bytes) {
20485
21052
  const count2 = u32();
20486
21053
  for (let i = 0; i < count2; i++) {
20487
21054
  const module = name2();
20488
- const field3 = name2();
21055
+ const field4 = name2();
20489
21056
  const kind = bytes[at++];
20490
21057
  if (kind === 0) u32();
20491
21058
  else if (kind === 1) {
@@ -20493,7 +21060,7 @@ function importedMemory(bytes) {
20493
21060
  limits();
20494
21061
  } else if (kind === 2) {
20495
21062
  const l = limits();
20496
- return { module, name: field3, ...l };
21063
+ return { module, name: field4, ...l };
20497
21064
  } else if (kind === 3) at += 2;
20498
21065
  else if (kind === 4) {
20499
21066
  at++;
@@ -20584,12 +21151,12 @@ function readImports(r, types) {
20584
21151
  const foreign = {};
20585
21152
  for (let i = r.u32(); i > 0; i--) {
20586
21153
  const module = r.name();
20587
- const field3 = r.name();
21154
+ const field4 = r.name();
20588
21155
  const kind = r.byte();
20589
21156
  if (kind !== 0) skipImport(r, kind);
20590
21157
  else {
20591
21158
  const type = types[r.u32()] ?? "other";
20592
- if (!RESERVED_NAMESPACES.has(module)) (foreign[module] ??= {})[field3] = type;
21159
+ if (!RESERVED_NAMESPACES.has(module)) (foreign[module] ??= {})[field4] = type;
20593
21160
  }
20594
21161
  }
20595
21162
  return foreign;
@@ -21102,7 +21669,7 @@ var LAYOUT = [
21102
21669
  ];
21103
21670
  var LOAD_SAMPLE_MS = 5e3;
21104
21671
  var LOAD_WINDOWS_MS = [6e4, 3e5, 9e5];
21105
- var encoder7 = new TextEncoder();
21672
+ var encoder8 = new TextEncoder();
21106
21673
  var USERS_MODES = ["off", "report", "enforce"];
21107
21674
  function usersMode(mode = "off") {
21108
21675
  if (USERS_MODES.includes(mode)) return mode;
@@ -21162,10 +21729,10 @@ function shebangCommand(words2) {
21162
21729
  const arg2 = words2.slice(1).join(" ");
21163
21730
  return { interp: words2[0], args: arg2 ? [arg2] : [] };
21164
21731
  }
21165
- const split2 = words2[1] === "-S";
21166
- const [interp, ...rest2] = words2.slice(split2 ? 2 : 1);
21732
+ const split3 = words2[1] === "-S";
21733
+ const [interp, ...rest2] = words2.slice(split3 ? 2 : 1);
21167
21734
  const arg = rest2.join(" ");
21168
- return { interp, args: split2 ? rest2 : arg ? [arg] : [] };
21735
+ return { interp, args: split3 ? rest2 : arg ? [arg] : [] };
21169
21736
  }
21170
21737
  function interpreter(head) {
21171
21738
  const words2 = shebang(head);
@@ -21176,9 +21743,9 @@ function interpreter(head) {
21176
21743
  }
21177
21744
  function expandDefaults(defaults, env) {
21178
21745
  const out = {};
21179
- for (const [key, value] of Object.entries(defaults ?? {})) {
21746
+ for (const [key, value2] of Object.entries(defaults ?? {})) {
21180
21747
  let missing4 = false;
21181
- const expanded = value.replace(ENV_REFERENCE, (_, name2) => {
21748
+ const expanded = value2.replace(ENV_REFERENCE, (_, name2) => {
21182
21749
  const set3 = Object.hasOwn(env, name2) ? env[name2] : void 0;
21183
21750
  if (set3 === void 0) missing4 = true;
21184
21751
  return set3 ?? "";
@@ -21220,7 +21787,7 @@ function childHandle(handle) {
21220
21787
  onState: (listener) => handle.onState(listener)
21221
21788
  };
21222
21789
  }
21223
- function concat6(chunks2) {
21790
+ function concat7(chunks2) {
21224
21791
  const out = new Uint8Array(chunks2.reduce((n, chunk2) => n + chunk2.length, 0));
21225
21792
  let offset = 0;
21226
21793
  for (const chunk2 of chunks2) {
@@ -21325,6 +21892,8 @@ var Launcher = class {
21325
21892
  fileWatches;
21326
21893
  nextPid = 1e3;
21327
21894
  boot = Date.now();
21895
+ bootId = crypto.randomUUID();
21896
+ cron;
21328
21897
  terminals = 0;
21329
21898
  constructor(options) {
21330
21899
  this.usersMode = usersMode(options.users);
@@ -21455,6 +22024,7 @@ var Launcher = class {
21455
22024
  approve: options.approve,
21456
22025
  timeoutMs: options.sudoTimeoutMs
21457
22026
  });
22027
+ this.cron = this.cronService(options.cron);
21458
22028
  void this.unlinked.sweep("/");
21459
22029
  this.watchers.watch(
21460
22030
  [this.modulesDir, this.pnpmHome, ...this.appended],
@@ -21466,6 +22036,38 @@ var Launcher = class {
21466
22036
  this.resetCatalogs();
21467
22037
  });
21468
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
+ }
21469
22071
  get owners() {
21470
22072
  return this.usersMode !== "off";
21471
22073
  }
@@ -21825,10 +22427,10 @@ var Launcher = class {
21825
22427
  if (!swap) throw new SpawnError("EACCES");
21826
22428
  const secrets = [];
21827
22429
  for (const [name2, placeholder] of Object.entries(swap.placeholders)) {
21828
- const value = swap.values[name2];
21829
- if (value === void 0 || env[name2] !== placeholder) continue;
21830
- env[name2] = value;
21831
- 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 });
21832
22434
  }
21833
22435
  const scrub = scrubberOf(secrets);
21834
22436
  return { env, pid, cwd: booked.cwd, ...scrub ? { scrub } : {} };
@@ -21935,7 +22537,7 @@ var Launcher = class {
21935
22537
  if (hit !== void 0) return hit;
21936
22538
  const revocations = this.revocations;
21937
22539
  const loading2 = load();
21938
- const found = loading2.then(({ value }) => value);
22540
+ const found = loading2.then(({ value: value2 }) => value2);
21939
22541
  cache.set(key, found);
21940
22542
  const drop = () => {
21941
22543
  if (cache.get(key) === found) cache.delete(key);
@@ -22802,6 +23404,7 @@ var Launcher = class {
22802
23404
  for (const holds2 of this.held) holds2.revoke(at);
22803
23405
  }
22804
23406
  unmountAll() {
23407
+ this.cron.stop();
22805
23408
  this.booting.abort();
22806
23409
  const targets = this.mounts.list().map((m) => m.target);
22807
23410
  for (const target of targets.sort((a, b) => b.length - a.length)) this.umount(target, true);
@@ -22868,7 +23471,9 @@ var Launcher = class {
22868
23471
  if (this.owners) await this.stampLayout();
22869
23472
  if (this.owners) await this.sudoer.provision();
22870
23473
  await writeCaFile(this.base, this.ca).catch(() => void 0);
23474
+ await this.cron.provision().catch(() => void 0);
22871
23475
  this.fstab = this.mountFstab();
23476
+ void this.cron.start();
22872
23477
  }
22873
23478
  async mountFstab() {
22874
23479
  const text = await this.base.readFile(FSTAB_PATH).catch(() => "");
@@ -22890,9 +23495,9 @@ var Launcher = class {
22890
23495
  }
22891
23496
  );
22892
23497
  }
22893
- environment(cwd, extra, account) {
23498
+ environment(cwd, extra, account, login = false) {
22894
23499
  const env = {
22895
- ...this.env,
23500
+ ...login ? networkEnv(this.hostname) : this.env,
22896
23501
  ...userEnv(account, this.pnpmHome),
22897
23502
  PWD: cwd,
22898
23503
  ...extra
@@ -23044,7 +23649,7 @@ var Launcher = class {
23044
23649
  },
23045
23650
  account
23046
23651
  );
23047
- const report = (message3) => options.onData(encoder7.encode(`${message3}\r
23652
+ const report = (message3) => options.onData(encoder8.encode(`${message3}\r
23048
23653
  `));
23049
23654
  const handle = await this.launch(planned, {
23050
23655
  env,
@@ -23072,7 +23677,7 @@ var Launcher = class {
23072
23677
  tagOption(options.tag);
23073
23678
  const account = await this.account(options.user);
23074
23679
  const { cwd, file, planned } = await this.starting(argv, options.cwd, account, options.tag);
23075
- const env = this.environment(cwd, options.env, account);
23680
+ const env = this.environment(cwd, options.env, account, options.login);
23076
23681
  const out = [];
23077
23682
  const err = [];
23078
23683
  const keep2 = options.collect !== false;
@@ -23082,13 +23687,13 @@ var Launcher = class {
23082
23687
  };
23083
23688
  const stdout = collect(out, options.onStdout);
23084
23689
  const stderr = collect(err, options.onStderr);
23085
- const report = (message3) => stderr(encoder7.encode(`${message3}
23690
+ const report = (message3) => stderr(encoder8.encode(`${message3}
23086
23691
  `));
23087
23692
  if (!planned) {
23088
23693
  const directory = await this.directory(file, this.fs.resolvePath(cwd, file));
23089
23694
  report(`${file}: ${directory ? "Is a directory" : "command not found"}`);
23090
23695
  const status2 = directory ? NOT_EXECUTABLE : NOT_FOUND;
23091
- return { status: status2, stdout: concat6(out), stderr: concat6(err) };
23696
+ return { status: status2, stdout: concat7(out), stderr: concat7(err) };
23092
23697
  }
23093
23698
  const fds = new FdTable();
23094
23699
  fds.installAt(0, options.stdin ? bytesSource(options.stdin) : deviceFile("null"));
@@ -23106,9 +23711,12 @@ var Launcher = class {
23106
23711
  options.onStarted?.(handle.pid);
23107
23712
  const status = await handle.exited;
23108
23713
  const signal = handle.termsig();
23109
- return { status, ...signal ? { signal } : {}, stdout: concat6(out), stderr: concat6(err) };
23714
+ return { status, ...signal ? { signal } : {}, stdout: concat7(out), stderr: concat7(err) };
23110
23715
  }
23111
23716
  };
23717
+ function cronLocks() {
23718
+ return globalThis.navigator?.locks;
23719
+ }
23112
23720
 
23113
23721
  // src/node/loopback.ts
23114
23722
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -23148,10 +23756,10 @@ function hextets2(address) {
23148
23756
  const [a, b, c, d] = dotted.split(".").map(Number);
23149
23757
  text = `${address.slice(0, -dotted.length)}${(a << 8 | b).toString(16)}:${(c << 8 | d).toString(16)}`;
23150
23758
  }
23151
- const [head = "", tail] = text.split("::");
23759
+ const [head = "", tail2] = text.split("::");
23152
23760
  const part = (side) => side ? side.split(":").map((w) => Number.parseInt(w, 16)) : [];
23153
23761
  const left = part(head);
23154
- const right = tail === void 0 ? [] : part(tail);
23762
+ const right = tail2 === void 0 ? [] : part(tail2);
23155
23763
  const gap = Array(8 - left.length - right.length).fill(0);
23156
23764
  return [...left, ...gap, ...right];
23157
23765
  }
@@ -23879,7 +24487,7 @@ function dialStream(port, onClose) {
23879
24487
 
23880
24488
  // src/client/loopback-fetch.ts
23881
24489
  var OWN_HEADERS2 = /* @__PURE__ */ new Set(["host", "connection", "content-length", "transfer-encoding"]);
23882
- var encoder8 = new TextEncoder();
24490
+ var encoder9 = new TextEncoder();
23883
24491
  var latin12 = new TextDecoder("latin1");
23884
24492
  var ByteSource = class {
23885
24493
  buffered = new Uint8Array(0);
@@ -23888,16 +24496,16 @@ var ByteSource = class {
23888
24496
  this.reader = reader;
23889
24497
  }
23890
24498
  async more() {
23891
- const { done: done4, value } = await this.reader.read();
24499
+ const { done: done4, value: value2 } = await this.reader.read();
23892
24500
  if (done4) return false;
23893
- const joined3 = new Uint8Array(this.buffered.length + value.length);
24501
+ const joined3 = new Uint8Array(this.buffered.length + value2.length);
23894
24502
  joined3.set(this.buffered);
23895
- joined3.set(value, this.buffered.length);
24503
+ joined3.set(value2, this.buffered.length);
23896
24504
  this.buffered = joined3;
23897
24505
  return true;
23898
24506
  }
23899
24507
  async until(marker) {
23900
- const needle = encoder8.encode(marker);
24508
+ const needle = encoder9.encode(marker);
23901
24509
  for (; ; ) {
23902
24510
  const at = indexOf(this.buffered, needle);
23903
24511
  if (at >= 0) return this.take(at + needle.length);
@@ -24000,12 +24608,12 @@ async function requestBytes(request) {
24000
24608
  const url = new URL(request.url);
24001
24609
  const body = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
24002
24610
  const lines2 = [`${request.method} ${url.pathname}${url.search} HTTP/1.1`, `Host: ${url.host}`];
24003
- request.headers.forEach((value, name2) => {
24004
- 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}`);
24005
24613
  });
24006
24614
  if (body) lines2.push(`Content-Length: ${body.length}`);
24007
24615
  lines2.push("Connection: close", "", "");
24008
- const head = encoder8.encode(lines2.join("\r\n"));
24616
+ const head = encoder9.encode(lines2.join("\r\n"));
24009
24617
  const out = new Uint8Array(head.length + (body?.length ?? 0));
24010
24618
  out.set(head);
24011
24619
  if (body) out.set(body, head.length);
@@ -24059,8 +24667,8 @@ var KernelCallError = class extends Error {
24059
24667
  this.code = code;
24060
24668
  }
24061
24669
  };
24062
- var encoder9 = new TextEncoder();
24063
- 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;
24064
24672
  var UNAVAILABLE = {
24065
24673
  manualRedirects: false,
24066
24674
  encodedBodies: false,
@@ -24080,7 +24688,7 @@ async function holdLock(locks) {
24080
24688
  await granted2.promise;
24081
24689
  return { name: name2, release: () => held.resolve() };
24082
24690
  }
24083
- function concat7(chunks2) {
24691
+ function concat8(chunks2) {
24084
24692
  const out = new Uint8Array(chunks2.reduce((n, c) => n + c.length, 0));
24085
24693
  let at = 0;
24086
24694
  for (const chunk2 of chunks2) {
@@ -24307,7 +24915,7 @@ async function runOn(channel, argv, opts) {
24307
24915
  onStderr: tee(2, onStderr)
24308
24916
  });
24309
24917
  const { status, signal } = await child.ended;
24310
- const text = (fd) => new TextDecoder().decode(concat7(chunks2[fd]));
24918
+ const text = (fd) => new TextDecoder().decode(concat8(chunks2[fd]));
24311
24919
  return {
24312
24920
  pid: child.pid,
24313
24921
  status,
@@ -24556,6 +25164,12 @@ function textOf(on) {
24556
25164
  const decoder4 = new TextDecoder();
24557
25165
  return (bytes) => on(decoder4.decode(bytes, { stream: true }));
24558
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
+ }
24559
25173
  async function createNodeKernel(options = {}) {
24560
25174
  const root = options.root ?? memoryRoot();
24561
25175
  const fs = new OpfsFs(root, void 0, void 0, { ranged: isMemoryRoot(root) });
@@ -24592,7 +25206,8 @@ async function createNodeKernel(options = {}) {
24592
25206
  ...options.protect ? { protect: options.protect } : {},
24593
25207
  ...options.sealed ? { sealed: options.sealed } : {},
24594
25208
  ...options.clipboard ? { clipboard: options.clipboard } : {},
24595
- ...options.approve ? { approve: options.approve } : {}
25209
+ ...options.approve ? { approve: options.approve } : {},
25210
+ cron: { lock: cronLock(root), ...options.cron?.clock ? { clock: options.cron.clock } : {} }
24596
25211
  });
24597
25212
  await launcher.prepare();
24598
25213
  const guard2 = (work) => new Promise((resolve2, reject) => {