using System.Collections.Generic; using System.Text.Json.Serialization; namespace StellaOps.Scanner.WebService.Contracts; public sealed record RuntimePolicyRequestDto { [JsonPropertyName("namespace")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Namespace { get; init; } [JsonPropertyName("labels")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IDictionary? Labels { get; init; } [JsonPropertyName("images")] public IReadOnlyList Images { get; init; } = Array.Empty(); } public sealed record RuntimePolicyResponseDto { [JsonPropertyName("ttlSeconds")] public int TtlSeconds { get; init; } [JsonPropertyName("expiresAtUtc")] public DateTimeOffset ExpiresAtUtc { get; init; } [JsonPropertyName("policyRevision")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? PolicyRevision { get; init; } [JsonPropertyName("results")] public IReadOnlyDictionary Results { get; init; } = new Dictionary(StringComparer.Ordinal); } public sealed record RuntimePolicyImageResponseDto { [JsonPropertyName("policyVerdict")] public string PolicyVerdict { get; init; } = "unknown"; [JsonPropertyName("signed")] public bool Signed { get; init; } [JsonPropertyName("hasSbomReferrers")] public bool HasSbomReferrers { get; init; } [JsonPropertyName("hasSbom")] public bool HasSbomLegacy { get; init; } [JsonPropertyName("reasons")] public IReadOnlyList Reasons { get; init; } = Array.Empty(); [JsonPropertyName("rekor")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public RuntimePolicyRekorDto? Rekor { get; init; } [JsonPropertyName("confidence")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public double? Confidence { get; init; } [JsonPropertyName("quieted")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Quieted { get; init; } [JsonPropertyName("quietedBy")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? QuietedBy { get; init; } [JsonPropertyName("metadata")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Metadata { get; init; } [JsonPropertyName("buildIds")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IReadOnlyList? BuildIds { get; init; } [JsonPropertyName("linksets")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IReadOnlyList? Linksets { get; init; } } public sealed record RuntimePolicyRekorDto { [JsonPropertyName("uuid")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Uuid { get; init; } [JsonPropertyName("url")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Url { get; init; } [JsonPropertyName("verified")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Verified { get; init; } } /// /// Request for policy overlays on graph nodes (for Cartographer integration). /// public sealed record PolicyOverlayRequestDto { [JsonPropertyName("tenant")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Tenant { get; init; } [JsonPropertyName("nodes")] public IReadOnlyList Nodes { get; init; } = Array.Empty(); [JsonPropertyName("overlayKind")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? OverlayKind { get; init; } [JsonPropertyName("includeEvidence")] public bool IncludeEvidence { get; init; } } /// /// A graph node for policy overlay evaluation. /// public sealed record PolicyOverlayNodeDto { [JsonPropertyName("nodeId")] public string NodeId { get; init; } = string.Empty; [JsonPropertyName("nodeType")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? NodeType { get; init; } [JsonPropertyName("purl")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Purl { get; init; } [JsonPropertyName("imageDigest")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? ImageDigest { get; init; } [JsonPropertyName("advisoryKey")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? AdvisoryKey { get; init; } } /// /// Response containing policy overlays for graph nodes. /// public sealed record PolicyOverlayResponseDto { [JsonPropertyName("tenant")] public string Tenant { get; init; } = string.Empty; [JsonPropertyName("generatedAt")] public DateTimeOffset GeneratedAt { get; init; } [JsonPropertyName("policyRevision")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? PolicyRevision { get; init; } [JsonPropertyName("overlays")] public IReadOnlyList Overlays { get; init; } = Array.Empty(); } /// /// A single policy overlay for a graph node with deterministic ID. /// public sealed record PolicyOverlayDto { [JsonPropertyName("overlayId")] public string OverlayId { get; init; } = string.Empty; [JsonPropertyName("nodeId")] public string NodeId { get; init; } = string.Empty; [JsonPropertyName("overlayKind")] public string OverlayKind { get; init; } = "policy.overlay.v1"; [JsonPropertyName("verdict")] public string Verdict { get; init; } = "unknown"; [JsonPropertyName("reasons")] public IReadOnlyList Reasons { get; init; } = Array.Empty(); [JsonPropertyName("confidence")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public double? Confidence { get; init; } [JsonPropertyName("quieted")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public bool? Quieted { get; init; } [JsonPropertyName("evidence")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public PolicyOverlayEvidenceDto? Evidence { get; init; } } /// /// Runtime evidence attached to a policy overlay. /// public sealed record PolicyOverlayEvidenceDto { [JsonPropertyName("signed")] public bool Signed { get; init; } [JsonPropertyName("hasSbomReferrers")] public bool HasSbomReferrers { get; init; } [JsonPropertyName("rekor")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public RuntimePolicyRekorDto? Rekor { get; init; } [JsonPropertyName("buildIds")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IReadOnlyList? BuildIds { get; init; } [JsonPropertyName("metadata")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IReadOnlyDictionary? Metadata { get; init; } }