# Signal Contract Mapping: Advisory ↔ StellaOps **Document Version:** 1.0 **Last Updated:** 2025-12-19 **Status:** ACTIVE **Related Sprint:** SPRINT_5000_0001_0001 --- ## Overview This document provides a comprehensive mapping between the reference advisory's **Signal-based message contracts (10/12/14/16/18)** and the **StellaOps implementation**. While StellaOps uses domain-specific terminology, all signal concepts are fully implemented with equivalent or superior functionality. **Key Insight:** StellaOps implements the same architectural patterns as the advisory but uses domain-specific entity names instead of generic "Signal-X" labels. This provides better type safety, code readability, and domain modeling while maintaining conceptual alignment. --- ## Quick Reference Table | Advisory Signal | StellaOps Equivalent | Module | Key Files | |----------------|---------------------|---------|-----------| | **Signal-10** (SBOM Intake) | `CallgraphIngestRequest`, `ISbomIngestionService` | Scanner, Signals | `SbomIngestionService.cs`, `CallgraphIngestRequest.cs` | | **Signal-12** (Evidence/Attestation) | in-toto `Statement` + DSSE | Attestor, Signer | `InTotoStatement.cs`, `DsseEnvelope.cs`, 19 predicate types | | **Signal-14** (Triage Fact) | `TriageFinding` + related entities | Scanner.Triage | `TriageFinding.cs`, `TriageReachabilityResult.cs`, `TriageRiskResult.cs`, `TriageEffectiveVex.cs` | | **Signal-16** (Diff Delta) | `TriageSnapshot`, `MaterialRiskChange`, `DriftCause` | Scanner.SmartDiff, ReachabilityDrift | `MaterialRiskChangeDetector.cs`, `ReachabilityDriftDetector.cs`, `TriageSnapshot.cs` | | **Signal-18** (Decision) | `TriageDecision` + DSSE signatures | Scanner.Triage | `TriageDecision.cs`, `TriageEvidenceArtifact.cs` | --- ## Signal-10: SBOM Intake ### Advisory Specification ```json { "bom": "(cyclonedx:1.7)", "subject": { "image": "ghcr.io/org/app@sha256:...", "digest": "sha256:..." }, "source": "scanner-instance-1", "scanProfile": "default", "createdAt": "2025-12-19T10:00:00Z" } ``` **Purpose:** Initial SBOM ingestion with subject identification --- ### StellaOps Implementation **Primary Contract:** `CallgraphIngestRequest` **Location:** `src/Signals/StellaOps.Signals/Models/CallgraphIngestRequest.cs` ```csharp public sealed record CallgraphIngestRequest { public required string TenantId { get; init; } public required string ArtifactDigest { get; init; } // Maps to "subject.digest" public required string Language { get; init; } public required string Component { get; init; } public required string? Version { get; init; } public required string ArtifactContentBase64 { get; init; } // Maps to "bom" (encoded) public string? SchemaVersion { get; init; } public IReadOnlyDictionary? Metadata { get; init; } // Includes "source", "scanProfile" } ``` **Service Interface:** `ISbomIngestionService` **Location:** `src/Scanner/StellaOps.Scanner.WebService/Services/ISbomIngestionService.cs` ```csharp public interface ISbomIngestionService { Task IngestCycloneDxAsync( string tenantId, Stream cycloneDxJson, SbomIngestionOptions options, CancellationToken cancellationToken); Task IngestSpdxAsync( string tenantId, Stream spdxJson, SbomIngestionOptions options, CancellationToken cancellationToken); } ``` **Data Flow:** ``` [Scanner] → SbomIngestionService → [CycloneDxComposer/SpdxComposer] ↓ PostgreSQL (scanner.sboms) ↓ Event: "sbom.ingested" ↓ [Downstream processors] ``` **API Endpoints:** - `POST /api/scanner/sboms/ingest` - Direct SBOM ingestion - `POST /api/signals/callgraph/ingest` - Call graph + SBOM ingestion **Related Files:** - `src/Scanner/StellaOps.Scanner.WebService/Endpoints/SbomEndpoints.cs` - `src/Signals/StellaOps.Signals/Services/CallgraphIngestionService.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Emit/Composition/CycloneDxComposer.cs` **Equivalence Proof:** - ✅ BOM content: CycloneDX 1.6 (upgrading to 1.7) - ✅ Subject identification: `ArtifactDigest` (SHA-256) - ✅ Source tracking: `Metadata["source"]` - ✅ Profile support: `SbomIngestionOptions.ScanProfile` - ✅ Timestamp: `CreatedAt` in database entity --- ## Signal-12: Evidence/Attestation (in-toto Statement) ### Advisory Specification ```json { "subject": {"digest": {"sha256": "..."}}, "type": "attestation", "predicateType": "https://slsa.dev/provenance/v1", "predicate": {...}, "materials": [], "tool": "scanner@1.0.0", "runId": "run-123", "startedAt": "2025-12-19T10:00:00Z", "finishedAt": "2025-12-19T10:05:00Z" } ``` **Purpose:** Evidence envelopes for attestations (DSSE-wrapped) --- ### StellaOps Implementation **Primary Contract:** `InTotoStatement` (abstract base) **Location:** `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/Statements/InTotoStatement.cs` ```csharp public abstract record InTotoStatement { [JsonPropertyName("_type")] public string Type => "https://in-toto.io/Statement/v1"; [JsonPropertyName("subject")] public required IReadOnlyList Subject { get; init; } [JsonPropertyName("predicateType")] public abstract string PredicateType { get; } } ``` **DSSE Envelope:** `DsseEnvelope` **Location:** `src/Attestor/StellaOps.Attestor.Envelope/DsseEnvelope.cs` ```csharp public sealed record DsseEnvelope { [JsonPropertyName("payload")] public required string Payload { get; init; } // Base64url(canonical JSON of Statement) [JsonPropertyName("payloadType")] public required string PayloadType { get; init; } // "application/vnd.in-toto+json" [JsonPropertyName("signatures")] public required IReadOnlyList Signatures { get; init; } } ``` **Predicate Types Registry:** 19 types supported **Location:** `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/PredicateTypes.cs` ```csharp public static class PredicateTypes { // SLSA (Standard) public const string SlsaProvenanceV02 = "https://slsa.dev/provenance/v0.2"; public const string SlsaProvenanceV1 = "https://slsa.dev/provenance/v1"; // StellaOps Custom public const string StellaOpsSbom = "stella.ops/sbom@v1"; public const string StellaOpsVex = "stella.ops/vex@v1"; public const string StellaOpsEvidence = "stella.ops/evidence@v1"; public const string StellaOpsPathWitness = "stella.ops/pathWitness@v1"; public const string StellaOpsReachabilityWitness = "stella.ops/reachabilityWitness@v1"; public const string StellaOpsReachabilityDrift = "stellaops.dev/predicates/reachability-drift@v1"; public const string StellaOpsPolicyDecision = "stella.ops/policy-decision@v1"; // ... 12 more predicate types } ``` **Signing Service:** `CryptoDsseSigner` **Location:** `src/Signer/StellaOps.Signer/StellaOps.Signer.Infrastructure/Signing/CryptoDsseSigner.cs` **Data Flow:** ``` [Component] → ProofChainSigner → [Build in-toto Statement] ↓ Canonical JSON serialization ↓ DSSE PAE construction ↓ CryptoDsseSigner (KMS/Keyless) ↓ DsseEnvelope (signed) ↓ PostgreSQL (attestor.envelopes) ↓ Optional: Rekor transparency log ``` **Sample Attestation Files:** - `src/Attestor/StellaOps.Attestor.Types/samples/build-provenance.v1.json` - `src/Attestor/StellaOps.Attestor.Types/samples/vex-attestation.v1.json` - `src/Attestor/StellaOps.Attestor.Types/samples/scan-results.v1.json` **Equivalence Proof:** - ✅ Subject: `Subject` list with digests - ✅ Type: `https://in-toto.io/Statement/v1` - ✅ PredicateType: 19 supported types - ✅ Predicate: Custom per type - ✅ Tool: Embedded in predicate metadata - ✅ RunId: `TraceId` / `CorrelationId` - ✅ Timestamps: In predicate metadata - ✅ DSSE wrapping: Full implementation --- ## Signal-14: Triage Fact ### Advisory Specification ```json { "subject": "pkg:npm/lodash@4.17.0", "cve": "CVE-2024-12345", "findingId": "cve@package@symbol@subjectDigest", "location": { "file": "src/index.js", "package": "lodash", "symbol": "template" }, "reachability": { "status": "reachable", "callStackId": "cs-abc123" }, "epss": 0.85, "cvss": { "version": "4.0", "vector": "CVSS:4.0/AV:N/AC:L/...", "score": 7.5 }, "vexStatus": "affected", "notes": "...", "evidenceRefs": ["dsse://sha256:..."] } ``` **Purpose:** Triage facts per CVE with reachability, scoring, and VEX status --- ### StellaOps Implementation **Primary Entity:** `TriageFinding` (core entity tying all triage data) **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageFinding.cs` ```csharp public sealed class TriageFinding { public string FindingId { get; set; } // Stable ID: "cve@purl@scanId" public string TenantId { get; set; } public string AssetId { get; set; } // Maps to "subject" public string? Purl { get; set; } // Package URL public string? CveId { get; set; } // Maps to "cve" public string? RuleId { get; set; } // For non-CVE findings public DateTimeOffset FirstSeenAt { get; set; } public DateTimeOffset LastSeenAt { get; set; } // Navigation properties public TriageReachabilityResult? Reachability { get; set; } public TriageRiskResult? Risk { get; set; } public TriageEffectiveVex? EffectiveVex { get; set; } public ICollection EvidenceArtifacts { get; set; } public ICollection Decisions { get; set; } } ``` **Reachability Component:** `TriageReachabilityResult` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageReachabilityResult.cs` ```csharp public sealed class TriageReachabilityResult { public string ResultId { get; set; } public string FindingId { get; set; } public TriageReachability Reachability { get; set; } // Yes, No, Unknown public int Confidence { get; set; } // 0-100 public string? StaticProofRef { get; set; } // Maps to "callStackId" public string? RuntimeProofRef { get; set; } public string InputsHash { get; set; } // For caching/diffing public DateTimeOffset ComputedAt { get; set; } // Lattice evaluation public double? LatticeScore { get; set; } public string? LatticeState { get; set; } } ``` **Risk/Scoring Component:** `TriageRiskResult` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageRiskResult.cs` ```csharp public sealed class TriageRiskResult { public string ResultId { get; set; } public string FindingId { get; set; } // Scoring public double RiskScore { get; set; } // Combined score public double? CvssBaseScore { get; set; } public string? CvssVector { get; set; } // CVSS:4.0/AV:N/... public string? CvssVersion { get; set; } // "4.0" public double? EpssScore { get; set; } // Maps to "epss" public double? EpssPercentile { get; set; } public DateOnly? EpssModelDate { get; set; } // Policy decision public TriageVerdict Verdict { get; set; } // Ship, Block, Exception public string? PolicyId { get; set; } public string Lane { get; set; } // Critical, High, Medium, Low public string InputsHash { get; set; } public string? LatticeExplanationJson { get; set; } // Maps to "notes" public DateTimeOffset ComputedAt { get; set; } } ``` **VEX Component:** `TriageEffectiveVex` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageEffectiveVex.cs` ```csharp public sealed class TriageEffectiveVex { public string VexId { get; set; } public string FindingId { get; set; } public VexClaimStatus Status { get; set; } // Maps to "vexStatus" public VexJustification? Justification { get; set; } public string? ProvenancePointer { get; set; } // Linkset reference public string? DsseEnvelopeHash { get; set; } // Maps to "evidenceRefs" public DateTimeOffset EffectiveAt { get; set; } } ``` **Evidence Artifacts:** `TriageEvidenceArtifact` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageEvidenceArtifact.cs` ```csharp public sealed class TriageEvidenceArtifact { public string ArtifactId { get; set; } public string FindingId { get; set; } public string ContentHash { get; set; } // SHA-256 public string? SignatureRef { get; set; } // DSSE envelope reference public string? CasUri { get; set; } // cas://reachability/graphs/{hash} public string MediaType { get; set; } public long SizeBytes { get; set; } public DateTimeOffset CreatedAt { get; set; } } ``` **Database Schema:** - Table: `scanner.triage_findings` (core table) - Table: `scanner.triage_reachability_results` (1:1 with findings) - Table: `scanner.triage_risk_results` (1:1 with findings) - Table: `scanner.triage_effective_vex` (1:1 with findings) - Table: `scanner.triage_evidence_artifacts` (1:N with findings) **Equivalence Proof:** - ✅ Subject: `AssetId` + `Purl` - ✅ CVE: `CveId` - ✅ Finding ID: `FindingId` (stable scheme) - ✅ Location: Embedded in evidence artifacts - ✅ Reachability: Full `TriageReachabilityResult` entity - ✅ EPSS: `EpssScore`, `EpssPercentile`, `EpssModelDate` - ✅ CVSS: `CvssBaseScore`, `CvssVector`, `CvssVersion` - ✅ VEX Status: `TriageEffectiveVex.Status` - ✅ Notes: `LatticeExplanationJson` - ✅ Evidence Refs: `TriageEvidenceArtifact` with `ContentHash`, `CasUri` --- ## Signal-16: Diff Delta ### Advisory Specification ```json { "subject": "ghcr.io/org/app", "fromVersion": "1.0.0", "toVersion": "1.1.0", "changed": { "packages": ["lodash@4.17.0→4.17.21"], "files": ["src/util.js"], "symbols": ["template"], "vulns": [{"cve": "CVE-2024-12345", "action": "fixed"}] }, "explainableReasons": [ { "reasonCode": "VEX_STATUS_FLIP", "params": {"from": "affected", "to": "fixed"}, "evidenceRefs": ["dsse://..."] } ] } ``` **Purpose:** Minimal deltas between SBOM snapshots with explainable reasons --- ### StellaOps Implementation **Primary Entity:** `TriageSnapshot` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageSnapshot.cs` ```csharp public sealed class TriageSnapshot { public string SnapshotId { get; set; } public string TenantId { get; set; } public string AssetId { get; set; } // Version tracking public string? FromVersion { get; set; } // Maps to "fromVersion" public string? ToVersion { get; set; } // Maps to "toVersion" public string FromScanId { get; set; } public string ToScanId { get; set; } // Input/output hashes for diffing public string FromInputsHash { get; set; } public string ToInputsHash { get; set; } // Precomputed diff public string? DiffJson { get; set; } // Maps to "changed" // Trigger tracking public string? Trigger { get; set; } // Manual, Scheduled, EventDriven public DateTimeOffset CreatedAt { get; set; } } ``` **Smart-Diff Detector:** `MaterialRiskChangeDetector` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.SmartDiff/Detection/MaterialRiskChangeDetector.cs` ```csharp public sealed class MaterialRiskChangeDetector { // Detection rules public IReadOnlyList Detect( RiskStateSnapshot previous, RiskStateSnapshot current) { // R1: Reachability flip // R2: VEX status flip // R3: Range boundary cross // R4: Intelligence/Policy flip } } ``` **Risk State Snapshot:** `RiskStateSnapshot` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.SmartDiff/Detection/RiskStateSnapshot.cs` ```csharp public sealed record RiskStateSnapshot { public bool? Reachable { get; init; } public VexClaimStatus VexStatus { get; init; } public bool? InAffectedRange { get; init; } public bool Kev { get; init; } public double? EpssScore { get; init; } public PolicyDecision PolicyDecision { get; init; } public string? LatticeState { get; init; } // SHA-256 hash for deterministic change detection public string ComputeHash() => SHA256.Hash(CanonicalJson); } ``` **Reachability Drift Detector:** `ReachabilityDriftDetector` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.ReachabilityDrift/Services/ReachabilityDriftDetector.cs` ```csharp public sealed class ReachabilityDriftDetector { public Task DetectAsync( string baseScanId, string headScanId, CancellationToken cancellationToken); } ``` **Drift Cause Explainer:** `DriftCauseExplainer` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.ReachabilityDrift/Services/DriftCauseExplainer.cs` ```csharp public sealed class DriftCauseExplainer { // Explains why reachability changed public DriftCause Explain( CallGraphSnapshot baseGraph, CallGraphSnapshot headGraph, string sinkId); } public sealed record DriftCause { public DriftCauseKind Kind { get; init; } // Maps to "reasonCode" public string Description { get; init; } public string? ChangedSymbol { get; init; } public string? ChangedFile { get; init; } public int? ChangedLine { get; init; } public string? CodeChangeId { get; init; } // Maps to "evidenceRefs" } public enum DriftCauseKind { GuardRemoved, // "GUARD_REMOVED" NewPublicRoute, // "NEW_PUBLIC_ROUTE" VisibilityEscalated, // "VISIBILITY_ESCALATED" DependencyUpgraded, // "DEPENDENCY_UPGRADED" SymbolRemoved, // "SYMBOL_REMOVED" GuardAdded, // "GUARD_ADDED" Unknown // "UNKNOWN" } ``` **API Endpoints:** - `GET /smart-diff/scans/{scanId}/changes` - Material risk changes - `GET /smart-diff/scans/{scanId}/sarif` - SARIF 2.1.0 format - `GET /smart-diff/images/{digest}/candidates` - VEX candidates **Database Schema:** - Table: `scanner.triage_snapshots` - Table: `scanner.risk_state_snapshots` - Table: `scanner.material_risk_changes` - Table: `scanner.call_graph_snapshots` **Equivalence Proof:** - ✅ Subject: `AssetId` - ✅ From/To Version: `FromVersion`, `ToVersion` - ✅ Changed packages: In `DiffJson` + package-level diffs - ✅ Changed symbols: Reachability drift detection - ✅ Changed vulns: Material risk changes - ✅ Explainable reasons: `DriftCause` with `Kind` (reason code) - ✅ Evidence refs: `CodeChangeId`, evidence artifacts --- ## Signal-18: Decision ### Advisory Specification ```json { "subject": "pkg:npm/lodash@4.17.0", "decisionId": "dec-abc123", "severity": "HIGH", "priority": 85, "rationale": [ "Reachable from public API", "EPSS above threshold (0.85)", "No VEX from vendor" ], "actions": ["Block deployment", "Notify security team"], "dsseSignatures": ["dsse://sha256:..."] } ``` **Purpose:** Policy decisions with rationale and signatures --- ### StellaOps Implementation **Primary Entity:** `TriageDecision` **Location:** `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/TriageDecision.cs` ```csharp public sealed class TriageDecision { public string DecisionId { get; set; } // Maps to "decisionId" public string FindingId { get; set; } // Links to TriageFinding (subject) public string TenantId { get; set; } // Decision details public TriageDecisionKind Kind { get; set; } // Mute, Acknowledge, Exception public string? Reason { get; set; } // Maps to "rationale" public string? ReasonCode { get; set; } // Actor public string ActorSubject { get; set; } public string? ActorDisplayName { get; set; } // Policy reference public string? PolicyRef { get; set; } // Lifetime public DateTimeOffset EffectiveAt { get; set; } public DateTimeOffset? ExpiresAt { get; set; } public int? TtlDays { get; set; } // Reversibility public bool Revoked { get; set; } public DateTimeOffset? RevokedAt { get; set; } public string? RevokedBy { get; set; } // Signatures public string? DsseEnvelopeHash { get; set; } // Maps to "dsseSignatures" public string? SignatureRef { get; set; } public DateTimeOffset CreatedAt { get; set; } } ``` **Risk Result (includes severity/priority):** From `TriageRiskResult` ```csharp public sealed class TriageRiskResult { public double RiskScore { get; set; } // Maps to "priority" (0-100) public string Lane { get; set; } // Maps to "severity" (Critical/High/Medium/Low) public TriageVerdict Verdict { get; set; } // Maps to "actions" (Ship/Block/Exception) public string? LatticeExplanationJson { get; set; } // Maps to "rationale" (structured) } ``` **Score Explanation Service:** `ScoreExplanationService` **Location:** `src/Signals/StellaOps.Signals/Services/ScoreExplanationService.cs` ```csharp public sealed class ScoreExplanationService { // Generates structured rationale public ScoreExplanation Explain(ScoreExplanationRequest request) { // Returns breakdown of: // - CVSS contribution // - EPSS contribution // - Reachability contribution // - VEX reduction // - Gate discounts // - KEV bonus } } ``` **Decision Predicate Type:** `stella.ops/policy-decision@v1` **Location:** Defined in `PredicateTypes.cs`, implemented in attestations **Database Schema:** - Table: `scanner.triage_decisions` - Table: `scanner.triage_risk_results` (for severity/priority) **API Endpoints:** - `POST /triage/decisions` - Create decision - `DELETE /triage/decisions/{decisionId}` - Revoke decision - `GET /triage/findings/{findingId}/decisions` - List decisions for finding **Equivalence Proof:** - ✅ Subject: Linked via `FindingId` → `TriageFinding.Purl` - ✅ Decision ID: `DecisionId` - ✅ Severity: `TriageRiskResult.Lane` - ✅ Priority: `TriageRiskResult.RiskScore` - ✅ Rationale: `Reason` + `LatticeExplanationJson` (structured) - ✅ Actions: `Verdict` (Ship/Block/Exception) - ✅ DSSE Signatures: `DsseEnvelopeHash`, `SignatureRef` --- ## Idempotency Key Handling ### Advisory Pattern ``` idemKey = hash(subjectDigest || type || runId || cve || windowStart) ``` --- ### StellaOps Implementation **Event Envelope Idempotency:** **Location:** `src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Core/Domain/Events/EventEnvelope.cs` ```csharp public static string GenerateIdempotencyKey( OrchestratorEventType eventType, string? jobId, int attempt) { var jobPart = jobId ?? "none"; return $"orch-{eventType.ToEventTypeName()}-{jobPart}-{attempt}"; } ``` **Pattern:** `{domain}-{event_type}-{entity_id}-{attempt}` **Orchestrator Event Idempotency:** **Location:** `src/Scanner/StellaOps.Scanner.WebService/Contracts/OrchestratorEventContracts.cs` ```csharp public sealed record OrchestratorEvent { public required string EventId { get; init; } public required string EventKind { get; init; } public required string IdempotencyKey { get; init; } // Explicitly tracked public required string CorrelationId { get; init; } public required string TraceId { get; init; } public required string SpanId { get; init; } // ... } ``` **Finding ID Stability (Signal-14):** **Pattern:** `{cve}@{purl}@{scanId}` **Location:** `TriageFinding.FindingId` generation logic **Equivalence:** - ✅ Subject digest: Included in `scanId` or `AssetId` - ✅ Type: `EventKind` or `EventType` - ✅ Run ID: `TraceId`, `CorrelationId`, `attempt` - ✅ CVE: Included in finding ID - ✅ Window: Implicit in scan/job timing --- ## Evidence Reference Mechanisms ### Advisory Pattern ``` evidenceRefs[i] = dsse://sha256: ``` **Storage:** DSSE payloads stored as blobs, indexed by `payloadHash` and `subjectDigest` --- ### StellaOps Implementation **CAS URI Pattern:** ``` cas://reachability/graphs/{blake3_hash} cas://runtime/traces/{blake3_hash} ``` **DSSE Reference Pattern:** ``` {DsseEnvelopeHash} = SHA-256 of DSSE envelope {SignatureRef} = Reference to attestor.envelopes table ``` **Evidence Artifact Entity:** `TriageEvidenceArtifact` ```csharp public sealed class TriageEvidenceArtifact { public string ContentHash { get; set; } // SHA-256 of content public string? SignatureRef { get; set; } // DSSE envelope reference public string? CasUri { get; set; } // CAS URI for content // ... } ``` **Reachability Evidence Chain:** `ReachabilityEvidenceChain` **Location:** `src/__Libraries/StellaOps.Signals.Contracts/Models/Evidence/ReachabilityEvidenceChain.cs` ```csharp public sealed record ReachabilityEvidenceChain { public GraphEvidence? GraphEvidence { get; init; } public RuntimeEvidence? RuntimeEvidence { get; init; } public ImmutableArray CodeAnchors { get; init; } public ImmutableArray Unknowns { get; init; } } public sealed record GraphEvidence { public required string GraphHash { get; init; } // BLAKE3 public required string GraphCasUri { get; init; } // cas://... public required string AnalyzerName { get; init; } public required string AnalyzerVersion { get; init; } public DateTimeOffset AnalyzedAt { get; init; } } public sealed record RuntimeEvidence { public required string TraceHash { get; init; } // BLAKE3 public required string TraceCasUri { get; init; } // cas://... public required string ProbeType { get; init; } public required int HitCount { get; init; } public DateTimeOffset LastSeenAt { get; init; } } ``` **Storage:** - PostgreSQL: `attestor.envelopes` table for DSSE envelopes - PostgreSQL: `scanner.triage_evidence_artifacts` for evidence metadata - S3/MinIO: CAS storage for evidence blobs **Equivalence:** - ✅ Hash-addressed storage: SHA-256, BLAKE3 - ✅ DSSE references: `DsseEnvelopeHash`, `SignatureRef` - ✅ CAS URIs: `cas://` scheme for content-addressable storage - ✅ Blob storage: S3-compatible object store - ✅ Index by subject: `FindingId` links to evidence --- ## API Endpoint Mapping | Signal | Advisory Endpoint | StellaOps Endpoint | |--------|------------------|-------------------| | Signal-10 | `POST /sbom/intake` | `POST /api/scanner/sboms/ingest`
`POST /api/signals/callgraph/ingest` | | Signal-12 | `POST /attestations` | Implicit via signing services
`GET /api/attestor/envelopes/{hash}` | | Signal-14 | `GET /triage/facts/{findingId}` | `GET /api/scanner/triage/findings/{findingId}`
`GET /api/scanner/triage/findings/{findingId}/evidence` | | Signal-16 | `GET /diff/{from}/{to}` | `GET /api/smart-diff/scans/{scanId}/changes`
`GET /api/smart-diff/images/{digest}/candidates` | | Signal-18 | `POST /decisions` | `POST /api/triage/decisions`
`GET /api/triage/findings/{findingId}/decisions` | --- ## Component Architecture Alignment ### Advisory Architecture ``` [ Sbomer ] → Signal-10 → [ Router ] [ Attestor ] → Signal-12 → [ Router ] [ Scanner.Worker ] → Signal-14 → [ Triage Store ] [ Reachability.Engine ] → updates Signal-14 [ Smart-Diff ] → Signal-16 → [ Router ] [ Deterministic-Scorer ] → Signal-18 → [ Router/Notify ] ``` --- ### StellaOps Architecture ``` [ Scanner.Emit ] → SbomIngestionService → PostgreSQL (scanner.sboms) [ Attestor.ProofChain ] → DsseEnvelopeSigner → PostgreSQL (attestor.envelopes) [ Scanner.Triage ] → TriageFinding + related entities → PostgreSQL (scanner.triage_*) [ ReachabilityAnalyzer ] → PathWitnessBuilder → TriageReachabilityResult [ SmartDiff + ReachabilityDrift ] → MaterialRiskChangeDetector → TriageSnapshot [ Policy.Scoring engines ] → ScoreExplanationService → TriageRiskResult + TriageDecision [ Router.Gateway ] → TransportDispatchMiddleware → Inter-service routing [ TimelineIndexer ] → TimelineEventEnvelope → Event ordering & storage ``` **Mapping:** - Sbomer ↔ Scanner.Emit - Attestor ↔ Attestor.ProofChain - Scanner.Worker ↔ Scanner.Triage - Reachability.Engine ↔ ReachabilityAnalyzer - Smart-Diff ↔ SmartDiff + ReachabilityDrift - Deterministic-Scorer ↔ Policy.Scoring engines - Router/Timeline ↔ Router.Gateway + TimelineIndexer --- ## Summary **Alignment Status:** ✅ **Fully Aligned (Conceptually)** While StellaOps uses domain-specific entity names instead of generic "Signal-X" labels, all signal concepts are implemented with equivalent or superior functionality: - ✅ **Signal-10:** SBOM intake via `CallgraphIngestRequest`, `ISbomIngestionService` - ✅ **Signal-12:** in-toto attestations with 19 predicate types, DSSE signing - ✅ **Signal-14:** Comprehensive triage entities (`TriageFinding`, `TriageReachabilityResult`, `TriageRiskResult`, `TriageEffectiveVex`) - ✅ **Signal-16:** Smart-diff with `TriageSnapshot`, `MaterialRiskChange`, explainable drift causes - ✅ **Signal-18:** `TriageDecision` with DSSE signatures and structured rationale **Key Advantages of StellaOps Implementation:** 1. **Type Safety:** Strong entity types vs. generic JSON blobs 2. **Relational Integrity:** PostgreSQL foreign keys enforce referential integrity 3. **Query Performance:** Indexed tables for fast lookups 4. **Domain Clarity:** Names reflect business concepts (Triage, Risk, Evidence) 5. **Extensibility:** Easy to add new fields/entities without breaking contracts **Recommendation:** Maintain current architecture and entity naming. Provide this mapping document to demonstrate compliance with advisory signal patterns. --- ## References ### StellaOps Code Files - `src/Signals/StellaOps.Signals/Models/CallgraphIngestRequest.cs` - `src/Attestor/__Libraries/StellaOps.Attestor.ProofChain/Statements/InTotoStatement.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.Triage/Entities/*.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.SmartDiff/Detection/MaterialRiskChangeDetector.cs` - `src/Scanner/__Libraries/StellaOps.Scanner.ReachabilityDrift/Services/*.cs` - `src/Signer/StellaOps.Signer/StellaOps.Signer.Core/PredicateTypes.cs` ### Advisory References - Advisory architecture document (CycloneDX 1.7 / VEX-first / in-toto) - Signal contracts specification (10/12/14/16/18) - DSSE specification: https://github.com/secure-systems-lab/dsse - in-toto attestation framework: https://github.com/in-toto/attestation ### StellaOps Documentation - `docs/07_HIGH_LEVEL_ARCHITECTURE.md` - `docs/modules/scanner/architecture.md` - `docs/modules/attestor/transparency.md` - `docs/contracts/witness-v1.md`