using System.Text.Json.Serialization; namespace StellaOps.Policy.RiskProfile.Models; /// /// Represents a risk profile definition used to score and prioritize findings. /// public sealed class RiskProfileModel { /// /// Stable identifier for the risk profile (slug or URN). /// [JsonPropertyName("id")] public required string Id { get; set; } /// /// SemVer for the profile definition. /// [JsonPropertyName("version")] public required string Version { get; set; } /// /// Human-readable summary of the profile intent. /// [JsonPropertyName("description")] public string? Description { get; set; } /// /// Optional parent profile ID for inheritance. /// [JsonPropertyName("extends")] public string? Extends { get; set; } /// /// Signal definitions used for risk scoring. /// [JsonPropertyName("signals")] public List Signals { get; set; } = new(); /// /// Weight per signal name; weights are normalized by the consumer. /// [JsonPropertyName("weights")] public Dictionary Weights { get; set; } = new(); /// /// Override rules for severity and decisions. /// [JsonPropertyName("overrides")] public RiskOverrides Overrides { get; set; } = new(); /// /// Free-form metadata with stable keys. /// [JsonPropertyName("metadata")] public Dictionary? Metadata { get; set; } } /// /// A signal definition used in risk scoring. /// public sealed class RiskSignal { /// /// Logical signal key (e.g., reachability, kev, exploit_chain). /// [JsonPropertyName("name")] public required string Name { get; set; } /// /// Upstream provider or calculation origin. /// [JsonPropertyName("source")] public required string Source { get; set; } /// /// Signal type. /// [JsonPropertyName("type")] public required RiskSignalType Type { get; set; } /// /// JSON Pointer to the signal in the evidence document. /// [JsonPropertyName("path")] public string? Path { get; set; } /// /// Optional transform applied before weighting. /// [JsonPropertyName("transform")] public string? Transform { get; set; } /// /// Optional unit for numeric signals. /// [JsonPropertyName("unit")] public string? Unit { get; set; } } /// /// Signal type enumeration. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum RiskSignalType { [JsonPropertyName("boolean")] Boolean, [JsonPropertyName("numeric")] Numeric, [JsonPropertyName("categorical")] Categorical, } /// /// Override rules for severity and decisions. /// public sealed class RiskOverrides { /// /// Severity override rules. /// [JsonPropertyName("severity")] public List Severity { get; set; } = new(); /// /// Decision override rules. /// [JsonPropertyName("decisions")] public List Decisions { get; set; } = new(); } /// /// A severity override rule. /// public sealed class SeverityOverride { /// /// Predicate over signals (key/value equals). /// [JsonPropertyName("when")] public required Dictionary When { get; set; } /// /// Severity to set when predicate matches. /// [JsonPropertyName("set")] public required RiskSeverity Set { get; set; } } /// /// A decision override rule. /// public sealed class DecisionOverride { /// /// Predicate over signals (key/value equals). /// [JsonPropertyName("when")] public required Dictionary When { get; set; } /// /// Action to take when predicate matches. /// [JsonPropertyName("action")] public required RiskAction Action { get; set; } /// /// Optional reason for the override. /// [JsonPropertyName("reason")] public string? Reason { get; set; } } /// /// Severity levels. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum RiskSeverity { [JsonPropertyName("critical")] Critical, [JsonPropertyName("high")] High, [JsonPropertyName("medium")] Medium, [JsonPropertyName("low")] Low, [JsonPropertyName("informational")] Informational, } /// /// Decision actions. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum RiskAction { [JsonPropertyName("allow")] Allow, [JsonPropertyName("review")] Review, [JsonPropertyName("deny")] Deny, }