import { createHash } from "node:crypto"; import { existsSync, readFileSync } from "node:fs"; import { validateReleaseCandidateRecord } from "./release-candidate.mjs"; export const RESEND_DAILY_LIMIT = 80; export const RESEND_MONTHLY_LIMIT = 2_400; export const DELIVERY_CATEGORIES = Object.freeze(["qq", "163", "enterprise"]); export const DELIVERY_SAMPLE_SIZE = 20; export const DELIVERY_MINIMUM_WITHIN_TWO_MINUTES = 19; export const DELIVERY_WINDOW_SECONDS = 120; export const EXPECTED_WP7_01_COMMIT = "623cad25b2a2a9a003502c9a92ebd318dad06248"; const emailPattern = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i; const absolutePathPattern = /(?:[A-Z]:[\\/]|\\\\|\/Users\/|\/home\/)/i; const sensitiveKeyPattern = /"(?:api[_ -]?key|secret|password|authorization|bearer|cookie|session[_ -]?token|verification[_ -]?code|private[_ -]?content|prompt|image)"\s*:/i; function object(value) { return value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined; } function errorList(...values) { return [...new Set(values.flat().filter((value) => typeof value === "string" && value.length > 0))]; } export function validateDomainCheck(value) { const item = object(value); const freeRules = object(item?.free_rules); const spf = object(item?.spf); const dkim = object(item?.dkim); const errors = []; if (item?.schema_version !== "1.0") errors.push("schema_version"); if (item?.service !== "resend") errors.push("service"); if (item?.source !== "human_controlled_real") errors.push("source"); if (item?.status !== "verified") errors.push("status"); if (item?.domain_controlled !== true) errors.push("domain_controlled"); if (spf?.status !== "pass") errors.push("spf"); if (dkim?.status !== "pass") errors.push("dkim"); if (freeRules?.status !== "verified") errors.push("free_rules.status"); if (freeRules?.daily_limit !== RESEND_DAILY_LIMIT) errors.push("free_rules.daily_limit"); if (freeRules?.monthly_limit !== RESEND_MONTHLY_LIMIT) errors.push("free_rules.monthly_limit"); if (freeRules?.paid_fallback_enabled !== false) errors.push("free_rules.paid_fallback_enabled"); return errorList(errors); } export function validateDeliverySummary(value) { const item = object(value); const errors = []; if (item?.schema_version !== "1.0") errors.push("schema_version"); if (item?.service !== "resend") errors.push("service"); if (item?.source !== "human_controlled_real") errors.push("source"); if (item?.status !== "verified") errors.push("status"); if (!Array.isArray(item?.categories) || item.categories.length !== DELIVERY_CATEGORIES.length) { errors.push("categories"); } else { const categories = item.categories.map((entry) => entry?.category).sort(); if (categories.join("|") !== DELIVERY_CATEGORIES.slice().sort().join("|")) errors.push("categories.names"); for (const entry of item.categories) { if (!Number.isInteger(entry?.sent_count) || entry.sent_count !== DELIVERY_SAMPLE_SIZE) errors.push(`${entry?.category ?? "unknown"}.sent_count`); if (!Number.isInteger(entry?.delivered_within_120_seconds) || entry.delivered_within_120_seconds < DELIVERY_MINIMUM_WITHIN_TWO_MINUTES || entry.delivered_within_120_seconds > DELIVERY_SAMPLE_SIZE) { errors.push(`${entry?.category ?? "unknown"}.delivered_within_120_seconds`); } if (!Number.isFinite(entry?.max_latency_seconds) || entry.max_latency_seconds > DELIVERY_WINDOW_SECONDS) errors.push(`${entry?.category ?? "unknown"}.max_latency_seconds`); if (entry?.mock_used !== false) errors.push(`${entry?.category ?? "unknown"}.mock_used`); if (entry?.preseeded_account_used !== false) errors.push(`${entry?.category ?? "unknown"}.preseeded_account_used`); } } return errorList(errors); } export function validateAuthResult(value) { const item = object(value); const ordinary = object(item?.ordinary); const admin = object(item?.admin); const errors = []; if (item?.schema_version !== "1.0") errors.push("schema_version"); if (item?.service !== "resend") errors.push("service"); if (item?.source !== "human_controlled_real") errors.push("source"); if (item?.status !== "verified") errors.push("status"); if (item?.mock_used !== false) errors.push("mock_used"); if (item?.preseeded_account_used !== false) errors.push("preseeded_account_used"); for (const [name, auth] of [["ordinary", ordinary], ["admin", admin]]) { if (auth?.status !== "passed") errors.push(`${name}.status`); if (auth?.chain !== "formal") errors.push(`${name}.chain`); if (auth?.verification_code_source !== "real_delivery") errors.push(`${name}.verification_code_source`); } return errorList(errors); } export function validateRedaction(value, serializedEvidence = "") { const item = object(value); const errors = []; if (item?.schema_version !== "1.0") errors.push("schema_version"); if (item?.status !== "passed") errors.push("status"); if (item?.forbidden_matches !== 0) errors.push("forbidden_matches"); if (item?.credentials_in_evidence !== false) errors.push("credentials_in_evidence"); if (item?.mailboxes_in_evidence !== false) errors.push("mailboxes_in_evidence"); if (item?.private_content_in_evidence !== false) errors.push("private_content_in_evidence"); if (item?.absolute_paths_in_evidence !== false) errors.push("absolute_paths_in_evidence"); if (emailPattern.test(serializedEvidence)) errors.push("email_value"); if (absolutePathPattern.test(serializedEvidence)) errors.push("absolute_path"); if (sensitiveKeyPattern.test(serializedEvidence)) errors.push("sensitive_value"); return errorList(errors); } export function validateCandidateReference(record) { try { validateReleaseCandidateRecord(record); } catch (error) { return [error instanceof Error ? "candidate_record_invalid" : "candidate_record_invalid"]; } const errors = []; if (record.build_commit !== EXPECTED_WP7_01_COMMIT) errors.push("candidate_build_commit"); const versions = new Map((record.browsers ?? []).map((browser) => [browser.brand, browser.full_version])); if (versions.get("Google Chrome") !== "150.0.7871.187") errors.push("chrome_full_version"); if (versions.get("Microsoft Edge") !== "151.0.4129.59") errors.push("edge_full_version"); return errorList(errors); } export function readJson(path) { if (!path || !existsSync(path)) return undefined; try { return JSON.parse(readFileSync(path, "utf8")); } catch { return undefined; } } export function fileSha256(path) { return createHash("sha256").update(readFileSync(path)).digest("hex").toUpperCase(); } export function validateResendEvidence({ candidate, domainCheck, deliverySummary, authResult, redaction }) { const serializedEvidence = JSON.stringify({ domainCheck, deliverySummary, authResult }); const errors = [ ...validateCandidateReference(candidate), ...validateDomainCheck(domainCheck), ...validateDeliverySummary(deliverySummary), ...validateAuthResult(authResult), ...validateRedaction(redaction, serializedEvidence), ]; return errorList(errors); }