Refactor code structure for improved readability and maintainability; optimize performance in key functions.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using StellaOps.Evidence.Models;
|
||||
using StellaOps.Evidence.Serialization;
|
||||
|
||||
namespace StellaOps.Evidence.Validation;
|
||||
|
||||
public sealed class EvidenceIndexValidator : IEvidenceIndexValidator
|
||||
{
|
||||
public ValidationResult Validate(EvidenceIndex index)
|
||||
{
|
||||
var errors = new List<ValidationError>();
|
||||
|
||||
if (index.Sboms.Length == 0)
|
||||
{
|
||||
errors.Add(new ValidationError("Sboms", "At least one SBOM required"));
|
||||
}
|
||||
|
||||
foreach (var vex in index.VexDocuments)
|
||||
{
|
||||
if (vex.StatementCount == 0)
|
||||
{
|
||||
errors.Add(new ValidationError("VexDocuments", $"VEX {vex.VexId} has no statements"));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var proof in index.ReachabilityProofs)
|
||||
{
|
||||
if (proof.Status == ReachabilityStatus.Inconclusive &&
|
||||
!index.Unknowns.Any(u => u.VulnerabilityId == proof.VulnerabilityId))
|
||||
{
|
||||
errors.Add(new ValidationError("ReachabilityProofs",
|
||||
$"Inconclusive reachability for {proof.VulnerabilityId} not recorded as unknown"));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var att in index.Attestations)
|
||||
{
|
||||
if (!att.SignatureValid)
|
||||
{
|
||||
errors.Add(new ValidationError("Attestations",
|
||||
$"Attestation {att.AttestationId} has invalid signature"));
|
||||
}
|
||||
}
|
||||
|
||||
if (index.IndexDigest is not null)
|
||||
{
|
||||
var computed = EvidenceIndexSerializer.ComputeDigest(index);
|
||||
if (!string.Equals(computed, index.IndexDigest, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
errors.Add(new ValidationError("IndexDigest", "Digest mismatch"));
|
||||
}
|
||||
}
|
||||
|
||||
return new ValidationResult(errors.Count == 0, errors);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IEvidenceIndexValidator
|
||||
{
|
||||
ValidationResult Validate(EvidenceIndex index);
|
||||
}
|
||||
|
||||
public sealed record ValidationResult(bool IsValid, IReadOnlyList<ValidationError> Errors);
|
||||
public sealed record ValidationError(string Field, string Message);
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace StellaOps.Evidence.Validation;
|
||||
|
||||
internal static class SchemaLoader
|
||||
{
|
||||
public static string LoadSchema(string fileName)
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName = assembly.GetManifestResourceNames()
|
||||
.FirstOrDefault(name => name.EndsWith(fileName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (resourceName is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Schema resource not found: {fileName}");
|
||||
}
|
||||
|
||||
using var stream = assembly.GetManifestResourceStream(resourceName);
|
||||
if (stream is null)
|
||||
{
|
||||
throw new InvalidOperationException($"Schema resource not available: {resourceName}");
|
||||
}
|
||||
|
||||
using var reader = new StreamReader(stream);
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user