## Summary
This commit completes Phase 2 of the configuration-driven crypto architecture, achieving
100% crypto compliance by eliminating all hardcoded cryptographic implementations.
## Key Changes
### Phase 1: Plugin Loader Infrastructure
- **Plugin Discovery System**: Created StellaOps.Cryptography.PluginLoader with manifest-based loading
- **Configuration Model**: Added CryptoPluginConfiguration with regional profiles support
- **Dependency Injection**: Extended DI to support plugin-based crypto provider registration
- **Regional Configs**: Created appsettings.crypto.{international,russia,eu,china}.yaml
- **CI Workflow**: Added .gitea/workflows/crypto-compliance.yml for audit enforcement
### Phase 2: Code Refactoring
- **API Extension**: Added ICryptoProvider.CreateEphemeralVerifier for verification-only scenarios
- **Plugin Implementation**: Created OfflineVerificationCryptoProvider with ephemeral verifier support
- Supports ES256/384/512, RS256/384/512, PS256/384/512
- SubjectPublicKeyInfo (SPKI) public key format
- **100% Compliance**: Refactored DsseVerifier to remove all BouncyCastle cryptographic usage
- **Unit Tests**: Created OfflineVerificationProviderTests with 39 passing tests
- **Documentation**: Created comprehensive security guide at docs/security/offline-verification-crypto-provider.md
- **Audit Infrastructure**: Created scripts/audit-crypto-usage.ps1 for static analysis
### Testing Infrastructure (TestKit)
- **Determinism Gate**: Created DeterminismGate for reproducibility validation
- **Test Fixtures**: Added PostgresFixture and ValkeyFixture using Testcontainers
- **Traits System**: Implemented test lane attributes for parallel CI execution
- **JSON Assertions**: Added CanonicalJsonAssert for deterministic JSON comparisons
- **Test Lanes**: Created test-lanes.yml workflow for parallel test execution
### Documentation
- **Architecture**: Created CRYPTO_CONFIGURATION_DRIVEN_ARCHITECTURE.md master plan
- **Sprint Tracking**: Created SPRINT_1000_0007_0002_crypto_refactoring.md (COMPLETE)
- **API Documentation**: Updated docs2/cli/crypto-plugins.md and crypto.md
- **Testing Strategy**: Created testing strategy documents in docs/implplan/SPRINT_5100_0007_*
## Compliance & Testing
- ✅ Zero direct System.Security.Cryptography usage in production code
- ✅ All crypto operations go through ICryptoProvider abstraction
- ✅ 39/39 unit tests passing for OfflineVerificationCryptoProvider
- ✅ Build successful (AirGap, Crypto plugin, DI infrastructure)
- ✅ Audit script validates crypto boundaries
## Files Modified
**Core Crypto Infrastructure:**
- src/__Libraries/StellaOps.Cryptography/CryptoProvider.cs (API extension)
- src/__Libraries/StellaOps.Cryptography/CryptoSigningKey.cs (verification-only constructor)
- src/__Libraries/StellaOps.Cryptography/EcdsaSigner.cs (fixed ephemeral verifier)
**Plugin Implementation:**
- src/__Libraries/StellaOps.Cryptography.Plugin.OfflineVerification/ (new)
- src/__Libraries/StellaOps.Cryptography.PluginLoader/ (new)
**Production Code Refactoring:**
- src/AirGap/StellaOps.AirGap.Importer/Validation/DsseVerifier.cs (100% compliant)
**Tests:**
- src/__Libraries/__Tests/StellaOps.Cryptography.Plugin.OfflineVerification.Tests/ (new, 39 tests)
- src/__Libraries/__Tests/StellaOps.Cryptography.PluginLoader.Tests/ (new)
**Configuration:**
- etc/crypto-plugins-manifest.json (plugin registry)
- etc/appsettings.crypto.*.yaml (regional profiles)
**Documentation:**
- docs/security/offline-verification-crypto-provider.md (600+ lines)
- docs/implplan/CRYPTO_CONFIGURATION_DRIVEN_ARCHITECTURE.md (master plan)
- docs/implplan/SPRINT_1000_0007_0002_crypto_refactoring.md (Phase 2 complete)
## Next Steps
Phase 3: Docker & CI/CD Integration
- Create multi-stage Dockerfiles with all plugins
- Build regional Docker Compose files
- Implement runtime configuration selection
- Add deployment validation scripts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
265 lines
9.3 KiB
Markdown
Executable File
265 lines
9.3 KiB
Markdown
Executable File
# Automated Test-Suite Overview
|
|
|
|
This document enumerates **every automated check** executed by the Stella Ops
|
|
CI pipeline, from unit level to chaos experiments. It is intended for
|
|
contributors who need to extend coverage or diagnose failures.
|
|
|
|
> **Build parameters** – values such as `{{ dotnet }}` (runtime) and
|
|
> `{{ angular }}` (UI framework) are injected at build time.
|
|
|
|
---
|
|
|
|
## Test Philosophy
|
|
|
|
### Core Principles
|
|
|
|
1. **Determinism as Contract**: Scan verdicts must be reproducible. Same inputs → byte-identical outputs.
|
|
2. **Offline by Default**: Every test (except explicitly tagged "online") runs without network access.
|
|
3. **Evidence-First Validation**: Assertions verify the complete evidence chain, not just pass/fail.
|
|
4. **Interop is Required**: Compatibility with ecosystem tools (Syft, Grype, Trivy, cosign) blocks releases.
|
|
5. **Coverage by Risk**: Prioritize testing high-risk paths over line coverage metrics.
|
|
|
|
### Test Boundaries
|
|
|
|
- **Lattice/policy merge** algorithms run in `scanner.webservice`
|
|
- **Concelier/Excitors** preserve prune source (no conflict resolution)
|
|
- Tests enforce these boundaries explicitly
|
|
|
|
### Model taxonomy
|
|
|
|
See `docs/testing/testing-strategy-models.md` and `docs/testing/TEST_CATALOG.yml` for
|
|
the required test types per project model and the module-to-model mapping.
|
|
|
|
---
|
|
|
|
## Layer Map
|
|
|
|
| Layer | Tooling | Entry-point | Frequency |
|
|
|-------|---------|-------------|-----------|
|
|
| **1. Unit** | `xUnit` (<code>dotnet test</code>) | `*.Tests.csproj` | per PR / push |
|
|
| **2. Property-based** | `FsCheck` | `SbomPropertyTests`, `Canonicalization` | per PR |
|
|
| **3. Integration (API)** | `Testcontainers` suite | `test/Api.Integration` | per PR + nightly |
|
|
| **4. Integration (DB-merge)** | Testcontainers PostgreSQL + Valkey | `Concelier.Integration` | per PR |
|
|
| **5. Contract (OpenAPI)** | Schema validation | `docs/api/*.yaml` | per PR |
|
|
| **6. Front-end unit** | `Jest` | `ui/src/**/*.spec.ts` | per PR |
|
|
| **7. Front-end E2E** | `Playwright` | `ui/e2e/**` | nightly |
|
|
| **8. Lighthouse perf / a11y** | `lighthouse-ci` (Chrome headless) | `ui/dist/index.html` | nightly |
|
|
| **9. Load** | `k6` scripted scenarios | `tests/load/*.js` | nightly |
|
|
| **10. Chaos** | `pumba`, custom harness | `tests/chaos/` | weekly |
|
|
| **11. Interop** | Syft/Grype/cosign | `tests/interop/` | nightly |
|
|
| **12. Offline E2E** | Network-isolated containers | `tests/offline/` | nightly |
|
|
| **13. Replay Verification** | Golden corpus replay | `bench/golden-corpus/` | per PR |
|
|
| **14. Dependency scanning** | `Trivy fs` + `dotnet list package --vuln` | root | per PR |
|
|
| **15. License compliance** | `LicenceFinder` | root | per PR |
|
|
| **16. SBOM reproducibility** | `in-toto attestation` diff | GitLab job | release tags |
|
|
|
|
---
|
|
|
|
## Test Categories (xUnit Traits)
|
|
|
|
```csharp
|
|
[Trait("Category", "Unit")] // Fast, isolated unit tests
|
|
[Trait("Category", "Property")] // Property-based checks (sub-trait)
|
|
[Trait("Category", "Snapshot")] // Golden/snapshot assertions (sub-trait)
|
|
[Trait("Category", "Integration")] // Tests requiring infrastructure
|
|
[Trait("Category", "Contract")] // Schema and API contract checks
|
|
[Trait("Category", "E2E")] // Full end-to-end workflows
|
|
[Trait("Category", "AirGap")] // Must work without network
|
|
[Trait("Category", "Interop")] // Third-party tool compatibility
|
|
[Trait("Category", "Performance")] // Performance benchmarks
|
|
[Trait("Category", "Chaos")] // Failure injection tests
|
|
[Trait("Category", "Security")] // Security-focused tests
|
|
[Trait("Category", "Live")] // Opt-in upstream connector tests
|
|
```
|
|
|
|
---
|
|
|
|
## Quality Gates
|
|
|
|
| Metric | Budget | Gate |
|
|
|--------|--------|------|
|
|
| API unit coverage | ≥ 85% lines | PR merge |
|
|
| API response P95 | ≤ 120 ms | nightly alert |
|
|
| Δ-SBOM warm scan P95 (4 vCPU) | ≤ 5 s | nightly alert |
|
|
| Lighthouse performance score | ≥ 90 | nightly alert |
|
|
| Lighthouse accessibility score | ≥ 95 | nightly alert |
|
|
| k6 sustained RPS drop | < 5% vs baseline | nightly alert |
|
|
| **Replay determinism** | 0 byte diff | **Release** |
|
|
| **Interop findings parity** | ≥ 95% | **Release** |
|
|
| **Offline E2E** | All pass with no network | **Release** |
|
|
| **Unknowns budget (prod)** | ≤ configured limit | **Release** |
|
|
| **Router Retry-After compliance** | 100% | Nightly |
|
|
|
|
---
|
|
|
|
## Local Runner
|
|
|
|
```bash
|
|
# minimal run: unit + property + frontend tests
|
|
./scripts/dev-test.sh
|
|
|
|
# full stack incl. Playwright and lighthouse
|
|
./scripts/dev-test.sh --full
|
|
|
|
# category-specific
|
|
dotnet test --filter "Category=Unit"
|
|
dotnet test --filter "Category=AirGap"
|
|
dotnet test --filter "Category=Interop"
|
|
```
|
|
|
|
The script spins up PostgreSQL/Valkey via Testcontainers and requires:
|
|
|
|
* Docker ≥ 25
|
|
* Node 20 (for Jest/Playwright)
|
|
|
|
### PostgreSQL Testcontainers
|
|
|
|
Multiple suites (Concelier connectors, Excititor worker/WebService, Scheduler)
|
|
use Testcontainers with PostgreSQL for integration tests. If you don't have
|
|
Docker available, tests can also run against a local PostgreSQL instance
|
|
listening on `127.0.0.1:5432`.
|
|
|
|
### Local PostgreSQL Helper
|
|
|
|
Some suites (Concelier WebService/Core, Exporter JSON) need a full
|
|
PostgreSQL instance when you want to debug or inspect data with `psql`.
|
|
A helper script is available under `tools/postgres/local-postgres.sh`:
|
|
|
|
```bash
|
|
# start a local PostgreSQL instance
|
|
tools/postgres/local-postgres.sh start
|
|
|
|
# stop / clean
|
|
tools/postgres/local-postgres.sh stop
|
|
tools/postgres/local-postgres.sh clean
|
|
```
|
|
|
|
By default the script uses Docker to run PostgreSQL 16, binds to
|
|
`127.0.0.1:5432`, and creates a database called `stellaops`. The
|
|
connection string is printed on start and you can export it before
|
|
running `dotnet test` if a suite supports overriding its connection string.
|
|
|
|
---
|
|
|
|
## New Test Infrastructure (Epic 5100)
|
|
|
|
### Run Manifest & Replay
|
|
|
|
Every scan captures a **Run Manifest** containing all inputs (artifact digests, feed versions, policy versions, PRNG seed). This enables deterministic replay:
|
|
|
|
```bash
|
|
# Replay a scan from manifest
|
|
stella replay --manifest run-manifest.json --output verdict.json
|
|
|
|
# Verify determinism
|
|
stella replay verify --manifest run-manifest.json
|
|
```
|
|
|
|
### Evidence Index
|
|
|
|
The **Evidence Index** links verdicts to their supporting evidence chain:
|
|
- Verdict → SBOM digests → Attestation IDs → Tool versions
|
|
|
|
### Golden Corpus
|
|
|
|
Located at `bench/golden-corpus/`, contains 50+ test cases:
|
|
- Severity levels (Critical, High, Medium, Low)
|
|
- VEX scenarios (Not Affected, Affected, Conflicting)
|
|
- Reachability cases (Reachable, Not Reachable, Inconclusive)
|
|
- Unknowns scenarios
|
|
- Scale tests (200 to 50k+ packages)
|
|
- Multi-distro (Alpine, Debian, RHEL, SUSE, Ubuntu)
|
|
- Interop fixtures (Syft-generated, Trivy-generated)
|
|
- Negative cases (malformed inputs)
|
|
|
|
### Offline Testing
|
|
|
|
Inherit from `NetworkIsolatedTestBase` for air-gap compliance:
|
|
|
|
```csharp
|
|
[Trait("Category", "AirGap")]
|
|
public class OfflineTests : NetworkIsolatedTestBase
|
|
{
|
|
[Fact]
|
|
public async Task Test_WorksOffline()
|
|
{
|
|
// Test implementation
|
|
AssertNoNetworkCalls(); // Fails if network accessed
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Concelier OSV↔GHSA Parity Fixtures
|
|
|
|
The Concelier connector suite includes a regression test (`OsvGhsaParityRegressionTests`)
|
|
that checks a curated set of GHSA identifiers against OSV responses. The fixture
|
|
snapshots live in `src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/Fixtures/` and are kept
|
|
deterministic so the parity report remains reproducible.
|
|
|
|
To refresh the fixtures when GHSA/OSV payloads change:
|
|
|
|
1. Ensure outbound HTTPS access to `https://api.osv.dev` and `https://api.github.com`.
|
|
2. Run `UPDATE_PARITY_FIXTURES=1 dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/StellaOps.Concelier.Connector.Osv.Tests.csproj`.
|
|
3. Commit the regenerated `osv-ghsa.*.json` files that the test emits (raw snapshots and canonical advisories).
|
|
|
|
The regen flow logs `[Parity]` messages and normalises `recordedAt` timestamps so the
|
|
fixtures stay stable across machines.
|
|
|
|
---
|
|
|
|
## CI Job Layout
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph fast-path
|
|
U[xUnit] --> P[FsCheck] --> I1[Testcontainer API]
|
|
end
|
|
|
|
I1 --> FE[Jest]
|
|
FE --> E2E[Playwright]
|
|
E2E --> Lighthouse
|
|
|
|
subgraph release-gates
|
|
REPLAY[Replay Verify]
|
|
INTEROP[Interop E2E]
|
|
OFFLINE[Offline E2E]
|
|
BUDGET[Unknowns Gate]
|
|
end
|
|
|
|
Lighthouse --> INTEG2[Concelier]
|
|
INTEG2 --> LOAD[k6]
|
|
LOAD --> CHAOS[Chaos Suite]
|
|
CHAOS --> RELEASE[Attestation diff]
|
|
|
|
RELEASE --> release-gates
|
|
```
|
|
|
|
---
|
|
|
|
## Adding a New Test Layer
|
|
|
|
1. Extend `scripts/dev-test.sh` so local contributors get the layer by default.
|
|
2. Add a dedicated workflow in `.gitea/workflows/` (or GitLab job in `.gitlab-ci.yml`).
|
|
3. Register the job in `docs/19_TEST_SUITE_OVERVIEW.md` *and* list its metric
|
|
in `docs/metrics/README.md`.
|
|
4. If the test requires network isolation, inherit from `NetworkIsolatedTestBase`.
|
|
5. If the test uses golden corpus, add cases to `bench/golden-corpus/`.
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [Sprint Epic 5100 - Testing Strategy](implplan/SPRINT_5100_0000_0000_epic_summary.md)
|
|
- [Testing Strategy Models](testing/testing-strategy-models.md)
|
|
- [Test Catalog](testing/TEST_CATALOG.yml)
|
|
- [tests/AGENTS.md](../tests/AGENTS.md)
|
|
- [Offline Operation Guide](24_OFFLINE_KIT.md)
|
|
- [Module Architecture Dossiers](modules/)
|
|
|
|
---
|
|
|
|
*Last updated 2025-12-23*
|
|
|