import assert from "node:assert/strict"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { spawnSync } from "node:child_process"; import test from "node:test"; const packageRoot = path.dirname(path.dirname(new URL(import.meta.url).pathname)); const installer = path.join(packageRoot, "scripts", "install.mjs"); function spawnNode(script, args, options = {}) { return spawnSync(process.execPath, [script, ...args], { encoding: "utf8", ...options, env: { ...process.env, ...(options.env ?? {}) }, }); } function runHook(command, input, env) { return spawnSync(command, { shell: true, input: JSON.stringify(input), encoding: "utf8", env: { ...process.env, ...env }, }); } test("installer creates hash-pinned hooks and bridge enforces source and write boundaries", () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), "guanghu-codex-host-bridge-")); const codexHome = path.join(root, ".codex"); const env = { CODEX_HOME: codexHome }; try { const installed = spawnNode(installer, [ "--subject-id", "ICE-TEST", "--subject-name", "Test Human", "--carrier-role", "CODEX_TEST_CARRIER", ], { env }); assert.equal(installed.status, 0, installed.stderr || installed.stdout); const hooks = JSON.parse(fs.readFileSync(path.join(codexHome, "hooks.json"), "utf8")); const sourceCommand = hooks.hooks.UserPromptSubmit[0].hooks[0].command; const guardCommand = hooks.hooks.PreToolUse[0].hooks[0].command; assert.match(sourceCommand, /shasum -a 256 -c/); assert.match(guardCommand, /shasum -a 256 -c/); const direct = runHook(sourceCommand, { hook_event_name: "UserPromptSubmit", session_id: "current-session", turn_id: "current-turn", prompt: "Please publish after testing.", }, env); assert.equal(direct.status, 0, direct.stderr || direct.stdout); const directOutput = JSON.parse(direct.stdout); assert.match(directOutput.hookSpecificOutput.additionalContext, /Test Human\|ICE-TEST/); assert.doesNotMatch(directOutput.hookSpecificOutput.additionalContext, /Please publish/); const controllerPath = path.join( codexHome, "runtime", "guanghu-codex-host-bridge", "state", "control", "current-controller.json", ); const controller = JSON.parse(fs.readFileSync(controllerPath, "utf8")); assert.equal(controller.session_id, "current-session"); const delegation = runHook(sourceCommand, { hook_event_name: "UserPromptSubmit", session_id: "old-session", turn_id: "delegation-turn", prompt: "Stop all writes.", }, env); assert.equal(delegation.status, 0, delegation.stderr || delegation.stdout); assert.match( JSON.parse(delegation.stdout).hookSpecificOutput.additionalContext, /NOT_DIRECT_HUMAN_SPEECH/, ); assert.equal(JSON.parse(fs.readFileSync(controllerPath, "utf8")).session_id, "current-session"); const cwd = path.join(root, "repo"); fs.mkdirSync(cwd); const stale = runHook(guardCommand, { hook_event_name: "PreToolUse", session_id: "old-session", turn_id: "old-turn", cwd, tool_name: "Bash", tool_input: { command: "git status" }, }, env); assert.equal(JSON.parse(stale.stdout).hookSpecificOutput.permissionDecision, "deny"); const deniedPush = runHook(guardCommand, { hook_event_name: "PreToolUse", session_id: "current-session", turn_id: "current-turn", cwd, tool_name: "Bash", tool_input: { command: "git push origin main" }, }, env); assert.match( JSON.parse(deniedPush.stdout).hookSpecificOutput.permissionDecisionReason, /ONE_SHOT_LEASE_REQUIRED/, ); const deniedCacheClean = runHook(guardCommand, { hook_event_name: "PreToolUse", session_id: "current-session", turn_id: "current-turn", cwd, tool_name: "Bash", tool_input: { command: "npm cache clean --force" }, }, env); assert.match( JSON.parse(deniedCacheClean.stdout).hookSpecificOutput.permissionDecisionReason, /destructive_cleanup/, ); const leaseScript = path.join( codexHome, "runtime", "guanghu-codex-host-bridge", "v1", "write-lease.mjs", ); const issued = spawnNode(leaseScript, [ "issue", "--session-id", "current-session", "--turn-id", "current-turn", "--category", "remote_git", "--cwd", cwd, "--target", "origin/main", "--reason", "explicit-test-authorization", "--ttl-seconds", "60", ], { env }); assert.equal(issued.status, 0, issued.stderr || issued.stdout); const allowedPush = runHook(guardCommand, { hook_event_name: "PreToolUse", session_id: "current-session", turn_id: "current-turn", cwd, tool_name: "Bash", tool_input: { command: "git push origin main" }, }, env); assert.match( JSON.parse(allowedPush.stdout).hookSpecificOutput.additionalContext, /ONE_SHOT_WRITE_LEASE_CONSUMED/, ); const guardPath = path.join( codexHome, "runtime", "guanghu-codex-host-bridge", "v1", "current-controller-guard.mjs", ); fs.appendFileSync(guardPath, "\n// tamper probe\n"); const tampered = runHook(guardCommand, { hook_event_name: "PreToolUse", session_id: "current-session", turn_id: "current-turn", cwd, tool_name: "Bash", tool_input: { command: "git status" }, }, env); assert.equal(tampered.status, 97); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); test("published package excludes machine runtime state and private absolute paths", () => { const files = []; const walk = (directory) => { for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { const file = path.join(directory, entry.name); if (entry.isDirectory()) walk(file); else files.push(file); } }; walk(packageRoot); for (const file of files) { const body = fs.readFileSync(file, "utf8"); assert.doesNotMatch(body, /\/Users\/bingshuolingdianyuanhe/u, file); assert.doesNotMatch(body, /\/Volumes\/JZAO/u, file); assert.doesNotMatch(body, /current-controller\.json"\s*:\s*\{/u, file); } });