using System.Collections.Immutable; using System.Text.Json.Serialization; using StellaOps.Policy.RiskProfile.Models; namespace StellaOps.Policy.Engine.Simulation; /// /// Detailed breakdown of a risk simulation result. /// Per POLICY-RISK-67-003. /// public sealed record RiskSimulationBreakdown( [property: JsonPropertyName("simulation_id")] string SimulationId, [property: JsonPropertyName("profile_ref")] ProfileReference ProfileRef, [property: JsonPropertyName("signal_analysis")] SignalAnalysis SignalAnalysis, [property: JsonPropertyName("override_analysis")] OverrideAnalysis OverrideAnalysis, [property: JsonPropertyName("score_distribution")] ScoreDistributionAnalysis ScoreDistribution, [property: JsonPropertyName("severity_breakdown")] SeverityBreakdownAnalysis SeverityBreakdown, [property: JsonPropertyName("action_breakdown")] ActionBreakdownAnalysis ActionBreakdown, [property: JsonPropertyName("component_breakdown")] ComponentBreakdownAnalysis? ComponentBreakdown, [property: JsonPropertyName("risk_trends")] RiskTrendAnalysis? RiskTrends, [property: JsonPropertyName("determinism_hash")] string DeterminismHash); /// /// Reference to the risk profile used in simulation. /// public sealed record ProfileReference( [property: JsonPropertyName("id")] string Id, [property: JsonPropertyName("version")] string Version, [property: JsonPropertyName("hash")] string Hash, [property: JsonPropertyName("description")] string? Description, [property: JsonPropertyName("extends")] string? Extends); /// /// Analysis of signal contributions to risk scores. /// public sealed record SignalAnalysis( [property: JsonPropertyName("total_signals")] int TotalSignals, [property: JsonPropertyName("signals_used")] int SignalsUsed, [property: JsonPropertyName("signals_missing")] int SignalsMissing, [property: JsonPropertyName("signal_coverage")] double SignalCoverage, [property: JsonPropertyName("signal_stats")] ImmutableArray SignalStats, [property: JsonPropertyName("top_contributors")] ImmutableArray TopContributors, [property: JsonPropertyName("missing_signal_impact")] MissingSignalImpact MissingSignalImpact); /// /// Statistics for a single signal across all findings. /// public sealed record SignalStatistics( [property: JsonPropertyName("signal_name")] string SignalName, [property: JsonPropertyName("signal_type")] string SignalType, [property: JsonPropertyName("weight")] double Weight, [property: JsonPropertyName("findings_with_signal")] int FindingsWithSignal, [property: JsonPropertyName("findings_missing_signal")] int FindingsMissingSignal, [property: JsonPropertyName("coverage_percentage")] double CoveragePercentage, [property: JsonPropertyName("value_distribution")] ValueDistribution? ValueDistribution, [property: JsonPropertyName("total_contribution")] double TotalContribution, [property: JsonPropertyName("avg_contribution")] double AvgContribution); /// /// Distribution of values for a signal. /// public sealed record ValueDistribution( [property: JsonPropertyName("min")] double? Min, [property: JsonPropertyName("max")] double? Max, [property: JsonPropertyName("mean")] double? Mean, [property: JsonPropertyName("median")] double? Median, [property: JsonPropertyName("std_dev")] double? StdDev, [property: JsonPropertyName("histogram")] ImmutableArray? Histogram); /// /// Histogram bucket for value distribution. /// public sealed record HistogramBucket( [property: JsonPropertyName("range_min")] double RangeMin, [property: JsonPropertyName("range_max")] double RangeMax, [property: JsonPropertyName("count")] int Count, [property: JsonPropertyName("percentage")] double Percentage); /// /// A signal that significantly contributed to risk scores. /// public sealed record SignalContributor( [property: JsonPropertyName("signal_name")] string SignalName, [property: JsonPropertyName("total_contribution")] double TotalContribution, [property: JsonPropertyName("contribution_percentage")] double ContributionPercentage, [property: JsonPropertyName("avg_value")] double AvgValue, [property: JsonPropertyName("weight")] double Weight, [property: JsonPropertyName("impact_direction")] string ImpactDirection); /// /// Impact of missing signals on scoring. /// public sealed record MissingSignalImpact( [property: JsonPropertyName("findings_with_missing_signals")] int FindingsWithMissingSignals, [property: JsonPropertyName("avg_missing_signals_per_finding")] double AvgMissingSignalsPerFinding, [property: JsonPropertyName("estimated_score_impact")] double EstimatedScoreImpact, [property: JsonPropertyName("most_impactful_missing")] ImmutableArray MostImpactfulMissing); /// /// Analysis of override applications. /// public sealed record OverrideAnalysis( [property: JsonPropertyName("total_overrides_evaluated")] int TotalOverridesEvaluated, [property: JsonPropertyName("severity_overrides_applied")] int SeverityOverridesApplied, [property: JsonPropertyName("decision_overrides_applied")] int DecisionOverridesApplied, [property: JsonPropertyName("override_application_rate")] double OverrideApplicationRate, [property: JsonPropertyName("severity_override_details")] ImmutableArray SeverityOverrideDetails, [property: JsonPropertyName("decision_override_details")] ImmutableArray DecisionOverrideDetails, [property: JsonPropertyName("override_conflicts")] ImmutableArray OverrideConflicts); /// /// Details of severity override applications. /// public sealed record SeverityOverrideDetail( [property: JsonPropertyName("predicate_hash")] string PredicateHash, [property: JsonPropertyName("predicate_summary")] string PredicateSummary, [property: JsonPropertyName("target_severity")] string TargetSeverity, [property: JsonPropertyName("applications_count")] int ApplicationsCount, [property: JsonPropertyName("original_severities")] ImmutableDictionary OriginalSeverities); /// /// Details of decision override applications. /// public sealed record DecisionOverrideDetail( [property: JsonPropertyName("predicate_hash")] string PredicateHash, [property: JsonPropertyName("predicate_summary")] string PredicateSummary, [property: JsonPropertyName("target_action")] string TargetAction, [property: JsonPropertyName("reason")] string? Reason, [property: JsonPropertyName("applications_count")] int ApplicationsCount, [property: JsonPropertyName("original_actions")] ImmutableDictionary OriginalActions); /// /// Override conflict detected during evaluation. /// public sealed record OverrideConflict( [property: JsonPropertyName("finding_id")] string FindingId, [property: JsonPropertyName("conflict_type")] string ConflictType, [property: JsonPropertyName("override_1")] string Override1, [property: JsonPropertyName("override_2")] string Override2, [property: JsonPropertyName("resolution")] string Resolution); /// /// Analysis of score distribution. /// public sealed record ScoreDistributionAnalysis( [property: JsonPropertyName("raw_score_stats")] ScoreStatistics RawScoreStats, [property: JsonPropertyName("normalized_score_stats")] ScoreStatistics NormalizedScoreStats, [property: JsonPropertyName("score_buckets")] ImmutableArray ScoreBuckets, [property: JsonPropertyName("percentiles")] ImmutableDictionary Percentiles, [property: JsonPropertyName("outliers")] OutlierAnalysis Outliers); /// /// Statistical summary of scores. /// public sealed record ScoreStatistics( [property: JsonPropertyName("count")] int Count, [property: JsonPropertyName("min")] double Min, [property: JsonPropertyName("max")] double Max, [property: JsonPropertyName("mean")] double Mean, [property: JsonPropertyName("median")] double Median, [property: JsonPropertyName("std_dev")] double StdDev, [property: JsonPropertyName("variance")] double Variance, [property: JsonPropertyName("skewness")] double Skewness, [property: JsonPropertyName("kurtosis")] double Kurtosis); /// /// Score bucket for distribution. /// public sealed record ScoreBucket( [property: JsonPropertyName("range_min")] double RangeMin, [property: JsonPropertyName("range_max")] double RangeMax, [property: JsonPropertyName("label")] string Label, [property: JsonPropertyName("count")] int Count, [property: JsonPropertyName("percentage")] double Percentage); /// /// Outlier analysis for scores. /// public sealed record OutlierAnalysis( [property: JsonPropertyName("outlier_count")] int OutlierCount, [property: JsonPropertyName("outlier_threshold")] double OutlierThreshold, [property: JsonPropertyName("outlier_finding_ids")] ImmutableArray OutlierFindingIds); /// /// Breakdown by severity level. /// public sealed record SeverityBreakdownAnalysis( [property: JsonPropertyName("by_severity")] ImmutableDictionary BySeverity, [property: JsonPropertyName("severity_flow")] ImmutableArray SeverityFlow, [property: JsonPropertyName("severity_concentration")] double SeverityConcentration); /// /// Details for a severity bucket. /// public sealed record SeverityBucket( [property: JsonPropertyName("severity")] string Severity, [property: JsonPropertyName("count")] int Count, [property: JsonPropertyName("percentage")] double Percentage, [property: JsonPropertyName("avg_score")] double AvgScore, [property: JsonPropertyName("score_range")] ScoreRange ScoreRange, [property: JsonPropertyName("top_contributors")] ImmutableArray TopContributors); /// /// Score range for a bucket. /// public sealed record ScoreRange( [property: JsonPropertyName("min")] double Min, [property: JsonPropertyName("max")] double Max); /// /// Flow from original to final severity after overrides. /// public sealed record SeverityFlow( [property: JsonPropertyName("from_severity")] string FromSeverity, [property: JsonPropertyName("to_severity")] string ToSeverity, [property: JsonPropertyName("count")] int Count, [property: JsonPropertyName("is_escalation")] bool IsEscalation); /// /// Breakdown by recommended action. /// public sealed record ActionBreakdownAnalysis( [property: JsonPropertyName("by_action")] ImmutableDictionary ByAction, [property: JsonPropertyName("action_flow")] ImmutableArray ActionFlow, [property: JsonPropertyName("decision_stability")] double DecisionStability); /// /// Details for an action bucket. /// public sealed record ActionBucket( [property: JsonPropertyName("action")] string Action, [property: JsonPropertyName("count")] int Count, [property: JsonPropertyName("percentage")] double Percentage, [property: JsonPropertyName("avg_score")] double AvgScore, [property: JsonPropertyName("severity_breakdown")] ImmutableDictionary SeverityBreakdown); /// /// Flow from original to final action after overrides. /// public sealed record ActionFlow( [property: JsonPropertyName("from_action")] string FromAction, [property: JsonPropertyName("to_action")] string ToAction, [property: JsonPropertyName("count")] int Count); /// /// Breakdown by component/package. /// public sealed record ComponentBreakdownAnalysis( [property: JsonPropertyName("total_components")] int TotalComponents, [property: JsonPropertyName("components_with_findings")] int ComponentsWithFindings, [property: JsonPropertyName("top_risk_components")] ImmutableArray TopRiskComponents, [property: JsonPropertyName("ecosystem_breakdown")] ImmutableDictionary EcosystemBreakdown); /// /// Risk summary for a component. /// public sealed record ComponentRiskSummary( [property: JsonPropertyName("component_purl")] string ComponentPurl, [property: JsonPropertyName("finding_count")] int FindingCount, [property: JsonPropertyName("max_score")] double MaxScore, [property: JsonPropertyName("avg_score")] double AvgScore, [property: JsonPropertyName("highest_severity")] string HighestSeverity, [property: JsonPropertyName("recommended_action")] string RecommendedAction); /// /// Summary for a package ecosystem. /// public sealed record EcosystemSummary( [property: JsonPropertyName("ecosystem")] string Ecosystem, [property: JsonPropertyName("component_count")] int ComponentCount, [property: JsonPropertyName("finding_count")] int FindingCount, [property: JsonPropertyName("avg_score")] double AvgScore, [property: JsonPropertyName("critical_count")] int CriticalCount, [property: JsonPropertyName("high_count")] int HighCount); /// /// Risk trend analysis (for comparison simulations). /// public sealed record RiskTrendAnalysis( [property: JsonPropertyName("comparison_type")] string ComparisonType, [property: JsonPropertyName("score_trend")] TrendMetric ScoreTrend, [property: JsonPropertyName("severity_trend")] TrendMetric SeverityTrend, [property: JsonPropertyName("action_trend")] TrendMetric ActionTrend, [property: JsonPropertyName("findings_improved")] int FindingsImproved, [property: JsonPropertyName("findings_worsened")] int FindingsWorsened, [property: JsonPropertyName("findings_unchanged")] int FindingsUnchanged); /// /// Trend metric for comparison. /// public sealed record TrendMetric( [property: JsonPropertyName("direction")] string Direction, [property: JsonPropertyName("magnitude")] double Magnitude, [property: JsonPropertyName("percentage_change")] double PercentageChange, [property: JsonPropertyName("is_significant")] bool IsSignificant);