7.2 KiB
7.2 KiB
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(fordotnet efCLI) - Runtime factory:
VerdictDbContextFactory(compiled model for default schema, reflection for non-default) - DataSource:
VerdictDataSourceextendsDataSourceBasefor connection pooling and tenant context - Compiled model: Stub in
EfCore/CompiledModels/; assembly attributes excluded from compilation - Migration registry: Registered as
VerdictMigrationModulePluginin Platform.Database
Connection Pattern
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 PURLClaim: Status, confidence, reasonInputs: Advisory sources, VEX, CVSS, EPSS, KEV, reachabilityEvidenceGraph: Proof nodes and edges from ProofBundlePolicyPath: Rule evaluation traceResult: Disposition, score, expirationProvenance: Generator, run ID, timestampSignatures: DSSE signatures
Verdict Status Values
Pass: Component passed all policy checksBlocked: Component blocked by policyIgnored: Finding ignored per policyWarned: Warning issued but not blockingDeferred: Decision deferred for manual reviewEscalated: Escalated for security teamRequiresVex: Needs VEX statement to resolve
Usage Patterns
Assembling a Verdict
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
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
# 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
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, PolicyExplanationStellaOps.Attestor.Envelope: DSSE signingStellaOps.Cryptography: BLAKE3/SHA256 hashingStellaOps.Replay.Core: Bundle structuresStellaOps.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
- Determinism: All JSON output must be deterministic (sorted keys, stable ordering)
- Content Addressing: VerdictId must match
ComputeVerdictId()output - Immutability: Use records with
initproperties - Tenant Isolation: All store operations must include tenantId; RLS enforced at DB level
- Offline Support: OCI publisher and CLI must handle offline mode
- EF Core Standards: Follow
docs/db/EF_CORE_MODEL_GENERATION_STANDARDS.md - AsNoTracking: Always use for read-only queries
- 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)