audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories
This commit is contained in:
@@ -4,7 +4,7 @@ namespace StellaOps.Policy.Determinization.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Context for determinization evaluation.
|
||||
/// Contains environment, criticality, and policy settings.
|
||||
/// Contains environment, criticality, policy settings, and computed evidence data.
|
||||
/// </summary>
|
||||
public sealed record DeterminizationContext
|
||||
{
|
||||
@@ -18,56 +18,116 @@ public sealed record DeterminizationContext
|
||||
/// Asset criticality level.
|
||||
/// </summary>
|
||||
[JsonPropertyName("criticality")]
|
||||
public required AssetCriticality Criticality { get; init; }
|
||||
public AssetCriticality Criticality { get; init; } = AssetCriticality.Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Entropy threshold for this context.
|
||||
/// Observations above this trigger guardrails.
|
||||
/// </summary>
|
||||
[JsonPropertyName("entropy_threshold")]
|
||||
public required double EntropyThreshold { get; init; }
|
||||
public double EntropyThreshold { get; init; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// Decay threshold for this context.
|
||||
/// Observations below this are considered stale.
|
||||
/// </summary>
|
||||
[JsonPropertyName("decay_threshold")]
|
||||
public required double DecayThreshold { get; init; }
|
||||
public double DecayThreshold { get; init; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// Creates context with default production settings.
|
||||
/// Signal snapshot containing evidence from various sources.
|
||||
/// </summary>
|
||||
public static DeterminizationContext Production() => new()
|
||||
{
|
||||
Environment = DeploymentEnvironment.Production,
|
||||
Criticality = AssetCriticality.High,
|
||||
EntropyThreshold = 0.4,
|
||||
DecayThreshold = 0.50
|
||||
};
|
||||
[JsonPropertyName("signal_snapshot")]
|
||||
public required SignalSnapshot SignalSnapshot { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates context with relaxed development settings.
|
||||
/// Calculated uncertainty score for this context.
|
||||
/// </summary>
|
||||
public static DeterminizationContext Development() => new()
|
||||
{
|
||||
Environment = DeploymentEnvironment.Development,
|
||||
Criticality = AssetCriticality.Low,
|
||||
EntropyThreshold = 0.6,
|
||||
DecayThreshold = 0.35
|
||||
};
|
||||
[JsonPropertyName("uncertainty_score")]
|
||||
public required UncertaintyScore UncertaintyScore { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates context with custom thresholds.
|
||||
/// Observation decay information.
|
||||
/// </summary>
|
||||
[JsonPropertyName("decay")]
|
||||
public required ObservationDecay Decay { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Aggregated trust score (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("trust_score")]
|
||||
public required double TrustScore { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates context with default production settings and placeholder signal data.
|
||||
/// </summary>
|
||||
public static DeterminizationContext Production(
|
||||
SignalSnapshot? snapshot = null,
|
||||
UncertaintyScore? uncertaintyScore = null,
|
||||
ObservationDecay? decay = null,
|
||||
double trustScore = 0.5)
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
return new()
|
||||
{
|
||||
Environment = DeploymentEnvironment.Production,
|
||||
Criticality = AssetCriticality.High,
|
||||
EntropyThreshold = 0.4,
|
||||
DecayThreshold = 0.50,
|
||||
SignalSnapshot = snapshot ?? SignalSnapshot.Empty("CVE-0000-0000", "pkg:unknown/unknown@0.0.0", now),
|
||||
UncertaintyScore = uncertaintyScore ?? UncertaintyScore.Zero(1.0, now),
|
||||
Decay = decay ?? ObservationDecay.Fresh(now),
|
||||
TrustScore = trustScore
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates context with relaxed development settings and placeholder signal data.
|
||||
/// </summary>
|
||||
public static DeterminizationContext Development(
|
||||
SignalSnapshot? snapshot = null,
|
||||
UncertaintyScore? uncertaintyScore = null,
|
||||
ObservationDecay? decay = null,
|
||||
double trustScore = 0.5)
|
||||
{
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
return new()
|
||||
{
|
||||
Environment = DeploymentEnvironment.Development,
|
||||
Criticality = AssetCriticality.Low,
|
||||
EntropyThreshold = 0.6,
|
||||
DecayThreshold = 0.35,
|
||||
SignalSnapshot = snapshot ?? SignalSnapshot.Empty("CVE-0000-0000", "pkg:unknown/unknown@0.0.0", now),
|
||||
UncertaintyScore = uncertaintyScore ?? UncertaintyScore.Zero(1.0, now),
|
||||
Decay = decay ?? ObservationDecay.Fresh(now),
|
||||
TrustScore = trustScore
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates context with custom thresholds and placeholder signal data.
|
||||
/// </summary>
|
||||
public static DeterminizationContext Create(
|
||||
DeploymentEnvironment environment,
|
||||
AssetCriticality criticality,
|
||||
double entropyThreshold,
|
||||
double decayThreshold) => new()
|
||||
double decayThreshold,
|
||||
SignalSnapshot? snapshot = null,
|
||||
UncertaintyScore? uncertaintyScore = null,
|
||||
ObservationDecay? decay = null,
|
||||
double trustScore = 0.5)
|
||||
{
|
||||
Environment = environment,
|
||||
Criticality = criticality,
|
||||
EntropyThreshold = entropyThreshold,
|
||||
DecayThreshold = decayThreshold
|
||||
};
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
return new()
|
||||
{
|
||||
Environment = environment,
|
||||
Criticality = criticality,
|
||||
EntropyThreshold = entropyThreshold,
|
||||
DecayThreshold = decayThreshold,
|
||||
SignalSnapshot = snapshot ?? SignalSnapshot.Empty("CVE-0000-0000", "pkg:unknown/unknown@0.0.0", now),
|
||||
UncertaintyScore = uncertaintyScore ?? UncertaintyScore.Zero(1.0, now),
|
||||
Decay = decay ?? ObservationDecay.Fresh(now),
|
||||
TrustScore = trustScore
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,22 @@ public sealed record GuardRails
|
||||
[JsonPropertyName("notes")]
|
||||
public string? Notes { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Default guardrails instance with safe settings.
|
||||
/// </summary>
|
||||
public static GuardRails Default { get; } = new()
|
||||
{
|
||||
EnableMonitoring = true,
|
||||
RestrictToNonProd = false,
|
||||
RequireApproval = false,
|
||||
ReevalAfter = TimeSpan.FromDays(7),
|
||||
Notes = null
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Creates GuardRails with default safe settings.
|
||||
/// </summary>
|
||||
public static GuardRails Default() => new()
|
||||
public static GuardRails CreateDefault() => new()
|
||||
{
|
||||
EnableMonitoring = true,
|
||||
RestrictToNonProd = false,
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Text.Json.Serialization;
|
||||
namespace StellaOps.Policy.Determinization.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Per-observation decay configuration.
|
||||
/// Per-observation decay configuration and computed state.
|
||||
/// Tracks evidence staleness with configurable half-life.
|
||||
/// Formula: decayed = max(floor, exp(-ln(2) * age_days / half_life_days))
|
||||
/// </summary>
|
||||
@@ -13,27 +13,27 @@ public sealed record ObservationDecay
|
||||
/// When the observation was first recorded (UTC).
|
||||
/// </summary>
|
||||
[JsonPropertyName("observed_at")]
|
||||
public required DateTimeOffset ObservedAt { get; init; }
|
||||
public DateTimeOffset ObservedAt { get; init; } = DateTimeOffset.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// When the observation was last refreshed (UTC).
|
||||
/// </summary>
|
||||
[JsonPropertyName("refreshed_at")]
|
||||
public required DateTimeOffset RefreshedAt { get; init; }
|
||||
public DateTimeOffset RefreshedAt { get; init; } = DateTimeOffset.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Half-life in days.
|
||||
/// Default: 14 days.
|
||||
/// </summary>
|
||||
[JsonPropertyName("half_life_days")]
|
||||
public required double HalfLifeDays { get; init; }
|
||||
public double HalfLifeDays { get; init; } = 14.0;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum confidence floor.
|
||||
/// Default: 0.35 (consistent with FreshnessCalculator).
|
||||
/// </summary>
|
||||
[JsonPropertyName("floor")]
|
||||
public required double Floor { get; init; }
|
||||
public double Floor { get; init; } = 0.35;
|
||||
|
||||
/// <summary>
|
||||
/// Staleness threshold (0.0-1.0).
|
||||
@@ -41,7 +41,31 @@ public sealed record ObservationDecay
|
||||
/// Default: 0.50
|
||||
/// </summary>
|
||||
[JsonPropertyName("staleness_threshold")]
|
||||
public required double StalenessThreshold { get; init; }
|
||||
public double StalenessThreshold { get; init; } = 0.50;
|
||||
|
||||
/// <summary>
|
||||
/// Last signal update time (alias for RefreshedAt for convenience).
|
||||
/// </summary>
|
||||
[JsonPropertyName("last_signal_update")]
|
||||
public DateTimeOffset LastSignalUpdate { get; init; } = DateTimeOffset.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Age in days since last refresh.
|
||||
/// </summary>
|
||||
[JsonPropertyName("age_days")]
|
||||
public double AgeDays { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Pre-computed decay multiplier (0.0-1.0).
|
||||
/// </summary>
|
||||
[JsonPropertyName("decayed_multiplier")]
|
||||
public double DecayedMultiplier { get; init; } = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the observation is considered stale.
|
||||
/// </summary>
|
||||
[JsonPropertyName("is_stale")]
|
||||
public bool IsStale { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the current decay multiplier.
|
||||
@@ -59,7 +83,7 @@ public sealed record ObservationDecay
|
||||
/// <summary>
|
||||
/// Returns true if the observation is stale (decay below threshold).
|
||||
/// </summary>
|
||||
public bool IsStale(DateTimeOffset now) =>
|
||||
public bool CheckIsStale(DateTimeOffset now) =>
|
||||
CalculateDecay(now) < StalenessThreshold;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -82,6 +82,12 @@ public sealed record UncertaintyScore
|
||||
[JsonPropertyName("calculated_at")]
|
||||
public required DateTimeOffset CalculatedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Completeness ratio (present_weight / max_weight).
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public double Completeness => MaxWeight > 0 ? PresentWeight / MaxWeight : 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an UncertaintyScore with calculated tier.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user