import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import { closeSync, chmodSync, mkdtempSync, openSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { test } from "node:test"; import { planSecretInput } from "./secret-input.js"; const fixture = "synthetic-provisioning-value-not-a-real-secret"; function protectedInput(body: (dir: string, file: string) => void) { const dir = realpathSync(mkdtempSync(join(tmpdir(), "sentinel-secret-contract-"))); const file = join(dir, "release-token"); try { chmodSync(dir, 0o700); writeFileSync(file, fixture, { mode: 0o600 }); body(dir, file); } finally { rmSync(dir, { recursive: true, force: true }); } } for (const invalid of ["public-file", "public-directory", "symlink", "relative", "repository", "missing", "directory", "empty", "login"] as const) { test(`protected provisioning plan refuses ${invalid} input without reading or echoing it`, () => protectedInput((dir, file) => { let path = file; let root = resolve("."); let login = "fixture-login"; if (invalid === "public-file") chmodSync(file, 0o644); if (invalid === "public-directory") chmodSync(dir, 0o755); if (invalid === "symlink") { path = join(dir, "link"); symlinkSync(file, path); } if (invalid === "relative") path = "relative-token"; if (invalid === "repository") root = dir; if (invalid === "missing") path = join(dir, "missing"); if (invalid === "directory") path = dir; if (invalid === "empty") writeFileSync(file, ""); if (invalid === "login") login = "--debug"; assert.throws(() => planSecretInput(login, path, "file", root), { message: "Invalid protected secret input; no provisioning was performed.", }); })); } for (const mode of ["file", "stdin"] as const) { test(`protected ${mode} plan follows tea contract without credential argv, logs or actual provisioning`, () => protectedInput((dir, file) => { const plan = planSecretInput("fixture-login", file, mode, resolve(".")); assert.equal(plan.command, "tea"); assert.deepEqual(plan.args, ["actions", "secrets", "create", "--login", "fixture-login", "--repo", "dmg/purpur-sentinel", ...(mode === "file" ? ["--file", file] : ["--stdin"]), "RELEASE_TOKEN"]); assert.equal(plan.stdinFile, mode === "stdin" ? file : undefined); assert.ok(!JSON.stringify(plan).includes(fixture)); // Execute only an isolated local fake, NEVER the installed tea command. const fake = join(dir, "fake-tea.cjs"); writeFileSync(fake, ` const fs = require('node:fs'); const args = process.argv.slice(2); const bytes = args.includes('--stdin') ? fs.readFileSync(0, 'utf8') : fs.readFileSync(args[args.indexOf('--file') + 1], 'utf8'); if (bytes !== ${JSON.stringify(fixture)} || args.join(' ').includes(bytes)) process.exit(1); process.stdout.write('Accepted protected input for RELEASE_TOKEN.\\n'); `, { mode: 0o600 }); const fd = plan.stdinFile ? openSync(plan.stdinFile, "r") : undefined; try { const child = spawnSync(process.execPath, [fake, ...plan.args], { env: {}, encoding: "utf8", stdio: [fd ?? "ignore", "pipe", "pipe"], }); assert.equal(child.status, 0, child.stderr); assert.equal(child.stdout, "Accepted protected input for RELEASE_TOKEN.\n"); assert.equal(child.stderr, ""); } finally { if (fd !== undefined) closeSync(fd); } })); }