import assert from "node:assert/strict"; import { execFileSync, spawnSync } from "node:child_process"; import { chmod, mkdtemp, mkdir, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { pathToFileURL } from "node:url"; import test from "node:test"; const verifier = new URL("../../scripts/verify-git-package.mjs", import.meta.url); function runVerifier(args: string[], cache?: string) { return spawnSync(process.execPath, [verifier.pathname, ...args], { encoding: "utf8", env: cache === undefined ? process.env : { ...process.env, CODEX_CHIEF_OF_STAFF_NPM_CACHE: cache }, timeout: 60_000, }); } test("Git-package verifier requires exactly one immutable package spec without leaking credentials", () => { const secret = "credential-must-not-appear"; const invalid = [ [], ["git+https://git.example.invalid/team/codex-chief-of-staff.git#main"], [`git+https://user:${secret}@git.example.invalid/team/codex-chief-of-staff.git#main`], ["git+https://git.example.invalid/team/codex-chief-of-staff.git#abc123"], [ "git+https://git.example.invalid/team/codex-chief-of-staff.git#v0.1.1", "git+https://git.example.invalid/team/codex-chief-of-staff.git#v0.1.0", ], ]; for (const args of invalid) { const result = runVerifier(args); assert.notEqual(result.status, 0); assert.equal(result.stderr.includes(secret), false); assert.match(result.stderr, /Git-package verification failed:/); } }); test("Git-package verifier installs and initializes a disposable prebuilt Git revision", async () => { const root = await mkdtemp(join(tmpdir(), "codex-chief-of-staff-git-test-")); const repository = join(root, "codex-chief-of-staff.git"); const cache = join(root, "npm-cache"); try { await mkdir(join(repository, "dist", "src"), { recursive: true }); await writeFile(join(repository, "package.json"), `${JSON.stringify({ name: "codex-chief-of-staff", version: "9.9.9", private: true, type: "module", bin: { "codex-chief-of-staff": "dist/src/index.js" }, files: ["dist/src"], engines: { node: ">=24 <25" }, }, null, 2)}\n`); const server = `#!/usr/bin/env node const tools = ["overview", "list_threads", "inspect_thread", "wait_for_change"]; let buffered = ""; const send = (id, result) => process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, result }) + "\\n"); process.stdin.setEncoding("utf8"); process.stdin.on("data", (chunk) => { buffered += chunk; for (;;) { const newline = buffered.indexOf("\\n"); if (newline < 0) break; const line = buffered.slice(0, newline); buffered = buffered.slice(newline + 1); if (line === "") continue; const request = JSON.parse(line); if (request.id === undefined) continue; if (request.method === "initialize") { send(request.id, { protocolVersion: request.params.protocolVersion, capabilities: { tools: {} }, serverInfo: { name: "fixture-chief-of-staff", version: "9.9.9" }, instructions: "Call overview first for current Codex thread state.", }); } else if (request.method === "tools/list") { send(request.id, { tools: tools.map((name) => ({ name, description: name, inputSchema: { type: "object", properties: {}, additionalProperties: false }, })) }); } } }); `; const executable = join(repository, "dist", "src", "index.js"); await writeFile(executable, server); await chmod(executable, 0o755); execFileSync("git", ["init", "--quiet"], { cwd: repository }); execFileSync("git", ["config", "user.name", "Codex Test"], { cwd: repository }); execFileSync("git", ["config", "user.email", "codex-test@example.invalid"], { cwd: repository }); execFileSync("git", ["add", "."], { cwd: repository }); execFileSync("git", ["commit", "--quiet", "-m", "prebuilt fixture"], { cwd: repository }); const revision = execFileSync("git", ["rev-parse", "HEAD"], { cwd: repository, encoding: "utf8", }).trim(); const packageSpec = `git+${pathToFileURL(repository).href}#${revision}`; const result = runVerifier([packageSpec], cache); assert.equal(result.status, 0, result.stderr); const report = JSON.parse(result.stdout) as { ok: boolean; revision: string; storage: string; instructions: string; tools: string[]; }; assert.equal(report.ok, true); assert.equal(report.revision, revision); assert.equal(report.storage, "isolated-prefix"); assert.equal(report.instructions, "verified"); assert.deepEqual(report.tools, ["overview", "list_threads", "inspect_thread", "wait_for_change"]); } finally { await rm(root, { recursive: true, force: true }); } });