This commit is contained in:
StellaOps Bot
2025-12-15 09:03:56 +02:00
parent b058dbe031
commit 8c8f0c632d
8 changed files with 423 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
namespace StellaOps.Evidence.Bundle;
/// <summary>Builder for constructing evidence bundles.</summary>
public sealed class EvidenceBundleBuilder
{
private readonly TimeProvider _timeProvider;
private string? _alertId;
private string? _artifactId;
private ReachabilityEvidence? _reachability;
private CallStackEvidence? _callStack;
private ProvenanceEvidence? _provenance;
private VexStatusEvidence? _vexStatus;
private DiffEvidence? _diff;
private GraphRevisionEvidence? _graphRevision;
public EvidenceBundleBuilder(TimeProvider timeProvider)
{
_timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
}
public EvidenceBundleBuilder() : this(TimeProvider.System) { }
public EvidenceBundleBuilder WithAlertId(string alertId) { _alertId = alertId; return this; }
public EvidenceBundleBuilder WithArtifactId(string artifactId) { _artifactId = artifactId; return this; }
public EvidenceBundleBuilder WithReachability(ReachabilityEvidence evidence) { _reachability = evidence; return this; }
public EvidenceBundleBuilder WithCallStack(CallStackEvidence evidence) { _callStack = evidence; return this; }
public EvidenceBundleBuilder WithProvenance(ProvenanceEvidence evidence) { _provenance = evidence; return this; }
public EvidenceBundleBuilder WithVexStatus(VexStatusEvidence evidence) { _vexStatus = evidence; return this; }
public EvidenceBundleBuilder WithDiff(DiffEvidence evidence) { _diff = evidence; return this; }
public EvidenceBundleBuilder WithGraphRevision(GraphRevisionEvidence evidence) { _graphRevision = evidence; return this; }
public EvidenceBundle Build()
{
if (string.IsNullOrWhiteSpace(_alertId))
throw new InvalidOperationException("AlertId is required");
if (string.IsNullOrWhiteSpace(_artifactId))
throw new InvalidOperationException("ArtifactId is required");
var hashes = new Dictionary<string, string>();
if (_reachability?.Hash is not null) hashes["reachability"] = _reachability.Hash;
if (_callStack?.Hash is not null) hashes["callstack"] = _callStack.Hash;
if (_provenance?.Hash is not null) hashes["provenance"] = _provenance.Hash;
if (_vexStatus?.Hash is not null) hashes["vex"] = _vexStatus.Hash;
if (_diff?.Hash is not null) hashes["diff"] = _diff.Hash;
if (_graphRevision?.Hash is not null) hashes["graph"] = _graphRevision.Hash;
return new EvidenceBundle
{
AlertId = _alertId,
ArtifactId = _artifactId,
Reachability = _reachability,
CallStack = _callStack,
Provenance = _provenance,
VexStatus = _vexStatus,
Diff = _diff,
GraphRevision = _graphRevision,
Hashes = hashes.Count > 0 ? EvidenceHashSet.Compute(hashes) : EvidenceHashSet.Empty(),
CreatedAt = _timeProvider.GetUtcNow()
};
}
}