Add tests for SBOM generation determinism across multiple formats

- Created `StellaOps.TestKit.Tests` project for unit tests related to determinism.
- Implemented `DeterminismManifestTests` to validate deterministic output for canonical bytes and strings, file read/write operations, and error handling for invalid schema versions.
- Added `SbomDeterminismTests` to ensure identical inputs produce consistent SBOMs across SPDX 3.0.1 and CycloneDX 1.6/1.7 formats, including parallel execution tests.
- Updated project references in `StellaOps.Integration.Determinism` to include the new determinism testing library.
This commit is contained in:
master
2025-12-23 18:56:12 +02:00
committed by StellaOps Bot
parent 7ac70ece71
commit 5590a99a1a
381 changed files with 21071 additions and 14678 deletions

View File

@@ -0,0 +1,119 @@
# Architecture Enforcement Rules
This document describes the automated architecture rules enforced by `tests/architecture/StellaOps.Architecture.Tests`. These rules run on every PR and gate merges, ensuring consistent adherence to StellaOps architectural boundaries.
## Overview
Architecture tests use [NetArchTest.Rules](https://github.com/BenMorris/NetArchTest) to enforce structural constraints at compile time. Rules are categorized into four areas:
1. **Lattice Engine Placement** Ensures lattice/scoring logic stays in Scanner
2. **Module Dependencies** Enforces proper layering between Core, Storage, WebServices, and Workers
3. **Forbidden Packages** Blocks deprecated or non-compliant dependencies
4. **Naming Conventions** Ensures consistent project/assembly naming
---
## 1. Lattice Engine Placement Rules
**Purpose**: The lattice engine computes vulnerability scoring, VEX decisions, and reachability proofs. These computations must remain in Scanner to preserve "prune at source" semantics—no other module should re-derive decisions.
| Rule ID | Description | Assemblies Affected | Enforcement |
|---------|-------------|---------------------|-------------|
| `Lattice_Concelier_NoReference` | Concelier assemblies must NOT reference Scanner lattice engine | `StellaOps.Concelier.*` | Fail if any reference to `StellaOps.Scanner.Lattice` |
| `Lattice_Excititor_NoReference` | Excititor assemblies must NOT reference Scanner lattice engine | `StellaOps.Excititor.*` | Fail if any reference to `StellaOps.Scanner.Lattice` |
| `Lattice_Scanner_MayReference` | Scanner.WebService MAY reference Scanner lattice engine | `StellaOps.Scanner.WebService` | Allowed (no constraint) |
| `Lattice_PreservePruneSource` | Excititor does not compute lattice decisions (verified via type search) | `StellaOps.Excititor.*` | Fail if types named `*LatticeEngine*`, `*VexDecision*`, or `*ScoreCalculator*` exist |
**Rationale**: If Excititor or Concelier computed their own lattice decisions, findings could drift from Scanner's authoritative scoring. Downstream consumers must accept pre-computed verdicts.
---
## 2. Module Dependency Rules
**Purpose**: Enforce clean architecture layering. Core business logic must not depend on infrastructure; services must not cross-call each other.
| Rule ID | Description | Source | Forbidden Target |
|---------|-------------|--------|------------------|
| `Dependency_Core_NoInfrastructure` | Core libraries must not depend on infrastructure | `*.Core` | `*.Storage.*`, `*.Postgres`, `*.WebService` |
| `Dependency_WebService_NoWebService` | WebServices may not depend on other WebServices | `*.WebService` | Other `*.WebService` assemblies |
| `Dependency_Worker_NoWebService` | Workers must not depend directly on WebServices | `*.Worker` | `*.WebService` |
**Rationale**:
- Core libraries define contracts and business rules; they must remain portable.
- WebServices should communicate via HTTP/gRPC, not direct assembly references.
- Workers may share Core and Storage, but reaching into another service's WebService layer violates service boundaries.
---
## 3. Forbidden Package Rules
**Purpose**: Block usage of deprecated, non-compliant, or strategically-replaced dependencies.
| Rule ID | Description | Forbidden Namespace/Type | Rationale |
|---------|-------------|-------------------------|-----------|
| `Forbidden_Redis` | No direct Redis library usage | `StackExchange.Redis`, `ServiceStack.Redis` | StellaOps uses Valkey; Redis clients may introduce incompatible commands |
| `Forbidden_MongoDB` | No MongoDB usage | `MongoDB.Driver`, `MongoDB.Bson` | MongoDB storage was deprecated in Sprint 4400; all persistence is PostgreSQL |
| `Forbidden_BouncyCastle_Core` | No direct BouncyCastle in core assemblies | `Org.BouncyCastle.*` | Cryptography must be plugin-based (`StellaOps.Cryptography.Plugin.*`); core assemblies reference only `StellaOps.Cryptography.Abstractions` |
**Exception**: `StellaOps.Cryptography.Plugin.BouncyCastle` is the designated wrapper and may reference BouncyCastle directly.
---
## 4. Naming Convention Rules
**Purpose**: Ensure consistent assembly naming for discoverability and tooling.
| Rule ID | Pattern | Enforcement |
|---------|---------|-------------|
| `Naming_TestProjects` | Test projects must end with `.Tests` | Assemblies matching `StellaOps.*Tests*` must end with `.Tests` |
| `Naming_Plugins` | Plugins must follow `StellaOps.<Module>.Plugin.*` or `StellaOps.<Module>.Connector.*` | Assemblies with "Plugin" or "Connector" in name must match pattern |
**Rationale**: Consistent naming enables CI glob patterns (`**/*.Tests.csproj`) and plugin discovery (`Assembly.Load("StellaOps.*.Plugin.*")`).
---
## Running Architecture Tests
```bash
# From repository root
dotnet test tests/architecture/StellaOps.Architecture.Tests --logger "console;verbosity=detailed"
```
**CI Integration**: Architecture tests run in the Unit test lane on every PR. They are PR-gating—failures block merge.
---
## Adding New Rules
1. Open `tests/architecture/StellaOps.Architecture.Tests/`
2. Add test method to the appropriate `*RulesTests.cs` file
3. Use NetArchTest fluent API:
```csharp
[Fact]
public void NewRule_Description()
{
var result = Types.InAssembly(typeof(SomeType).Assembly)
.That()
.HaveDependencyOn("Forbidden.Namespace")
.Should()
.NotExist()
.GetResult();
result.IsSuccessful.Should().BeTrue(
"Assemblies should not reference Forbidden.Namespace");
}
```
4. Document the rule in this file
---
## References
- [docs/07_HIGH_LEVEL_ARCHITECTURE.md](../07_HIGH_LEVEL_ARCHITECTURE.md) High-level architecture overview
- [docs/modules/scanner/architecture.md](../modules/scanner/architecture.md) Scanner module architecture (lattice engine details)
- [AGENTS.md](../../AGENTS.md) Project-wide agent guidelines and module boundaries
- [NetArchTest Documentation](https://github.com/BenMorris/NetArchTest)
---
*Last updated: 2025-06-30 · Sprint 5100.0007.0007*