# 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 |