Files
playbook/antigravity-awesome-skills/tools/scripts/tests/aas_v1_adapters.test.js
T
2026-07-20 00:03:02 +00:00

212 lines
13 KiB
JavaScript

"use strict";
const assert = require("node:assert/strict");
const fs = require("node:fs");
const fsp = require("node:fs/promises");
const os = require("node:os");
const path = require("node:path");
const test = require("node:test");
const {
applyHostConfigPatch,
buildPatch,
cleanupBackups,
inspectHostConfig,
} = require("../../lib/aas-v1/adapters");
const { inspectRegularFile } = require("../../lib/aas-v1/adapters/safety");
const FIXTURES = path.join(__dirname, "fixtures", "aas-v1-adapters");
const CODEX_SERVER = { command: "/opt/aas/aas-mcp", args: ["--stdio", "--runtime", "14.6.0"], enabled: true };
const CLAUDE_SERVER = { command: "/opt/aas/aas-mcp", args: ["--stdio"], env: { AAS_MODE: "offline", SECRET: "new-secret-never-previewed" } };
async function temporaryDirectory(t, prefix = "aas-adapter-") {
const directory = await fsp.mkdtemp(path.join(os.tmpdir(), prefix));
t.after(() => fsp.rm(directory, { recursive: true, force: true }));
return directory;
}
async function copyFixture(t, name, mode = 0o640) {
const directory = await temporaryDirectory(t);
const target = path.join(directory, name.endsWith("json") ? ".mcp.json" : "config.toml");
await fsp.copyFile(path.join(FIXTURES, name), target);
await fsp.chmod(target, mode);
return { directory, target };
}
async function backupFiles(directory) {
return (await fsp.readdir(directory)).filter((name) => name.endsWith(".bak") || name.endsWith(".json")).sort();
}
test("fixture provenance pins the validated host contracts without real user data", async () => {
const provenance = JSON.parse(await fsp.readFile(path.join(FIXTURES, "provenance.json"), "utf8"));
assert.equal(provenance.validatedAt, "2026-07-17");
assert.equal(provenance.anonymized, true);
assert.deepEqual(provenance.hosts.map((entry) => entry.host), ["codex", "claude"]);
assert.ok(provenance.hosts.every((entry) => entry.hostVersion && entry.documentation.startsWith("https://")));
});
test("Codex preview is value-free and patches only the aas table while preserving unknown text", async (t) => {
const { target } = await copyFixture(t, "codex-existing.toml");
const original = await fsp.readFile(target, "utf8");
const inspected = await inspectHostConfig({ host: "codex", scope: "project", configPath: target });
assert.equal(inspected.sectionPresent, true);
assert.deepEqual(inspected.unknownKeys, ["startup_timeout_sec"]);
const patch = await buildPatch({ host: "codex", scope: "project", configPath: target, server: CODEX_SERVER });
assert.equal(patch.changed, true);
assert.deepEqual(patch.redactedDiff.changedPaths, ["mcp_servers.aas.args", "mcp_servers.aas.command", "mcp_servers.aas.enabled"]);
const serialized = JSON.stringify(patch);
assert.ok(!serialized.includes("fixture-secret"));
assert.ok(!serialized.includes(CODEX_SERVER.command));
assert.ok(!serialized.includes("14.6.0"));
assert.equal(await fsp.readFile(target, "utf8"), original);
});
test("Claude preview preserves unknown objects and never exposes env values", async (t) => {
const { directory, target } = await copyFixture(t, "claude-existing.mcp.json");
const patch = await buildPatch({ host: "claude", scope: "user", configPath: target, server: CLAUDE_SERVER });
const serialized = JSON.stringify(patch);
for (const forbidden of ["fixture-root-secret", "fixture-other-secret", "fixture-old-secret", "new-secret", CLAUDE_SERVER.command]) {
assert.ok(!serialized.includes(forbidden), forbidden);
}
assert.deepEqual(patch.inspection.unknownKeys, ["disabled"]);
const result = await applyHostConfigPatch({ patch, approved: true, backupDirectory: path.join(directory, "backups"), now: "2026-07-17T01:02:03.000Z" });
assert.equal(result.status, "applied");
const parsed = JSON.parse(await fsp.readFile(target, "utf8"));
assert.equal(parsed.unrelated.token, "fixture-root-secret-must-not-appear-in-preview");
assert.equal(parsed.mcpServers.other.env.TOKEN, "fixture-other-secret-must-not-appear-in-preview");
assert.equal(parsed.mcpServers.aas.disabled, false);
assert.deepEqual(parsed.mcpServers.aas.env, CLAUDE_SERVER.env);
});
test("apply requires approval, preserves mode and owner, writes 0600 backups, and leaves no stage or lock", async (t) => {
const { directory, target } = await copyFixture(t, "codex-existing.toml", 0o640);
const originalStat = await fsp.stat(target);
const original = await fsp.readFile(target);
const patch = await buildPatch({ host: "codex", scope: "project", configPath: target, server: CODEX_SERVER });
await assert.rejects(applyHostConfigPatch({ patch, backupDirectory: path.join(directory, "backups") }), (error) => error.code === "AAS_ADAPTER_APPROVAL_REQUIRED");
assert.deepEqual(await fsp.readFile(target), original);
const result = await applyHostConfigPatch({ patch, approved: true, backupDirectory: path.join(directory, "backups"), retention: 3, now: "2026-07-17T02:00:00.000Z" });
assert.equal(result.status, "applied");
const nextStat = await fsp.stat(target);
assert.equal(nextStat.mode & 0o777, originalStat.mode & 0o777);
assert.equal(nextStat.uid, originalStat.uid);
assert.equal(nextStat.gid, originalStat.gid);
const configured = await fsp.readFile(target, "utf8");
assert.match(configured, /startup_timeout_sec = 20/);
assert.match(configured, /# preserve this comment/);
assert.match(configured, /fixture-secret-must-not-appear-in-preview/);
assert.ok(configured.includes('command = "/opt/aas/aas-mcp"'));
const files = await backupFiles(path.join(directory, "backups"));
assert.equal(files.length, 2);
for (const name of files) assert.equal((await fsp.stat(path.join(directory, "backups", name))).mode & 0o777, 0o600);
const metadataName = files.find((name) => name.endsWith(".json"));
const metadata = JSON.parse(await fsp.readFile(path.join(directory, "backups", metadataName), "utf8"));
assert.deepEqual(metadata.retention, { enforcement: "explicit-cleanup", maxEntries: 3 });
assert.deepEqual(await fsp.readFile(result.backup.backupPath), original);
assert.ok((await fsp.readdir(directory)).every((name) => !name.includes("aas-stage") && !name.endsWith(".aas.lock")));
});
test("apply blocks drift and an existing lock without overwriting current bytes", async (t) => {
const { directory, target } = await copyFixture(t, "codex-existing.toml");
const patch = await buildPatch({ host: "codex", scope: "project", configPath: target, server: CODEX_SERVER });
await fsp.appendFile(target, "\n# concurrent edit\n");
const drifted = await fsp.readFile(target);
await assert.rejects(
applyHostConfigPatch({ patch, approved: true, backupDirectory: path.join(directory, "backups") }),
(error) => error.code === "AAS_ADAPTER_CONFIG_CHANGED",
);
assert.deepEqual(await fsp.readFile(target), drifted);
const fresh = await buildPatch({ host: "codex", scope: "project", configPath: target, server: CODEX_SERVER });
const lockPath = path.join(directory, ".config.toml.aas.lock");
await fsp.writeFile(lockPath, "occupied", { mode: 0o600 });
await assert.rejects(
applyHostConfigPatch({ patch: fresh, approved: true, backupDirectory: path.join(directory, "backups") }),
(error) => error.code === "AAS_ADAPTER_LOCKED",
);
assert.deepEqual(await fsp.readFile(target), drifted);
});
test("symlink, non-regular, and ownership mismatches are rejected", async (t) => {
const directory = await temporaryDirectory(t);
const real = path.join(directory, "real.toml");
const link = path.join(directory, "link.toml");
const nonRegular = path.join(directory, "non-regular");
await fsp.writeFile(real, "");
await fsp.symlink(real, link);
await fsp.mkdir(nonRegular);
await assert.rejects(inspectHostConfig({ host: "codex", scope: "project", configPath: link }), (error) => error.code === "AAS_ADAPTER_CONFIG_UNSAFE");
await assert.rejects(inspectHostConfig({ host: "codex", scope: "project", configPath: nonRegular }), (error) => error.code === "AAS_ADAPTER_CONFIG_UNSAFE");
const stat = await fsp.stat(real);
await assert.rejects(inspectRegularFile(real, { expectedUid: stat.uid + 1 }), (error) => error.code === "AAS_ADAPTER_OWNERSHIP_MISMATCH");
});
test("ambiguous TOML and duplicate JSON keys fail closed", async (t) => {
const directory = await temporaryDirectory(t);
const toml = path.join(directory, "config.toml");
await fsp.writeFile(toml, "[mcp_servers]\naas.command = \"ambiguous\"\n");
await assert.rejects(buildPatch({ host: "codex", scope: "project", configPath: toml, server: CODEX_SERVER }), (error) => error.code === "AAS_ADAPTER_CODEX_SECTION_AMBIGUOUS");
const json = path.join(directory, ".mcp.json");
await fsp.writeFile(json, '{"mcpServers":{},"mcpServers":{}}');
await assert.rejects(buildPatch({ host: "claude", scope: "project", configPath: json, server: CLAUDE_SERVER }), (error) => error.code === "AAS_ADAPTER_CLAUDE_JSON_DUPLICATE_KEY");
});
test("a missing explicit path is created with 0600 and no implicit backup", async (t) => {
const directory = await temporaryDirectory(t);
const target = path.join(directory, ".mcp.json");
const patch = await buildPatch({ host: "claude", scope: "project", configPath: target, server: CLAUDE_SERVER });
assert.equal(patch.exists, false);
const result = await applyHostConfigPatch({ patch, approved: true });
assert.equal(result.backup, null);
assert.equal((await fsp.stat(target)).mode & 0o777, 0o600);
assert.deepEqual(JSON.parse(await fsp.readFile(target, "utf8")).mcpServers.aas, CLAUDE_SERVER);
});
test("retention is metadata only until explicit cleanup is approved", async (t) => {
const { directory, target } = await copyFixture(t, "codex-existing.toml");
const backups = path.join(directory, "backups");
const first = await buildPatch({ host: "codex", scope: "project", configPath: target, server: CODEX_SERVER });
await applyHostConfigPatch({ patch: first, approved: true, backupDirectory: backups, retention: 1, now: "2026-07-17T03:00:00.000Z" });
const secondServer = { ...CODEX_SERVER, args: [...CODEX_SERVER.args, "--second"] };
const second = await buildPatch({ host: "codex", scope: "project", configPath: target, server: secondServer });
await applyHostConfigPatch({ patch: second, approved: true, backupDirectory: backups, retention: 1, now: "2026-07-17T04:00:00.000Z" });
assert.equal((await backupFiles(backups)).length, 4);
await assert.rejects(cleanupBackups({ backupDirectory: backups, configPath: target, keep: 1 }), (error) => error.code === "AAS_ADAPTER_APPROVAL_REQUIRED");
assert.equal((await backupFiles(backups)).length, 4);
const cleaned = await cleanupBackups({ backupDirectory: backups, configPath: target, keep: 1, approved: true });
assert.equal(cleaned.removed.length, 1);
assert.equal((await backupFiles(backups)).length, 2);
});
test("adapters never infer HOME and reject relative config and backup paths", async (t) => {
const { directory, target } = await copyFixture(t, "codex-existing.toml");
await assert.rejects(buildPatch({ host: "codex", scope: "user", configPath: "config.toml", server: CODEX_SERVER }), (error) => error.code === "AAS_ADAPTER_PATH_INVALID");
const patch = await buildPatch({ host: "codex", scope: "user", configPath: target, server: CODEX_SERVER });
await assert.rejects(applyHostConfigPatch({ patch, approved: true, backupDirectory: "backups" }), (error) => error.code === "AAS_ADAPTER_BACKUP_PATH_INVALID");
const publicBackups = path.join(directory, "public-backups");
await fsp.mkdir(publicBackups, { mode: 0o755 });
await fsp.chmod(publicBackups, 0o755);
await assert.rejects(applyHostConfigPatch({ patch, approved: true, backupDirectory: publicBackups }), (error) => error.code === "AAS_ADAPTER_BACKUP_DIRECTORY_PERMISSIONS");
});
test("Windows sensitive-byte and directory-flush contracts stay fail-closed", async () => {
const adapterSource = await fsp.readFile(path.join(__dirname, "../../lib/aas-v1/adapters/index.js"), "utf8");
const safetySource = await fsp.readFile(path.join(__dirname, "../../lib/aas-v1/adapters/safety.js"), "utf8");
const durabilitySource = await fsp.readFile(path.join(__dirname, "../../lib/aas-v1/durability.js"), "utf8");
const stageCreate = adapterSource.indexOf('const handle = await fsp.open(stagePath, "wx", targetMode)');
const stageAcl = adapterSource.indexOf("copyWindowsAcl(patch.configPath, stagePath)", stageCreate);
const stageWrite = adapterSource.indexOf("await handle.writeFile(internal.nextBytes)", stageCreate);
assert.ok(stageCreate >= 0 && stageAcl > stageCreate && stageAcl < stageWrite);
const privateWriteStart = safetySource.indexOf("async function writeExclusiveSynced");
const privateAcl = safetySource.indexOf("hardenWindowsPrivatePath(filePath, false)", privateWriteStart);
const privateWrite = safetySource.indexOf("await handle.writeFile(bytes)", privateWriteStart);
assert.ok(privateAcl > privateWriteStart && privateAcl < privateWrite);
assert.ok(durabilitySource.includes("CreateFileW($directoryPath,0x40000000,7,"));
assert.ok(!durabilitySource.includes("CreateFileW($directoryPath,0x80000000,7,"));
assert.ok(durabilitySource.includes("$env:${WINDOWS_DIRECTORY_FLUSH_PATH_ENV}"));
assert.ok(!durabilitySource.includes("CreateFileW($args[0]"));
assert.ok(durabilitySource.includes("AAS_WIN32_DIRECTORY_FLUSH_FAILURE"));
assert.ok(durabilitySource.includes("GetLastWin32Error()"));
});