From 3d29ef9d39b51de1e7892a1d3022ecdf72a56d05 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 10:07:28 +0900 Subject: [PATCH 01/10] test(governance): require fatal UTF-8 production evidence --- ...uction-environment-governance-utf8.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test/production-environment-governance-utf8.test.ts diff --git a/test/production-environment-governance-utf8.test.ts b/test/production-environment-governance-utf8.test.ts new file mode 100644 index 000000000..8ab66b0a6 --- /dev/null +++ b/test/production-environment-governance-utf8.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from "vitest"; + +import { decodeGhOutput } from "../scripts/production-environment-governance-audit.mjs"; + +describe("production environment governance GitHub CLI UTF-8 boundary", () => { + it("rejects malformed UTF-8 instead of replacement-decoding production evidence", () => { + expect(() => + decodeGhOutput( + Uint8Array.from([0x7b, 0x22, 0xff, 0x22, 0x7d]), + "stdout", + ), + ).toThrow("GitHub CLI returned invalid UTF-8 in stdout."); + }); + + it("decodes valid UTF-8 bytes exactly", () => { + const bytes = new TextEncoder().encode('{"name":"production"}\n'); + expect(decodeGhOutput(bytes, "stdout")).toBe('{"name":"production"}\n'); + }); +}); From efd4bd49e43bce2d558d6afee427ad4f39ecb722 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 10:09:21 +0900 Subject: [PATCH 02/10] fix(governance): fatal-decode production evidence UTF-8 --- ...roduction-environment-governance-audit.mjs | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/scripts/production-environment-governance-audit.mjs b/scripts/production-environment-governance-audit.mjs index bb61a1c9a..d07d76c47 100644 --- a/scripts/production-environment-governance-audit.mjs +++ b/scripts/production-environment-governance-audit.mjs @@ -42,10 +42,25 @@ export function createGhSubprocessEnvironment(sourceEnvironment = process.env) { return childEnvironment; } +/** + * Decode GitHub CLI output without allowing replacement characters to convert + * malformed remote evidence into a different, parseable JSON document. + * + * @param {Uint8Array} value Raw subprocess bytes. + * @param {string} [label="output"] Diagnostic stream label. + * @returns {string} Exact UTF-8 text. + */ +export function decodeGhOutput(value, label = "output") { + try { + return new TextDecoder("utf-8", { fatal: true }).decode(value); + } catch { + throw new Error(`GitHub CLI returned invalid UTF-8 in ${label}.`); + } +} + function runGh(args) { const childEnvironment = createGhSubprocessEnvironment(); const completed = spawnSync("gh", args, { - encoding: "utf8", env: childEnvironment, maxBuffer: MAX_GH_OUTPUT_BYTES, shell: false, @@ -55,11 +70,18 @@ function runGh(args) { throw new Error(`GitHub CLI could not start: ${bound(detail)}`); } if (completed.status !== 0) { - const rawDetail = completed.stderr || completed.stdout || `exit ${completed.status}`; + let rawDetail; + if (completed.stderr?.length) { + rawDetail = decodeGhOutput(completed.stderr, "stderr"); + } else if (completed.stdout?.length) { + rawDetail = decodeGhOutput(completed.stdout, "stdout"); + } else { + rawDetail = `exit ${completed.status}`; + } const detail = redactSensitiveValue(rawDetail, [childEnvironment.GH_TOKEN]); throw new Error(`GitHub CLI failed: ${bound(detail)}`); } - return completed.stdout.trim(); + return decodeGhOutput(completed.stdout, "stdout").trim(); } function collectEnvironment(repository) { From 5feba689118490e9d7795a9cafe7e77cd02c9694 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 10:17:09 +0900 Subject: [PATCH 03/10] test(governance): exercise runGh failure byte boundary --- ...uction-environment-governance-utf8.test.ts | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/test/production-environment-governance-utf8.test.ts b/test/production-environment-governance-utf8.test.ts index 8ab66b0a6..a4f75fefc 100644 --- a/test/production-environment-governance-utf8.test.ts +++ b/test/production-environment-governance-utf8.test.ts @@ -1,6 +1,18 @@ import { describe, expect, it } from "vitest"; -import { decodeGhOutput } from "../scripts/production-environment-governance-audit.mjs"; +import { + decodeGhOutput, + runGh, +} from "../scripts/production-environment-governance-audit.mjs"; + +function failureMessage(action: () => unknown) { + try { + action(); + } catch (error) { + return error instanceof Error ? error.message : String(error); + } + throw new Error("expected action to fail"); +} describe("production environment governance GitHub CLI UTF-8 boundary", () => { it("rejects malformed UTF-8 instead of replacement-decoding production evidence", () => { @@ -16,4 +28,51 @@ describe("production environment governance GitHub CLI UTF-8 boundary", () => { const bytes = new TextEncoder().encode('{"name":"production"}\n'); expect(decodeGhOutput(bytes, "stdout")).toBe('{"name":"production"}\n'); }); + + it("prefers stderr and redacts GH_TOKEN on the real runGh failure path", () => { + const token = "read-only-secret-token"; + const message = failureMessage(() => + runGh(["api", "example"], { + sourceEnvironment: { PATH: "/usr/bin:/bin", GH_TOKEN: token }, + spawnSyncImpl: () => ({ + status: 1, + stdout: Buffer.from(`stdout exposed ${token}`, "utf8"), + stderr: Buffer.from(`stderr exposed ${token}`, "utf8"), + }), + }), + ); + + expect(message).toBe("GitHub CLI failed: stderr exposed [REDACTED]"); + expect(message).not.toContain(token); + expect(message).not.toContain("stdout exposed"); + }); + + it("falls back to stdout and redacts GH_TOKEN when stderr is empty", () => { + const token = "read-only-secret-token"; + const message = failureMessage(() => + runGh(["api", "example"], { + sourceEnvironment: { PATH: "/usr/bin:/bin", GH_TOKEN: token }, + spawnSyncImpl: () => ({ + status: 1, + stdout: Buffer.from(`stdout exposed ${token}`, "utf8"), + stderr: Buffer.alloc(0), + }), + }), + ); + + expect(message).toBe("GitHub CLI failed: stdout exposed [REDACTED]"); + expect(message).not.toContain(token); + }); + + it.each([ + ["stderr", Buffer.from([0xff]), Buffer.from("valid stdout", "utf8")], + ["stdout", Buffer.alloc(0), Buffer.from([0xff])], + ] as const)("fails closed on malformed %s bytes from runGh", (label, stderr, stdout) => { + expect(() => + runGh(["api", "example"], { + sourceEnvironment: { PATH: "/usr/bin:/bin", GH_TOKEN: "secret" }, + spawnSyncImpl: () => ({ status: 1, stdout, stderr }), + }), + ).toThrow(`GitHub CLI returned invalid UTF-8 in ${label}.`); + }); }); From 5c37a5f177b65e8350bfcc5ddc457bf8c2235c51 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 10:18:23 +0900 Subject: [PATCH 04/10] fix(governance): test runGh failure byte handling --- ...roduction-environment-governance-audit.mjs | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/scripts/production-environment-governance-audit.mjs b/scripts/production-environment-governance-audit.mjs index d07d76c47..5f21a8403 100644 --- a/scripts/production-environment-governance-audit.mjs +++ b/scripts/production-environment-governance-audit.mjs @@ -58,9 +58,26 @@ export function decodeGhOutput(value, label = "output") { } } -function runGh(args) { - const childEnvironment = createGhSubprocessEnvironment(); - const completed = spawnSync("gh", args, { +/** + * Execute one bounded GitHub CLI request for production-governance evidence. + * Runtime callers use the real shell-free spawn implementation and current + * process environment. Tests may inject only these two boundaries so failure + * byte selection, UTF-8 handling, and secret redaction are exercised directly. + * + * @param {string[]} args GitHub CLI arguments. + * @param {{sourceEnvironment?: NodeJS.ProcessEnv, spawnSyncImpl?: typeof spawnSync}} [options] + * Explicit environment source and subprocess primitive. + * @returns {string} Trimmed, fatal-decoded stdout on success. + */ +export function runGh( + args, + { + sourceEnvironment = process.env, + spawnSyncImpl = spawnSync, + } = {}, +) { + const childEnvironment = createGhSubprocessEnvironment(sourceEnvironment); + const completed = spawnSyncImpl("gh", args, { env: childEnvironment, maxBuffer: MAX_GH_OUTPUT_BYTES, shell: false, From 37a0aee2b610d46be38ed3d91ec51bd13fcd227f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 10:19:52 +0900 Subject: [PATCH 05/10] test(governance): bind shell-free injected spawn contract --- test/production-environment-governance.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/production-environment-governance.test.ts b/test/production-environment-governance.test.ts index c1239b5f2..e0903b389 100644 --- a/test/production-environment-governance.test.ts +++ b/test/production-environment-governance.test.ts @@ -144,7 +144,8 @@ describe("production environment governance", () => { it("uses a shell-free current-version GitHub API audit and bounded evidence", () => { const script = readFileSync("scripts/production-environment-governance-audit.mjs", "utf8"); - expect(script).toContain('spawnSync("gh"'); + expect(script).toContain("spawnSyncImpl = spawnSync"); + expect(script).toContain('spawnSyncImpl("gh"'); expect(script).toContain("shell: false"); expect(script).toContain("env: childEnvironment"); expect(script).not.toContain("env: process.env"); From afba3a19d68ece58a55f9ead743db53b64bae136 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 11:02:14 +0900 Subject: [PATCH 06/10] test(coverage): measure production governance audit --- vitest.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/vitest.config.ts b/vitest.config.ts index fef24afa4..c3dfe1bd2 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -10,6 +10,7 @@ export default defineConfig({ "scripts/normalize-commercial-readiness-evidence.mjs", "scripts/prepare-agent-pr-message.mjs", "scripts/workflow-registry-audit.mjs", + "scripts/production-environment-governance-audit.mjs", "scripts/lib/external-scheduler-evidence-audit.mjs", "scripts/external-scheduler-evidence-audit.mjs", ], From 5e1db5934e634bc8fc656bdfef47c3381b58604e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 11:04:52 +0900 Subject: [PATCH 07/10] refactor(governance): inject read-only audit runtime --- ...roduction-environment-governance-audit.mjs | 66 ++++++++++++++----- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/scripts/production-environment-governance-audit.mjs b/scripts/production-environment-governance-audit.mjs index 5f21a8403..507a68946 100644 --- a/scripts/production-environment-governance-audit.mjs +++ b/scripts/production-environment-governance-audit.mjs @@ -17,6 +17,13 @@ function bound(value, limit = MAX_ERROR_CHARS) { return valueText.length <= limit ? valueText : `${valueText.slice(0, limit)}…`; } +/** + * Redact exact sensitive values from a diagnostic before it is retained. + * + * @param {unknown} value Diagnostic value to render. + * @param {unknown[]} [sensitiveValues=[]] Exact secret values that must not escape. + * @returns {string} Redacted diagnostic text. + */ export function redactSensitiveValue(value, sensitiveValues = []) { let redacted = String(value ?? ""); for (const sensitiveValue of sensitiveValues) { @@ -28,6 +35,12 @@ export function redactSensitiveValue(value, sensitiveValues = []) { return redacted; } +/** + * Build the least-authority environment passed to the read-only GitHub CLI. + * + * @param {NodeJS.ProcessEnv} [sourceEnvironment=process.env] Ambient process environment. + * @returns {Record} Allow-listed child-process environment. + */ export function createGhSubprocessEnvironment(sourceEnvironment = process.env) { const childEnvironment = { GH_HOST: "github.com", @@ -101,8 +114,8 @@ export function runGh( return decodeGhOutput(completed.stdout, "stdout").trim(); } -function collectEnvironment(repository) { - const raw = runGh([ +function collectEnvironment(repository, runGhImpl) { + const raw = runGhImpl([ "api", "-H", "Accept: application/vnd.github+json", @@ -127,15 +140,15 @@ function writeReport(path, report) { return absolutePath; } -function appendOutput(name, value) { - const outputPath = process.env.GITHUB_OUTPUT; +function appendOutput(name, value, sourceEnvironment) { + const outputPath = sourceEnvironment.GITHUB_OUTPUT; if (outputPath) { appendFileSync(outputPath, `${name}=${String(value).replace(/[\r\n]/g, "")}\n`, "utf8"); } } -function appendSummary(report) { - const summaryPath = process.env.GITHUB_STEP_SUMMARY; +function appendSummary(report, sourceEnvironment) { + const summaryPath = sourceEnvironment.GITHUB_STEP_SUMMARY; if (!summaryPath) { return; } @@ -184,17 +197,40 @@ function buildFailureReport(repository, error) { }; } -export function main() { - const repository = String(process.env.GITHUB_REPOSITORY ?? "").trim(); +/** + * Collect and evaluate the live production-environment governance evidence. + * Dependency injection is deliberately limited to the read-only GitHub CLI, + * process environment, logging sink, and exit-code sink so realistic tests can + * exercise every evidence boundary without granting network or write authority. + * + * @param {{ + * sourceEnvironment?: NodeJS.ProcessEnv, + * runGhImpl?: typeof runGh, + * log?: (value: string) => void, + * setExitCode?: (value: number) => void, + * }} [options] Bounded runtime dependencies. + * @returns {Record} Evaluated report written to the evidence path. + */ +export function main( + { + sourceEnvironment = process.env, + runGhImpl = runGh, + log = console.log, + setExitCode = (value) => { + process.exitCode = value; + }, + } = {}, +) { + const repository = String(sourceEnvironment.GITHUB_REPOSITORY ?? "").trim(); const reportPath = String( - process.env.NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH ?? defaultReportPath, + sourceEnvironment.NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH ?? defaultReportPath, ).trim() || defaultReportPath; let report; try { if (!repositoryPattern.test(repository)) { throw new Error("GITHUB_REPOSITORY must identify a ContextualWisdomLab repository."); } - const environment = collectEnvironment(repository); + const environment = collectEnvironment(repository, runGhImpl); const evaluation = evaluateProductionEnvironment(environment); report = { schema_version: 1, @@ -219,12 +255,12 @@ export function main() { } const absoluteReportPath = writeReport(reportPath, report); - appendOutput("production_environment_governance_status", report.status); - appendOutput("production_environment_governance_report_path", absoluteReportPath); - appendSummary(report); - console.log(JSON.stringify(report, null, 2)); + appendOutput("production_environment_governance_status", report.status, sourceEnvironment); + appendOutput("production_environment_governance_report_path", absoluteReportPath, sourceEnvironment); + appendSummary(report, sourceEnvironment); + log(JSON.stringify(report, null, 2)); if (report.status !== "PASS") { - process.exitCode = 1; + setExitCode(1); } return report; } From 3e92c71251e139d4177aae6bcaf101c3a18c7d9b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 11:05:49 +0900 Subject: [PATCH 08/10] test(governance): cover production audit runtime --- ...uction-environment-governance-utf8.test.ts | 329 +++++++++++++++++- 1 file changed, 323 insertions(+), 6 deletions(-) diff --git a/test/production-environment-governance-utf8.test.ts b/test/production-environment-governance-utf8.test.ts index a4f75fefc..f7c466ff5 100644 --- a/test/production-environment-governance-utf8.test.ts +++ b/test/production-environment-governance-utf8.test.ts @@ -1,10 +1,53 @@ -import { describe, expect, it } from "vitest"; +import { mkdtempSync, readFileSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { + createGhSubprocessEnvironment, decodeGhOutput, + main, runGh, } from "../scripts/production-environment-governance-audit.mjs"; +const temporaryDirectories: string[] = []; + +function temporaryDirectory() { + const directory = mkdtempSync(join(tmpdir(), "noema-production-governance-")); + temporaryDirectories.push(directory); + return directory; +} + +function protectedEnvironment() { + return { + id: 12345, + name: "production", + html_url: "https://github.com/ContextualWisdomLab/noema/deployments/activity_log?environments_filter=production", + protection_rules: [ + { + id: 100, + type: "required_reviewers", + prevent_self_review: true, + reviewers: [ + { + type: "Team", + reviewer: { + id: 2468, + slug: "production-approvers", + name: "Production Approvers", + }, + }, + ], + }, + { id: 101, type: "branch_policy" }, + ], + deployment_branch_policy: { + protected_branches: true, + custom_branch_policies: false, + }, + }; +} + function failureMessage(action: () => unknown) { try { action(); @@ -14,14 +57,18 @@ function failureMessage(action: () => unknown) { throw new Error("expected action to fail"); } +afterEach(() => { + for (const directory of temporaryDirectories.splice(0)) { + rmSync(directory, { recursive: true, force: true }); + } + vi.restoreAllMocks(); +}); + describe("production environment governance GitHub CLI UTF-8 boundary", () => { it("rejects malformed UTF-8 instead of replacement-decoding production evidence", () => { expect(() => - decodeGhOutput( - Uint8Array.from([0x7b, 0x22, 0xff, 0x22, 0x7d]), - "stdout", - ), - ).toThrow("GitHub CLI returned invalid UTF-8 in stdout."); + decodeGhOutput(Uint8Array.from([0x7b, 0x22, 0xff, 0x22, 0x7d])), + ).toThrow("GitHub CLI returned invalid UTF-8 in output."); }); it("decodes valid UTF-8 bytes exactly", () => { @@ -29,6 +76,58 @@ describe("production environment governance GitHub CLI UTF-8 boundary", () => { expect(decodeGhOutput(bytes, "stdout")).toBe('{"name":"production"}\n'); }); + it("executes a successful shell-free bounded request with the least-authority environment", () => { + let invocation: { command?: string; args?: string[]; options?: Record } = {}; + const result = runGh(["api", "example"], { + sourceEnvironment: {}, + spawnSyncImpl: (command, args, options) => { + invocation = { command, args: args as string[], options: options as Record }; + return { + status: 0, + stdout: Buffer.from(" evidence \n", "utf8"), + stderr: Buffer.alloc(0), + pid: 1, + output: [], + signal: null, + }; + }, + }); + + expect(result).toBe("evidence"); + expect(invocation).toMatchObject({ + command: "gh", + args: ["api", "example"], + options: { + env: { GH_HOST: "github.com", NO_COLOR: "1" }, + maxBuffer: 2 * 1024 * 1024, + shell: false, + }, + }); + expect(createGhSubprocessEnvironment({ PATH: "", GH_TOKEN: "" })).toEqual({ + GH_HOST: "github.com", + NO_COLOR: "1", + }); + }); + + it("redacts and bounds a subprocess-start failure", () => { + const token = "read-only-secret-token"; + const message = failureMessage(() => + runGh(["api", "example"], { + sourceEnvironment: { GH_TOKEN: token }, + spawnSyncImpl: () => ({ + status: null, + stdout: Buffer.alloc(0), + stderr: Buffer.alloc(0), + error: new Error(`${token}${"x".repeat(5_000)}`), + }), + }), + ); + + expect(message).toContain("GitHub CLI could not start: [REDACTED]"); + expect(message).not.toContain(token); + expect(message.endsWith("…")).toBe(true); + }); + it("prefers stderr and redacts GH_TOKEN on the real runGh failure path", () => { const token = "read-only-secret-token"; const message = failureMessage(() => @@ -64,6 +163,15 @@ describe("production environment governance GitHub CLI UTF-8 boundary", () => { expect(message).not.toContain(token); }); + it("reports the numeric exit status when GitHub CLI emits no diagnostic bytes", () => { + expect(() => + runGh(["api", "example"], { + sourceEnvironment: {}, + spawnSyncImpl: () => ({ status: 9, stdout: Buffer.alloc(0), stderr: Buffer.alloc(0) }), + }), + ).toThrow("GitHub CLI failed: exit 9"); + }); + it.each([ ["stderr", Buffer.from([0xff]), Buffer.from("valid stdout", "utf8")], ["stdout", Buffer.alloc(0), Buffer.from([0xff])], @@ -76,3 +184,212 @@ describe("production environment governance GitHub CLI UTF-8 boundary", () => { ).toThrow(`GitHub CLI returned invalid UTF-8 in ${label}.`); }); }); + +describe("production environment governance audit runtime", () => { + it("writes PASS evidence, outputs, and reviewer summary from an injected read-only response", () => { + const directory = temporaryDirectory(); + const reportPath = join(directory, "report.json"); + const outputPath = join(directory, "github-output.txt"); + const summaryPath = join(directory, "summary.md"); + const log = vi.fn(); + const setExitCode = vi.fn(); + const environment = protectedEnvironment(); + + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "ContextualWisdomLab/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: reportPath, + GITHUB_OUTPUT: outputPath, + GITHUB_STEP_SUMMARY: summaryPath, + }, + runGhImpl: (args) => { + expect(args).toEqual([ + "api", + "-H", + "Accept: application/vnd.github+json", + "-H", + "X-GitHub-Api-Version: 2026-03-10", + "repos/ContextualWisdomLab/noema/environments/production", + ]); + return JSON.stringify(environment); + }, + log, + setExitCode, + }); + + expect(report).toMatchObject({ + repository: "ContextualWisdomLab/noema", + status: "PASS", + environment_id: 12345, + environment_url: environment.html_url, + reviewer_count: 1, + failures: [], + }); + expect(JSON.parse(readFileSync(reportPath, "utf8"))).toMatchObject({ status: "PASS" }); + expect(readFileSync(outputPath, "utf8")).toContain("production_environment_governance_status=PASS"); + expect(readFileSync(summaryPath, "utf8")).toContain("### Reviewers"); + expect(readFileSync(summaryPath, "utf8")).toContain("production-approvers"); + expect(log).toHaveBeenCalledOnce(); + expect(setExitCode).not.toHaveBeenCalled(); + }); + + it("normalizes unsafe environment identity metadata without changing a valid policy result", () => { + const directory = temporaryDirectory(); + const environment = protectedEnvironment(); + environment.id = Number.MAX_SAFE_INTEGER + 1; + environment.html_url = `https://example.invalid/${"x".repeat(1_200)}`; + + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "ContextualWisdomLab/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: join(directory, "report.json"), + }, + runGhImpl: () => JSON.stringify(environment), + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report.status).toBe("PASS"); + expect(report.environment_id).toBeNull(); + expect(String(report.environment_url)).toHaveLength(1_001); + expect(String(report.environment_url).endsWith("…")).toBe(true); + }); + + it("fails closed for an empty GitHub API response and writes failure summary evidence", () => { + const directory = temporaryDirectory(); + const reportPath = join(directory, "report.json"); + const summaryPath = join(directory, "summary.md"); + const setExitCode = vi.fn(); + + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "ContextualWisdomLab/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: reportPath, + GITHUB_STEP_SUMMARY: summaryPath, + }, + runGhImpl: () => "", + log: () => undefined, + setExitCode, + }); + + expect(report.status).toBe("FAIL"); + expect(report.failures[0]).toMatchObject({ + code: "production_environment_collection_failed", + detail: "GitHub CLI returned an empty production environment response.", + }); + expect(readFileSync(summaryPath, "utf8")).toContain("### Failures"); + expect(setExitCode).toHaveBeenCalledWith(1); + }); + + it("fails closed for malformed JSON returned by the GitHub API", () => { + const directory = temporaryDirectory(); + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "ContextualWisdomLab/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: join(directory, "report.json"), + }, + runGhImpl: () => "{not-json", + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report.status).toBe("FAIL"); + expect(report.failures[0].detail).toContain("GitHub CLI returned invalid JSON:"); + }); + + it("fails closed before GitHub access for an invalid repository and emits no optional outputs", () => { + const directory = temporaryDirectory(); + const runGhImpl = vi.fn(); + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "outside/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: join(directory, "report.json"), + }, + runGhImpl, + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report).toMatchObject({ repository: "outside/noema", status: "FAIL" }); + expect(runGhImpl).not.toHaveBeenCalled(); + }); + + it("uses unknown repository and default relative report path for empty ambient identity", () => { + const directory = temporaryDirectory(); + const previousDirectory = process.cwd(); + try { + process.chdir(directory); + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: " ", + }, + runGhImpl: () => { + throw "must not run"; + }, + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report).toMatchObject({ repository: "unknown", status: "FAIL" }); + expect( + JSON.parse( + readFileSync( + join(directory, "artifacts/governance/production-environment-governance.json"), + "utf8", + ), + ), + ).toMatchObject({ repository: "unknown", status: "FAIL" }); + } finally { + process.chdir(previousDirectory); + } + }); + + it("retains a non-Error collection failure without inventing a message", () => { + const directory = temporaryDirectory(); + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "ContextualWisdomLab/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: join(directory, "report.json"), + }, + runGhImpl: () => { + throw "opaque collection failure"; + }, + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report.failures[0].detail).toBe("opaque collection failure"); + }); + + it("executes the CLI entrypoint branch fail-closed without network access", async () => { + const directory = temporaryDirectory(); + const previousArgv = process.argv[1]; + const previousRepository = process.env.GITHUB_REPOSITORY; + const previousPath = process.env.NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH; + const previousExitCode = process.exitCode; + const logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined); + try { + process.argv[1] = resolve("scripts/production-environment-governance-audit.mjs"); + process.env.GITHUB_REPOSITORY = ""; + process.env.NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH = join(directory, "entrypoint.json"); + process.exitCode = undefined; + vi.resetModules(); + await import("../scripts/production-environment-governance-audit.mjs"); + + expect(JSON.parse(readFileSync(join(directory, "entrypoint.json"), "utf8"))).toMatchObject({ + repository: "unknown", + status: "FAIL", + }); + expect(process.exitCode).toBe(1); + expect(logSpy).toHaveBeenCalled(); + } finally { + process.argv[1] = previousArgv; + if (previousRepository === undefined) delete process.env.GITHUB_REPOSITORY; + else process.env.GITHUB_REPOSITORY = previousRepository; + if (previousPath === undefined) delete process.env.NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH; + else process.env.NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH = previousPath; + process.exitCode = previousExitCode; + } + }); +}); From fc7cecf0bc463ec7092332fb26822531ce8c09a8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 11:09:59 +0900 Subject: [PATCH 09/10] test(governance): close exact branch coverage gaps --- ...uction-environment-governance-utf8.test.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test/production-environment-governance-utf8.test.ts b/test/production-environment-governance-utf8.test.ts index f7c466ff5..e2a3e5ad8 100644 --- a/test/production-environment-governance-utf8.test.ts +++ b/test/production-environment-governance-utf8.test.ts @@ -255,6 +255,23 @@ describe("production environment governance audit runtime", () => { expect(String(report.environment_url).endsWith("…")).toBe(true); }); + it("uses null for absent environment URL without changing a valid policy result", () => { + const directory = temporaryDirectory(); + const environment = { ...protectedEnvironment(), html_url: "" }; + + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "ContextualWisdomLab/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: join(directory, "report.json"), + }, + runGhImpl: () => JSON.stringify(environment), + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report).toMatchObject({ status: "PASS", environment_url: null }); + }); + it("fails closed for an empty GitHub API response and writes failure summary evidence", () => { const directory = temporaryDirectory(); const reportPath = join(directory, "report.json"); @@ -314,6 +331,34 @@ describe("production environment governance audit runtime", () => { expect(runGhImpl).not.toHaveBeenCalled(); }); + it("uses nullish ambient defaults when repository and report path are absent", () => { + const directory = temporaryDirectory(); + const previousDirectory = process.cwd(); + const runGhImpl = vi.fn(); + try { + process.chdir(directory); + const report = main({ + sourceEnvironment: {}, + runGhImpl, + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report).toMatchObject({ repository: "unknown", status: "FAIL" }); + expect(runGhImpl).not.toHaveBeenCalled(); + expect( + JSON.parse( + readFileSync( + join(directory, "artifacts/governance/production-environment-governance.json"), + "utf8", + ), + ), + ).toMatchObject({ repository: "unknown", status: "FAIL" }); + } finally { + process.chdir(previousDirectory); + } + }); + it("uses unknown repository and default relative report path for empty ambient identity", () => { const directory = temporaryDirectory(); const previousDirectory = process.cwd(); @@ -362,6 +407,23 @@ describe("production environment governance audit runtime", () => { expect(report.failures[0].detail).toBe("opaque collection failure"); }); + it("does not execute the CLI entrypoint when argv has no script path", async () => { + const previousArgv = process.argv[1]; + const previousExitCode = process.exitCode; + try { + process.argv[1] = ""; + process.exitCode = undefined; + vi.resetModules(); + const imported = await import("../scripts/production-environment-governance-audit.mjs"); + + expect(imported.main).toBeTypeOf("function"); + expect(process.exitCode).toBeUndefined(); + } finally { + process.argv[1] = previousArgv; + process.exitCode = previousExitCode; + } + }); + it("executes the CLI entrypoint branch fail-closed without network access", async () => { const directory = temporaryDirectory(); const previousArgv = process.argv[1]; From ede6fcb7b79044b57630b8acf42473ad564cf0d6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 15 Aug 2026 11:13:09 +0900 Subject: [PATCH 10/10] test(governance): cover remaining production audit branches --- ...uction-environment-governance-utf8.test.ts | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/test/production-environment-governance-utf8.test.ts b/test/production-environment-governance-utf8.test.ts index e2a3e5ad8..d037c5699 100644 --- a/test/production-environment-governance-utf8.test.ts +++ b/test/production-environment-governance-utf8.test.ts @@ -7,6 +7,7 @@ import { createGhSubprocessEnvironment, decodeGhOutput, main, + redactSensitiveValue, runGh, } from "../scripts/production-environment-governance-audit.mjs"; @@ -76,6 +77,10 @@ describe("production environment governance GitHub CLI UTF-8 boundary", () => { expect(decodeGhOutput(bytes, "stdout")).toBe('{"name":"production"}\n'); }); + it("normalizes an absent diagnostic before redaction", () => { + expect(redactSensitiveValue(undefined)).toBe(""); + }); + it("executes a successful shell-free bounded request with the least-authority environment", () => { let invocation: { command?: string; args?: string[]; options?: Record } = {}; const result = runGh(["api", "example"], { @@ -257,7 +262,7 @@ describe("production environment governance audit runtime", () => { it("uses null for absent environment URL without changing a valid policy result", () => { const directory = temporaryDirectory(); - const environment = { ...protectedEnvironment(), html_url: "" }; + const environment = { ...protectedEnvironment(), html_url: undefined }; const report = main({ sourceEnvironment: { @@ -314,6 +319,26 @@ describe("production environment governance audit runtime", () => { expect(report.failures[0].detail).toContain("GitHub CLI returned invalid JSON:"); }); + it("retains a non-Error JSON parse failure in the collection diagnostic", () => { + const directory = temporaryDirectory(); + vi.spyOn(JSON, "parse").mockImplementationOnce(() => { + throw "opaque parse failure"; + }); + + const report = main({ + sourceEnvironment: { + GITHUB_REPOSITORY: "ContextualWisdomLab/noema", + NOEMA_PRODUCTION_ENVIRONMENT_GOVERNANCE_PATH: join(directory, "report.json"), + }, + runGhImpl: () => "{}", + log: () => undefined, + setExitCode: () => undefined, + }); + + expect(report).toMatchObject({ status: "FAIL" }); + expect(report.failures[0].detail).toContain("GitHub CLI returned invalid JSON: opaque parse failure"); + }); + it("fails closed before GitHub access for an invalid repository and emits no optional outputs", () => { const directory = temporaryDirectory(); const runGhImpl = vi.fn();