@ai-ecoverse/slicc-kernel 1.180.0 → 1.181.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/README.md +25 -1
- package/dist/driver-worker.js +15 -1
- package/dist/driver-worker.js.map +2 -2
- package/dist/index.js +26 -1
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +351 -88
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-driver-worker.js +15 -1
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.cjs +1 -1
- package/dist/node-process-worker.js +1 -1
- package/dist/node.js +367 -87
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +1 -1
- package/dist/types/client/attach.d.ts +12 -0
- package/dist/types/client/protocol.d.ts +9 -0
- package/dist/types/index.d.ts +5 -3
- package/dist/types/kernel/children.d.ts +2 -1
- package/dist/types/launcher.d.ts +22 -0
- package/dist/types/node.d.ts +5 -3
- package/dist/types/serve.d.ts +11 -1
- package/dist/types/sudo.d.ts +15 -1
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -3787,7 +3787,7 @@ function satisfies(version, range2) {
|
|
|
3787
3787
|
}
|
|
3788
3788
|
|
|
3789
3789
|
// src/version.ts
|
|
3790
|
-
var KERNEL_VERSION = true ? "1.
|
|
3790
|
+
var KERNEL_VERSION = true ? "1.181.0" : "0.0.0-dev";
|
|
3791
3791
|
var OS_RELEASE = "6.0.0-slicc";
|
|
3792
3792
|
function procVersion() {
|
|
3793
3793
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -4652,27 +4652,27 @@ function hashId(text) {
|
|
|
4652
4652
|
return hex4(a) + hex4(b);
|
|
4653
4653
|
}
|
|
4654
4654
|
function split(text, count2) {
|
|
4655
|
-
const
|
|
4655
|
+
const words3 = [];
|
|
4656
4656
|
let rest2 = text;
|
|
4657
4657
|
for (let i = 0; i < count2; i++) {
|
|
4658
4658
|
const match = /^(\S+)\s+/.exec(rest2);
|
|
4659
4659
|
if (!match) return void 0;
|
|
4660
|
-
|
|
4660
|
+
words3.push(match[1]);
|
|
4661
4661
|
rest2 = rest2.slice(match[0].length);
|
|
4662
4662
|
}
|
|
4663
|
-
return [
|
|
4663
|
+
return [words3, rest2.trim()];
|
|
4664
4664
|
}
|
|
4665
4665
|
function jobOf(content, pending, ctx, env) {
|
|
4666
4666
|
const fields = content.startsWith("@") ? 1 : 5;
|
|
4667
4667
|
const parts2 = split(content, fields + (ctx.system ? 1 : 0));
|
|
4668
4668
|
if (!parts2 || parts2[1] === "") throw new Error("no command");
|
|
4669
|
-
const [
|
|
4670
|
-
const schedule =
|
|
4669
|
+
const [words3, command] = parts2;
|
|
4670
|
+
const schedule = words3.slice(0, fields).join(" ");
|
|
4671
4671
|
const when = parseWhen(schedule);
|
|
4672
4672
|
const zone = env.CRON_TZ;
|
|
4673
4673
|
if (zone && !when.reboot && canonicalZone(zone) === void 0)
|
|
4674
4674
|
throw new Error(`CRON_TZ: unknown time zone "${zone}"`);
|
|
4675
|
-
const user = ctx.system ?
|
|
4675
|
+
const user = ctx.system ? words3[fields] : void 0;
|
|
4676
4676
|
if (user !== void 0 && !USER_NAME.test(user)) throw new Error(`bad user name ${user}`);
|
|
4677
4677
|
if (pending !== void 0 && !JOB_NAME.test(pending))
|
|
4678
4678
|
throw new Error(`bad job name "${pending}"`);
|
|
@@ -8374,9 +8374,11 @@ var SpawnError = class extends Error {
|
|
|
8374
8374
|
};
|
|
8375
8375
|
var ChangedError = class extends SpawnError {
|
|
8376
8376
|
notice;
|
|
8377
|
-
|
|
8377
|
+
file;
|
|
8378
|
+
constructor(notice, file) {
|
|
8378
8379
|
super("EPERM");
|
|
8379
8380
|
this.notice = notice;
|
|
8381
|
+
this.file = file;
|
|
8380
8382
|
}
|
|
8381
8383
|
};
|
|
8382
8384
|
function interrupted(signal) {
|
|
@@ -15453,21 +15455,21 @@ function unescaped(double) {
|
|
|
15453
15455
|
}
|
|
15454
15456
|
function splitWords(text) {
|
|
15455
15457
|
const piece = /'([^']*)'|"((?:[^"\\]|\\[\s\S])*)"|\\([\s\S])|([^\s'"\\]+)|(\s+)/y;
|
|
15456
|
-
const
|
|
15458
|
+
const words3 = [];
|
|
15457
15459
|
let word;
|
|
15458
15460
|
while (piece.lastIndex < text.length) {
|
|
15459
15461
|
const m = piece.exec(text);
|
|
15460
15462
|
if (!m) return void 0;
|
|
15461
15463
|
const [, single, double, escaped, plain3, space] = m;
|
|
15462
15464
|
if (space !== void 0) {
|
|
15463
|
-
if (word !== void 0)
|
|
15465
|
+
if (word !== void 0) words3.push(word);
|
|
15464
15466
|
word = void 0;
|
|
15465
15467
|
continue;
|
|
15466
15468
|
}
|
|
15467
15469
|
word = (word ?? "") + (single ?? (double !== void 0 ? unescaped(double) : escaped ?? plain3));
|
|
15468
15470
|
}
|
|
15469
|
-
if (word !== void 0)
|
|
15470
|
-
return
|
|
15471
|
+
if (word !== void 0) words3.push(word);
|
|
15472
|
+
return words3;
|
|
15471
15473
|
}
|
|
15472
15474
|
function quoteWord(word) {
|
|
15473
15475
|
const text = hasControl(word) ? withoutControl(word) : word;
|
|
@@ -15488,14 +15490,14 @@ function addPlain(word, plain3) {
|
|
|
15488
15490
|
}
|
|
15489
15491
|
function splitPatterns(text) {
|
|
15490
15492
|
const piece = /'([^']*)'|"((?:[^"\\]|\\[\s\S])*)"|\\([\s\S])|([^\s'"\\]+)|(\s+)/y;
|
|
15491
|
-
const
|
|
15493
|
+
const words3 = [];
|
|
15492
15494
|
let word;
|
|
15493
15495
|
while (piece.lastIndex < text.length) {
|
|
15494
15496
|
const m = piece.exec(text);
|
|
15495
15497
|
if (!m) return void 0;
|
|
15496
15498
|
const [, single, double, escaped, plain3, space] = m;
|
|
15497
15499
|
if (space !== void 0) {
|
|
15498
|
-
if (word !== void 0)
|
|
15500
|
+
if (word !== void 0) words3.push(word);
|
|
15499
15501
|
word = void 0;
|
|
15500
15502
|
continue;
|
|
15501
15503
|
}
|
|
@@ -15503,8 +15505,8 @@ function splitPatterns(text) {
|
|
|
15503
15505
|
if (plain3 !== void 0) addPlain(word, plain3);
|
|
15504
15506
|
else addPart(word, single ?? (double !== void 0 ? unescaped(double) : escaped));
|
|
15505
15507
|
}
|
|
15506
|
-
if (word !== void 0)
|
|
15507
|
-
return
|
|
15508
|
+
if (word !== void 0) words3.push(word);
|
|
15509
|
+
return words3;
|
|
15508
15510
|
}
|
|
15509
15511
|
var literal = (pattern) => pattern.map((p) => p ?? "*").join("");
|
|
15510
15512
|
var isAny = (pattern) => pattern?.length === 1 && pattern[0] === null;
|
|
@@ -15577,14 +15579,14 @@ function whoError(who) {
|
|
|
15577
15579
|
return `expected a user name, %group or ALL first, not ${shown(who)}`;
|
|
15578
15580
|
}
|
|
15579
15581
|
function cwdOf(word) {
|
|
15580
|
-
const
|
|
15581
|
-
const path =
|
|
15582
|
+
const words3 = splitWords(word);
|
|
15583
|
+
const path = words3?.length === 1 ? words3[0] : "";
|
|
15582
15584
|
return path.startsWith("/") ? normalizePath(path) : "";
|
|
15583
15585
|
}
|
|
15584
15586
|
function commandOf2(text, after) {
|
|
15585
|
-
const
|
|
15586
|
-
if (
|
|
15587
|
-
const [first, ...args] =
|
|
15587
|
+
const words3 = splitPatterns(text);
|
|
15588
|
+
if (words3 === void 0) return "a quote in the command is not closed, or it ends in a \\";
|
|
15589
|
+
const [first, ...args] = words3;
|
|
15588
15590
|
const path = first ? literal(first) : "";
|
|
15589
15591
|
if (path === "") return `expected a command after ${after}`;
|
|
15590
15592
|
if (!path.startsWith("/")) return `expected an absolute command path, not ${shown(path)}`;
|
|
@@ -16274,6 +16276,9 @@ function recordable(cwd, argv) {
|
|
|
16274
16276
|
function changedText(file) {
|
|
16275
16277
|
return `sudo: ${file} changed since it was approved`;
|
|
16276
16278
|
}
|
|
16279
|
+
function requestedText(file) {
|
|
16280
|
+
return `sudo: ${file} changed since it was requested`;
|
|
16281
|
+
}
|
|
16277
16282
|
function changedFile(approved, now) {
|
|
16278
16283
|
const files = /* @__PURE__ */ new Set([...Object.keys(approved), ...Object.keys(now)]);
|
|
16279
16284
|
return [...files].find((file) => approved[file] !== now[file]);
|
|
@@ -16281,6 +16286,67 @@ function changedFile(approved, now) {
|
|
|
16281
16286
|
function pinned(rule, bound3) {
|
|
16282
16287
|
return rule.sha256 === void 0 || changedFile(rule.sha256, bound3) === void 0;
|
|
16283
16288
|
}
|
|
16289
|
+
var REPLAY_ID = /^[!-~]{1,256}$/;
|
|
16290
|
+
var REPLAY_TAGS_MAX = 64;
|
|
16291
|
+
var REPLAY_ARGV_MAX = 4096;
|
|
16292
|
+
var REPLAY_BYTES_MAX = 1024 * 1024;
|
|
16293
|
+
var NOT_A_REQUEST = "sudo: that isn't a sudo request this kernel can run";
|
|
16294
|
+
function strings(value2, max) {
|
|
16295
|
+
return Array.isArray(value2) && value2.length <= max && value2.every((s) => typeof s === "string");
|
|
16296
|
+
}
|
|
16297
|
+
function words(value2) {
|
|
16298
|
+
if (!strings(value2, REPLAY_ARGV_MAX) || value2.length === 0) return false;
|
|
16299
|
+
const bytes = value2.reduce((n, s) => n + s.length + 1, 0);
|
|
16300
|
+
return bytes <= REPLAY_BYTES_MAX && !value2.some((s) => s.includes("\0"));
|
|
16301
|
+
}
|
|
16302
|
+
function filesOf(value2) {
|
|
16303
|
+
if (value2 === void 0) return {};
|
|
16304
|
+
if (!Array.isArray(value2) || value2.length > OPERANDS_MAX) return void 0;
|
|
16305
|
+
const files = {};
|
|
16306
|
+
for (const file of value2) {
|
|
16307
|
+
const { path, sha256: hex4 } = file ?? {};
|
|
16308
|
+
if (typeof path !== "string" || typeof hex4 !== "string") return void 0;
|
|
16309
|
+
files[path] = hex4;
|
|
16310
|
+
}
|
|
16311
|
+
return files;
|
|
16312
|
+
}
|
|
16313
|
+
function flagsOf(value2) {
|
|
16314
|
+
if (typeof value2 !== "object" || value2 === null || Array.isArray(value2)) return void 0;
|
|
16315
|
+
const entries = Object.entries(value2);
|
|
16316
|
+
if (entries.length > ROOT_ONLY_MAX || entries.some(([, v]) => typeof v !== "boolean")) {
|
|
16317
|
+
return void 0;
|
|
16318
|
+
}
|
|
16319
|
+
return Object.fromEntries(entries);
|
|
16320
|
+
}
|
|
16321
|
+
function replayOf(value2) {
|
|
16322
|
+
if (typeof value2 !== "object" || value2 === null) return failed2("EINVAL", NOT_A_REQUEST);
|
|
16323
|
+
const r = value2;
|
|
16324
|
+
if (r.validate === true) return failed2("EINVAL", "sudo: a sudo -v request runs no command");
|
|
16325
|
+
if (r.stdin === "pipe" || r.stdin === "file") {
|
|
16326
|
+
return failed2("EINVAL", `sudo: the request read a ${r.stdin}, and that input is gone`);
|
|
16327
|
+
}
|
|
16328
|
+
const { id: id2, user, uid, target, argv, path, cwd, stdin, tag, tags } = r;
|
|
16329
|
+
const rootOnly2 = flagsOf(r.rootOnly);
|
|
16330
|
+
const bound3 = filesOf(r.userWritable);
|
|
16331
|
+
const named = (s) => typeof s === "string" && s !== "";
|
|
16332
|
+
const absolute2 = (s) => typeof s === "string" && s.startsWith("/") && s.length <= PATH_MAX && !s.includes("\0");
|
|
16333
|
+
const valid2 = typeof id2 === "string" && REPLAY_ID.test(id2) && named(user) && named(target) && Number.isInteger(uid) && uid >= 0 && words(argv) && absolute2(path) && absolute2(cwd) && (stdin === "tty" || stdin === "none") && (tag === void 0 || typeof tag === "string") && (tags === void 0 || strings(tags, REPLAY_TAGS_MAX)) && rootOnly2 !== void 0 && bound3 !== void 0;
|
|
16334
|
+
if (!valid2) return failed2("EINVAL", NOT_A_REQUEST);
|
|
16335
|
+
const all = tags ?? (tag === void 0 ? [] : [tag]);
|
|
16336
|
+
return {
|
|
16337
|
+
id: id2,
|
|
16338
|
+
user,
|
|
16339
|
+
uid,
|
|
16340
|
+
target,
|
|
16341
|
+
argv,
|
|
16342
|
+
path,
|
|
16343
|
+
cwd,
|
|
16344
|
+
stdin,
|
|
16345
|
+
rootOnly: rootOnly2,
|
|
16346
|
+
bound: bound3,
|
|
16347
|
+
tags: [...new Set(all)]
|
|
16348
|
+
};
|
|
16349
|
+
}
|
|
16284
16350
|
var VISUDO_FILES_MAX = 64;
|
|
16285
16351
|
var VISUDO_TEXT_MAX = 1024 * 1024;
|
|
16286
16352
|
function visudoCall(req) {
|
|
@@ -16682,6 +16748,61 @@ var Sudo = class {
|
|
|
16682
16748
|
if (parsed2.validate) return this.validate(session, root, mine, call.cwd);
|
|
16683
16749
|
return this.command(session, root, mine, call);
|
|
16684
16750
|
}
|
|
16751
|
+
async replay(value2) {
|
|
16752
|
+
const r = replayOf(value2);
|
|
16753
|
+
if ("error" in r) return r;
|
|
16754
|
+
if (this.o.mode !== "enforce") {
|
|
16755
|
+
return failed2("EINVAL", `sudo: users are '${this.o.mode}', so no request needed approval`);
|
|
16756
|
+
}
|
|
16757
|
+
const self = await this.o.users.lookup(r.user);
|
|
16758
|
+
if (!self) return failed2("ENOENT", `sudo: unknown user ${r.user}`);
|
|
16759
|
+
if (self.uid !== r.uid) return failed2("EPERM", `sudo: ${self.name} is no longer uid ${r.uid}`);
|
|
16760
|
+
const target = await this.lookup(r.target);
|
|
16761
|
+
if (!target) return failed2("ENOENT", `sudo: unknown user ${r.target}`);
|
|
16762
|
+
const cred = credOf(self);
|
|
16763
|
+
const [word = "", ...args] = r.argv;
|
|
16764
|
+
const argv = [r.path, ...args];
|
|
16765
|
+
if (!await this.mayAsk(self, target, r, argv)) {
|
|
16766
|
+
const quoted = argv.map(quoteWord).join(" ");
|
|
16767
|
+
return failed2(
|
|
16768
|
+
"EACCES",
|
|
16769
|
+
`sudo: ${self.name} may no longer ask to run ${quoted} as ${target.name}`
|
|
16770
|
+
);
|
|
16771
|
+
}
|
|
16772
|
+
if (await this.canonical(r.cwd) !== r.cwd) {
|
|
16773
|
+
return failed2("EACCES", `sudo: ${r.cwd} changed since it was requested`);
|
|
16774
|
+
}
|
|
16775
|
+
if (!await this.reachable(cred, r.cwd)) {
|
|
16776
|
+
return failed2(
|
|
16777
|
+
"EACCES",
|
|
16778
|
+
`sudo: cannot run in ${r.cwd}: it isn't a directory ${self.name} can enter`
|
|
16779
|
+
);
|
|
16780
|
+
}
|
|
16781
|
+
const path = await this.locate(word, r.cwd);
|
|
16782
|
+
if (!path) return failed2("ENOENT", `sudo: ${word}: command not found`);
|
|
16783
|
+
if (path !== r.path) return failed2("EPERM", `sudo: ${word} now runs ${path}, not ${r.path}`);
|
|
16784
|
+
const bound3 = await this.bound(path, r.cwd);
|
|
16785
|
+
if (!bound3) return failed2("ENOENT", `sudo: ${word}: command not found`);
|
|
16786
|
+
const changed = changedFile(r.bound, bound3);
|
|
16787
|
+
if (changed !== void 0) return failed2("EPERM", requestedText(changed));
|
|
16788
|
+
const now = await this.rootOnly(r.cwd, args);
|
|
16789
|
+
const flipped = Object.keys(r.rootOnly).find((at) => r.rootOnly[at] && now[at] !== true);
|
|
16790
|
+
if (flipped !== void 0) return failed2("EPERM", `sudo: ${flipped} is no longer root-only`);
|
|
16791
|
+
const { grant } = this.grant(self, target, cred, r.argv, path, r.cwd, void 0, bound3);
|
|
16792
|
+
(this.o.warn ?? console.warn)(
|
|
16793
|
+
`sudo: ${self.name} : TTY=unknown ; PWD=${quoteWord(r.cwd)} ; USER=${target.name} ; REPLAY=${r.id} ; COMMAND=${argv.map(quoteWord).join(" ")}`
|
|
16794
|
+
);
|
|
16795
|
+
return { grant, caller: self, target, tags: r.tags };
|
|
16796
|
+
}
|
|
16797
|
+
async mayAsk(self, target, r, argv) {
|
|
16798
|
+
if (self.uid === 0) return true;
|
|
16799
|
+
const cred = credOf(self);
|
|
16800
|
+
const { rules } = await this.policyRules({ cred, pid: 0, stdin: r.stdin });
|
|
16801
|
+
const applies = await this.applies(self, cred);
|
|
16802
|
+
return rules.some(
|
|
16803
|
+
(rule) => applies(rule.who) && (rule.target === "ALL" || rule.target === target.name) && (rule.cwd === void 0 || rule.cwd === r.cwd) && stdinMatches(rule, r.stdin) && commandMatches(rule.cmnd, argv) && pinned(rule, r.bound)
|
|
16804
|
+
);
|
|
16805
|
+
}
|
|
16685
16806
|
async command(s, root, mine, call) {
|
|
16686
16807
|
const { caller, self, target, parsed: parsed2 } = s;
|
|
16687
16808
|
const { cred } = caller;
|
|
@@ -16861,8 +16982,8 @@ ${lines2}
|
|
|
16861
16982
|
const st = await fs.lstat(path).catch(() => void 0);
|
|
16862
16983
|
if (st && !await this.trusted(path)) return false;
|
|
16863
16984
|
const old = st ? await fs.readFile(path) : "";
|
|
16864
|
-
const
|
|
16865
|
-
const line = `NOPASSWD ${self.name} (${target.name}) Cwd ${quoteWord(cwd)} Stdin none ${sha256Text(bound3)}Cmnd ${
|
|
16985
|
+
const words3 = recordedCommand(argv);
|
|
16986
|
+
const line = `NOPASSWD ${self.name} (${target.name}) Cwd ${quoteWord(cwd)} Stdin none ${sha256Text(bound3)}Cmnd ${words3}
|
|
16866
16987
|
`;
|
|
16867
16988
|
const text = old === "" || old.endsWith("\n") ? `${old}${line}` : `${old}
|
|
16868
16989
|
${line}`;
|
|
@@ -18167,8 +18288,8 @@ function ipv6(host) {
|
|
|
18167
18288
|
const head = groups(halves[0]);
|
|
18168
18289
|
const back = halves.length === 2 ? groups(halves[1]) : [];
|
|
18169
18290
|
if (![...head, ...back].every((g) => /^[0-9A-Fa-f]{1,4}$/.test(g))) return void 0;
|
|
18170
|
-
const
|
|
18171
|
-
const missing6 = 8 -
|
|
18291
|
+
const words3 = [...head, ...back].map((g) => Number.parseInt(g, 16));
|
|
18292
|
+
const missing6 = 8 - words3.length - tail2.length;
|
|
18172
18293
|
if (halves.length === 2 ? missing6 < 1 : missing6 !== 0) return void 0;
|
|
18173
18294
|
const all = [
|
|
18174
18295
|
...head.map((g) => Number.parseInt(g, 16)),
|
|
@@ -21652,7 +21773,7 @@ function selectFlag(req) {
|
|
|
21652
21773
|
throw new KernelError("EINVAL", "ERR_TLS_ALPN_CALLBACK_WITH_PROTOCOLS: alpn with select");
|
|
21653
21774
|
return TLS_SERVER_SELECT;
|
|
21654
21775
|
}
|
|
21655
|
-
function
|
|
21776
|
+
function flagsOf2(req) {
|
|
21656
21777
|
return certFlags(req) | selectFlag(req) | (req.keylog ? TLS_KEYLOG : 0);
|
|
21657
21778
|
}
|
|
21658
21779
|
async function engineOf(proc, { select, keylog }) {
|
|
@@ -21703,7 +21824,7 @@ async function serverOf(proc, req) {
|
|
|
21703
21824
|
let mine;
|
|
21704
21825
|
try {
|
|
21705
21826
|
mine = req.ca && req.ca.length > 0 ? storeOf(engine, req.ca) : void 0;
|
|
21706
|
-
const flags2 =
|
|
21827
|
+
const flags2 = flagsOf2(req);
|
|
21707
21828
|
const store = mine ?? (flags2 & CERT_FLAGS ? await defaultStore(engine, supportOf(proc.net).roots) : void 0);
|
|
21708
21829
|
return {
|
|
21709
21830
|
engine,
|
|
@@ -23592,7 +23713,7 @@ var WRITE_ACCESS = 3;
|
|
|
23592
23713
|
var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
|
|
23593
23714
|
var STUCK_ESCAPES = /* @__PURE__ */ new Set([SIG.INT, SIG.TERM, SIG.QUIT, SIG.HUP]);
|
|
23594
23715
|
var DEFAULT_UMASK2 = 18;
|
|
23595
|
-
function
|
|
23716
|
+
function words2(value2) {
|
|
23596
23717
|
if (!Array.isArray(value2) || !value2.every((w) => typeof w === "string")) {
|
|
23597
23718
|
throw new KernelError("EINVAL");
|
|
23598
23719
|
}
|
|
@@ -25045,7 +25166,7 @@ var WasmProcess = class {
|
|
|
25045
25166
|
if (!sudo) throw new KernelError("ENOSYS");
|
|
25046
25167
|
const call = {
|
|
25047
25168
|
op: "proc-sudo",
|
|
25048
|
-
args:
|
|
25169
|
+
args: words2(req.args),
|
|
25049
25170
|
cwd: typeof req.cwd === "string" && req.cwd.startsWith("/") ? req.cwd : "/",
|
|
25050
25171
|
...typeof req.term === "string" ? { term: req.term } : {}
|
|
25051
25172
|
};
|
|
@@ -28334,8 +28455,8 @@ function serveFilesystem(port, handlers, capabilities = {}, options = {}) {
|
|
|
28334
28455
|
function noticeOf(data) {
|
|
28335
28456
|
if (Array.isArray(data)) return { paths: data.filter((p) => typeof p === "string"), trees: [] };
|
|
28336
28457
|
const notice = data ?? {};
|
|
28337
|
-
const
|
|
28338
|
-
return { paths:
|
|
28458
|
+
const strings2 = (list) => Array.isArray(list) ? list.filter((p) => typeof p === "string") : [];
|
|
28459
|
+
return { paths: strings2(notice.paths), trees: strings2(notice.trees), outside: true };
|
|
28339
28460
|
}
|
|
28340
28461
|
|
|
28341
28462
|
// src/fs/opfs.ts
|
|
@@ -32648,7 +32769,40 @@ function describe(req, tty) {
|
|
|
32648
32769
|
}
|
|
32649
32770
|
function refuseChanged(approved, now) {
|
|
32650
32771
|
const changed = changedFile(approved, now);
|
|
32651
|
-
if (changed !== void 0) throw new ChangedError(changedText(changed));
|
|
32772
|
+
if (changed !== void 0) throw new ChangedError(changedText(changed), changed);
|
|
32773
|
+
}
|
|
32774
|
+
var O_WRONLY2 = 1;
|
|
32775
|
+
var OUTPUT_MODE = 384;
|
|
32776
|
+
var ERRNO_TEXT = {
|
|
32777
|
+
EACCES: "Permission denied",
|
|
32778
|
+
EISDIR: "Is a directory",
|
|
32779
|
+
ENOENT: "No such file or directory",
|
|
32780
|
+
ENOTDIR: "Not a directory",
|
|
32781
|
+
EROFS: "Read-only file system"
|
|
32782
|
+
};
|
|
32783
|
+
function sudoFailure(errno3, message3) {
|
|
32784
|
+
return Object.assign(new Error(message3), { code: errno3 });
|
|
32785
|
+
}
|
|
32786
|
+
function sudoCause(err) {
|
|
32787
|
+
const code = codeOf8(err);
|
|
32788
|
+
if (typeof code !== "string") throw err;
|
|
32789
|
+
return code;
|
|
32790
|
+
}
|
|
32791
|
+
function requested(err) {
|
|
32792
|
+
if (err instanceof ChangedError) throw sudoFailure(err.code, requestedText(err.file));
|
|
32793
|
+
throw err;
|
|
32794
|
+
}
|
|
32795
|
+
var MAX_SPAWN_TAGS = 8;
|
|
32796
|
+
function tagList(value2) {
|
|
32797
|
+
if (!Array.isArray(value2)) {
|
|
32798
|
+
tagOption(value2);
|
|
32799
|
+
return value2 === void 0 ? [] : [value2];
|
|
32800
|
+
}
|
|
32801
|
+
if (value2.length > MAX_SPAWN_TAGS) {
|
|
32802
|
+
throw new TypeError(`a spawn adds at most ${MAX_SPAWN_TAGS} tags`);
|
|
32803
|
+
}
|
|
32804
|
+
for (const each of value2) tagOption(each ?? 0);
|
|
32805
|
+
return value2;
|
|
32652
32806
|
}
|
|
32653
32807
|
function linksOf2(req) {
|
|
32654
32808
|
return req.links === void 0 ? {} : { links: req.links };
|
|
@@ -32774,27 +32928,27 @@ function appendedRoots(given) {
|
|
|
32774
32928
|
}
|
|
32775
32929
|
return [...roots];
|
|
32776
32930
|
}
|
|
32777
|
-
function plainEnv(
|
|
32778
|
-
const next3 =
|
|
32779
|
-
if (baseName2(
|
|
32931
|
+
function plainEnv(words3) {
|
|
32932
|
+
const next3 = words3[1];
|
|
32933
|
+
if (baseName2(words3[0] ?? "") !== "env" || next3 === void 0) return false;
|
|
32780
32934
|
return next3 === "-S" || !next3.startsWith("-") && !next3.includes("=");
|
|
32781
32935
|
}
|
|
32782
|
-
function shebangCommand(
|
|
32783
|
-
if (!plainEnv(
|
|
32784
|
-
const arg2 =
|
|
32785
|
-
return { interp:
|
|
32936
|
+
function shebangCommand(words3) {
|
|
32937
|
+
if (!plainEnv(words3)) {
|
|
32938
|
+
const arg2 = words3.slice(1).join(" ");
|
|
32939
|
+
return { interp: words3[0], args: arg2 ? [arg2] : [] };
|
|
32786
32940
|
}
|
|
32787
|
-
const split3 =
|
|
32788
|
-
const [interp, ...rest2] =
|
|
32941
|
+
const split3 = words3[1] === "-S";
|
|
32942
|
+
const [interp, ...rest2] = words3.slice(split3 ? 2 : 1);
|
|
32789
32943
|
const arg = rest2.join(" ");
|
|
32790
32944
|
return { interp, args: split3 ? rest2 : arg ? [arg] : [] };
|
|
32791
32945
|
}
|
|
32792
32946
|
function interpreter(head) {
|
|
32793
|
-
const
|
|
32794
|
-
if (!
|
|
32795
|
-
if (baseName2(
|
|
32796
|
-
if (
|
|
32797
|
-
return baseName2(
|
|
32947
|
+
const words3 = shebang(head);
|
|
32948
|
+
if (!words3) return "node";
|
|
32949
|
+
if (baseName2(words3[0]) === "env") words3.shift();
|
|
32950
|
+
if (words3[0] === "-S") words3.shift();
|
|
32951
|
+
return baseName2(words3[0] ?? "");
|
|
32798
32952
|
}
|
|
32799
32953
|
function expandDefaults(defaults2, env) {
|
|
32800
32954
|
const out = {};
|
|
@@ -33569,9 +33723,9 @@ var Launcher = class {
|
|
|
33569
33723
|
const head = await this.head(script);
|
|
33570
33724
|
if (!head) return void 0;
|
|
33571
33725
|
const binfmt = isWasm(head) ? void 0 : binfmtOf(await this.interpreters(scope), script);
|
|
33572
|
-
const
|
|
33573
|
-
if (!
|
|
33574
|
-
const { interp, args } = shebangCommand(
|
|
33726
|
+
const words3 = shebang(head) ?? (binfmt ? [binfmt] : void 0);
|
|
33727
|
+
if (!words3) return void 0;
|
|
33728
|
+
const { interp, args } = shebangCommand(words3);
|
|
33575
33729
|
const passed = [...args, command ? script : file, ...argv.slice(1)];
|
|
33576
33730
|
if (!interp) return void 0;
|
|
33577
33731
|
const found = await this.resolve(interp, interp, cwd, scope);
|
|
@@ -33802,7 +33956,7 @@ var Launcher = class {
|
|
|
33802
33956
|
const hex4 = pinned2[real];
|
|
33803
33957
|
if (hex4 !== void 0) return { [real]: hex4 };
|
|
33804
33958
|
if (await this.sudoer.trusted(real)) return {};
|
|
33805
|
-
throw new ChangedError(changedText(real));
|
|
33959
|
+
throw new ChangedError(changedText(real), real);
|
|
33806
33960
|
}
|
|
33807
33961
|
async pinnedBytes(pin, bytes) {
|
|
33808
33962
|
const [real = ""] = Object.keys(pin);
|
|
@@ -34081,6 +34235,10 @@ var Launcher = class {
|
|
|
34081
34235
|
}
|
|
34082
34236
|
async launch(asked, req) {
|
|
34083
34237
|
const cwd = await physicalPathAsync(this.base, req.cwd);
|
|
34238
|
+
if (req.exactCwd && cwd !== req.cwd) {
|
|
34239
|
+
await req.fds.closeAll();
|
|
34240
|
+
throw sudoFailure("EACCES", `sudo: ${req.cwd} changed since it was requested`);
|
|
34241
|
+
}
|
|
34084
34242
|
const seen = { ...req.env, HOSTNAME: this.hostname, cwd };
|
|
34085
34243
|
await this.pnpmReady();
|
|
34086
34244
|
let loaded;
|
|
@@ -35776,6 +35934,96 @@ var Launcher = class {
|
|
|
35776
35934
|
const signal = handle.termsig();
|
|
35777
35935
|
return { status, ...signal ? { signal } : {}, stdout: concat7(out), stderr: concat7(err) };
|
|
35778
35936
|
}
|
|
35937
|
+
async sudoRun(replay, options = {}) {
|
|
35938
|
+
const added = tagList(options.tag);
|
|
35939
|
+
const replayed = await this.sudoer.replay(replay);
|
|
35940
|
+
if ("error" in replayed) throw sudoFailure(replayed.errno, replayed.error);
|
|
35941
|
+
const { grant, caller, target } = replayed;
|
|
35942
|
+
let tags = withTag(void 0, options.base);
|
|
35943
|
+
for (const tag of [...replayed.tags, ...added]) tags = withTag(tags, tag);
|
|
35944
|
+
const tagged = { tags, tagBase: options.base === void 0 ? 0 : 1 };
|
|
35945
|
+
await this.swaps.settled();
|
|
35946
|
+
this.resetCatalogs();
|
|
35947
|
+
const req = { file: grant.file, argv: grant.argv, env: grant.env, cwd: grant.cwd };
|
|
35948
|
+
const ctx = { ppid: 0, cred: grant.cred, scope: "" };
|
|
35949
|
+
const planned = await this.planOne(req, ctx).catch((err2) => {
|
|
35950
|
+
const code = sudoCause(err2);
|
|
35951
|
+
const word = grant.argv[0] ?? grant.file;
|
|
35952
|
+
if (code === "ENOENT") throw sudoFailure(code, `sudo: ${word}: command not found`);
|
|
35953
|
+
throw sudoFailure(code, `sudo: ${grant.file}: ${ERRNO_TEXT[code] ?? code}`);
|
|
35954
|
+
});
|
|
35955
|
+
const pin = await this.unchanged(planned, grant.file, grant.cwd, grant).catch(requested);
|
|
35956
|
+
const fds = await this.sudoOutputs(options, caller, this.stackFor(tags, tagged.tagBase));
|
|
35957
|
+
const err = fds.get(2).file;
|
|
35958
|
+
const report = (message3) => void Promise.resolve(err.write?.(encoder10.encode(`${message3}
|
|
35959
|
+
`))).catch(() => void 0);
|
|
35960
|
+
const replan = () => this.planOne(req, ctx);
|
|
35961
|
+
if (!await this.grantedCwd(grant.caller, grant.cwd)) {
|
|
35962
|
+
await fds.closeAll();
|
|
35963
|
+
throw sudoFailure("EACCES", `sudo: ${grant.cwd} changed since it was requested`);
|
|
35964
|
+
}
|
|
35965
|
+
const handle = await this.launch(
|
|
35966
|
+
{ ...planned, replan },
|
|
35967
|
+
{
|
|
35968
|
+
...pin,
|
|
35969
|
+
env: grant.env,
|
|
35970
|
+
cwd: grant.cwd,
|
|
35971
|
+
fds,
|
|
35972
|
+
report,
|
|
35973
|
+
...this.identity(target, tagged, options.session),
|
|
35974
|
+
...caller.umask !== void 0 ? { umask: caller.umask } : {},
|
|
35975
|
+
links: grant.cred.euid,
|
|
35976
|
+
exactCwd: true
|
|
35977
|
+
}
|
|
35978
|
+
).catch(requested);
|
|
35979
|
+
const ended = handle.exited.then((status) => {
|
|
35980
|
+
const signal = handle.termsig();
|
|
35981
|
+
return { status, ...signal ? { signal } : {} };
|
|
35982
|
+
});
|
|
35983
|
+
return { pid: handle.pid, ended };
|
|
35984
|
+
}
|
|
35985
|
+
async sudoOutputs(options, caller, stack) {
|
|
35986
|
+
const fds = new FdTable();
|
|
35987
|
+
const opened2 = /* @__PURE__ */ new Map();
|
|
35988
|
+
fds.installAt(0, deviceFile("null"));
|
|
35989
|
+
try {
|
|
35990
|
+
fds.installAt(1, await this.sudoOutput(options.stdout, caller, stack, opened2));
|
|
35991
|
+
fds.installAt(2, await this.sudoOutput(options.stderr, caller, stack, opened2));
|
|
35992
|
+
} catch (err) {
|
|
35993
|
+
await fds.closeAll();
|
|
35994
|
+
throw err;
|
|
35995
|
+
}
|
|
35996
|
+
return fds;
|
|
35997
|
+
}
|
|
35998
|
+
async sudoOutput(path, caller, stack, opened2) {
|
|
35999
|
+
if (path === void 0) return deviceFile("null");
|
|
36000
|
+
if (typeof path !== "string" || !path.startsWith("/")) {
|
|
36001
|
+
throw sudoFailure("EINVAL", `sudo: ${String(path)} is not an absolute path`);
|
|
36002
|
+
}
|
|
36003
|
+
const cred = credOf(caller);
|
|
36004
|
+
const walked = await walk(this.fs, cred, normalizePath(path), true, caller.uid);
|
|
36005
|
+
const real = walked.path;
|
|
36006
|
+
const same2 = opened2.get(real);
|
|
36007
|
+
if (same2) return same2.retain();
|
|
36008
|
+
try {
|
|
36009
|
+
if (walked.denied !== void 0) throw fsError("EACCES", path);
|
|
36010
|
+
await writable({ ...this.execGuard(cred, 0), links: caller.uid }, "open", real);
|
|
36011
|
+
const owner = { uid: caller.uid, gid: caller.gid, mode: OUTPUT_MODE };
|
|
36012
|
+
await stack.noLinks.writeFile(real, new Uint8Array(0), owner);
|
|
36013
|
+
} catch (err) {
|
|
36014
|
+
const code = sudoCause(err);
|
|
36015
|
+
throw sudoFailure(code, `sudo: ${path}: ${ERRNO_TEXT[code] ?? code}`);
|
|
36016
|
+
}
|
|
36017
|
+
const file = vfsFile(stack.fs, { path: real, flags: O_WRONLY2, position: 0 }, stack.nodes);
|
|
36018
|
+
const again = await walk(this.fs, cred, real, true, caller.uid);
|
|
36019
|
+
const st = await stack.noLinks.lstat(real).catch(() => void 0);
|
|
36020
|
+
if (again.path !== real || again.denied !== void 0 || !st?.isFile) {
|
|
36021
|
+
await file.release();
|
|
36022
|
+
throw sudoFailure("EACCES", `sudo: ${path} changed while it was opened`);
|
|
36023
|
+
}
|
|
36024
|
+
opened2.set(real, file);
|
|
36025
|
+
return file;
|
|
36026
|
+
}
|
|
35779
36027
|
};
|
|
35780
36028
|
function cronLocks() {
|
|
35781
36029
|
return globalThis.navigator?.locks;
|
|
@@ -36260,7 +36508,7 @@ function serveTransport(peer, transport, {
|
|
|
36260
36508
|
}
|
|
36261
36509
|
|
|
36262
36510
|
// src/client/protocol.ts
|
|
36263
|
-
var PROTOCOL = [1,
|
|
36511
|
+
var PROTOCOL = [1, 16];
|
|
36264
36512
|
var FS_METHODS = [
|
|
36265
36513
|
"readFile",
|
|
36266
36514
|
"writeFile",
|
|
@@ -36416,9 +36664,9 @@ async function accountOf(l, user) {
|
|
|
36416
36664
|
if (!found) throw fsError("ENOENT", `no user ${String(user)}`);
|
|
36417
36665
|
return found;
|
|
36418
36666
|
}
|
|
36419
|
-
async function runAs(l, self,
|
|
36420
|
-
if (
|
|
36421
|
-
const target = await accountOf(l,
|
|
36667
|
+
async function runAs(l, self, requested2) {
|
|
36668
|
+
if (requested2 === void 0) return self;
|
|
36669
|
+
const target = await accountOf(l, requested2);
|
|
36422
36670
|
if (self.uid !== 0 && target.uid !== self.uid) {
|
|
36423
36671
|
throw fsError("EPERM", `${self.name} may not run as ${target.name}`);
|
|
36424
36672
|
}
|
|
@@ -36427,21 +36675,9 @@ async function runAs(l, self, requested) {
|
|
|
36427
36675
|
function clientCred(self) {
|
|
36428
36676
|
return self ? credOf(self) : copyCred(ROOT);
|
|
36429
36677
|
}
|
|
36430
|
-
var MAX_SPAWN_TAGS = 8;
|
|
36431
|
-
function spawnTags(value2) {
|
|
36432
|
-
if (!Array.isArray(value2)) {
|
|
36433
|
-
tagOption(value2);
|
|
36434
|
-
return value2 === void 0 ? [] : [value2];
|
|
36435
|
-
}
|
|
36436
|
-
if (value2.length > MAX_SPAWN_TAGS) {
|
|
36437
|
-
throw new TypeError(`a spawn adds at most ${MAX_SPAWN_TAGS} tags`);
|
|
36438
|
-
}
|
|
36439
|
-
for (const each of value2) tagOption(each ?? 0);
|
|
36440
|
-
return value2;
|
|
36441
|
-
}
|
|
36442
36678
|
async function runTagged(l, self, options, tag, session = -1) {
|
|
36443
36679
|
let tags = withTag(void 0, tag);
|
|
36444
|
-
for (const added of
|
|
36680
|
+
for (const added of tagList(options.tag)) tags = withTag(tags, added);
|
|
36445
36681
|
return {
|
|
36446
36682
|
user: await runAs(l, self, options.user),
|
|
36447
36683
|
tag,
|
|
@@ -36626,6 +36862,20 @@ function requestBinding(send2, port) {
|
|
|
36626
36862
|
close: () => unbind?.()
|
|
36627
36863
|
};
|
|
36628
36864
|
}
|
|
36865
|
+
async function sudoRunAs(l, self, host, req, reply) {
|
|
36866
|
+
if (self.uid !== 0) throw sudoFailure("EPERM", "sudo: only a root client may run a sudo request");
|
|
36867
|
+
const { stdout, stderr, tag } = req.options;
|
|
36868
|
+
const running = await l.sudoRun(req.replay, {
|
|
36869
|
+
stdout,
|
|
36870
|
+
stderr,
|
|
36871
|
+
tag,
|
|
36872
|
+
base: host.tag,
|
|
36873
|
+
session: host.session
|
|
36874
|
+
});
|
|
36875
|
+
reply(req.id, { started: running.pid });
|
|
36876
|
+
const { status, signal } = await running.ended;
|
|
36877
|
+
return { result: status, ...signalField(signal) };
|
|
36878
|
+
}
|
|
36629
36879
|
function answered(pending, req, reply, detach) {
|
|
36630
36880
|
pending.then(
|
|
36631
36881
|
({ result, signal, transfer }) => {
|
|
@@ -36775,6 +37025,8 @@ function serveClient(port, host) {
|
|
|
36775
37025
|
case "trace":
|
|
36776
37026
|
case "untrace":
|
|
36777
37027
|
return traces.answer(l, self, req);
|
|
37028
|
+
case "sudo-run":
|
|
37029
|
+
return sudoRunAs(l, self, host, req, reply);
|
|
36778
37030
|
case "detach":
|
|
36779
37031
|
return { result: true };
|
|
36780
37032
|
default:
|
|
@@ -36880,16 +37132,16 @@ function placeOf(address) {
|
|
|
36880
37132
|
const kind = isIP3(plain3);
|
|
36881
37133
|
if (kind === 4) return ipv4Place(plain3);
|
|
36882
37134
|
if (kind !== 6) return void 0;
|
|
36883
|
-
const
|
|
36884
|
-
const embedded2 =
|
|
36885
|
-
if (embedded2 && (
|
|
36886
|
-
if (
|
|
36887
|
-
if (((
|
|
36888
|
-
if (
|
|
37135
|
+
const words3 = hextets2(plain3);
|
|
37136
|
+
const embedded2 = words3.slice(0, 5).every((w) => w === 0) && (words3[5] === 65535 || words3[5] === 0);
|
|
37137
|
+
if (embedded2 && (words3[5] === 65535 || words3[6] !== 0)) return ipv4Place(ipv4Of(words3));
|
|
37138
|
+
if (words3.slice(0, 7).every((w) => w === 0) && (words3[7] ?? 0) <= 1) return "loopback";
|
|
37139
|
+
if (((words3[0] ?? 0) & 65472) === 65152) return "link-local";
|
|
37140
|
+
if (words3.join(":") === METADATA_V6) return "link-local";
|
|
36889
37141
|
return void 0;
|
|
36890
37142
|
}
|
|
36891
|
-
function ipv4Of(
|
|
36892
|
-
const [high = 0, low = 0] =
|
|
37143
|
+
function ipv4Of(words3) {
|
|
37144
|
+
const [high = 0, low = 0] = words3.slice(6);
|
|
36893
37145
|
return [high >> 8, high & 255, low >> 8, low & 255].join(".");
|
|
36894
37146
|
}
|
|
36895
37147
|
function hextets2(address) {
|
|
@@ -37970,6 +38222,19 @@ async function spawnOn(channel, argv, opts) {
|
|
|
37970
38222
|
signal: async (name2 = "SIGTERM") => void await channel.call({ op: "kill", pid: -pgid, signal: name2 })
|
|
37971
38223
|
};
|
|
37972
38224
|
}
|
|
38225
|
+
async function sudoRunOn(channel, replay, { stdout, stderr, tag }) {
|
|
38226
|
+
await since(channel, 16, "sudoRun", async () => {
|
|
38227
|
+
});
|
|
38228
|
+
const started = Promise.withResolvers();
|
|
38229
|
+
let endedBy;
|
|
38230
|
+
const { done: done4 } = channel.request(
|
|
38231
|
+
{ op: "sudo-run", replay, options: { stdout, stderr, tag } },
|
|
38232
|
+
{ started: started.resolve, ended: (signal) => endedBy = signal }
|
|
38233
|
+
);
|
|
38234
|
+
done4.catch(started.reject);
|
|
38235
|
+
const pid = await started.promise;
|
|
38236
|
+
return { pid, pgid: pid, ended: endedOf(done4, () => endedBy) };
|
|
38237
|
+
}
|
|
37973
38238
|
function endedOf(done4, signal) {
|
|
37974
38239
|
return quiet(
|
|
37975
38240
|
done4.then((status) => {
|
|
@@ -38171,6 +38436,7 @@ async function attachKernel(port, options = {}) {
|
|
|
38171
38436
|
return () => channel.traitsListeners.delete(listener);
|
|
38172
38437
|
},
|
|
38173
38438
|
trace: (tag, onEvents, options2 = {}) => traceOn(channel, tag, onEvents, options2),
|
|
38439
|
+
sudoRun: (replay, options2 = {}) => sudoRunOn(channel, replay, options2),
|
|
38174
38440
|
async close(o = {}) {
|
|
38175
38441
|
if (channel.failure) return;
|
|
38176
38442
|
await channel.call({ op: "detach", ...o.kill ? { kill: true } : {} }).catch(() => void 0);
|
|
@@ -38485,6 +38751,30 @@ function checkedRequests(hook) {
|
|
|
38485
38751
|
const kinds = kindsOf(hook);
|
|
38486
38752
|
return { kinds, handle: (request) => hook.handle(request) };
|
|
38487
38753
|
}
|
|
38754
|
+
function nodeAccounts(launcher, guard2) {
|
|
38755
|
+
return {
|
|
38756
|
+
users: {
|
|
38757
|
+
mode: launcher.usersMode,
|
|
38758
|
+
add: (user) => guard2(() => launcher.users.add(user)),
|
|
38759
|
+
remove: (name2, options) => guard2(() => launcher.users.remove(name2, options)),
|
|
38760
|
+
list: () => guard2(() => launcher.users.list())
|
|
38761
|
+
},
|
|
38762
|
+
groups: {
|
|
38763
|
+
list: () => guard2(() => launcher.users.groups()),
|
|
38764
|
+
add: (name2, options) => guard2(() => launcher.users.addGroup(name2, options?.gid)),
|
|
38765
|
+
addMember: (group, user) => guard2(() => launcher.users.addMember(group, user)),
|
|
38766
|
+
removeMember: (group, user) => guard2(() => launcher.users.removeMember(group, user))
|
|
38767
|
+
}
|
|
38768
|
+
};
|
|
38769
|
+
}
|
|
38770
|
+
async function nodeSudoRun(launcher, guard2, replay, options) {
|
|
38771
|
+
const running = await guard2(() => launcher.sudoRun(replay, options));
|
|
38772
|
+
const ended = guard2(async () => {
|
|
38773
|
+
const { status, signal } = await running.ended;
|
|
38774
|
+
return { status, ...signalField(signal) };
|
|
38775
|
+
});
|
|
38776
|
+
return { pid: running.pid, pgid: running.pid, ended: quiet(ended) };
|
|
38777
|
+
}
|
|
38488
38778
|
async function createNodeKernel(options = {}) {
|
|
38489
38779
|
const hooks = sealedHooks(options.sealed);
|
|
38490
38780
|
const timeZone = systemTimeZone(options.timeZone, clockZone(options.cron?.clock));
|
|
@@ -38613,18 +38903,8 @@ async function createNodeKernel(options = {}) {
|
|
|
38613
38903
|
mounts: async () => launcher.mounts.listed(),
|
|
38614
38904
|
setRoutes: (routes) => guard2(async () => launcher.setRoutes(routes)),
|
|
38615
38905
|
updateTransportTraits: () => guard2(async () => launcher.updateTransportTraits()),
|
|
38616
|
-
|
|
38617
|
-
|
|
38618
|
-
add: (user) => guard2(() => launcher.users.add(user)),
|
|
38619
|
-
remove: (name2, options2) => guard2(() => launcher.users.remove(name2, options2)),
|
|
38620
|
-
list: () => guard2(() => launcher.users.list())
|
|
38621
|
-
},
|
|
38622
|
-
groups: {
|
|
38623
|
-
list: () => guard2(() => launcher.users.groups()),
|
|
38624
|
-
add: (name2, options2) => guard2(() => launcher.users.addGroup(name2, options2?.gid)),
|
|
38625
|
-
addMember: (group, user) => guard2(() => launcher.users.addMember(group, user)),
|
|
38626
|
-
removeMember: (group, user) => guard2(() => launcher.users.removeMember(group, user))
|
|
38627
|
-
},
|
|
38906
|
+
...nodeAccounts(launcher, guard2),
|
|
38907
|
+
sudoRun: (replay, sudoOptions = {}) => nodeSudoRun(launcher, guard2, replay, sudoOptions),
|
|
38628
38908
|
async connect(connectOptions = {}) {
|
|
38629
38909
|
if (terminated) throw new Error(TERMINATED);
|
|
38630
38910
|
const { user } = connectOptions;
|