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