import { chmodSync, mkdtempSync, rmSync, writeFileSync, existsSync, readdirSync, readFileSync, } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; import { spawnSync } from "node:child_process"; import { describe, expect, it } from "vitest"; function runScript(scriptPath: string, env: Record) { const tmpScriptDir = mkdtempSync(join(tmpdir(), "skymoney-a08-script-")); const normalizedScript = join(tmpScriptDir, "script.sh"); writeFileSync(normalizedScript, readFileSync(scriptPath, "utf8").replace(/\r/g, "")); chmodSync(normalizedScript, 0o755); const result = spawnSync("bash", [normalizedScript], { env: { ...process.env, ...env }, encoding: "utf8", }); rmSync(tmpScriptDir, { recursive: true, force: true }); return result; } describe("A08 Software and Data Integrity Failures", () => { it("creates checksum artifacts during backup execution", () => { const repoRoot = resolve(__dirname, "..", ".."); const backupScriptPath = resolve(repoRoot, "scripts/backup.sh"); const tmpRoot = mkdtempSync(join(tmpdir(), "skymoney-a08-backup-")); const fakeBin = join(tmpRoot, "bin"); const outDir = join(tmpRoot, "backups"); const fakePgDump = join(fakeBin, "pg_dump"); try { spawnSync("mkdir", ["-p", fakeBin], { encoding: "utf8" }); writeFileSync( fakePgDump, "#!/usr/bin/env bash\nset -euo pipefail\nout=''\nwhile [[ $# -gt 0 ]]; do\n if [[ \"$1\" == '-f' ]]; then out=\"$2\"; shift 2; continue; fi\n shift\ndone\nprintf 'fake-dump-data' > \"$out\"\n" ); chmodSync(fakePgDump, 0o755); const res = runScript(backupScriptPath, { PATH: `${fakeBin}:${process.env.PATH ?? ""}`, BACKUP_DATABASE_URL: "postgres://app:app@127.0.0.1:5432/skymoney", BACKUP_DIR: outDir, }); expect(res.status).toBe(0); const names = readdirSync(outDir); expect(names.some((n) => n.endsWith(".dump"))).toBe(true); expect(names.some((n) => n.endsWith(".sha256"))).toBe(true); } finally { rmSync(tmpRoot, { recursive: true, force: true }); } }); it("blocks restore on checksum mismatch before DB commands execute", () => { const repoRoot = resolve(__dirname, "..", ".."); const restoreScriptPath = resolve(repoRoot, "scripts/restore.sh"); const tmpRoot = mkdtempSync(join(tmpdir(), "skymoney-a08-restore-")); const fakeBin = join(tmpRoot, "bin"); const backupFile = join(tmpRoot, "sample.dump"); const checksumFile = `${backupFile}.sha256`; const markerFile = join(tmpRoot, "db_called.marker"); try { spawnSync("mkdir", ["-p", fakeBin], { encoding: "utf8" }); writeFileSync(backupFile, "tampered-content"); writeFileSync(checksumFile, `${"0".repeat(64)} sample.dump\n`); const fakePsql = join(fakeBin, "psql"); const fakePgRestore = join(fakeBin, "pg_restore"); writeFileSync(fakePsql, `#!/usr/bin/env bash\nset -euo pipefail\ntouch "${markerFile}"\n`); writeFileSync(fakePgRestore, `#!/usr/bin/env bash\nset -euo pipefail\ntouch "${markerFile}"\n`); chmodSync(fakePsql, 0o755); chmodSync(fakePgRestore, 0o755); const res = runScript(restoreScriptPath, { PATH: `${fakeBin}:${process.env.PATH ?? ""}`, BACKUP_FILE: backupFile, DATABASE_URL: "postgres://app:app@127.0.0.1:5432/skymoney", RESTORE_DATABASE_URL: "postgres://app:app@127.0.0.1:5432/skymoney_restore_test", }); expect(res.status).not.toBe(0); expect(`${res.stdout}${res.stderr}`).toContain("checksum verification failed"); expect(existsSync(markerFile)).toBe(false); } finally { rmSync(tmpRoot, { recursive: true, force: true }); } }); });