Assessor_2.0/src/persistence/reference-run-validation.ts

30 lines
2.2 KiB
TypeScript

import type { CanonicalAssessmentModel } from '../domain/canonical-model';
import { createReferenceRecognizer, type ReferenceCatalogSnapshot, type ReferenceRecognitionRun } from '../domain/reference-recognition';
import { canonicalJson } from '../shared/canonical-json';
import { RepositoryValidationError } from './repository-errors';
export function validateReferenceRun(run: ReferenceRecognitionRun, catalogs: ReferenceCatalogSnapshot[], model: CanonicalAssessmentModel | null): void {
const hash = /^[a-f0-9]{64}$/;
if (!model || model.project.id !== run.projectId || model.assessment.id !== run.assessmentId
|| !model.scanRuns.some(scan => scan.id === run.scanRunId) || run.schemaVersion !== 1
|| !run.id || !run.recognizerVersion || !hash.test(run.inputSha256) || !Number.isFinite(Date.parse(run.createdAt))
|| catalogs.length !== 2 || new Set(catalogs.map(catalog => catalog.framework)).size !== 2
|| catalogs.some(catalog => !hash.test(catalog.sha256) || !catalog.entries.length || !catalog.license)
|| canonicalJson([...run.catalogHashes].sort()) !== canonicalJson(catalogs.map(catalog => catalog.sha256).sort())) {
throw new RepositoryValidationError('Ungültiger Referenzlauf oder fremder Scan-/Katalogkontext.');
}
const occurrences = model.findingOccurrences.filter(item => item.scanRunId === run.scanRunId);
const results = new Map(run.results.map(result => [result.occurrenceId, result]));
const recognize = createReferenceRecognizer(catalogs);
if (results.size !== occurrences.length || results.size !== run.results.length) throw new RepositoryValidationError('Unvollständiger Referenzlauf.');
for (const occurrence of occurrences) {
const result = results.get(occurrence.id);
const file = model.importFiles.find(item => item.id === occurrence.importFileId);
if (!result || result.importFileId !== occurrence.importFileId || result.sourceFileSha256 !== file?.sha256
|| canonicalJson(result.sourcePosition) !== canonicalJson(occurrence.sourcePosition)
|| canonicalJson(result.references) !== canonicalJson(recognize(occurrence.originalFields))) {
throw new RepositoryValidationError('Referenzherkunft stimmt nicht mit dem gespeicherten Original überein.');
}
}
}