# Evidence API Reference This document provides the complete API reference for the StellaOps unified evidence model. ## Interfaces ### IEvidence Base interface for all evidence records. ```csharp namespace StellaOps.Evidence.Core; public interface IEvidence { /// /// Content-addressed evidence identifier (e.g., "sha256:abc123..."). /// string EvidenceId { get; } /// /// The type of evidence this record represents. /// EvidenceType Type { get; } /// /// The subject (node ID) this evidence is about. /// string SubjectNodeId { get; } /// /// When the evidence was created (UTC). /// DateTimeOffset CreatedAt { get; } /// /// Cryptographic signatures attesting to this evidence. /// IReadOnlyList Signatures { get; } /// /// Origin and provenance information. /// EvidenceProvenance? Provenance { get; } /// /// Type-specific properties as key-value pairs. /// IReadOnlyDictionary Properties { get; } } ``` ### IEvidenceStore Storage interface for evidence persistence. ```csharp namespace StellaOps.Evidence.Core; public interface IEvidenceStore { /// /// Retrieves evidence by its content-addressed ID. /// Task GetAsync(string evidenceId, CancellationToken ct = default); /// /// Retrieves all evidence records for a given subject. /// Task> GetBySubjectAsync( string subjectNodeId, CancellationToken ct = default); /// /// Retrieves all evidence records of a specific type. /// Task> GetByTypeAsync( EvidenceType type, CancellationToken ct = default); /// /// Stores an evidence record. /// Task StoreAsync(IEvidence evidence, CancellationToken ct = default); /// /// Checks if evidence with the given ID exists. /// Task ExistsAsync(string evidenceId, CancellationToken ct = default); } ``` ### IEvidenceAdapter Adapter interface for converting module-specific types to evidence. ```csharp namespace StellaOps.Evidence.Core.Adapters; public interface IEvidenceAdapter { /// /// Converts a module-specific input to one or more evidence records. /// IReadOnlyList ToEvidence(TInput input); } ``` --- ## Records ### EvidenceRecord Standard implementation of IEvidence. ```csharp namespace StellaOps.Evidence.Core; public sealed record EvidenceRecord : IEvidence { public required string EvidenceId { get; init; } public required EvidenceType Type { get; init; } public required string SubjectNodeId { get; init; } public required DateTimeOffset CreatedAt { get; init; } public IReadOnlyList Signatures { get; init; } = []; public EvidenceProvenance? Provenance { get; init; } public IReadOnlyDictionary Properties { get; init; } = new Dictionary(); } ``` ### EvidenceSignature Cryptographic signature attached to evidence. ```csharp namespace StellaOps.Evidence.Core; public sealed record EvidenceSignature { /// /// Identifier of the signer (key ID, tool name, etc.). /// public required string SignerId { get; init; } /// /// Signing algorithm (e.g., "Ed25519", "ES256"). /// public required string Algorithm { get; init; } /// /// Base64-encoded signature bytes. /// public required string SignatureBase64 { get; init; } /// /// When the signature was created (UTC). /// public required DateTimeOffset SignedAt { get; init; } /// /// Type of entity that produced the signature. /// public required SignerType SignerType { get; init; } } ``` ### EvidenceProvenance Origin and provenance information. ```csharp namespace StellaOps.Evidence.Core; public sealed record EvidenceProvenance { /// /// Source that produced this evidence (e.g., "grype", "trivy"). /// public required string Source { get; init; } /// /// Version of the source tool. /// public string? SourceVersion { get; init; } /// /// URI where original data was obtained. /// public string? SourceUri { get; init; } /// /// Digest of the original content. /// public string? ContentDigest { get; init; } } ``` --- ## Enumerations ### EvidenceType ```csharp namespace StellaOps.Evidence.Core; public enum EvidenceType { Unknown = 0, Sbom = 1, Vulnerability = 2, Vex = 3, Attestation = 4, PolicyDecision = 5, ScanResult = 6, Provenance = 7, Signature = 8, ProofSegment = 9, Exception = 10, Advisory = 11, CveMatch = 12, ReachabilityResult = 13 } ``` ### SignerType ```csharp namespace StellaOps.Evidence.Core; public enum SignerType { Unknown = 0, Tool = 1, Human = 2, Authority = 3, Vendor = 4, Service = 5 } ``` --- ## Adapters ### EvidenceStatementAdapter Converts `EvidenceStatement` from Attestor module. **Input**: `EvidenceStatementInput` ```csharp public sealed record EvidenceStatementInput { public required string StatementId { get; init; } public required string SubjectDigest { get; init; } public required string StatementType { get; init; } public required string PredicateType { get; init; } public required DateTimeOffset IssuedAt { get; init; } public IReadOnlyList? Signatures { get; init; } public IReadOnlyDictionary? Metadata { get; init; } } ``` **Output**: Single `IEvidence` record with `Type = Attestation`. --- ### ProofSegmentAdapter Converts `ProofSegment` from Scanner module. **Input**: `ProofSegmentInput` ```csharp public sealed record ProofSegmentInput { public required string SegmentId { get; init; } public required string SubjectNodeId { get; init; } public required string SegmentType { get; init; } public required string Status { get; init; } public required DateTimeOffset CreatedAt { get; init; } public string? PreviousSegmentId { get; init; } public string? PayloadDigest { get; init; } public IReadOnlyList? Signatures { get; init; } public IReadOnlyDictionary? Properties { get; init; } } ``` **Output**: Single `IEvidence` record with `Type = ProofSegment`. --- ### VexObservationAdapter Converts `VexObservation` from Excititor module. **Input**: `VexObservationInput` ```csharp public sealed record VexObservationInput { public required string SubjectDigest { get; init; } public VexObservationUpstreamInput? Upstream { get; init; } public IReadOnlyList? Statements { get; init; } public IReadOnlyDictionary? Properties { get; init; } } public sealed record VexObservationUpstreamInput { public required string VexDocumentId { get; init; } public required string VendorName { get; init; } public required DateTimeOffset PublishedAt { get; init; } public string? DocumentDigest { get; init; } } public sealed record VexObservationStatementInput { public required string VulnerabilityId { get; init; } public required string ProductId { get; init; } public required string Status { get; init; } public required DateTimeOffset Timestamp { get; init; } public string? Justification { get; init; } } ``` **Output**: Multiple `IEvidence` records: - 1 record with `Type = Provenance` (from upstream) - N records with `Type = Vex` (one per statement) --- ### ExceptionApplicationAdapter Converts `ExceptionApplication` from Policy module. **Input**: `ExceptionApplicationInput` ```csharp public sealed record ExceptionApplicationInput { public required string ApplicationId { get; init; } public required string TenantId { get; init; } public required string ExceptionId { get; init; } public required string FindingId { get; init; } public required DateTimeOffset AppliedAt { get; init; } public DateTimeOffset? ExpiresAt { get; init; } public string? Reason { get; init; } public string? AppliedBy { get; init; } public IReadOnlyDictionary? Properties { get; init; } } ``` **Output**: Single `IEvidence` record with `Type = Exception`. --- ## Implementations ### InMemoryEvidenceStore Thread-safe in-memory evidence store for testing and caching. ```csharp var store = new InMemoryEvidenceStore(); // Store evidence await store.StoreAsync(record); // Retrieve by ID var evidence = await store.GetAsync("sha256:abc123..."); // Query by subject var subjectEvidence = await store.GetBySubjectAsync("pkg:npm/lodash@4.17.21"); // Query by type var vexRecords = await store.GetByTypeAsync(EvidenceType.Vex); // Check existence var exists = await store.ExistsAsync("sha256:abc123..."); ``` **Thread Safety**: Uses `ConcurrentDictionary` for all operations. --- ## Common Property Keys Standard property keys used across evidence types: | Key | Used By | Description | |-----|---------|-------------| | `cve` | Vulnerability, CveMatch | CVE identifier | | `severity` | Vulnerability | Severity level (CRITICAL, HIGH, etc.) | | `cvss` | Vulnerability | CVSS score | | `status` | Vex, ProofSegment | Current status | | `justification` | Vex, Exception | Reason for status | | `productId` | Vex | Affected product identifier | | `exceptionId` | Exception | Parent exception ID | | `findingId` | Exception | Finding being excepted | | `tenantId` | Exception | Tenant context | | `segmentType` | ProofSegment | Type of proof segment | | `previousSegmentId` | ProofSegment | Chain link to previous segment | | `payloadDigest` | ProofSegment | Content digest | | `predicateType` | Attestation | In-toto predicate type URI | | `statementType` | Attestation | Statement type identifier |