sprints and audit work
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Policy.Determinization.Models;
|
||||
|
||||
namespace StellaOps.Policy.Engine.Gates.Determinization;
|
||||
|
||||
/// <summary>
|
||||
/// Builds signal snapshots for determinization evaluation by querying signal repositories.
|
||||
/// </summary>
|
||||
public sealed class SignalSnapshotBuilder : ISignalSnapshotBuilder
|
||||
{
|
||||
private readonly ISignalRepository _signalRepository;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly ILogger<SignalSnapshotBuilder> _logger;
|
||||
|
||||
public SignalSnapshotBuilder(
|
||||
ISignalRepository signalRepository,
|
||||
TimeProvider timeProvider,
|
||||
ILogger<SignalSnapshotBuilder> logger)
|
||||
{
|
||||
_signalRepository = signalRepository;
|
||||
_timeProvider = timeProvider;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<SignalSnapshot> BuildAsync(
|
||||
string cveId,
|
||||
string componentPurl,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(cveId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(componentPurl);
|
||||
|
||||
_logger.LogDebug(
|
||||
"Building signal snapshot for CVE {CveId} on {Purl}",
|
||||
cveId,
|
||||
componentPurl);
|
||||
|
||||
var snapshotAt = _timeProvider.GetUtcNow();
|
||||
var subjectKey = BuildSubjectKey(cveId, componentPurl);
|
||||
|
||||
// Query all signals in parallel
|
||||
var signalsTask = _signalRepository.GetSignalsAsync(subjectKey, ct);
|
||||
var signals = await signalsTask;
|
||||
|
||||
// Build snapshot from retrieved signals
|
||||
var snapshot = SignalSnapshot.Empty(cveId, componentPurl, snapshotAt);
|
||||
|
||||
foreach (var signal in signals)
|
||||
{
|
||||
snapshot = ApplySignal(snapshot, signal);
|
||||
}
|
||||
|
||||
_logger.LogDebug(
|
||||
"Built signal snapshot for CVE {CveId} on {Purl}: {SignalCount} signals present",
|
||||
cveId,
|
||||
componentPurl,
|
||||
signals.Count);
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
private static string BuildSubjectKey(string cveId, string componentPurl)
|
||||
=> $"{cveId}::{componentPurl}";
|
||||
|
||||
private SignalSnapshot ApplySignal(SignalSnapshot snapshot, Signal signal)
|
||||
{
|
||||
// This is a placeholder implementation
|
||||
// In a real implementation, this would map Signal objects to SignalState<T> instances
|
||||
// based on signal type and update the appropriate field in the snapshot
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Repository for retrieving signals.
|
||||
/// </summary>
|
||||
public interface ISignalRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all signals for the given subject key.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<Signal>> GetSignalsAsync(string subjectKey, CancellationToken ct = default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a signal retrieved from storage.
|
||||
/// </summary>
|
||||
public sealed record Signal
|
||||
{
|
||||
public required string Type { get; init; }
|
||||
public required string SubjectKey { get; init; }
|
||||
public required DateTimeOffset ObservedAt { get; init; }
|
||||
public required object? Evidence { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user