Sprint: SPRINT_4100_0006_0001 Status: COMPLETED Implemented plugin-based crypto command architecture for regional compliance with build-time distribution selection (GOST/eIDAS/SM) and runtime validation. ## New Commands - `stella crypto sign` - Sign artifacts with regional crypto providers - `stella crypto verify` - Verify signatures with trust policy support - `stella crypto profiles` - List available crypto providers & capabilities ## Build-Time Distribution Selection ```bash # International (default - BouncyCastle) dotnet build src/Cli/StellaOps.Cli/StellaOps.Cli.csproj # Russia distribution (GOST R 34.10-2012) dotnet build -p:StellaOpsEnableGOST=true # EU distribution (eIDAS Regulation 910/2014) dotnet build -p:StellaOpsEnableEIDAS=true # China distribution (SM2/SM3/SM4) dotnet build -p:StellaOpsEnableSM=true ``` ## Key Features - Build-time conditional compilation prevents export control violations - Runtime crypto profile validation on CLI startup - 8 predefined profiles (international, russia-prod/dev, eu-prod/dev, china-prod/dev) - Comprehensive configuration with environment variable substitution - Integration tests with distribution-specific assertions - Full migration path from deprecated `cryptoru` CLI ## Files Added - src/Cli/StellaOps.Cli/Commands/CryptoCommandGroup.cs - src/Cli/StellaOps.Cli/Commands/CommandHandlers.Crypto.cs - src/Cli/StellaOps.Cli/Services/CryptoProfileValidator.cs - src/Cli/StellaOps.Cli/appsettings.crypto.yaml.example - src/Cli/__Tests/StellaOps.Cli.Tests/CryptoCommandTests.cs - docs/cli/crypto-commands.md - docs/implplan/SPRINT_4100_0006_0001_COMPLETION_SUMMARY.md ## Files Modified - src/Cli/StellaOps.Cli/StellaOps.Cli.csproj (conditional plugin refs) - src/Cli/StellaOps.Cli/Program.cs (plugin registration + validation) - src/Cli/StellaOps.Cli/Commands/CommandFactory.cs (command wiring) - src/Scanner/__Libraries/StellaOps.Scanner.Core/Configuration/PoEConfiguration.cs (fix) ## Compliance - GOST (Russia): GOST R 34.10-2012, FSB certified - eIDAS (EU): Regulation (EU) No 910/2014, QES/AES/AdES - SM (China): GM/T 0003-2012 (SM2), OSCCA certified ## Migration `cryptoru` CLI deprecated → sunset date: 2025-07-01 - `cryptoru providers` → `stella crypto profiles` - `cryptoru sign` → `stella crypto sign` ## Testing ✅ All crypto code compiles successfully ✅ Integration tests pass ✅ Build verification for all distributions (international/GOST/eIDAS/SM) Next: SPRINT_4100_0006_0002 (eIDAS plugin implementation) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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:
-
VerdictPredicate.cs - Core predicate models
VerdictPredicate- Main predicate structure matching JSON schemaVerdictInfo- Verdict details (status/severity/score)VerdictRuleExecution- Rule chain execution traceVerdictEvidence- Evidence references (advisories, VEX, SBOM)VerdictVexImpact- VEX impact assessmentVerdictReachability- Call graph reachability data- Uses canonical JSON serialization with lexicographic key ordering
-
VerdictPredicateBuilder.cs - Predicate assembly service
Build(PolicyExplainTrace)- Converts existing trace to attestation predicateSerialize(VerdictPredicate)- Canonical JSON with sorted keysComputeDeterminismHash(VerdictPredicate)- SHA256 over sorted evidence + verdict- Maps all existing Policy Engine trace data to new attestation format
-
IVerdictAttestationService.cs - Service interface
AttestVerdictAsync(trace)- Orchestrates attestation creationVerdictAttestationRequest- Request DTO with predicate, subject, metadataVerdictAttestationResult- Response DTO with verdict ID and URI
-
VerdictAttestationService.cs - Service implementation
- Feature-flagged via
VerdictAttestationOptions.Enabled - Calls
VerdictPredicateBuilderto create predicate - Calls
HttpAttestorClientto request signing - Returns verdict ID for downstream tracking
- Feature-flagged via
-
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:
-
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
- Table:
-
Storage/IVerdictRepository.cs - Repository interface
StoreVerdictAsync(record)- Upsert verdict attestationGetVerdictAsync(verdictId)- Retrieve full record with envelopeListVerdictsForRunAsync(runId, options)- Query verdicts by run with filteringListVerdictsAsync(tenantId, options)- Query verdicts by tenantCountVerdictsForRunAsync(runId, options)- Pagination count- Records:
VerdictAttestationRecord,VerdictAttestationSummary,VerdictListOptions
-
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
-
Api/VerdictContracts.cs - API response DTOs
GetVerdictResponse- Full verdict with envelopeListVerdictsResponse- Paged list of summariesVerdictSummary- Lightweight verdict metadataVerifyVerdictResponse- Signature verification resultsSignatureVerification,RekorVerification- Crypto details- JSON serialization with snake_case naming
-
Api/VerdictEndpoints.cs - Minimal API endpoints
GET /api/v1/verdicts/{verdictId}- Retrieve verdictGET /api/v1/runs/{runId}/verdicts- List verdicts for runPOST /api/v1/verdicts/{verdictId}/verify- Verify signature (TODO: implementation)- Structured logging for all operations
- Error handling with problem details
-
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:
-
DI Registration - Updated
EvidenceLockerInfrastructureServiceCollectionExtensions.cs- Registered
IVerdictRepository→PostgresVerdictRepository - Connection string from
EvidenceLockerOptions.Database.ConnectionString
- Registered
-
WebService Wiring - Updated
StellaOps.EvidenceLocker.WebService/Program.cs- Added
using StellaOps.EvidenceLocker.Api - Called
app.MapVerdictEndpoints()beforeapp.Run()
- Added
-
Project References - Updated
.csprojfilesWebService.csproj→ referencesStellaOps.EvidenceLocker.csprojInfrastructure.csproj→ referencesStellaOps.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 referenceStellaOps.Attestor.ProofChain: Missing Envelope namespace, ILogger references
Planned Implementation (when unblocked):
Location: src/Attestor/StellaOps.Attestor/StellaOps.Attestor.WebService/
Planned Files:
-
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 } } -
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
-
DI Registration
- Register
VerdictAttestationHandleras scoped service - Wire up dependencies: signing, storage, transparency
- Register
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:
- Inject
IVerdictAttestationServiceinto evaluator - After successful policy evaluation, call
AttestVerdictAsync(trace) - Store returned verdict ID in evaluation metadata
- 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:
-
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)
-
VerdictAttestationServiceTests.cs
- Test: Feature flag disabled (returns null)
- Test: Successful attestation flow
- Test: HTTP client failure handling
- Test: Predicate serialization errors
-
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:
stella verdict get <verdict-id>- Retrieve verdict attestationstella verdict verify <verdict-id>- Verify signaturestella verdict list --run <run-id>- List verdicts for runstella 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:
-
Fix Attestor Build Errors (Infrastructure team)
- Add missing YamlDotNet package reference to Replay.Core
- Fix ProofChain namespace/using issues
- Verify all Attestor dependencies compile
-
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
-
Integrate Policy Engine (This sprint)
- Inject attestation service into evaluator
- Call after successful verdicts
- Store verdict IDs
-
Write Unit Tests (This sprint)
- VerdictPredicateBuilder schema/determinism tests
- Service integration tests
- End-to-end replay tests
-
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
-
EvidenceLockerDataSource Integration
- Current: PostgresVerdictRepository uses connection string directly
- Future: Migrate to use EvidenceLockerDataSource.OpenConnectionAsync()
- Benefit: Unified session management, tenant scoping
-
Signature Verification Placeholder
- Current:
VerdictEndpoints.VerifyVerdictAsyncreturns placeholder response - Future: Implement actual DSSE signature verification
- Dependency: Integrate with Attestor verification service
- Current:
-
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