mesh/merge-gate pass: builds zsh → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group withhold-login-shell-execute delivered: every member is delivered
execute runs any command as the operator account, which can become root without a person. The operator withholds it on the control-node until a call needs a person's approval (hq ADR 0268); the other machines keep it for now. The setting execute (serve by default) is written into a root-owned file the tools bundle reads at start, and anything but serve withholds the verb, so the machine's runtime does not offer it.
95 lines
5.3 KiB
TypeScript
95 lines
5.3 KiB
TypeScript
// The zsh module's shape (novox/hq ADR 0203, ADR 0204, to-be 41 WP3): it claims the mesh's
|
|
// node-login-shell and declares no seat; its ~/.zshrc block goes at the start and holds the three
|
|
// slots in order; its ~/.zshenv block sources the path node-environment fixes and nothing else; its
|
|
// environment is a contribution, never an export in its own lines.
|
|
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
|
|
const m = JSON.parse(readFileSync(new URL("../module.json", import.meta.url), "utf8"));
|
|
const resource = (id: string) => m.resources.find((r: { id: string }) => r.id === id);
|
|
|
|
test("it claims node-login-shell serving execute, and declares no seat", () => {
|
|
assert.equal(m.seats, undefined);
|
|
assert.deepEqual(m.claims, [{ name: "node-login-shell", scope: "node", serves: ["execute"] }]);
|
|
});
|
|
|
|
test("the .zshrc block is at the start and holds the three slots in order, after the defaults' header", () => {
|
|
const rc = resource("rc");
|
|
assert.equal(rc.path, "${machine:account-home}/.zshrc");
|
|
assert.equal(rc.into, "block");
|
|
assert.equal(rc.at, "start");
|
|
const c: string = rc.content;
|
|
const first = c.indexOf("${shell:zsh:first}");
|
|
const normal = c.indexOf("${shell:zsh:normal}");
|
|
const last = c.indexOf("${shell:zsh:last}");
|
|
assert.ok(c.startsWith("# The mesh's block"), "it opens by saying whose it is");
|
|
assert.ok(first > 0 && first < normal && normal < last, "first, normal, last, in that order");
|
|
assert.ok(c.indexOf("set_terminal_title") > first && c.indexOf("sudo-disksize") < normal, "the defaults sit between first and normal");
|
|
for (const slot of ["first", "normal", "last"]) assert.equal(c.split(`\${shell:zsh:${slot}}`).length, 2, `${slot} appears once`);
|
|
});
|
|
|
|
test("the .zshrc block carries the shared defaults and none of the operator's own lines", () => {
|
|
const c: string = resource("rc").content;
|
|
for (const want of ["precmd_functions+=(set_terminal_title)", "alias egrep='egrep --color=auto'", "alias ll='ls -alhF'", "alias drun=", "disksize()", "sudo-disksize()"]) {
|
|
assert.ok(c.includes(want), want);
|
|
}
|
|
assert.equal((c.match(/^bindkey /gm) ?? []).length, 7);
|
|
for (const not of ["export ", "p10k", "powerlevel10k", "nvm", ".dotnet", "MY_KV_PATH", "MY_LIB_PATH", "CLAUDE_CODE_DISABLE_TERMINAL_TITLE", "killport", "findport", ".zshrc.local", "zsh-autosuggestions", "zsh-syntax-highlighting"]) {
|
|
assert.ok(!c.includes(not), `the block holds no ${not}`);
|
|
}
|
|
});
|
|
|
|
test("the .zshenv block sources exactly the environment file node-environment fixes", () => {
|
|
const env = resource("env");
|
|
assert.equal(env.path, "${machine:account-home}/.zshenv");
|
|
assert.equal(env.into, "block");
|
|
assert.equal(env.at, "start");
|
|
const sourced = [...(env.content as string).matchAll(/^\s*(?:source|\.)\s+"?([^"\s]+)"?/gm)].map((x) => x[1]);
|
|
assert.deepEqual(sourced, ["${machine:account-home}/.config/mesh/environment.sh"]);
|
|
});
|
|
|
|
test("its environment is a contribution: the editor, the configuration home, and three PATH entries at the start", () => {
|
|
assert.deepEqual(m.environment.variables, { EDITOR: "vim", VISUAL: "vim", XDG_CONFIG_HOME: "${machine:account-home}/.config" });
|
|
assert.deepEqual(m.environment.path, [
|
|
{ entry: "${machine:account-home}/.local/bin", at: "start" },
|
|
{ entry: "${machine:account-home}/scripts", at: "start" },
|
|
{ entry: "${machine:account-home}/scripts/bin", at: "start" },
|
|
]);
|
|
});
|
|
|
|
test("it keeps the package and sets the login shell through the user shape", () => {
|
|
assert.deepEqual(resource("package"), { id: "package", type: "package", package: "zsh" });
|
|
assert.deepEqual(resource("login"), { id: "login", type: "user", name: "${machine:account}", shell: "/usr/bin/zsh" });
|
|
assert.ok(m.capabilities.includes("package-manager"));
|
|
});
|
|
|
|
test("the tools bundle registers the seat's verb under node-login-shell", () => {
|
|
const src = readFileSync(new URL("../tools/index.ts", import.meta.url), "utf8");
|
|
assert.match(src, /registerModuleTools\("node-login-shell", seatVerbs\)/);
|
|
assert.doesNotMatch(src, /runuser|"login-shell"/);
|
|
});
|
|
|
|
test("execute is a per-machine setting, served unless a machine withholds it (ADR 0268)", () => {
|
|
assert.deepEqual(Object.keys(m.settings), ["execute"]);
|
|
assert.equal(m.settings.execute.kind, "preference");
|
|
assert.equal(m.settings.execute.default, "serve");
|
|
assert.match(m.settings.execute.why, /withhold/);
|
|
const dir = resource("state");
|
|
assert.deepEqual(dir, { id: "state", type: "directory", place: ".", owner: "root", mode: "0755" });
|
|
const conf = resource("tools-conf");
|
|
assert.equal(conf.type, "file");
|
|
assert.equal(conf.path, "${dir:state}/tools.conf");
|
|
assert.equal(conf.owner, "root", "the account the runtime runs as may read it, never change it");
|
|
assert.equal(conf.mode, "0644");
|
|
assert.match(conf.content, /^execute=\$\{setting:execute\}$/m);
|
|
const [bundle] = m.build.artifacts;
|
|
assert.deepEqual(bundle.env, { ZSH_TOOLS_CONF: conf.path }, "the word names the file exactly, so its change restarts the runtime");
|
|
});
|
|
|
|
test("the tools bundle registers execute only where the machine's setting serves it", () => {
|
|
const src = readFileSync(new URL("../tools/index.ts", import.meta.url), "utf8");
|
|
assert.match(src, /readExecuteSetting\(env\)/);
|
|
assert.match(src, /if \(!setting\.served\)[\s\S]{0,200}return \[\]/);
|
|
});
|