import type { RiskLevel, UserAuthorization } from "./assessment.js"; import type { ReviewResult } from "./reviewer.js"; export const REVIEW_ENTRY = "approve-for-me.review.v1"; export interface ReviewAudit { version: 1; status: "allowed" | "denied" | "failed-closed" | "timed-out" | "aborted"; tool: string; source: "builtin" | "custom" | "unresolved"; attempts: number; riskLevel?: RiskLevel; userAuthorization?: UserAuthorization; } function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } const STATUSES = new Set(["allowed", "denied", "failed-closed", "timed-out", "aborted"]); const SOURCES = new Set(["builtin", "custom", "unresolved"]); const RISKS = new Set(["low", "medium", "high", "critical"]); const AUTHORIZATIONS = new Set(["unknown", "low", "medium", "high"]); export function parseReviewAudit(value: unknown): ReviewAudit | undefined { if (!isRecord(value) || value["version"] !== 1) return undefined; const status = value["status"]; const tool = value["tool"]; const source = value["source"]; const attempts = value["attempts"]; const riskLevel = value["riskLevel"]; const userAuthorization = value["userAuthorization"]; if (typeof status !== "string" || !STATUSES.has(status as ReviewAudit["status"])) return undefined; if (typeof tool !== "string" || tool.length === 0) return undefined; if (typeof source !== "string" || !SOURCES.has(source as ReviewAudit["source"])) return undefined; if (typeof attempts !== "number" || !Number.isInteger(attempts) || attempts < 0) return undefined; if (riskLevel !== undefined && (typeof riskLevel !== "string" || !RISKS.has(riskLevel as RiskLevel))) return undefined; if ( userAuthorization !== undefined && (typeof userAuthorization !== "string" || !AUTHORIZATIONS.has(userAuthorization as UserAuthorization)) ) { return undefined; } return { version: 1, status: status as ReviewAudit["status"], tool, source: source as ReviewAudit["source"], attempts, ...(riskLevel === undefined ? {} : { riskLevel: riskLevel as RiskLevel }), ...(userAuthorization === undefined ? {} : { userAuthorization: userAuthorization as UserAuthorization }), }; } export function createReviewAudit( tool: string, source: ReviewAudit["source"], result: ReviewResult, ): ReviewAudit { const assessment = result.status === "allowed" || result.status === "denied" ? result.assessment : undefined; return { version: 1, status: result.status, tool, source, attempts: result.attempts, ...(assessment === undefined ? {} : { riskLevel: assessment.riskLevel, userAuthorization: assessment.userAuthorization }), }; }