52 lines
3.2 KiB
JavaScript
52 lines
3.2 KiB
JavaScript
import { createHash } from "node:crypto";
|
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { basename, resolve } from "node:path";
|
|
|
|
import { validateReleaseCandidateRecord } from "./lib/release-candidate.mjs";
|
|
|
|
const runId = process.argv[2];
|
|
if (!runId) throw new Error("Usage: node scripts/record-wp7-01-manual-review.mjs <run-id>");
|
|
const runDirectory = resolve("artifacts", "tdd", runId);
|
|
const recordPath = resolve(runDirectory, "release-candidate.json");
|
|
const evidencePath = resolve(runDirectory, "evidence.json");
|
|
if (!existsSync(recordPath) || !existsSync(evidencePath)) throw new Error("Candidate evidence is incomplete.");
|
|
const record = validateReleaseCandidateRecord(JSON.parse(readFileSync(recordPath, "utf8")));
|
|
const evidence = JSON.parse(readFileSync(evidencePath, "utf8"));
|
|
if (evidence.status !== "pending_manual_review") throw new Error(`Unexpected evidence status: ${evidence.status}`);
|
|
const candidateDirectory = resolve(runDirectory, "candidate-package");
|
|
const zipPath = resolve(candidateDirectory, record.candidate_package.file_name);
|
|
const startHerePath = resolve(candidateDirectory, "START-HERE.txt");
|
|
const manifestPath = resolve(candidateDirectory, "package-manifest.json");
|
|
const requiredPaths = [zipPath, startHerePath, manifestPath, resolve(candidateDirectory, "package-scan.json"), resolve(candidateDirectory, "process-tree.json")];
|
|
if (requiredPaths.some((path) => !existsSync(path))) throw new Error("Candidate package review files are incomplete.");
|
|
const zipHash = createHash("sha256").update(readFileSync(zipPath)).digest("hex").toUpperCase();
|
|
if (zipHash !== record.candidate_package.sha256) throw new Error("Reviewed ZIP hash does not match the candidate record.");
|
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
if (manifest.zip_sha256 !== zipHash || manifest.fixed_port !== record.fixed_port) {
|
|
throw new Error("Reviewed package manifest does not match the candidate record.");
|
|
}
|
|
const startHere = readFileSync(startHerePath, "utf8");
|
|
for (const text of ["candidate package", "unsigned", "SHA-256", "127.0.0.1:43121", "not a final P0-A release"]) {
|
|
if (!startHere.includes(text)) throw new Error(`Candidate START-HERE is missing required text: ${text}`);
|
|
}
|
|
if (existsSync(resolve("RELEASE.json"))) throw new Error("A final repository RELEASE.json was written prematurely.");
|
|
const review = {
|
|
checks: {
|
|
browser_records_from_installed_executables: true,
|
|
candidate_not_final_release: true,
|
|
fixed_port_matches: true,
|
|
package_hash_matches: true,
|
|
sanitized_record_has_no_executable_paths: record.browsers.every((browser) => !("path" in browser) && !("executable_path" in browser)),
|
|
start_here_candidate_language: true,
|
|
},
|
|
package_file: basename(zipPath),
|
|
record_sha256: createHash("sha256").update(readFileSync(recordPath)).digest("hex").toUpperCase(),
|
|
reviewed_at: new Date().toISOString(),
|
|
reviewer: "codex",
|
|
schema_version: "1.0",
|
|
status: "passed",
|
|
};
|
|
writeFileSync(resolve(runDirectory, "manual-review.json"), `${JSON.stringify(review, null, 2)}\n`);
|
|
writeFileSync(evidencePath, `${JSON.stringify({ ...evidence, manual_review: "manual-review.json", status: "passed" }, null, 2)}\n`);
|
|
console.log(JSON.stringify(review, null, 2));
|