fix: dedupe sentinel report artifact findings

This commit is contained in:
Codex
2026-07-02 00:38:13 +00:00
parent 47f7482bf5
commit 7056dd6040
+44 -1
View File
@@ -336,8 +336,9 @@ function compactSentinelReportRawPayload(
function mergeSentinelReportFindings(primary: readonly Record<string, unknown>[], artifact: readonly Record<string, unknown>[]): Record<string, unknown>[] {
const merged: Record<string, unknown>[] = [];
const seen = new Set<string>();
const aliases = sentinelReportFindingIdentityAliases(primary);
for (const item of [...primary, ...artifact]) {
const id = sentinelReportFindingIdentity(item);
const id = sentinelReportCanonicalFindingIdentity(item, aliases);
const key = id ?? `${JSON.stringify(item).slice(0, 160)}:${stringAtNullable(item, "severity") ?? stringAtNullable(item, "level") ?? ""}`;
if (seen.has(key)) continue;
seen.add(key);
@@ -346,6 +347,48 @@ function mergeSentinelReportFindings(primary: readonly Record<string, unknown>[]
return merged;
}
function sentinelReportFindingIdentityAliases(items: readonly Record<string, unknown>[]): Map<string, string> {
const aliases = new Map<string, string>();
for (const item of items) {
const canonical = sentinelReportFindingCanonicalCandidate(item) ?? sentinelReportFindingIdentity(item);
if (canonical === null) continue;
for (const candidate of sentinelReportFindingIdentityCandidates(item)) aliases.set(candidate, canonical);
}
return aliases;
}
function sentinelReportCanonicalFindingIdentity(item: Record<string, unknown>, aliases: ReadonlyMap<string, string>): string | null {
for (const candidate of sentinelReportFindingIdentityCandidates(item)) {
const canonical = aliases.get(candidate);
if (canonical !== undefined) return canonical;
}
return sentinelReportFindingCanonicalCandidate(item) ?? sentinelReportFindingIdentity(item);
}
function sentinelReportFindingCanonicalCandidate(item: Record<string, unknown>): string | null {
const check = record(item.check);
return stringAtNullable(item, "checkCode")
?? stringAtNullable(check, "code")
?? stringAtNullable(item, "checkId")
?? stringAtNullable(check, "id");
}
function sentinelReportFindingIdentityCandidates(item: Record<string, unknown>): readonly string[] {
const check = record(item.check);
const candidates = [
stringAtNullable(item, "finding_id"),
stringAtNullable(item, "findingId"),
stringAtNullable(item, "id"),
stringAtNullable(item, "kind"),
stringAtNullable(item, "code"),
stringAtNullable(item, "checkId"),
stringAtNullable(item, "checkCode"),
stringAtNullable(check, "id"),
stringAtNullable(check, "code"),
];
return [...new Set(candidates.filter((item): item is string => item !== null))];
}
function sentinelReportFindingIdentity(item: Record<string, unknown>): string | null {
return stringAtNullable(item, "finding_id")
?? stringAtNullable(item, "findingId")