# AGENTS.md -- StellaOps.Verdict Module ## Overview The StellaOps.Verdict module provides a **unified StellaVerdict artifact** that consolidates vulnerability disposition decisions into a single, signed, portable proof. It combines PolicyVerdict, ProofBundle, and KnowledgeSnapshot into a content-addressable artifact with JSON-LD support. ## Module Structure ``` src/__Libraries/StellaOps.Verdict/ +-- Schema/ | +-- StellaVerdict.cs # Core verdict schema and supporting types +-- Contexts/ | +-- verdict-1.0.jsonld # JSON-LD context for standards interop +-- Services/ | +-- VerdictAssemblyService.cs # Assembles verdicts from components | +-- VerdictSigningService.cs # DSSE signing integration | +-- IVerdictAssemblyService.cs +-- Persistence/ | +-- PostgresVerdictStore.cs # PostgreSQL (EF Core) storage implementation | +-- IVerdictStore.cs # Storage interface | +-- VerdictRow.cs # EF Core entity (Fluent API mappings) | +-- EfCore/ | | +-- Context/ | | | +-- VerdictDbContext.cs # Partial DbContext with Fluent API | | | +-- VerdictDesignTimeDbContextFactory.cs # For dotnet ef CLI | | +-- CompiledModels/ | | +-- VerdictDbContextModel.cs # Compiled model singleton | | +-- VerdictDbContextModelBuilder.cs # Compiled model builder | | +-- VerdictDbContextAssemblyAttributes.cs # Excluded from compilation | +-- Postgres/ | | +-- VerdictDataSource.cs # DataSourceBase derivation, connection pool | | +-- VerdictDbContextFactory.cs # Runtime factory with compiled model hookup | +-- Migrations/ | +-- 001_create_verdicts.sql +-- Api/ | +-- VerdictEndpoints.cs # REST API endpoints | +-- VerdictContracts.cs # Request/response DTOs | +-- VerdictPolicies.cs # Authorization policies +-- Oci/ | +-- OciAttestationPublisher.cs # OCI registry attestation +-- Export/ | +-- VerdictBundleExporter.cs # Replay bundle export +-- StellaOps.Verdict.csproj ``` ## DAL Architecture (EF Core v10) The Verdict persistence layer follows the EF Core v10 standards documented in `docs/db/EF_CORE_MODEL_GENERATION_STANDARDS.md`: - **DbContext**: `VerdictDbContext` (partial class, schema-injectable, Fluent API mappings) - **Schema**: `stellaops` (shared platform schema) - **Design-time factory**: `VerdictDesignTimeDbContextFactory` (for `dotnet ef` CLI) - **Runtime factory**: `VerdictDbContextFactory` (compiled model for default schema, reflection for non-default) - **DataSource**: `VerdictDataSource` extends `DataSourceBase` for connection pooling and tenant context - **Compiled model**: Stub in `EfCore/CompiledModels/`; assembly attributes excluded from compilation - **Migration registry**: Registered as `VerdictMigrationModulePlugin` in Platform.Database ### Connection Pattern ```csharp await using var connection = await _dataSource.OpenConnectionAsync(tenantId.ToString(), "reader", ct); await using var context = VerdictDbContextFactory.Create(connection, CommandTimeoutSeconds, GetSchemaName()); // Use context.Verdicts with AsNoTracking() for reads... ``` ### Schema Governance - SQL migrations in `Persistence/Migrations/` are the authoritative schema definition - EF Core models are derived from schema, not the reverse - No EF Core auto-migrations at runtime - Schema changes require new SQL migration files ## Key Concepts ### StellaVerdict Schema The core `StellaVerdict` record contains: - `VerdictId`: Content-addressable ID (`urn:stella:verdict:sha256:...`) - `Subject`: Vulnerability ID + Component PURL - `Claim`: Status, confidence, reason - `Inputs`: Advisory sources, VEX, CVSS, EPSS, KEV, reachability - `EvidenceGraph`: Proof nodes and edges from ProofBundle - `PolicyPath`: Rule evaluation trace - `Result`: Disposition, score, expiration - `Provenance`: Generator, run ID, timestamp - `Signatures`: DSSE signatures ### Verdict Status Values - `Pass`: Component passed all policy checks - `Blocked`: Component blocked by policy - `Ignored`: Finding ignored per policy - `Warned`: Warning issued but not blocking - `Deferred`: Decision deferred for manual review - `Escalated`: Escalated for security team - `RequiresVex`: Needs VEX statement to resolve ## Usage Patterns ### Assembling a Verdict ```csharp var context = new VerdictAssemblyContext { VulnerabilityId = "CVE-2024-1234", Purl = "pkg:npm/lodash@4.17.15", PolicyVerdict = policyResult, Knowledge = knowledgeInputs, Generator = "StellaOps Scanner", RunId = scanId }; var verdict = assemblyService.AssembleVerdict(context); ``` ### Storing and Querying ```csharp await store.StoreAsync(verdict, tenantId, cancellationToken); var query = new VerdictQuery { Purl = "pkg:npm/lodash@*", Status = VerdictStatus.Blocked }; var results = await store.QueryAsync(query, cancellationToken); ``` ### CLI Verification ```bash # Verify by ID (fetches from API) stella verify verdict --verdict urn:stella:verdict:sha256:abc123 # Verify from file with replay bundle stella verify verdict --verdict ./verdict.json --replay ./bundle/ # Show full policy trace stella verify verdict --verdict ./verdict.json --show-trace ``` ### OCI Attestation ```csharp var result = await publisher.PublishAsync(verdict, "registry.io/app:latest@sha256:..."); ``` ## API Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/v1/verdicts` | POST | Create and store verdict | | `/v1/verdicts/{id}` | GET | Get verdict by ID | | `/v1/verdicts` | GET | Query verdicts (purl, cve, status) | | `/v1/verdicts/{id}/verify` | POST | Verify signature and content ID | | `/v1/verdicts/{id}/download` | GET | Download as JSON-LD | | `/v1/verdicts/latest` | GET | Get latest for purl+cve | | `/v1/verdicts/expired` | DELETE | Clean up expired verdicts | ## Dependencies - `StellaOps.Policy`: PolicyVerdict, PolicyExplanation - `StellaOps.Attestor.Envelope`: DSSE signing - `StellaOps.Cryptography`: BLAKE3/SHA256 hashing - `StellaOps.Replay.Core`: Bundle structures - `StellaOps.Infrastructure.Postgres`: DataSourceBase, PostgresOptions, connection pooling ## Testing Unit tests should cover: - Schema serialization determinism (sorted keys) - Content-addressable ID computation - Assembly from various input combinations - Signature verification - Query filtering and pagination Integration tests should cover: - Full assembly -> sign -> store -> query -> verify flow - OCI publish/fetch cycle - Replay bundle export and verification ## Coding Guidelines 1. **Determinism**: All JSON output must be deterministic (sorted keys, stable ordering) 2. **Content Addressing**: VerdictId must match `ComputeVerdictId()` output 3. **Immutability**: Use records with `init` properties 4. **Tenant Isolation**: All store operations must include tenantId; RLS enforced at DB level 5. **Offline Support**: OCI publisher and CLI must handle offline mode 6. **EF Core Standards**: Follow `docs/db/EF_CORE_MODEL_GENERATION_STANDARDS.md` 7. **AsNoTracking**: Always use for read-only queries 8. **DbContext per operation**: Create via VerdictDbContextFactory, not cached ## Related Sprints - SPRINT_1227_0014_0001: StellaVerdict Unified Artifact Consolidation - SPRINT_1227_0014_0002: Verdict UI Components (pending) - SPRINT_20260222_080: Verdict Persistence DAL to EF Core (queue order 16)