A single normalized security finding.
Findings come from many sources — Hex mix_audit, osv-scanner,
the OpenSSL/SQLite/Erlef advisory feeds, semgrep, etc. — and are
normalized into this struct so the report and rubric treat them
uniformly. source records which scanner produced it; layer
records which surface area it covers (:hex_deps, :bundled_runtime,
:c_source, ...).
severity is one of :critical, :high, :medium, :low,
:unknown. Scanners report severity differently (CVSS scores,
GHSA ratings, vendor scales); upstream callers normalize before
building a Finding.
Summary
Functions
Deduplication key. Two findings dedupe to the same key when they
describe the same advisory against the same package+version, even
if they came from different sources (e.g. mix_audit and osv-scanner
both reporting GHSA-XXXX against :plug 1.10).
Sort order helper: severities ranked critical → unknown.
Types
@type severity() :: :critical | :high | :medium | :low | :unknown
Functions
Deduplication key. Two findings dedupe to the same key when they
describe the same advisory against the same package+version, even
if they came from different sources (e.g. mix_audit and osv-scanner
both reporting GHSA-XXXX against :plug 1.10).
@spec sort_key(t()) :: {non_neg_integer(), String.t()}
Sort order helper: severities ranked critical → unknown.
Use as Enum.sort_by(findings, &Finding.sort_key/1).