Files
git.stella-ops.org/src/VexLens/__Libraries/StellaOps.VexLens.Spdx3/IVexToSpdx3Mapper.cs

294 lines
8.4 KiB
C#

// <copyright file="IVexToSpdx3Mapper.cs" company="StellaOps">
// Copyright (c) StellaOps. Licensed under the BUSL-1.1.
// </copyright>
using StellaOps.Spdx3.Model;
namespace StellaOps.VexLens.Spdx3;
/// <summary>
/// Interface for mapping VEX consensus results to SPDX 3.0.1 Security profile documents.
/// Sprint: SPRINT_20260107_004_004 Task SP-005
/// </summary>
public interface IVexToSpdx3Mapper
{
/// <summary>
/// Maps a VEX consensus result to an SPDX 3.0.1 document with Security profile.
/// </summary>
/// <param name="consensus">The VEX consensus containing statements.</param>
/// <param name="options">Mapping options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The mapped SPDX 3.0.1 document.</returns>
Task<Spdx3Document> MapConsensusAsync(
VexConsensus consensus,
VexToSpdx3Options options,
CancellationToken cancellationToken = default);
/// <summary>
/// Maps individual VEX statements to SPDX 3.0.1 elements.
/// </summary>
/// <param name="statements">The VEX statements to map.</param>
/// <param name="spdxIdPrefix">Prefix for generating SPDX IDs.</param>
/// <returns>The mapped elements including vulnerabilities and assessment relationships.</returns>
VexMappingResult MapStatements(
IEnumerable<OpenVexStatement> statements,
string spdxIdPrefix);
}
/// <summary>
/// Options for VEX to SPDX 3.0.1 mapping.
/// </summary>
public sealed record VexToSpdx3Options
{
/// <summary>
/// Gets the SPDX ID prefix for generated elements.
/// </summary>
public required string SpdxIdPrefix { get; init; }
/// <summary>
/// Gets the document name.
/// </summary>
public string? DocumentName { get; init; }
/// <summary>
/// Gets whether to include CVSS scores.
/// </summary>
public bool IncludeCvss { get; init; } = true;
/// <summary>
/// Gets whether to include EPSS scores.
/// </summary>
public bool IncludeEpss { get; init; } = true;
/// <summary>
/// Gets the tool identifier to include in creation info.
/// </summary>
public string ToolId { get; init; } = "StellaOps VexLens";
/// <summary>
/// Gets a filter for specific products (null = all).
/// </summary>
public IReadOnlyList<string>? ProductFilter { get; init; }
/// <summary>
/// Gets a filter for specific CVEs (null = all).
/// </summary>
public IReadOnlyList<string>? VulnerabilityFilter { get; init; }
}
/// <summary>
/// Result of mapping VEX statements to SPDX 3.0.1 elements.
/// </summary>
public sealed record VexMappingResult
{
/// <summary>
/// Gets the vulnerability elements.
/// </summary>
public required IReadOnlyList<Spdx3Element> Vulnerabilities { get; init; }
/// <summary>
/// Gets the VEX assessment relationships.
/// </summary>
public required IReadOnlyList<Spdx3Element> Assessments { get; init; }
/// <summary>
/// Gets the CVSS assessment relationships.
/// </summary>
public IReadOnlyList<Spdx3Element> CvssAssessments { get; init; } = Array.Empty<Spdx3Element>();
/// <summary>
/// Gets the EPSS assessment relationships.
/// </summary>
public IReadOnlyList<Spdx3Element> EpssAssessments { get; init; } = Array.Empty<Spdx3Element>();
/// <summary>
/// Gets all elements combined.
/// </summary>
public IEnumerable<Spdx3Element> AllElements =>
Vulnerabilities
.Concat(Assessments)
.Concat(CvssAssessments)
.Concat(EpssAssessments);
}
/// <summary>
/// Represents a VEX consensus containing multiple statements.
/// </summary>
public sealed record VexConsensus
{
/// <summary>
/// Gets the document identifier.
/// </summary>
public required string DocumentId { get; init; }
/// <summary>
/// Gets the document version.
/// </summary>
public string? Version { get; init; }
/// <summary>
/// Gets the statements in this consensus.
/// </summary>
public required IReadOnlyList<OpenVexStatement> Statements { get; init; }
/// <summary>
/// Gets the supplier/author.
/// </summary>
public string? Author { get; init; }
/// <summary>
/// Gets the timestamp.
/// </summary>
public DateTimeOffset? Timestamp { get; init; }
}
/// <summary>
/// Represents an OpenVEX statement.
/// </summary>
public sealed record OpenVexStatement
{
/// <summary>
/// Gets the vulnerability ID (e.g., CVE-2026-1234).
/// </summary>
public required string VulnerabilityId { get; init; }
/// <summary>
/// Gets the product ID (e.g., PURL).
/// </summary>
public required string ProductId { get; init; }
/// <summary>
/// Gets the VEX status.
/// </summary>
public required VexStatus Status { get; init; }
/// <summary>
/// Gets the justification for not_affected status.
/// </summary>
public VexJustification? Justification { get; init; }
/// <summary>
/// Gets the status notes.
/// </summary>
public string? StatusNotes { get; init; }
/// <summary>
/// Gets the impact statement.
/// </summary>
public string? ImpactStatement { get; init; }
/// <summary>
/// Gets the action statement for affected status.
/// </summary>
public string? ActionStatement { get; init; }
/// <summary>
/// Gets the action statement deadline.
/// </summary>
public DateTimeOffset? ActionStatementTime { get; init; }
/// <summary>
/// Gets the statement timestamp.
/// </summary>
public DateTimeOffset? Timestamp { get; init; }
/// <summary>
/// Gets the supplier/author.
/// </summary>
public string? Supplier { get; init; }
/// <summary>
/// Gets CVSS v3 data if available.
/// </summary>
public CvssV3Data? CvssV3 { get; init; }
/// <summary>
/// Gets EPSS data if available.
/// </summary>
public EpssData? Epss { get; init; }
}
/// <summary>
/// VEX status values.
/// </summary>
public enum VexStatus
{
/// <summary>The product is affected by the vulnerability.</summary>
Affected,
/// <summary>The product is not affected by the vulnerability.</summary>
NotAffected,
/// <summary>The vulnerability is fixed in the product.</summary>
Fixed,
/// <summary>The status is under investigation.</summary>
UnderInvestigation
}
/// <summary>
/// VEX justification values for not_affected status.
/// </summary>
public enum VexJustification
{
/// <summary>The component is not present.</summary>
ComponentNotPresent,
/// <summary>The vulnerable code is not present.</summary>
VulnerableCodeNotPresent,
/// <summary>The vulnerable code cannot be controlled by an adversary.</summary>
VulnerableCodeCannotBeControlledByAdversary,
/// <summary>The vulnerable code is not in the execute path.</summary>
VulnerableCodeNotInExecutePath,
/// <summary>Inline mitigations already exist.</summary>
InlineMitigationsAlreadyExist
}
/// <summary>
/// CVSS v3 scoring data.
/// Sprint: SPRINT_20260107_004_004 Task SP-007
/// </summary>
public sealed record CvssV3Data
{
/// <summary>Gets the CVSS v3 base score (0.0-10.0).</summary>
public decimal? BaseScore { get; init; }
/// <summary>Gets the CVSS v3 vector string.</summary>
public string? VectorString { get; init; }
/// <summary>Gets the temporal score if available.</summary>
public decimal? TemporalScore { get; init; }
/// <summary>Gets the environmental score if available.</summary>
public decimal? EnvironmentalScore { get; init; }
/// <summary>Gets when the score was published.</summary>
public DateTimeOffset? PublishedTime { get; init; }
/// <summary>Gets when the score was modified.</summary>
public DateTimeOffset? ModifiedTime { get; init; }
/// <summary>Gets the source of the CVSS data.</summary>
public string? Source { get; init; }
}
/// <summary>
/// EPSS (Exploit Prediction Scoring System) data.
/// Sprint: SPRINT_20260107_004_004 Task SP-007
/// </summary>
public sealed record EpssData
{
/// <summary>Gets the EPSS probability (0.0-1.0).</summary>
public decimal? Probability { get; init; }
/// <summary>Gets the EPSS percentile (0.0-1.0).</summary>
public decimal? Percentile { get; init; }
/// <summary>Gets the date of the EPSS score.</summary>
public DateTimeOffset? ScoreDate { get; init; }
}