Files
git.stella-ops.org/src/Scanner/StellaOps.Scanner.WebService/Contracts/OrchestratorEventContracts.cs
master 9e5e958d42
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
feat: Document completed tasks for KMS, Cryptography, and Plugin Libraries
- Added detailed task completion records for KMS interface implementation and CLI support for file-based keys.
- Documented security enhancements including Argon2id password hashing, audit event contracts, and rate limiting configurations.
- Included scoped service support and integration updates for the Plugin platform, ensuring proper DI handling and testing coverage.
2025-10-31 14:33:05 +02:00

290 lines
9.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text.Json.Serialization;
namespace StellaOps.Scanner.WebService.Contracts;
internal static class OrchestratorEventKinds
{
public const string ScannerReportReady = "scanner.event.report.ready";
public const string ScannerScanCompleted = "scanner.event.scan.completed";
}
internal sealed record OrchestratorEvent
{
[JsonPropertyName("eventId")]
[JsonPropertyOrder(0)]
public Guid EventId { get; init; }
[JsonPropertyName("kind")]
[JsonPropertyOrder(1)]
public string Kind { get; init; } = string.Empty;
[JsonPropertyName("version")]
[JsonPropertyOrder(2)]
public int Version { get; init; } = 1;
[JsonPropertyName("tenant")]
[JsonPropertyOrder(3)]
public string Tenant { get; init; } = string.Empty;
[JsonPropertyName("occurredAt")]
[JsonPropertyOrder(4)]
public DateTimeOffset OccurredAt { get; init; }
[JsonPropertyName("recordedAt")]
[JsonPropertyOrder(5)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTimeOffset? RecordedAt { get; init; }
[JsonPropertyName("source")]
[JsonPropertyOrder(6)]
public string Source { get; init; } = string.Empty;
[JsonPropertyName("idempotencyKey")]
[JsonPropertyOrder(7)]
public string IdempotencyKey { get; init; } = string.Empty;
[JsonPropertyName("correlationId")]
[JsonPropertyOrder(8)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? CorrelationId { get; init; }
[JsonPropertyName("traceId")]
[JsonPropertyOrder(9)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? TraceId { get; init; }
[JsonPropertyName("spanId")]
[JsonPropertyOrder(10)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? SpanId { get; init; }
[JsonPropertyName("scope")]
[JsonPropertyOrder(11)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public OrchestratorEventScope? Scope { get; init; }
[JsonPropertyName("payload")]
[JsonPropertyOrder(12)]
public OrchestratorEventPayload Payload { get; init; } = default!;
[JsonPropertyName("attributes")]
[JsonPropertyOrder(13)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ImmutableSortedDictionary<string, string>? Attributes { get; init; }
}
internal sealed record OrchestratorEventScope
{
[JsonPropertyName("namespace")]
[JsonPropertyOrder(0)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Namespace { get; init; }
[JsonPropertyName("repo")]
[JsonPropertyOrder(1)]
public string Repo { get; init; } = string.Empty;
[JsonPropertyName("digest")]
[JsonPropertyOrder(2)]
public string Digest { get; init; } = string.Empty;
[JsonPropertyName("component")]
[JsonPropertyOrder(3)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Component { get; init; }
[JsonPropertyName("image")]
[JsonPropertyOrder(4)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Image { get; init; }
}
internal abstract record OrchestratorEventPayload;
internal sealed record ReportReadyEventPayload : OrchestratorEventPayload
{
[JsonPropertyName("reportId")]
[JsonPropertyOrder(0)]
public string ReportId { get; init; } = string.Empty;
[JsonPropertyName("scanId")]
[JsonPropertyOrder(1)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ScanId { get; init; }
[JsonPropertyName("imageDigest")]
[JsonPropertyOrder(2)]
public string ImageDigest { get; init; } = string.Empty;
[JsonPropertyName("generatedAt")]
[JsonPropertyOrder(3)]
public DateTimeOffset GeneratedAt { get; init; }
[JsonPropertyName("verdict")]
[JsonPropertyOrder(4)]
public string Verdict { get; init; } = string.Empty;
[JsonPropertyName("summary")]
[JsonPropertyOrder(5)]
public ReportSummaryDto Summary { get; init; } = new();
[JsonPropertyName("delta")]
[JsonPropertyOrder(6)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ReportDeltaPayload? Delta { get; init; }
[JsonPropertyName("quietedFindingCount")]
[JsonPropertyOrder(7)]
public int QuietedFindingCount { get; init; }
[JsonPropertyName("policy")]
[JsonPropertyOrder(8)]
public ReportPolicyDto Policy { get; init; } = new();
[JsonPropertyName("links")]
[JsonPropertyOrder(9)]
public ReportLinksPayload Links { get; init; } = new();
[JsonPropertyName("dsse")]
[JsonPropertyOrder(10)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DsseEnvelopeDto? Dsse { get; init; }
[JsonPropertyName("report")]
[JsonPropertyOrder(11)]
public ReportDocumentDto Report { get; init; } = new();
}
internal sealed record ScanCompletedEventPayload : OrchestratorEventPayload
{
[JsonPropertyName("reportId")]
[JsonPropertyOrder(0)]
public string ReportId { get; init; } = string.Empty;
[JsonPropertyName("scanId")]
[JsonPropertyOrder(1)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? ScanId { get; init; }
[JsonPropertyName("imageDigest")]
[JsonPropertyOrder(2)]
public string ImageDigest { get; init; } = string.Empty;
[JsonPropertyName("verdict")]
[JsonPropertyOrder(3)]
public string Verdict { get; init; } = string.Empty;
[JsonPropertyName("summary")]
[JsonPropertyOrder(4)]
public ReportSummaryDto Summary { get; init; } = new();
[JsonPropertyName("delta")]
[JsonPropertyOrder(5)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public ReportDeltaPayload? Delta { get; init; }
[JsonPropertyName("policy")]
[JsonPropertyOrder(6)]
public ReportPolicyDto Policy { get; init; } = new();
[JsonPropertyName("findings")]
[JsonPropertyOrder(7)]
public IReadOnlyList<FindingSummaryPayload> Findings { get; init; } = Array.Empty<FindingSummaryPayload>();
[JsonPropertyName("links")]
[JsonPropertyOrder(8)]
public ReportLinksPayload Links { get; init; } = new();
[JsonPropertyName("dsse")]
[JsonPropertyOrder(9)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DsseEnvelopeDto? Dsse { get; init; }
[JsonPropertyName("report")]
[JsonPropertyOrder(10)]
public ReportDocumentDto Report { get; init; } = new();
}
internal sealed record ReportDeltaPayload
{
[JsonPropertyName("newCritical")]
[JsonPropertyOrder(0)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? NewCritical { get; init; }
[JsonPropertyName("newHigh")]
[JsonPropertyOrder(1)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? NewHigh { get; init; }
[JsonPropertyName("kev")]
[JsonPropertyOrder(2)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IReadOnlyList<string>? Kev { get; init; }
}
internal sealed record ReportLinksPayload
{
[JsonPropertyName("report")]
[JsonPropertyOrder(0)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public LinkTarget? Report { get; init; }
[JsonPropertyName("policy")]
[JsonPropertyOrder(1)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public LinkTarget? Policy { get; init; }
[JsonPropertyName("attestation")]
[JsonPropertyOrder(2)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public LinkTarget? Attestation { get; init; }
}
internal sealed record LinkTarget(
[property: JsonPropertyName("ui"), JsonPropertyOrder(0), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string? Ui,
[property: JsonPropertyName("api"), JsonPropertyOrder(1), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string? Api)
{
public static LinkTarget? Create(string? ui, string? api)
{
if (string.IsNullOrWhiteSpace(ui) && string.IsNullOrWhiteSpace(api))
{
return null;
}
return new LinkTarget(
string.IsNullOrWhiteSpace(ui) ? null : ui,
string.IsNullOrWhiteSpace(api) ? null : api);
}
}
internal sealed record FindingSummaryPayload
{
[JsonPropertyName("id")]
[JsonPropertyOrder(0)]
public string Id { get; init; } = string.Empty;
[JsonPropertyName("severity")]
[JsonPropertyOrder(1)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Severity { get; init; }
[JsonPropertyName("cve")]
[JsonPropertyOrder(2)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Cve { get; init; }
[JsonPropertyName("purl")]
[JsonPropertyOrder(3)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Purl { get; init; }
[JsonPropertyName("reachability")]
[JsonPropertyOrder(4)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Reachability { get; init; }
}