← back to Homesonspec
packages/validation/src/engine.ts
42 lines
import type {
RuleContext,
StagedCandidate,
ValidationEventInput,
ValidationOutcome,
ValidationRule,
} from "./types";
/**
* Run every applicable rule and fold the results into one verdict.
* Deterministic: same record + same DB state → same verdict, always.
*
* any failed error → rejected
* any failed review → needs_review
* otherwise → publishable (failed warns log but don't block)
*/
export async function runValidation(
record: StagedCandidate,
rules: ValidationRule[],
ctx: RuleContext,
): Promise<ValidationOutcome> {
const events: ValidationEventInput[] = [];
for (const rule of rules) {
if (!rule.entityTypes.includes(record.entityType)) continue;
const result = await rule.check(record, ctx);
events.push({
ruleId: rule.id,
severity: rule.severity,
passed: result.passed,
message: result.passed ? undefined : result.message,
details: result.passed ? undefined : result.details,
});
}
const failedError = events.some((e) => !e.passed && e.severity === "error");
const failedReview = events.some((e) => !e.passed && e.severity === "review");
const verdict = failedError ? "rejected" : failedReview ? "needs_review" : "publishable";
return { events, verdict };
}