stabilize tests
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# StellaOps.Attestor.Conformance.Tests Task Board
|
||||
This board mirrors active sprint tasks for this module.
|
||||
Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_solid_review.md`.
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Attestor/__Tests/StellaOps.Attestor.Conformance.Tests/StellaOps.Attestor.Conformance.Tests.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
@@ -0,0 +1,8 @@
|
||||
# StellaOps.Attestor.EvidencePack.IntegrationTests Task Board
|
||||
This board mirrors active sprint tasks for this module.
|
||||
Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_solid_review.md`.
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Attestor/__Tests/StellaOps.Attestor.EvidencePack.IntegrationTests/StellaOps.Attestor.EvidencePack.IntegrationTests.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
@@ -0,0 +1,8 @@
|
||||
# StellaOps.Attestor.EvidencePack.Tests Task Board
|
||||
This board mirrors active sprint tasks for this module.
|
||||
Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_solid_review.md`.
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Attestor/__Tests/StellaOps.Attestor.EvidencePack.Tests/StellaOps.Attestor.EvidencePack.Tests.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
@@ -0,0 +1,8 @@
|
||||
# StellaOps.Attestor.FixChain.Tests Task Board
|
||||
This board mirrors active sprint tasks for this module.
|
||||
Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_solid_review.md`.
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Attestor/__Tests/StellaOps.Attestor.FixChain.Tests/StellaOps.Attestor.FixChain.Tests.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
@@ -0,0 +1,8 @@
|
||||
# StellaOps.Attestor.GraphRoot.Tests Task Board
|
||||
This board mirrors active sprint tasks for this module.
|
||||
Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_solid_review.md`.
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Attestor/__Tests/StellaOps.Attestor.GraphRoot.Tests/StellaOps.Attestor.GraphRoot.Tests.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
## Required Reading (treat as read before DOING)
|
||||
- `docs/modules/attestor/architecture.md`
|
||||
- `docs/product/advisories/14-Dec-2025 - Proof and Evidence Chain Technical Reference.md`
|
||||
- `docs-archived/product/advisories/2025-12-21-moat-gap-closure/14-Dec-2025 - Proof and Evidence Chain Technical Reference.md`
|
||||
- RFC 8785 (JSON Canonicalization Scheme)
|
||||
- Relevant sprint files.
|
||||
|
||||
@@ -20,3 +20,4 @@
|
||||
## Testing
|
||||
- Use xUnit + FluentAssertions + TestKit; prefer deterministic data.
|
||||
- Cover canonicalization numeric edge cases, schema validation, and proof signing/verification.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
## Required Reading (treat as read before DOING)
|
||||
- `docs/modules/attestor/architecture.md`
|
||||
- `docs/product/advisories/14-Dec-2025 - Proof and Evidence Chain Technical Reference.md`
|
||||
- `docs-archived/product/advisories/2025-12-21-moat-gap-closure/14-Dec-2025 - Proof and Evidence Chain Technical Reference.md`
|
||||
- RFC 8785 (JSON Canonicalization Scheme)
|
||||
- SPDX 3.0.1, CycloneDX 1.6/1.7, and SLSA provenance v1.0 references
|
||||
- Relevant sprint files.
|
||||
@@ -21,3 +21,4 @@
|
||||
## Testing
|
||||
- Use xUnit + FluentAssertions + TestKit; prefer deterministic data.
|
||||
- Cover canonicalization numeric edge cases, parser warnings/errors, and SBOM hash determinism.
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ public sealed class GeneratorOutputTests
|
||||
["stellaops-path-witness.v1.schema.json"] = "https://stella.ops/schemas/predicates/path-witness/v1",
|
||||
["uncertainty-budget-statement.v1.schema.json"] = "https://stella-ops.org/schemas/attestation/uncertainty-budget-statement.v1.json",
|
||||
["uncertainty-statement.v1.schema.json"] = "https://stella-ops.org/schemas/attestation/uncertainty-statement.v1.json",
|
||||
["stellaops-binary-micro-witness.v1.schema.json"] = "https://stellaops.dev/schemas/predicates/binary-micro-witness.v1.schema.json",
|
||||
["verification-policy.v1.schema.json"] = "https://stellaops.io/schemas/verification-policy.v1.json"
|
||||
};
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ public sealed class PatternCompilerTests
|
||||
public void Performance_Match100EntriesUnder1Ms()
|
||||
{
|
||||
// Pre-compile 100 patterns of various modes
|
||||
var patterns = new List<ICompiledPattern>();
|
||||
var patterns = new List<CompiledPattern>();
|
||||
for (int i = 0; i < 25; i++)
|
||||
{
|
||||
patterns.Add(_compiler.Compile($"issuer-{i}", WatchlistMatchMode.Exact));
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Attestor.Watchlist.Events;
|
||||
using StellaOps.Attestor.Watchlist.Matching;
|
||||
using StellaOps.Attestor.Watchlist.Models;
|
||||
@@ -35,19 +35,18 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
_dedupRepository = new InMemoryAlertDedupRepository();
|
||||
_alertPublisher = new InMemoryIdentityAlertPublisher();
|
||||
|
||||
var cache = new MemoryCache(new MemoryCacheOptions());
|
||||
var patternCompiler = new PatternCompiler();
|
||||
|
||||
_matcher = new IdentityMatcher(
|
||||
_watchlistRepository,
|
||||
patternCompiler,
|
||||
cache,
|
||||
NullLogger<IdentityMatcher>.Instance);
|
||||
|
||||
_service = new IdentityMonitorService(
|
||||
_matcher,
|
||||
_dedupRepository,
|
||||
_alertPublisher,
|
||||
Options.Create(new WatchlistMonitorOptions()),
|
||||
NullLogger<IdentityMonitorService>.Instance);
|
||||
}
|
||||
|
||||
@@ -79,20 +78,17 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 99999,
|
||||
ArtifactSha256 = "sha256:abcdef123456",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://token.actions.githubusercontent.com",
|
||||
SubjectAlternativeName = "repo:org/repo:ref:refs/heads/main"
|
||||
}
|
||||
SignerIssuer = "https://token.actions.githubusercontent.com",
|
||||
SignerSan = "repo:org/repo:ref:refs/heads/main"
|
||||
};
|
||||
|
||||
// Act
|
||||
await _service.ProcessEntryAsync(entryInfo, CancellationToken.None);
|
||||
|
||||
// Assert: Alert should be emitted
|
||||
_alertPublisher.PublishedEvents.Should().HaveCount(1);
|
||||
_alertPublisher.GetEvents().Should().HaveCount(1);
|
||||
|
||||
var alert = _alertPublisher.PublishedEvents[0];
|
||||
var alert = _alertPublisher.GetEvents()[0];
|
||||
alert.EventKind.Should().Be(IdentityAlertEventKinds.IdentityMatched);
|
||||
alert.TenantId.Should().Be("tenant-1");
|
||||
alert.WatchlistEntryId.Should().Be(watchlistEntry.Id);
|
||||
@@ -131,18 +127,15 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 99998,
|
||||
ArtifactSha256 = "sha256:different123",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://accounts.google.com", // Different issuer
|
||||
SubjectAlternativeName = "user@example.com"
|
||||
}
|
||||
SignerIssuer = "https://accounts.google.com", // Different issuer
|
||||
SignerSan = "user@example.com"
|
||||
};
|
||||
|
||||
// Act
|
||||
await _service.ProcessEntryAsync(entryInfo, CancellationToken.None);
|
||||
|
||||
// Assert: No alert should be emitted
|
||||
_alertPublisher.PublishedEvents.Should().BeEmpty();
|
||||
_alertPublisher.GetEvents().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -173,10 +166,7 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 99997,
|
||||
ArtifactSha256 = "sha256:first123",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://token.actions.githubusercontent.com"
|
||||
}
|
||||
SignerIssuer = "https://token.actions.githubusercontent.com"
|
||||
};
|
||||
|
||||
// Act: Process the same identity twice
|
||||
@@ -190,16 +180,13 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 99996,
|
||||
ArtifactSha256 = "sha256:second123",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://token.actions.githubusercontent.com"
|
||||
}
|
||||
SignerIssuer = "https://token.actions.githubusercontent.com"
|
||||
};
|
||||
await _service.ProcessEntryAsync(entryInfo2, CancellationToken.None);
|
||||
|
||||
// Assert: Only first alert should be emitted (second is suppressed)
|
||||
_alertPublisher.PublishedEvents.Should().HaveCount(1);
|
||||
_alertPublisher.PublishedEvents[0].RekorEntry.Uuid.Should().Be("test-rekor-uuid-789");
|
||||
_alertPublisher.GetEvents().Should().HaveCount(1);
|
||||
_alertPublisher.GetEvents()[0].RekorEntry.Uuid.Should().Be("test-rekor-uuid-789");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -231,19 +218,16 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 12345,
|
||||
ArtifactSha256 = "sha256:glob123",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://token.actions.githubusercontent.com",
|
||||
SubjectAlternativeName = "repo:org/my-repo:ref:refs/heads/main"
|
||||
}
|
||||
SignerIssuer = "https://token.actions.githubusercontent.com",
|
||||
SignerSan = "repo:org/my-repo:ref:refs/heads/main"
|
||||
};
|
||||
|
||||
// Act
|
||||
await _service.ProcessEntryAsync(entryInfo, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
_alertPublisher.PublishedEvents.Should().HaveCount(1);
|
||||
_alertPublisher.PublishedEvents[0].MatchedIdentity.SubjectAlternativeName
|
||||
_alertPublisher.GetEvents().Should().HaveCount(1);
|
||||
_alertPublisher.GetEvents()[0].MatchedIdentity.SubjectAlternativeName
|
||||
.Should().Be("repo:org/my-repo:ref:refs/heads/main");
|
||||
}
|
||||
|
||||
@@ -274,17 +258,14 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 11111,
|
||||
ArtifactSha256 = "sha256:disabled123",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://token.actions.githubusercontent.com"
|
||||
}
|
||||
SignerIssuer = "https://token.actions.githubusercontent.com"
|
||||
};
|
||||
|
||||
// Act
|
||||
await _service.ProcessEntryAsync(entryInfo, CancellationToken.None);
|
||||
|
||||
// Assert: No alert (entry is disabled)
|
||||
_alertPublisher.PublishedEvents.Should().BeEmpty();
|
||||
_alertPublisher.GetEvents().Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -315,17 +296,14 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 22222,
|
||||
ArtifactSha256 = "sha256:global123",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://token.actions.githubusercontent.com"
|
||||
}
|
||||
SignerIssuer = "https://token.actions.githubusercontent.com"
|
||||
};
|
||||
|
||||
// Act
|
||||
await _service.ProcessEntryAsync(entryInfo, CancellationToken.None);
|
||||
|
||||
// Assert: Global entry should match across tenants
|
||||
_alertPublisher.PublishedEvents.Should().HaveCount(1);
|
||||
_alertPublisher.GetEvents().Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -370,31 +348,15 @@ public sealed class IdentityMonitorServiceIntegrationTests
|
||||
LogIndex = 33333,
|
||||
ArtifactSha256 = "sha256:multi123",
|
||||
IntegratedTimeUtc = DateTimeOffset.UtcNow,
|
||||
Identity = new SignerIdentityInput
|
||||
{
|
||||
Issuer = "https://token.actions.githubusercontent.com"
|
||||
}
|
||||
SignerIssuer = "https://token.actions.githubusercontent.com"
|
||||
};
|
||||
|
||||
// Act
|
||||
await _service.ProcessEntryAsync(entryInfo, CancellationToken.None);
|
||||
|
||||
// Assert: Both entries should match and emit alerts
|
||||
_alertPublisher.PublishedEvents.Should().HaveCount(2);
|
||||
_alertPublisher.PublishedEvents.Should().Contain(e => e.WatchlistEntryName == "GitHub Watcher 1");
|
||||
_alertPublisher.PublishedEvents.Should().Contain(e => e.WatchlistEntryName == "GitHub Watcher 2");
|
||||
_alertPublisher.GetEvents().Should().HaveCount(2);
|
||||
_alertPublisher.GetEvents().Should().Contain(e => e.WatchlistEntryName == "GitHub Watcher 1");
|
||||
_alertPublisher.GetEvents().Should().Contain(e => e.WatchlistEntryName == "GitHub Watcher 2");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test helper: Attestor entry information for processing.
|
||||
/// </summary>
|
||||
public sealed record AttestorEntryInfo
|
||||
{
|
||||
public required string TenantId { get; init; }
|
||||
public required string RekorUuid { get; init; }
|
||||
public required long LogIndex { get; init; }
|
||||
public required string ArtifactSha256 { get; init; }
|
||||
public required DateTimeOffset IntegratedTimeUtc { get; init; }
|
||||
public required SignerIdentityInput Identity { get; init; }
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Npgsql;
|
||||
using StellaOps.Attestor.Infrastructure.Watchlist;
|
||||
using StellaOps.Attestor.Watchlist.Models;
|
||||
using StellaOps.Attestor.Watchlist.Storage;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Attestor.Watchlist.Tests.Storage;
|
||||
@@ -200,7 +199,7 @@ public sealed class PostgresAlertDedupRepositoryTests : IAsyncLifetime
|
||||
var result = await _repository.CheckAndUpdateAsync(
|
||||
created.Id, "test-identity-hash", 60, CancellationToken.None);
|
||||
|
||||
result.ShouldSend.Should().BeTrue();
|
||||
result.ShouldSuppress.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Npgsql;
|
||||
using Testcontainers.PostgreSql;
|
||||
using Xunit;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace StellaOps.Attestor.Watchlist.Tests.Storage;
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# StellaOps.Attestor.Watchlist.Tests Task Board
|
||||
This board mirrors active sprint tasks for this module.
|
||||
Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_solid_review.md`.
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Attestor/__Tests/StellaOps.Attestor.Watchlist.Tests/StellaOps.Attestor.Watchlist.Tests.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
Reference in New Issue
Block a user