187 lines
7.2 KiB
Markdown
187 lines
7.2 KiB
Markdown
# 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)
|