using System.Text.Json.Serialization; namespace StellaOps.Findings.Ledger.Domain; /// /// Immutable decision event per advisory ยง11. /// public sealed class DecisionEvent { /// /// Unique identifier for this decision event. /// public string Id { get; init; } = Guid.NewGuid().ToString("N"); /// /// Alert identifier. /// public required string AlertId { get; init; } /// /// Artifact identifier (image digest/commit hash). /// public required string ArtifactId { get; init; } /// /// Actor who made the decision. /// public required string ActorId { get; init; } /// /// When the decision was recorded (UTC). /// public required DateTimeOffset Timestamp { get; init; } /// /// Decision status: affected, not_affected, under_investigation. /// public required string DecisionStatus { get; init; } /// /// Preset reason code. /// public required string ReasonCode { get; init; } /// /// Custom reason text. /// public string? ReasonText { get; init; } /// /// Content-addressed evidence hashes. /// public required List EvidenceHashes { get; init; } /// /// Policy context (ruleset version, policy id). /// public string? PolicyContext { get; init; } /// /// Deterministic replay token for reproducibility. /// public required string ReplayToken { get; init; } } /// /// Alert entity for triage. /// public sealed class Alert { /// /// Unique alert identifier. /// public required string AlertId { get; init; } /// /// Tenant identifier. /// public required string TenantId { get; init; } /// /// Artifact identifier (image digest/commit hash). /// public required string ArtifactId { get; init; } /// /// Vulnerability identifier. /// public required string VulnId { get; init; } /// /// Affected component PURL. /// public string? ComponentPurl { get; init; } /// /// Severity level (critical, high, medium, low). /// public required string Severity { get; init; } /// /// Triage band (hot, warm, cold). /// public required string Band { get; init; } /// /// Alert status (open, in_review, decided, closed). /// public required string Status { get; init; } /// /// Composite triage score. /// public double Score { get; init; } /// /// When the alert was created. /// public required DateTimeOffset CreatedAt { get; init; } /// /// When the alert was last updated. /// public DateTimeOffset? UpdatedAt { get; init; } /// /// Number of decisions recorded for this alert. /// public int DecisionCount { get; init; } } /// /// Evidence bundle for an alert. /// public sealed class EvidenceBundle { /// /// Alert identifier. /// public required string AlertId { get; init; } /// /// Reachability evidence. /// public EvidenceSection? Reachability { get; init; } /// /// Call stack evidence. /// public EvidenceSection? CallStack { get; init; } /// /// Provenance evidence. /// public EvidenceSection? Provenance { get; init; } /// /// VEX status evidence. /// public VexStatusEvidence? VexStatus { get; init; } /// /// Content-addressed hashes for all evidence. /// public required EvidenceHashes Hashes { get; init; } /// /// When the bundle was computed. /// public required DateTimeOffset ComputedAt { get; init; } } /// /// Evidence section with status and proof. /// public sealed class EvidenceSection { /// /// Status: available, loading, unavailable, error. /// public required string Status { get; init; } /// /// Content hash for this evidence. /// public string? Hash { get; init; } /// /// Proof data (type-specific). /// public object? Proof { get; init; } } /// /// VEX status evidence with history. /// public sealed class VexStatusEvidence { /// /// Status: available, unavailable. /// public required string Status { get; init; } /// /// Current VEX statement. /// public VexStatement? Current { get; init; } /// /// Historical VEX statements. /// public IReadOnlyList? History { get; init; } } /// /// VEX statement summary. /// public sealed class VexStatement { /// /// Statement identifier. /// public required string StatementId { get; init; } /// /// VEX status. /// public required string Status { get; init; } /// /// Justification code. /// public string? Justification { get; init; } /// /// Impact statement. /// public string? ImpactStatement { get; init; } /// /// When the statement was issued. /// public required DateTimeOffset Timestamp { get; init; } /// /// Statement issuer. /// public string? Issuer { get; init; } } /// /// Content-addressed hashes for evidence bundle. /// public sealed class EvidenceHashes { /// /// All hashes for the bundle. /// public required IReadOnlyList Hashes { get; init; } } /// /// Audit timeline for an alert. /// public sealed class AuditTimeline { /// /// Alert identifier. /// public required string AlertId { get; init; } /// /// List of audit events. /// public required IReadOnlyList Events { get; init; } /// /// Total count of events. /// public int TotalCount { get; init; } } /// /// Single audit event. /// public sealed class AuditEvent { /// /// Event identifier. /// public required string EventId { get; init; } /// /// Type of audit event. /// public required string EventType { get; init; } /// /// Actor who triggered the event. /// public required string ActorId { get; init; } /// /// When the event occurred. /// public required DateTimeOffset Timestamp { get; init; } /// /// Event-specific details. /// public object? Details { get; init; } /// /// Replay token if applicable. /// public string? ReplayToken { get; init; } } /// /// Alert diff result. /// public sealed class AlertDiff { /// /// Alert identifier. /// public required string AlertId { get; init; } /// /// Baseline scan identifier. /// public string? BaselineScanId { get; init; } /// /// Current scan identifier. /// public required string CurrentScanId { get; init; } /// /// SBOM diff summary. /// public SbomDiff? SbomDiff { get; init; } /// /// VEX diff summary. /// public VexDiff? VexDiff { get; init; } /// /// When the diff was computed. /// public required DateTimeOffset ComputedAt { get; init; } } /// /// SBOM diff summary. /// public sealed class SbomDiff { /// /// Number of added components. /// public int AddedComponents { get; init; } /// /// Number of removed components. /// public int RemovedComponents { get; init; } /// /// Number of changed components. /// public int ChangedComponents { get; init; } /// /// Detailed changes. /// public IReadOnlyList? Changes { get; init; } } /// /// Single component diff. /// public sealed class ComponentDiff { /// /// Component PURL. /// public required string Purl { get; init; } /// /// Type of change: added, removed, changed. /// public required string ChangeType { get; init; } /// /// Old version if changed/removed. /// public string? OldVersion { get; init; } /// /// New version if changed/added. /// public string? NewVersion { get; init; } } /// /// VEX diff summary. /// public sealed class VexDiff { /// /// Number of status changes. /// public int StatusChanges { get; init; } /// /// Number of new statements. /// public int NewStatements { get; init; } /// /// Detailed changes. /// public IReadOnlyList? Changes { get; init; } } /// /// Single VEX status diff. /// public sealed class VexStatusDiff { /// /// Vulnerability identifier. /// public required string VulnId { get; init; } /// /// Old status. /// public string? OldStatus { get; init; } /// /// New status. /// public required string NewStatus { get; init; } /// /// When the change occurred. /// public required DateTimeOffset Timestamp { get; init; } }