Files
git.stella-ops.org/docs/implplan/archived/IMPLEMENTATION_STATUS_VERDICT_ATTESTATIONS.md
master dac8e10e36 feat(crypto): Complete Phase 2 - Configuration-driven crypto architecture with 100% compliance
## 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>
2025-12-23 18:20:00 +02:00

14 KiB

Verdict Attestation Implementation Status

Sprint: SPRINT_3000_0100_0001 - Signed Delta-Verdicts Status: Phase 1 Complete (Policy Engine + Evidence Locker), Phase 2 Blocked Last Updated: 2025-12-23

Completed Work

1. Policy Engine - Verdict Predicate & Attestation Service

Location: src/Policy/StellaOps.Policy.Engine/Attestation/

Files Created:

  1. VerdictPredicate.cs - Core predicate models

    • VerdictPredicate - Main predicate structure matching JSON schema
    • VerdictInfo - Verdict details (status/severity/score)
    • VerdictRuleExecution - Rule chain execution trace
    • VerdictEvidence - Evidence references (advisories, VEX, SBOM)
    • VerdictVexImpact - VEX impact assessment
    • VerdictReachability - Call graph reachability data
    • Uses canonical JSON serialization with lexicographic key ordering
  2. VerdictPredicateBuilder.cs - Predicate assembly service

    • Build(PolicyExplainTrace) - Converts existing trace to attestation predicate
    • Serialize(VerdictPredicate) - Canonical JSON with sorted keys
    • ComputeDeterminismHash(VerdictPredicate) - SHA256 over sorted evidence + verdict
    • Maps all existing Policy Engine trace data to new attestation format
  3. IVerdictAttestationService.cs - Service interface

    • AttestVerdictAsync(trace) - Orchestrates attestation creation
    • VerdictAttestationRequest - Request DTO with predicate, subject, metadata
    • VerdictAttestationResult - Response DTO with verdict ID and URI
  4. VerdictAttestationService.cs - Service implementation

    • Feature-flagged via VerdictAttestationOptions.Enabled
    • Calls VerdictPredicateBuilder to create predicate
    • Calls HttpAttestorClient to request signing
    • Returns verdict ID for downstream tracking
  5. HttpAttestorClient.cs - HTTP client for Attestor service

    • POST /internal/api/v1/attestations/verdict
    • Sends predicate JSON + subject descriptor
    • Receives signed attestation metadata

Design Decisions:

  • Predicate strictly matches stellaops-policy-verdict.v1.schema.json
  • Determinism hash uses sorted evidence digests + verdict triple
  • Offline-first: no hard dependencies on external services
  • Feature flag allows gradual rollout

2. Evidence Locker - Verdict Storage & API

Location: src/EvidenceLocker/StellaOps.EvidenceLocker/

Files Created:

  1. Migrations/001_CreateVerdictAttestations.sql

    • Table: evidence_locker.verdict_attestations
    • Columns: verdict_id (PK), tenant_id, run_id, finding_id, policy metadata, verdict triple, envelope (JSONB), digests, rekor_log_index, timestamps
    • Indexes: run_id, finding_id, tenant+evaluated_at
    • CHECK constraint on verdict_status enum
    • Audit trigger: audit_verdict_attestations_changes
  2. Storage/IVerdictRepository.cs - Repository interface

    • StoreVerdictAsync(record) - Upsert verdict attestation
    • GetVerdictAsync(verdictId) - Retrieve full record with envelope
    • ListVerdictsForRunAsync(runId, options) - Query verdicts by run with filtering
    • ListVerdictsAsync(tenantId, options) - Query verdicts by tenant
    • CountVerdictsForRunAsync(runId, options) - Pagination count
    • Records: VerdictAttestationRecord, VerdictAttestationSummary, VerdictListOptions
  3. Storage/PostgresVerdictRepository.cs - PostgreSQL implementation

    • Uses Npgsql + Dapper for data access
    • JSONB storage for DSSE envelope with GIN index
    • ON CONFLICT handling for idempotent upserts
    • Filtering by status/severity with pagination
    • Tenant isolation via WHERE clauses
  4. Api/VerdictContracts.cs - API response DTOs

    • GetVerdictResponse - Full verdict with envelope
    • ListVerdictsResponse - Paged list of summaries
    • VerdictSummary - Lightweight verdict metadata
    • VerifyVerdictResponse - Signature verification results
    • SignatureVerification, RekorVerification - Crypto details
    • JSON serialization with snake_case naming
  5. Api/VerdictEndpoints.cs - Minimal API endpoints

    • GET /api/v1/verdicts/{verdictId} - Retrieve verdict
    • GET /api/v1/runs/{runId}/verdicts - List verdicts for run
    • POST /api/v1/verdicts/{verdictId}/verify - Verify signature (TODO: implementation)
    • Structured logging for all operations
    • Error handling with problem details
  6. StellaOps.EvidenceLocker.csproj - Project file

    • Dependencies: Npgsql 9.0.3, Dapper 2.1.35, OpenTelemetry, Serilog
    • Project references: Scheduler.Models, Policy.Engine, Configuration, DependencyInjection, Auth, Telemetry

Integration Points:

  1. DI Registration - Updated EvidenceLockerInfrastructureServiceCollectionExtensions.cs

    • Registered IVerdictRepositoryPostgresVerdictRepository
    • Connection string from EvidenceLockerOptions.Database.ConnectionString
  2. WebService Wiring - Updated StellaOps.EvidenceLocker.WebService/Program.cs

    • Added using StellaOps.EvidenceLocker.Api
    • Called app.MapVerdictEndpoints() before app.Run()
  3. Project References - Updated .csproj files

    • WebService.csproj → references StellaOps.EvidenceLocker.csproj
    • Infrastructure.csproj → references StellaOps.EvidenceLocker.csproj
    • Fixed package versions: Npgsql 9.0.3, Dapper 2.1.35

Design Decisions:

  • PostgreSQL JSONB for envelope storage (queryable + compact)
  • Separate verdict fields for efficient indexing without JSON extraction
  • Determinism hash stored for replay verification
  • Optional Rekor log index for transparency
  • Repository pattern for testability
  • Minimal APIs for lightweight endpoints

Blocked Work

3. Attestor - VerdictAttestationHandler ⚠️ BLOCKED

Blocking Issue: Pre-existing build errors in Attestor dependencies:

  • StellaOps.Replay.Core: Missing YamlDotNet assembly reference
  • StellaOps.Attestor.ProofChain: Missing Envelope namespace, ILogger references

Planned Implementation (when unblocked):

Location: src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService/

Planned Files:

  1. Handlers/VerdictAttestationHandler.cs

    public class VerdictAttestationHandler
    {
        private readonly IAttestationSigningService _signingService;
        private readonly IVerdictRepository _verdictRepository;
        private readonly ITransparencyWitnessClient _transparencyClient;
    
        public async Task<VerdictAttestationResponse> HandleAsync(
            VerdictAttestationRequest request,
            CancellationToken cancellationToken)
        {
            // 1. Validate predicate schema
            // 2. Create AttestationSignRequest with predicate payload
            // 3. Sign with IAttestationSigningService
            // 4. Extract DSSE envelope from result
            // 5. Store in Evidence Locker via IVerdictRepository
            // 6. Optional: Submit to Rekor via ITransparencyWitnessClient
            // 7. Return verdict ID + attestation URI
        }
    }
    
  2. Endpoints - Add to WebService Program.cs

    • POST /internal/api/v1/attestations/verdict - Create verdict attestation
    • Accepts predicate JSON + subject descriptor
    • Returns verdict ID + DSSE envelope URI
  3. DI Registration

    • Register VerdictAttestationHandler as scoped service
    • Wire up dependencies: signing, storage, transparency

Dependencies:

  • IAttestationSigningService - Existing
  • ITransparencyWitnessClient - Existing
  • IVerdictRepository - Implemented (Evidence Locker)
  • Build environment - BLOCKED

Pending Work

4. Policy Engine Integration ⏸️

Task: Wire Policy Engine to call VerdictAttestationService after verdict evaluation

Location: src/Policy/StellaOps.Policy.Engine/Evaluation/PolicyEvaluator.cs (or similar)

Changes Needed:

  1. Inject IVerdictAttestationService into evaluator
  2. After successful policy evaluation, call AttestVerdictAsync(trace)
  3. Store returned verdict ID in evaluation metadata
  4. Ensure async context properly propagated

Depends On: Task 3 (Attestor Handler) completion

5. Unit Tests ⏸️

Location: src/Policy/StellaOps.Policy.Engine/__Tests/

Files to Create:

  1. VerdictPredicateBuilderTests.cs

    • Test: Schema validation (predicate matches JSON schema)
    • Test: Determinism hash stability (same input → same hash)
    • Test: Rule chain mapping accuracy
    • Test: Evidence digest computation
    • Test: VEX impact extraction
    • Test: Reachability data mapping
    • Test: Canonical JSON serialization (key ordering)
  2. VerdictAttestationServiceTests.cs

    • Test: Feature flag disabled (returns null)
    • Test: Successful attestation flow
    • Test: HTTP client failure handling
    • Test: Predicate serialization errors
  3. Integration Test

    • Test: End-to-end policy run → verdict attestation → storage → retrieval
    • Test: Deterministic replay (same inputs → same determinism hash)
    • Test: Signature verification

Depends On: Task 3, 4 completion

6. CLI Commands ⏸️

Location: src/Cli/StellaOps.Cli/Commands/

Commands to Add:

  1. stella verdict get <verdict-id> - Retrieve verdict attestation
  2. stella verdict verify <verdict-id> - Verify signature
  3. stella verdict list --run <run-id> - List verdicts for run
  4. stella verdict download <verdict-id> --output <path> - Download DSSE bundle

Depends On: Task 3, 4, 5 completion

Architecture Summary

┌─────────────────┐
│ Policy Engine   │
│  - Evaluates    │
│  - Generates    │
│    Trace        │
└────────┬────────┘
         │ PolicyExplainTrace
         ▼
┌────────────────────────────┐
│ VerdictPredicateBuilder    │
│  - Converts Trace          │
│  - Computes Determinism    │
│  - Serializes Canonical    │
└────────┬───────────────────┘
         │ VerdictPredicate
         ▼
┌─────────────────────────────────┐
│ VerdictAttestationService       │
│  - Orchestrates Signing         │
│  - Calls Attestor               │
└────────┬────────────────────────┘
         │ HTTP POST /internal/api/v1/attestations/verdict
         ▼
┌────────────────────────────────────┐
│ Attestor                           │  ⚠️ BLOCKED
│  - VerdictAttestationHandler       │
│  - IAttestationSigningService      │
│  - Creates DSSE Envelope           │
└────────┬───────────────────────────┘
         │ VerdictAttestationRecord
         ▼
┌──────────────────────────────────┐
│ Evidence Locker                  │  ✅ COMPLETE
│  - PostgresVerdictRepository     │
│  - Stores Attestations           │
│  - Provides Query API            │
└──────────────────────────────────┘

Next Steps

Immediate Actions Required:

  1. Fix Attestor Build Errors (Infrastructure team)

    • Add missing YamlDotNet package reference to Replay.Core
    • Fix ProofChain namespace/using issues
    • Verify all Attestor dependencies compile
  2. Implement VerdictAttestationHandler (This sprint)

    • Create handler class in Attestor.WebService
    • Wire up signing service, storage, transparency
    • Add endpoint to Program.cs
    • Test end-to-end flow
  3. Integrate Policy Engine (This sprint)

    • Inject attestation service into evaluator
    • Call after successful verdicts
    • Store verdict IDs
  4. Write Unit Tests (This sprint)

    • VerdictPredicateBuilder schema/determinism tests
    • Service integration tests
    • End-to-end replay tests
  5. CLI Commands (Next sprint)

    • verdict get/verify/list/download
    • Interactive verification UI

Success Criteria:

  • Policy runs generate cryptographically-signed verdict attestations
  • Verdicts stored in Evidence Locker with DSSE envelopes
  • Determinism hashes enable bit-for-bit replay verification
  • Optional Rekor anchoring for public auditability
  • CLI commands for verdict inspection and verification
  • Unit test coverage >80% for new code
  • Integration tests validate end-to-end flow

Technical Debt

  1. EvidenceLockerDataSource Integration

    • Current: PostgresVerdictRepository uses connection string directly
    • Future: Migrate to use EvidenceLockerDataSource.OpenConnectionAsync()
    • Benefit: Unified session management, tenant scoping
  2. Signature Verification Placeholder

    • Current: VerdictEndpoints.VerifyVerdictAsync returns placeholder response
    • Future: Implement actual DSSE signature verification
    • Dependency: Integrate with Attestor verification service
  3. Pre-existing Attestor Errors

    • EvidencePortableBundleService.cs static field access errors
    • Blocking unrelated to verdict attestation work
    • Needs separate investigation

Resources

  • JSON Schema: docs/schemas/stellaops-policy-verdict.v1.schema.json
  • Documentation: docs/policy/verdict-attestations.md
  • Sprint Plan: docs/implplan/SPRINT_3000_0100_0001_signed_verdicts.md
  • Evidence Pack Sprint: docs/implplan/SPRINT_3000_0100_0002_evidence_packs.md

Status Legend:

  • Complete
  • ⚠️ Blocked
  • ⏸️ Pending (blocked by dependencies)
  • 🔄 In Progress