import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join, resolve } from "node:path"; import { fileSha256, readJson, validateCandidateReference, validateResendEvidence, } from "./lib/resend-release-gate.mjs"; const phaseIndex = process.argv.indexOf("--phase"); const phase = phaseIndex >= 0 ? process.argv[phaseIndex + 1] : "green"; if (!new Set(["red", "green"]).has(phase)) throw new Error(`Unsupported phase: ${phase}`); const candidateRunId = process.env.DADA_WP7_01_RUN_ID ?? "wp7-01-candidate-20260804052447717"; const runId = process.env.DADA_TDD_RUN_ID ?? `wp7-03-${phase}-${new Date().toISOString().replace(/[^0-9]/g, "")}`; const runDirectory = resolve("artifacts", "tdd", runId); const caseId = "TDD-WP7-EXT-002-real-resend"; const caseDirectory = resolve(runDirectory, "cases", caseId); if (existsSync(runDirectory)) throw new Error(`Evidence run already exists: ${runId}`); mkdirSync(caseDirectory, { recursive: true }); function writeJson(path, value) { writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`); } function runCommand(name, command) { const startedAt = new Date().toISOString(); const result = spawnSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/s", "/c", command], { encoding: "utf8", env: process.env, maxBuffer: 40 * 1024 * 1024, stdio: "inherit", }); return { command, exit_code: result.status ?? 1, finished_at: new Date().toISOString(), name, started_at: startedAt, }; } const candidateEvidenceRoot = resolve( process.env.DADA_WP7_01_EVIDENCE_DIR ?? join("artifacts", "tdd", candidateRunId), ); const candidate = readJson(join(candidateEvidenceRoot, "release-candidate.json")); const candidateErrors = candidate ? validateCandidateReference(candidate) : ["candidate_record_missing"]; writeJson(resolve(caseDirectory, "candidate-reference.json"), candidate ? { browsers: candidate.browsers.map(({ brand, full_version: fullVersion, major }) => ({ brand, full_version: fullVersion, major })), build_commit: candidate.build_commit, candidate_status: candidate.status, final_release: candidate.final_release, fixed_port: candidate.fixed_port, run_id: candidateRunId, schema_version: "1.0", } : { candidate_status: "not_available", reason: "candidate_record_missing", run_id: candidateRunId, schema_version: "1.0", }); const commands = phase === "red" ? [] : [ ["workspace-build", "pnpm build:workspace-packages"], ["integration", "pnpm test:integration"], ["api", "pnpm check:openapi && pnpm exec vitest run tests/api --maxWorkers=1"], ["security", "pnpm test:security"], ["tdd-trace", "pnpm validate:tdd-trace"], ].map(([name, command]) => runCommand(name, command)); const localGatePassed = phase === "red" || commands.length > 0 && commands.every(({ exit_code }) => exit_code === 0); const redaction = { absolute_paths_in_evidence: false, credentials_in_evidence: false, forbidden_matches: 0, mailboxes_in_evidence: false, private_content_in_evidence: false, schema_version: "1.0", status: "passed", }; const externalRoot = process.env.DADA_RESEND_EVIDENCE_DIR ? resolve(process.env.DADA_RESEND_EVIDENCE_DIR) : undefined; const realAuthorized = process.env.DADA_RESEND_REAL_AUTHORIZED === "1"; const externalFiles = ["domain-check.json", "delivery-summary.json", "auth-result.json", "redaction.json"]; const externalEvidence = externalRoot ? Object.fromEntries(externalFiles.map((file) => [file, readJson(join(externalRoot, file))])) : {}; const externalEvidenceMissing = externalRoot ? externalFiles.filter((file) => !externalEvidence[file]) : externalFiles; const externalErrors = externalRoot && externalEvidenceMissing.length === 0 && candidate ? validateResendEvidence({ authResult: externalEvidence["auth-result.json"], candidate, deliverySummary: externalEvidence["delivery-summary.json"], domainCheck: externalEvidence["domain-check.json"], redaction: externalEvidence["redaction.json"], }) : []; const externalBlockers = []; if (candidateErrors.length > 0) externalBlockers.push("candidate_record_unavailable_or_drifted"); if (!realAuthorized) externalBlockers.push("controlled_domain_or_real_mailbox_authorization_absent"); if (!externalRoot) externalBlockers.push("real_resend_evidence_not_supplied"); if (externalRoot && externalEvidenceMissing.length > 0) externalBlockers.push("real_resend_evidence_incomplete"); if (externalErrors.length > 0) externalBlockers.push("real_resend_evidence_invalid"); if (phase === "red") { writeJson(resolve(caseDirectory, "red-observation.json"), { expected_failure: "Resend SPF/DKIM, free-rule, delivery, and formal authentication evidence is absent before TASK-WP7-03.", observed_commands: ["pnpm test:wp7-03:red"], red_reason: "TDD-WP7-EXT-002 requires controlled real domain/mailbox evidence; mock or pre-seeded accounts are not release evidence.", status: "red_confirmed", }); } else if (externalRoot && externalEvidenceMissing.length === 0 && candidateErrors.length === 0 && realAuthorized && externalErrors.length === 0) { for (const file of externalFiles) writeJson(resolve(caseDirectory, file), externalEvidence[file]); writeJson(resolve(caseDirectory, "source-hashes.json"), { files: Object.fromEntries(externalFiles.map((file) => [file, fileSha256(join(externalRoot, file))])), schema_version: "1.0", }); } else { writeJson(resolve(caseDirectory, "blocker.json"), { blockers: externalErrors.length > 0 ? ["real_resend_evidence_invalid"] : externalBlockers, mock_accepted_as_evidence: false, paid_fallback_enabled: false, preseeded_accounts_accepted_as_evidence: false, real_calls_started: false, schema_version: "1.0", status: "externally_blocked", }); writeJson(resolve(caseDirectory, "redaction.json"), redaction); writeJson(resolve(caseDirectory, "source-hashes.json"), { files: {}, schema_version: "1.0" }); } const expectedEvidence = phase === "red" ? ["candidate-reference.json", "red-observation.json"] : externalRoot && externalEvidenceMissing.length === 0 && candidateErrors.length === 0 && realAuthorized && externalErrors.length === 0 ? ["candidate-reference.json", "domain-check.json", "delivery-summary.json", "auth-result.json", "redaction.json", "source-hashes.json"] : ["candidate-reference.json", "blocker.json", "redaction.json", "source-hashes.json"]; const missingEvidence = expectedEvidence.filter((file) => !existsSync(resolve(caseDirectory, file))); const status = phase === "red" ? localGatePassed && missingEvidence.length === 0 ? "red_confirmed" : "failed" : !localGatePassed || missingEvidence.length > 0 ? "failed" : realAuthorized && (!externalRoot || externalEvidenceMissing.length > 0 || externalErrors.length > 0) ? "failed" : externalRoot && externalEvidenceMissing.length === 0 && candidateErrors.length === 0 && realAuthorized && externalErrors.length === 0 ? "passed" : "externally_blocked"; const manifest = { path: "tasks.manifest.json", sha256: createHash("sha256").update(readFileSync("tasks.manifest.json")).digest("hex").toUpperCase(), }; const result = { acceptance_criteria: ["AC-01", "AC-33", "AC-41", "AC-47", "AC-49"], automation: ["controlled_real", "manual_review"], candidate_run_id: candidateRunId, commit: spawnSync("git", ["rev-parse", "HEAD"], { encoding: "utf8" }).stdout.trim(), evidence_refs: expectedEvidence, external_blockers: phase === "green" && status === "externally_blocked" ? externalBlockers : [], finished_at: new Date().toISOString(), layer: ["EXT-REAL", "MANUAL"], manifest, missing_evidence: missingEvidence, phase, requirements: ["AUTH-01", "AUTH-02", "AUTH-07"], run_id: runId, schema_version: "1.0", status, task_id: "TASK-WP7-03", test_id: caseId, work_package: "WP-7", }; writeJson(resolve(caseDirectory, "commands.json"), { commands, phase, run_id: runId, schema_version: "1.0" }); writeJson(resolve(caseDirectory, "result.json"), result); writeJson(resolve(runDirectory, "evidence.json"), { cases: [{ external_blockers: result.external_blockers, missing_evidence: missingEvidence, status, test_id: caseId }], phase, run_id: runId, status }); console.log(JSON.stringify({ external_blockers: result.external_blockers, phase, run_id: runId, status }, null, 2)); if (status === "failed") process.exit(1);