Files
openrig/scripts/product-control-plane.test.mjs
Mike Schwarz c4de1b2c38 build: read leak-guard rules from an optional local file (#2137)
The leak guard's term lists now come from an optional local rules file instead of a file tracked in the repository. Set `OPENRIG_LEAK_GUARD_RULES` (or pass `--rules`) to an absolute path, and every reader uses it through one loader: the leak guard, `build-package.sh`, the context packs, the skill mirror and the control-plane generator. The publishing rules, the frontmatter keys and the internal-section fence stay in the repository unchanged, so mirrored skills are the same.

Without the file, a contributor's `npm run build:package` still works and prints that the term checks were skipped. The release substance gate refuses to run without a rules file, so a release can't pass with the checks silently off. The tracked rules file is removed, and the tests write their own fixture rules.

16 files, +227 -244.
2026-10-26 18:46:46 -07:00

132 lines
7.1 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
const GENERATOR = resolve("packages/daemon/scripts/gen-control-plane-json.mjs");
const MIRROR = resolve("scripts/mirror-skills.mjs");
const NAMES = ["product-public-skills", "skill-edge-layout"];
test("regeneration preserves product policy bytes in place and when exporting", () => {
withFixture(({ root, policyBytes }) => {
for (const output of [join(root, "scripts"), join(root, "export")]) {
const result = run(GENERATOR, root, ["--repo-root", root, "--output", output]);
assert.equal(result.status, 0, result.stderr);
for (const name of NAMES) {
assert.deepEqual(readFileSync(join(output, `${name}.generated.json`)), policyBytes[name]);
assert.deepEqual(readFileSync(join(root, "scripts", `${name}.generated.json`)), policyBytes[name]);
}
const digests = JSON.parse(readFileSync(join(output, "skill-edge-digests.generated.json")));
assert.ok(digests.edges.plugin["alpha/SKILL.md"]);
}
});
});
test("legacy YAML inputs refuse with product pointers before changing policy files", () => {
withFixture(({ root, legacy, policyBytes }) => {
const result = run(GENERATOR, root, [
"--repo-root", root, "--output", join(root, "scripts"),
"--membership", legacy.membership, "--denylist", legacy.denylist, "--layout", legacy.layout,
]);
assert.notEqual(result.status, 0);
assert.match(result.stderr, /product-public-skills\.generated\.json/);
for (const name of NAMES) {
assert.deepEqual(readFileSync(join(root, "scripts", `${name}.generated.json`)), policyBytes[name]);
}
// The leak guard's term lists left the repository: a denylist override points at their local file instead.
for (const [flag, named] of [["membership", "product-public-skills.generated.json"], ["denylist", "OPENRIG_LEAK_GUARD_RULES"],
["layout", "skill-edge-layout.generated.json"]]) {
const single = run(GENERATOR, root, [
"--repo-root", root, "--output", join(root, "scripts"), `--${flag}`, legacy[flag],
]);
assert.notEqual(single.status, 0);
assert.ok(single.stderr.includes(named), single.stderr);
for (const name of NAMES) {
assert.deepEqual(readFileSync(join(root, "scripts", `${name}.generated.json`)), policyBytes[name]);
}
}
});
});
test("authoring apply uses product policy and in-repo sources despite legacy YAML and external canon environment", () => {
withFixture(({ root, legacy, policyBytes }) => {
const script = join(root, "packages/daemon/scripts/gen-control-plane-json.mjs");
mkdirSync(dirname(script), { recursive: true });
// Forward the real invocation: a symlink would defeat the generator's main-module check.
write(script, `import { spawnSync } from "node:child_process";\nconst r = spawnSync(process.execPath, [${JSON.stringify(GENERATOR)}, ...process.argv.slice(2)], { stdio: "inherit" });\nprocess.exitCode = r.status ?? 1;\n`);
write(join(root, "canon/alpha/SKILL.md"), "# Alpha from an outside canon\n");
const result = run(MIRROR, root, [], {
OPENRIG_SKILL_CANON_ROOT: join(root, "canon"),
OPENRIG_PRODUCT_PUBLIC_SKILLS_YAML: legacy.membership,
OPENRIG_INTERNAL_TOKENS_YAML: legacy.denylist,
OPENRIG_SKILL_EDGE_LAYOUT_YAML: legacy.layout,
});
assert.equal(result.status, 0, result.stderr);
assert.match(result.stderr, /OPENRIG_SKILL_CANON_ROOT is ignored/);
for (const name of NAMES) {
assert.deepEqual(readFileSync(join(root, "scripts", `${name}.generated.json`)), policyBytes[name]);
}
assert.equal(readFileSync(join(root, "plugin/alpha/SKILL.md"), "utf8"), "# Original alpha\n");
});
});
test("authoring apply regenerates from in-repo sources with no external authoring variables", () => {
withFixture(({ root }) => {
const script = join(root, "packages/daemon/scripts/gen-control-plane-json.mjs");
mkdirSync(dirname(script), { recursive: true });
write(script, `import { spawnSync } from "node:child_process";\nconst r = spawnSync(process.execPath, [${JSON.stringify(GENERATOR)}, ...process.argv.slice(2)], { stdio: "inherit" });\nprocess.exitCode = r.status ?? 1;\n`);
const env = { ...process.env };
delete env.OPENRIG_SKILL_CANON_ROOT;
const result = spawnSync(process.execPath, [MIRROR], { cwd: root, encoding: "utf8", env });
assert.equal(result.status, 0, result.stderr);
assert.doesNotMatch(result.stderr, /OPENRIG_SKILL_CANON_ROOT/);
assert.equal(readFileSync(join(root, "plugin/alpha/SKILL.md"), "utf8"), "# Original alpha\n");
const check = spawnSync(process.execPath, [MIRROR, "--check"], { cwd: root, encoding: "utf8", env });
assert.equal(check.status, 0, check.stderr);
});
});
function withFixture(check) {
const root = mkdtempSync(join(tmpdir(), "openrig-product-control-"));
const membership = {
product_public: { clean: ["alpha"], ship_after_fix: [], ship_misses_add: [], sanitize_borderlines_ship: [] },
vendored_ship_with_provenance: [], not_public: {}, pending_author_public: [],
};
const rules = {
path_prefixes: ["private/"], seat_and_rig_patterns: ["private-seat@"],
host_patterns: ["private-host"], charged_terms: ["private-term"],
frontmatter_drop_keys: [], internal_path_globs: ["**/internal/**"],
section_fence: { begin: "<!-- internal:begin -->", end: "<!-- internal:end -->" },
allowed_context_substrings: ["do not ship"], allowed_context_lines: ["Exact generic private/ placeholder"],
};
const edges = {
canonical: { path: "canonical", layout: "mirror-of-spec" },
plugin: { path: "plugin", layout: "flat" }, spec: { path: "spec", layout: "categorized" },
};
const layout = { version: 0, edges, skills: { alpha: { edges: ["plugin"], category: null } } };
const policyBytes = {};
for (const [i, data] of [membership, layout].entries()) {
// Deliberately nonstandard formatting must survive a refresh byte for byte.
policyBytes[NAMES[i]] = Buffer.from(JSON.stringify(data, null, 4) + "\n\n");
write(join(root, "scripts", `${NAMES[i]}.generated.json`), policyBytes[NAMES[i]]);
}
write(join(root, "plugin/alpha/SKILL.md"), "# Original alpha\n");
const legacy = Object.fromEntries(["membership", "denylist", "layout"].map(name => [name, join(root, `${name}.yaml`)]));
write(legacy.membership, JSON.stringify({ ...membership, product_public: { ...membership.product_public, clean: [] } }));
write(legacy.denylist, JSON.stringify({ ...rules, allowed_context_lines: [] }));
write(legacy.layout, JSON.stringify({ version: 0, edges, extract_from_committed_trees: true, forward_overrides: {} }));
try { check({ root, legacy, policyBytes }); }
finally { rmSync(root, { recursive: true, force: true }); }
}
function write(path, bytes) {
mkdirSync(dirname(path), { recursive: true });
writeFileSync(path, bytes);
}
function run(script, cwd, args, env = {}) {
return spawnSync(process.execPath, [script, ...args], { cwd, encoding: "utf8", env: { ...process.env, ...env } });
}