feat: Add VEX compact fixture and implement offline verifier for Findings Ledger exports
- Introduced a new VEX compact fixture for testing purposes. - Implemented `verify_export.py` script to validate Findings Ledger exports, ensuring deterministic ordering and applying redaction manifests. - Added a lightweight stub `HarnessRunner` for unit tests to validate ledger hashing expectations. - Documented tasks related to the Mirror Creator. - Created models for entropy signals and implemented the `EntropyPenaltyCalculator` to compute penalties based on scanner outputs. - Developed unit tests for `EntropyPenaltyCalculator` to ensure correct penalty calculations and handling of edge cases. - Added tests for symbol ID normalization in the reachability scanner. - Enhanced console status service with comprehensive unit tests for connection handling and error recovery. - Included Cosign tool version 2.6.0 with checksums for various platforms.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Concelier.Models.Observations;
|
||||
|
||||
@@ -29,6 +31,24 @@ public sealed class AdvisoryObservationWriteGuard : IAdvisoryObservationWriteGua
|
||||
ArgumentNullException.ThrowIfNull(observation);
|
||||
|
||||
var newContentHash = observation.Upstream.ContentHash;
|
||||
var signature = observation.Upstream.Signature;
|
||||
|
||||
if (!IsSha256(newContentHash))
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Observation {ObservationId} rejected: content hash must be canonical sha256:<hex64> but was {ContentHash}",
|
||||
observation.ObservationId,
|
||||
newContentHash);
|
||||
return ObservationWriteDisposition.RejectInvalidProvenance;
|
||||
}
|
||||
|
||||
if (!SignatureShapeIsValid(signature))
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Observation {ObservationId} rejected: signature metadata missing or inconsistent for provenance enforcement",
|
||||
observation.ObservationId);
|
||||
return ObservationWriteDisposition.RejectInvalidProvenance;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(existingContentHash))
|
||||
{
|
||||
@@ -56,4 +76,36 @@ public sealed class AdvisoryObservationWriteGuard : IAdvisoryObservationWriteGua
|
||||
|
||||
return ObservationWriteDisposition.RejectMutation;
|
||||
}
|
||||
|
||||
private static bool IsSha256(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return value.StartsWith("sha256:", StringComparison.OrdinalIgnoreCase)
|
||||
&& value.Length == "sha256:".Length + 64
|
||||
&& value["sha256:".Length..].All(c => Uri.IsHexDigit(c));
|
||||
}
|
||||
|
||||
private static bool SignatureShapeIsValid(AdvisoryObservationSignature signature)
|
||||
{
|
||||
if (signature is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (signature.Present)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(signature.Format)
|
||||
&& !string.IsNullOrWhiteSpace(signature.KeyId)
|
||||
&& !string.IsNullOrWhiteSpace(signature.Signature);
|
||||
}
|
||||
|
||||
// When signature is not present, auxiliary fields must be empty to prevent stale metadata.
|
||||
return string.IsNullOrEmpty(signature.Format)
|
||||
&& string.IsNullOrEmpty(signature.KeyId)
|
||||
&& string.IsNullOrEmpty(signature.Signature);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,11 @@ public enum ObservationWriteDisposition
|
||||
/// </summary>
|
||||
SkipIdentical,
|
||||
|
||||
/// <summary>
|
||||
/// Observation is malformed (missing provenance/signature/hash guarantees) and must be rejected.
|
||||
/// </summary>
|
||||
RejectInvalidProvenance,
|
||||
|
||||
/// <summary>
|
||||
/// Observation differs from existing - reject mutation (append-only violation).
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user