Files
git.stella-ops.org/src/Cli/StellaOps.Cli/Services/Models/VexObservationModels.cs
master d1cbb905f8
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
up
2025-11-28 18:21:46 +02:00

293 lines
8.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace StellaOps.Cli.Services.Models;
// CLI-LNM-22-002: VEX observation models for CLI commands
/// <summary>
/// Query options for VEX observations.
/// </summary>
internal sealed class VexObservationQuery
{
[JsonPropertyName("tenant")]
public string Tenant { get; init; } = string.Empty;
[JsonPropertyName("vulnerabilityIds")]
public IReadOnlyList<string> VulnerabilityIds { get; init; } = Array.Empty<string>();
[JsonPropertyName("productKeys")]
public IReadOnlyList<string> ProductKeys { get; init; } = Array.Empty<string>();
[JsonPropertyName("purls")]
public IReadOnlyList<string> Purls { get; init; } = Array.Empty<string>();
[JsonPropertyName("cpes")]
public IReadOnlyList<string> Cpes { get; init; } = Array.Empty<string>();
[JsonPropertyName("statuses")]
public IReadOnlyList<string> Statuses { get; init; } = Array.Empty<string>();
[JsonPropertyName("providerIds")]
public IReadOnlyList<string> ProviderIds { get; init; } = Array.Empty<string>();
[JsonPropertyName("limit")]
public int? Limit { get; init; }
[JsonPropertyName("cursor")]
public string? Cursor { get; init; }
}
/// <summary>
/// Response from VEX observation query.
/// </summary>
internal sealed class VexObservationResponse
{
[JsonPropertyName("observations")]
public IReadOnlyList<VexObservation> Observations { get; init; } = Array.Empty<VexObservation>();
[JsonPropertyName("aggregate")]
public VexObservationAggregate? Aggregate { get; init; }
[JsonPropertyName("nextCursor")]
public string? NextCursor { get; init; }
[JsonPropertyName("hasMore")]
public bool HasMore { get; init; }
}
/// <summary>
/// VEX observation document.
/// </summary>
internal sealed class VexObservation
{
[JsonPropertyName("observationId")]
public string ObservationId { get; init; } = string.Empty;
[JsonPropertyName("tenant")]
public string Tenant { get; init; } = string.Empty;
[JsonPropertyName("vulnerabilityId")]
public string VulnerabilityId { get; init; } = string.Empty;
[JsonPropertyName("providerId")]
public string ProviderId { get; init; } = string.Empty;
[JsonPropertyName("product")]
public VexObservationProduct? Product { get; init; }
[JsonPropertyName("status")]
public string Status { get; init; } = string.Empty;
[JsonPropertyName("justification")]
public string? Justification { get; init; }
[JsonPropertyName("detail")]
public string? Detail { get; init; }
[JsonPropertyName("document")]
public VexObservationDocument? Document { get; init; }
[JsonPropertyName("firstSeen")]
public DateTimeOffset FirstSeen { get; init; }
[JsonPropertyName("lastSeen")]
public DateTimeOffset LastSeen { get; init; }
[JsonPropertyName("confidence")]
public VexObservationConfidence? Confidence { get; init; }
[JsonPropertyName("createdAt")]
public DateTimeOffset CreatedAt { get; init; }
[JsonPropertyName("updatedAt")]
public DateTimeOffset? UpdatedAt { get; init; }
}
/// <summary>
/// Product information in VEX observation.
/// </summary>
internal sealed class VexObservationProduct
{
[JsonPropertyName("key")]
public string Key { get; init; } = string.Empty;
[JsonPropertyName("name")]
public string? Name { get; init; }
[JsonPropertyName("version")]
public string? Version { get; init; }
[JsonPropertyName("purl")]
public string? Purl { get; init; }
[JsonPropertyName("cpe")]
public string? Cpe { get; init; }
[JsonPropertyName("componentIdentifiers")]
public IReadOnlyList<string> ComponentIdentifiers { get; init; } = Array.Empty<string>();
}
/// <summary>
/// Document reference in VEX observation.
/// </summary>
internal sealed class VexObservationDocument
{
[JsonPropertyName("format")]
public string Format { get; init; } = string.Empty;
[JsonPropertyName("digest")]
public string Digest { get; init; } = string.Empty;
[JsonPropertyName("sourceUri")]
public string SourceUri { get; init; } = string.Empty;
[JsonPropertyName("revision")]
public string? Revision { get; init; }
[JsonPropertyName("signature")]
public VexObservationSignature? Signature { get; init; }
}
/// <summary>
/// Signature metadata for VEX document.
/// </summary>
internal sealed class VexObservationSignature
{
[JsonPropertyName("type")]
public string Type { get; init; } = string.Empty;
[JsonPropertyName("subject")]
public string? Subject { get; init; }
[JsonPropertyName("issuer")]
public string? Issuer { get; init; }
[JsonPropertyName("keyId")]
public string? KeyId { get; init; }
[JsonPropertyName("verifiedAt")]
public DateTimeOffset? VerifiedAt { get; init; }
[JsonPropertyName("transparencyLogReference")]
public string? TransparencyLogReference { get; init; }
}
/// <summary>
/// Confidence level in VEX observation.
/// </summary>
internal sealed class VexObservationConfidence
{
[JsonPropertyName("level")]
public string Level { get; init; } = string.Empty;
[JsonPropertyName("score")]
public double? Score { get; init; }
[JsonPropertyName("method")]
public string? Method { get; init; }
}
/// <summary>
/// Aggregate data from VEX observation query.
/// </summary>
internal sealed class VexObservationAggregate
{
[JsonPropertyName("vulnerabilityIds")]
public IReadOnlyList<string> VulnerabilityIds { get; init; } = Array.Empty<string>();
[JsonPropertyName("productKeys")]
public IReadOnlyList<string> ProductKeys { get; init; } = Array.Empty<string>();
[JsonPropertyName("purls")]
public IReadOnlyList<string> Purls { get; init; } = Array.Empty<string>();
[JsonPropertyName("cpes")]
public IReadOnlyList<string> Cpes { get; init; } = Array.Empty<string>();
[JsonPropertyName("providerIds")]
public IReadOnlyList<string> ProviderIds { get; init; } = Array.Empty<string>();
[JsonPropertyName("statusCounts")]
public IReadOnlyDictionary<string, int> StatusCounts { get; init; } = new Dictionary<string, int>();
}
/// <summary>
/// VEX linkset query options.
/// </summary>
internal sealed class VexLinksetQuery
{
[JsonPropertyName("tenant")]
public string Tenant { get; init; } = string.Empty;
[JsonPropertyName("vulnerabilityId")]
public string VulnerabilityId { get; init; } = string.Empty;
[JsonPropertyName("productKeys")]
public IReadOnlyList<string> ProductKeys { get; init; } = Array.Empty<string>();
[JsonPropertyName("purls")]
public IReadOnlyList<string> Purls { get; init; } = Array.Empty<string>();
[JsonPropertyName("statuses")]
public IReadOnlyList<string> Statuses { get; init; } = Array.Empty<string>();
}
/// <summary>
/// VEX linkset response showing linked observations.
/// </summary>
internal sealed class VexLinksetResponse
{
[JsonPropertyName("vulnerabilityId")]
public string VulnerabilityId { get; init; } = string.Empty;
[JsonPropertyName("observations")]
public IReadOnlyList<VexObservation> Observations { get; init; } = Array.Empty<VexObservation>();
[JsonPropertyName("summary")]
public VexLinksetSummary? Summary { get; init; }
[JsonPropertyName("conflicts")]
public IReadOnlyList<VexLinksetConflict> Conflicts { get; init; } = Array.Empty<VexLinksetConflict>();
}
/// <summary>
/// Summary of VEX linkset.
/// </summary>
internal sealed class VexLinksetSummary
{
[JsonPropertyName("totalObservations")]
public int TotalObservations { get; init; }
[JsonPropertyName("providers")]
public IReadOnlyList<string> Providers { get; init; } = Array.Empty<string>();
[JsonPropertyName("products")]
public IReadOnlyList<string> Products { get; init; } = Array.Empty<string>();
[JsonPropertyName("statusCounts")]
public IReadOnlyDictionary<string, int> StatusCounts { get; init; } = new Dictionary<string, int>();
[JsonPropertyName("hasConflicts")]
public bool HasConflicts { get; init; }
}
/// <summary>
/// Conflict between VEX observations.
/// </summary>
internal sealed class VexLinksetConflict
{
[JsonPropertyName("productKey")]
public string ProductKey { get; init; } = string.Empty;
[JsonPropertyName("conflictingStatuses")]
public IReadOnlyList<string> ConflictingStatuses { get; init; } = Array.Empty<string>();
[JsonPropertyName("observations")]
public IReadOnlyList<string> ObservationIds { get; init; } = Array.Empty<string>();
[JsonPropertyName("description")]
public string Description { get; init; } = string.Empty;
}