// SPDX-License-Identifier: BUSL-1.1
// Sprint: SPRINT_4000_0002_0001
// Task: T1 - Extend Findings API Response with version comparison metadata
using System.Collections.Immutable;
using System.Text.Json.Serialization;
namespace StellaOps.Scanner.Evidence.Models;
///
/// Evidence of version comparison used to determine vulnerability status.
/// Provides explainability for backport detection logic.
///
public sealed record VersionComparisonEvidence
{
///
/// Comparator algorithm used (rpm-evr, dpkg, apk, semver).
///
[JsonPropertyName("comparator")]
public required string Comparator { get; init; }
///
/// Installed version in native format.
///
[JsonPropertyName("installedVersion")]
public required string InstalledVersion { get; init; }
///
/// Fixed version threshold from advisory.
///
[JsonPropertyName("fixedVersion")]
public required string FixedVersion { get; init; }
///
/// Whether the installed version is >= fixed.
///
[JsonPropertyName("isFixed")]
public required bool IsFixed { get; init; }
///
/// Human-readable proof lines showing comparison steps.
///
[JsonPropertyName("proofLines")]
public ImmutableArray ProofLines { get; init; } = [];
///
/// Advisory source (DSA-1234, RHSA-2025:1234, USN-1234-1).
///
[JsonPropertyName("advisorySource")]
public string? AdvisorySource { get; init; }
///
/// Creates VersionComparisonEvidence from a version comparison result.
///
/// The comparator type identifier.
/// The installed version string.
/// The fixed version threshold.
/// The comparison result (negative if installed < fixed).
/// Human-readable comparison steps.
/// Optional advisory identifier.
public static VersionComparisonEvidence Create(
string comparator,
string installedVersion,
string fixedVersion,
int comparisonResult,
ImmutableArray proofLines,
string? advisorySource = null)
{
return new VersionComparisonEvidence
{
Comparator = comparator,
InstalledVersion = installedVersion,
FixedVersion = fixedVersion,
IsFixed = comparisonResult >= 0, // installed >= fixed means fixed
ProofLines = proofLines,
AdvisorySource = advisorySource
};
}
}