Files
git.stella-ops.org/docs/architecture/enforcement-rules.md
master 491e883653 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.
2025-12-24 00:36:14 +02:00

6.0 KiB
Raw Blame History

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 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

# 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:
    [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


Last updated: 2025-06-30 · Sprint 5100.0007.0007