docs consolidation
This commit is contained in:
408
docs/api/evidence-api-reference.md
Normal file
408
docs/api/evidence-api-reference.md
Normal file
@@ -0,0 +1,408 @@
|
||||
# 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Content-addressed evidence identifier (e.g., "sha256:abc123...").
|
||||
/// </summary>
|
||||
string EvidenceId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of evidence this record represents.
|
||||
/// </summary>
|
||||
EvidenceType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The subject (node ID) this evidence is about.
|
||||
/// </summary>
|
||||
string SubjectNodeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// When the evidence was created (UTC).
|
||||
/// </summary>
|
||||
DateTimeOffset CreatedAt { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Cryptographic signatures attesting to this evidence.
|
||||
/// </summary>
|
||||
IReadOnlyList<EvidenceSignature> Signatures { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Origin and provenance information.
|
||||
/// </summary>
|
||||
EvidenceProvenance? Provenance { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Type-specific properties as key-value pairs.
|
||||
/// </summary>
|
||||
IReadOnlyDictionary<string, string> Properties { get; }
|
||||
}
|
||||
```
|
||||
|
||||
### IEvidenceStore
|
||||
|
||||
Storage interface for evidence persistence.
|
||||
|
||||
```csharp
|
||||
namespace StellaOps.Evidence.Core;
|
||||
|
||||
public interface IEvidenceStore
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves evidence by its content-addressed ID.
|
||||
/// </summary>
|
||||
Task<IEvidence?> GetAsync(string evidenceId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all evidence records for a given subject.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<IEvidence>> GetBySubjectAsync(
|
||||
string subjectNodeId,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all evidence records of a specific type.
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<IEvidence>> GetByTypeAsync(
|
||||
EvidenceType type,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Stores an evidence record.
|
||||
/// </summary>
|
||||
Task StoreAsync(IEvidence evidence, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if evidence with the given ID exists.
|
||||
/// </summary>
|
||||
Task<bool> ExistsAsync(string evidenceId, CancellationToken ct = default);
|
||||
}
|
||||
```
|
||||
|
||||
### IEvidenceAdapter<TInput>
|
||||
|
||||
Adapter interface for converting module-specific types to evidence.
|
||||
|
||||
```csharp
|
||||
namespace StellaOps.Evidence.Core.Adapters;
|
||||
|
||||
public interface IEvidenceAdapter<TInput>
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a module-specific input to one or more evidence records.
|
||||
/// </summary>
|
||||
IReadOnlyList<IEvidence> 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<EvidenceSignature> Signatures { get; init; } = [];
|
||||
public EvidenceProvenance? Provenance { get; init; }
|
||||
public IReadOnlyDictionary<string, string> Properties { get; init; } =
|
||||
new Dictionary<string, string>();
|
||||
}
|
||||
```
|
||||
|
||||
### EvidenceSignature
|
||||
|
||||
Cryptographic signature attached to evidence.
|
||||
|
||||
```csharp
|
||||
namespace StellaOps.Evidence.Core;
|
||||
|
||||
public sealed record EvidenceSignature
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifier of the signer (key ID, tool name, etc.).
|
||||
/// </summary>
|
||||
public required string SignerId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Signing algorithm (e.g., "Ed25519", "ES256").
|
||||
/// </summary>
|
||||
public required string Algorithm { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Base64-encoded signature bytes.
|
||||
/// </summary>
|
||||
public required string SignatureBase64 { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the signature was created (UTC).
|
||||
/// </summary>
|
||||
public required DateTimeOffset SignedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of entity that produced the signature.
|
||||
/// </summary>
|
||||
public required SignerType SignerType { get; init; }
|
||||
}
|
||||
```
|
||||
|
||||
### EvidenceProvenance
|
||||
|
||||
Origin and provenance information.
|
||||
|
||||
```csharp
|
||||
namespace StellaOps.Evidence.Core;
|
||||
|
||||
public sealed record EvidenceProvenance
|
||||
{
|
||||
/// <summary>
|
||||
/// Source that produced this evidence (e.g., "grype", "trivy").
|
||||
/// </summary>
|
||||
public required string Source { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Version of the source tool.
|
||||
/// </summary>
|
||||
public string? SourceVersion { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// URI where original data was obtained.
|
||||
/// </summary>
|
||||
public string? SourceUri { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Digest of the original content.
|
||||
/// </summary>
|
||||
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<EvidenceSignatureInput>? Signatures { get; init; }
|
||||
public IReadOnlyDictionary<string, string>? 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<EvidenceSignatureInput>? Signatures { get; init; }
|
||||
public IReadOnlyDictionary<string, string>? 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<VexObservationStatementInput>? Statements { get; init; }
|
||||
public IReadOnlyDictionary<string, string>? 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<string, string>? 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 |
|
||||
Reference in New Issue
Block a user