45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
import type { VersionStatus } from "./db/types.js";
|
|
|
|
export type AuditEnforcement = "none" | "flag" | "block";
|
|
|
|
export function getAuditEnforcement(env: Env): AuditEnforcement {
|
|
const val = env.AUDIT_ENFORCEMENT;
|
|
if (val === "none" || val === "flag" || val === "block") return val;
|
|
return "flag";
|
|
}
|
|
|
|
/**
|
|
* Map (enforcement, codeVerdict, imageVerdict) → version status.
|
|
*
|
|
* Rules:
|
|
* none → always "published"
|
|
* flag → pass = "published", warn/fail = "flagged"
|
|
* block → pass = "published", warn = "flagged", fail = "rejected"
|
|
*
|
|
* In block mode, only an explicit "pass" from both auditors results in
|
|
* auto-publishing. A "warn" verdict (including from audit errors, which
|
|
* now return "fail") requires human review. This prevents fail-open
|
|
* bypasses where a crafted input causes the auditor to error.
|
|
*/
|
|
export function resolveVersionStatus(
|
|
enforcement: AuditEnforcement,
|
|
codeVerdict: string | null,
|
|
imageVerdict: string | null,
|
|
): VersionStatus {
|
|
if (enforcement === "none") return "published";
|
|
|
|
// Normalize: treat null/undefined as "pass" (no audit ran)
|
|
const code = codeVerdict ?? "pass";
|
|
const image = imageVerdict ?? "pass";
|
|
|
|
if (enforcement === "flag") {
|
|
if (code === "pass" && image === "pass") return "published";
|
|
return "flagged";
|
|
}
|
|
|
|
// enforcement === "block"
|
|
if (code === "fail" || image === "fail") return "rejected";
|
|
if (code === "warn" || image === "warn") return "flagged";
|
|
return "published";
|
|
}
|