old sprints work, new sprints for exposing functionality via cli, improve code_of_conduct and other agents instructions

This commit is contained in:
master
2026-01-15 18:37:59 +02:00
parent c631bacee2
commit 88a85cdd92
208 changed files with 32271 additions and 2287 deletions

View File

@@ -0,0 +1,305 @@
// <copyright file="BinaryDiffEvidenceTests.cs" company="StellaOps">
// SPDX-License-Identifier: AGPL-3.0-or-later
// Sprint: SPRINT_20260112_008_LB_binary_diff_evidence_models (BINDIFF-LB-004)
// </copyright>
using System;
using System.Collections.Immutable;
using Microsoft.Extensions.Time.Testing;
using StellaOps.TestKit;
using Xunit;
namespace StellaOps.Evidence.Bundle.Tests;
[Trait("Category", TestCategories.Unit)]
public sealed class BinaryDiffEvidenceTests
{
private readonly FakeTimeProvider _timeProvider = new(new DateTimeOffset(2026, 1, 15, 10, 30, 0, TimeSpan.Zero));
[Fact]
public void Builder_WithBinaryDiff_IncludesInBundle()
{
// Arrange
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available,
Hash = "sha256:abc123",
PreviousBinaryDigest = "sha256:old123",
CurrentBinaryDigest = "sha256:new456",
DiffType = BinaryDiffType.Semantic,
SimilarityScore = 0.95
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert
Assert.NotNull(bundle.BinaryDiff);
Assert.Equal(EvidenceStatus.Available, bundle.BinaryDiff.Status);
Assert.Equal("sha256:abc123", bundle.BinaryDiff.Hash);
Assert.Equal(0.95, bundle.BinaryDiff.SimilarityScore);
}
[Fact]
public void ComputeCompletenessScore_WithBinaryDiff_IncreasesScore()
{
// Arrange & Act - Bundle without binary diff
var bundleWithout = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithReachability(new ReachabilityEvidence { Status = EvidenceStatus.Available })
.Build();
// Bundle with binary diff
var bundleWith = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-002")
.WithArtifactId("sha256:abc123")
.WithReachability(new ReachabilityEvidence { Status = EvidenceStatus.Available })
.WithBinaryDiff(new BinaryDiffEvidence { Status = EvidenceStatus.Available })
.Build();
// Assert
Assert.True(bundleWith.ComputeCompletenessScore() > bundleWithout.ComputeCompletenessScore());
}
[Fact]
public void StatusSummary_IncludesBinaryDiffStatus()
{
// Arrange
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available,
DiffType = BinaryDiffType.Semantic
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert
var summary = bundle.CreateStatusSummary();
Assert.Equal(EvidenceStatus.Available, summary.BinaryDiff);
}
[Fact]
public void BinaryDiff_FunctionChanges_PreservesDeterministicOrder()
{
// Arrange - Create function changes in unsorted order
var functionChanges = ImmutableArray.Create(
new BinaryFunctionDiff
{
FunctionName = "z_function",
Operation = BinaryDiffOperation.Modified,
PreviousHash = "sha256:old1",
CurrentHash = "sha256:new1"
},
new BinaryFunctionDiff
{
FunctionName = "a_function",
Operation = BinaryDiffOperation.Added,
CurrentHash = "sha256:new2"
},
new BinaryFunctionDiff
{
FunctionName = "m_function",
Operation = BinaryDiffOperation.Removed,
PreviousHash = "sha256:old3"
}
);
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available,
FunctionChanges = functionChanges.Sort((a, b) =>
string.Compare(a.FunctionName, b.FunctionName, StringComparison.Ordinal))
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert - Should be sorted alphabetically
Assert.Equal("a_function", bundle.BinaryDiff!.FunctionChanges[0].FunctionName);
Assert.Equal("m_function", bundle.BinaryDiff.FunctionChanges[1].FunctionName);
Assert.Equal("z_function", bundle.BinaryDiff.FunctionChanges[2].FunctionName);
}
[Fact]
public void BinaryDiff_SecurityChanges_CapturesMitigationChanges()
{
// Arrange
var securityChanges = ImmutableArray.Create(
new BinarySecurityChange
{
ChangeType = BinarySecurityChangeType.MitigationAdded,
Description = "Stack canaries enabled",
AffectedSymbols = ImmutableArray.Create("main", "process_input"),
Severity = "info"
},
new BinarySecurityChange
{
ChangeType = BinarySecurityChangeType.MitigationRemoved,
Description = "ASLR disabled",
Severity = "high"
}
);
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available,
SecurityChanges = securityChanges
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert
Assert.Equal(2, bundle.BinaryDiff!.SecurityChanges.Length);
Assert.Contains(bundle.BinaryDiff.SecurityChanges,
c => c.ChangeType == BinarySecurityChangeType.MitigationAdded);
Assert.Contains(bundle.BinaryDiff.SecurityChanges,
c => c.ChangeType == BinarySecurityChangeType.MitigationRemoved);
}
[Fact]
public void BinaryDiff_SemanticDiff_CapturesFingerprints()
{
// Arrange
var semanticDiff = new BinarySemanticDiff
{
PreviousFingerprint = "fp:abc123",
CurrentFingerprint = "fp:def456",
SimilarityScore = 0.87,
SemanticChanges = ImmutableArray.Create("control_flow_modified", "data_flow_changed")
};
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available,
SemanticDiff = semanticDiff
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert
Assert.NotNull(bundle.BinaryDiff!.SemanticDiff);
Assert.Equal(0.87, bundle.BinaryDiff.SemanticDiff.SimilarityScore);
Assert.Equal(2, bundle.BinaryDiff.SemanticDiff.SemanticChanges.Length);
}
[Fact]
public void BinaryDiff_Unavailable_CapturesReason()
{
// Arrange
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Unavailable,
UnavailableReason = "No previous scan available for comparison"
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert
Assert.Equal(EvidenceStatus.Unavailable, bundle.BinaryDiff!.Status);
Assert.Equal("No previous scan available for comparison", bundle.BinaryDiff.UnavailableReason);
}
[Fact]
public void Hashes_IncludesBinaryDiffHash()
{
// Arrange
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available,
Hash = "binarydiffhash123"
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert
Assert.Contains(bundle.Hashes.Hashes, h => h.Value == "binarydiffhash123");
}
[Fact]
public void BinaryDiff_DiffTypes_AllSupported()
{
// Arrange & Act - Test all diff types
var diffTypes = new[]
{
BinaryDiffType.None,
BinaryDiffType.Structural,
BinaryDiffType.Semantic,
BinaryDiffType.Full
};
foreach (var diffType in diffTypes)
{
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available,
DiffType = diffType
};
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId($"ALERT-{diffType}")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert
Assert.Equal(diffType, bundle.BinaryDiff!.DiffType);
}
}
[Fact]
public void SchemaVersion_UpdatedForBinaryDiff()
{
// Arrange
var binaryDiff = new BinaryDiffEvidence
{
Status = EvidenceStatus.Available
};
// Act
var bundle = new EvidenceBundleBuilder(_timeProvider)
.WithAlertId("ALERT-001")
.WithArtifactId("sha256:abc123")
.WithBinaryDiff(binaryDiff)
.Build();
// Assert - Schema version should be 1.1 or higher when binary diff is included
Assert.True(
bundle.SchemaVersion == "1.1" ||
Version.Parse(bundle.SchemaVersion) >= Version.Parse("1.1"),
$"Expected schema version >= 1.1, got {bundle.SchemaVersion}");
}
}