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,
}