25 KiB
Reachability Analysis Technical Reference
Source Advisories:
- 05-Dec-2025 - Building a Deterministic, Reachability‑First Architecture
- 13-Dec-2025 - Designing the Call‑Stack Reachability Engine
- 03-Dec-2025 - Reachability Benchmarks and Moat Metrics
- 09-Dec-2025 - Caching Reachability the Smart Way
- 04-Dec-2025 - Ranking Unknowns in Reachability Graphs
- 02-Dec-2025 - Designing Deterministic Reachability UX
- 05-Dec-2025 - Design Notes on Smart‑Diff and Call‑Stack Analysis
Last Updated: 2025-12-14
1. ARCHITECTURE PATTERNS
1.1 Core System Architecture
Module Responsibilities
StellaOps.Scanner.WebService: Authoritative for reachability pipeline and lattice computation- Language workers: Stateless compute producing
CallGraph.v1.json - Runtime collectors: Agent/sidecar emitting evidence events only
- Concelier/Excititor: Provide pruned sources; never compute reachability
- Authority: Manages replay manifests, crypto profiles
- Scheduler: Executes rescan/escalation policies
Architectural Rules
- Scanner = origin of truth for reachability
- Concelier/Vexer = prune-preservers only
- Authority = replay manifest owner
- Scheduler = executor of policies
- Postgres = System of Record (SoR)
- Valkey = ephemeral only (dedupe, hot cache, rate limits)
1.2 Evidence Graph Structure
Node Types
Artifact,Component,Vulnerability,Attestation,Build,Deployment,RuntimeSignal
Edge Types
DESCRIBES,AFFECTS,NOT_AFFECTED_BY,FIXED_IN,DERIVED_FROM,DEPLOYS,OBSERVED_AT_RUNTIME
Edge Signing
- Sign edges, not just nodes (edge = claim)
1.3 Determinism Requirements
Input Manifest Structure
{
"scannerVersion": "1.3.0",
"rulesetId": "stella-default-2025.11",
"feeds": {
"nvdDigest": "sha256:...",
"osvDigest": "sha256:..."
},
"sbomDigest": "sha256:...",
"policyDigest": "sha256:..."
}
Canonicalization Rules
- Sort arrays by stable keys
- Normalize paths (POSIX style)
- Line endings (LF)
- Encodings (UTF-8)
- No environment variables in core algorithms
- No machine-local files
- No system clock inside algorithms
2. DATA CONTRACTS
2.1 CallGraph.v1.json Schema
{
"schema": "stella.callgraph.v1",
"scanKey": "uuid",
"language": "dotnet|java|node|python|go|rust|binary",
"artifacts": [{
"artifactKey": "…",
"kind": "assembly|jar|module|binary",
"sha256": "…"
}],
"nodes": [{
"nodeId": "…",
"artifactKey": "…",
"symbolKey": "Namespace.Type::Method(…)",
"visibility": "public|internal|private|unknown",
"isEntrypointCandidate": false
}],
"edges": [{
"from": "nodeId",
"to": "nodeId",
"kind": "static|heuristic",
"reason": "direct_call|virtual_call|reflection_string|di_binding|dynamic_import|unknown",
"weight": 1.0
}],
"entrypoints": [{
"nodeId": "…",
"kind": "http|grpc|cli|job|event|unknown",
"route": "/api/orders/{id}",
"framework": "aspnetcore|minimalapi|spring|express|unknown"
}]
}
2.2 RuntimeEvidence.v1.json Schema
{
"schema": "stella.runtimeevidence.v1",
"scanKey": "uuid",
"collectedAt": "2025-12-14T10:00:00Z",
"environment": {
"os": "linux|windows",
"k8s": {"namespace": "…", "pod": "…", "container": "…"},
"imageDigest": "sha256:…",
"buildId": "…"
},
"samples": [{
"timestamp": "…",
"pid": 1234,
"threadId": 77,
"frames": ["nodeId","nodeId","nodeId"],
"sampleWeight": 1.0
}],
"loadedArtifacts": [{
"artifactKey": "…",
"evidence": "loaded_module|mapped_file|jar_loaded"
}]
}
2.3 ReplayManifest.json Schema
{
"schema": "stella.replaymanifest.v1",
"scanId": "uuid",
"inputs": {
"sbomDigest": "sha256:…",
"callGraphs": [{"language":"dotnet","digest":"sha256:…"}],
"runtimeEvidence": [{"digest":"sha256:…"}],
"concelierSnapshot": "sha256:…",
"excititorSnapshot": "sha256:…",
"policyDigest": "sha256:…"
}
}
2.4 ProofSpine Data Model
public sealed record ProofSpine(
string SpineId,
string ArtifactId,
string VulnerabilityId,
string PolicyProfileId,
IReadOnlyList<ProofSegment> Segments,
string Verdict,
string VerdictReason,
string RootHash,
string ScanRunId,
DateTimeOffset CreatedAt,
string? SupersededBySpineId
);
public sealed record ProofSegment(
string SegmentId,
string SegmentType,
int Index,
string InputHash,
string ResultHash,
string? PrevSegmentHash,
DsseEnvelope Envelope,
string ToolId,
string ToolVersion,
string Status
);
Segment Types
SBOM_SLICE: Component relevanceMATCH: SBOM-to-vuln mappingREACHABILITY: Symbol reachabilityGUARD_ANALYSIS: Config/feature flag gatesRUNTIME_OBSERVATION: Runtime evidencePOLICY_EVAL: Lattice decision
3. DATABASE SCHEMAS
3.1 Core Reachability Tables (Postgres)
-- Scan tracking
CREATE TABLE scan (
scan_id uuid PRIMARY KEY,
created_at timestamptz,
repo_uri text,
commit_sha text,
sbom_digest text,
policy_digest text,
status text
);
CREATE INDEX idx_scan_cache ON scan(commit_sha, sbom_digest);
-- Artifacts
CREATE TABLE artifact (
artifact_id uuid PRIMARY KEY,
scan_id uuid REFERENCES scan,
artifact_key text,
kind text,
sha256 text,
build_id text,
purl text,
UNIQUE(scan_id, artifact_key)
);
-- Call graph nodes
CREATE TABLE cg_node (
scan_id uuid,
node_id text,
artifact_key text,
symbol_key text,
visibility text,
flags int,
PRIMARY KEY(scan_id, node_id)
);
-- Call graph edges
CREATE TABLE cg_edge (
scan_id uuid,
from_node_id text,
to_node_id text,
kind smallint,
reason smallint,
weight real,
PRIMARY KEY(scan_id, from_node_id, to_node_id, kind, reason)
);
CREATE INDEX idx_cg_edge_from ON cg_edge(scan_id, from_node_id);
CREATE INDEX idx_cg_edge_to ON cg_edge(scan_id, to_node_id);
-- Entrypoints
CREATE TABLE entrypoint (
scan_id uuid,
node_id text,
kind text,
framework text,
route text,
PRIMARY KEY(scan_id, node_id, kind, framework, route)
);
-- Runtime samples
CREATE TABLE runtime_sample (
scan_id uuid,
collected_at timestamptz,
env_hash text,
sample_id bigserial PRIMARY KEY,
timestamp timestamptz,
pid int,
thread_id int,
frames text[],
weight real
);
-- Symbol-to-component mapping
CREATE TABLE symbol_component_map (
scan_id uuid,
node_id text,
purl text,
mapping_kind text,
confidence real,
PRIMARY KEY(scan_id, node_id, purl)
);
-- Reachability results
CREATE TABLE reachability_component (
scan_id uuid,
purl text,
status smallint,
confidence real,
why jsonb,
evidence jsonb,
PRIMARY KEY(scan_id, purl)
);
CREATE TABLE reachability_finding (
scan_id uuid,
cve_id text,
purl text,
status smallint,
confidence real,
why jsonb,
evidence jsonb,
PRIMARY KEY(scan_id, cve_id, purl)
);
3.2 Unknowns Ranking Tables
CREATE TABLE unknowns (
unknown_id uuid PRIMARY KEY,
pkg_id text,
pkg_version text,
digest_anchor bytea,
unknown_flags jsonb,
popularity_p float,
potential_e float,
uncertainty_u float,
centrality_c float,
staleness_s float,
score float,
band text CHECK(band IN ('HOT','WARM','COLD')),
graph_slice_hash bytea,
evidence_set_hash bytea,
normalization_trace jsonb,
callgraph_attempt_hash bytea,
created_at timestamptz,
updated_at timestamptz
);
CREATE TABLE deploy_refs (
pkg_id text,
image_id text,
env text,
first_seen timestamptz,
last_seen timestamptz
);
CREATE TABLE graph_metrics (
pkg_id text PRIMARY KEY,
degree_c float,
betweenness_c float,
last_calc_at timestamptz
);
3.3 Proof Spine Tables
CREATE TABLE proof_spines (
spine_id uuid PRIMARY KEY,
artifact_id text,
vuln_id text,
policy_profile_id text,
verdict text,
verdict_reason text,
root_hash text,
scan_run_id uuid,
created_at timestamptz,
superseded_by_spine_id uuid,
segment_count int
);
CREATE INDEX idx_spine_lookup ON proof_spines(artifact_id, vuln_id, policy_profile_id);
CREATE TABLE proof_segments (
segment_id uuid PRIMARY KEY,
spine_id uuid REFERENCES proof_spines,
idx int,
segment_type text,
input_hash text,
result_hash text,
prev_segment_hash text,
envelope bytea,
tool_id text,
tool_version text,
status text,
created_at timestamptz
);
4. ALGORITHMS
4.1 Reachability Status Classification
Status Values
UNREACHABLE: No path from entrypointsPOSSIBLY_REACHABLE: Graph incomplete/dynamic behaviorREACHABLE_STATIC: Static path existsREACHABLE_PROVEN: Runtime evidence confirms
Confidence Scoring (Deterministic)
Base scores:
UNREACHABLE → 0.05
POSSIBLY_REACHABLE → 0.35
REACHABLE_STATIC → 0.70
REACHABLE_PROVEN → 0.95
Modifiers:
+0.10 if path uses only static edges
-0.15 if path includes reflection_string|dynamic_import
+0.10 if runtime evidence hits affected component
-0.10 if NO_ENTRYPOINTS_DISCOVERED
Clamp to [0, 1]
4.2 Reachability Computation Algorithm
Inputs:
- Call graph nodes/edges + entrypoints
- Runtime evidence (optional)
- SBOM with purls
- Vulnerability facts (CVE ↔ purl/version)
- VEX statements
Steps:
1. Build adjacency list for cg_edge.kind in (static, heuristic)
2. Optional: Compress SCCs (Tarjan/Kosaraju)
3. Seed from entrypoints; if empty → mark POSSIBLY_REACHABLE with NO_ENTRYPOINTS_DISCOVERED
4. Traverse reachable nodes; track:
- firstSeenFromEntrypoint[node]
- pathWitness[node]
5. Map reachable nodes to purls via symbol_component_map:
Priority order:
a. Exact binary symbol → package metadata
b. Assembly/jar/module to SBOM component (hash/purl)
c. Heuristics: namespace prefixes, import paths, jar manifest
6. Runtime evidence upgrade:
- Mark frame nodes as "executed"
- Mint runtime edges: consecutive frames → runtime_minted
- Upgrade to REACHABLE_PROVEN if executed node maps to affected purl
7. Compute confidence using deterministic formula
4.3 Unknowns Ranking Algorithm
Score Formula
Score = clamp01(
wP·P + # Popularity impact
wE·E + # Exploit consequence potential
wU·U + # Uncertainty density
wC·C + # Graph centrality
wS·S # Evidence staleness
)
Default Weights
wP = 0.25 (deployment impact)
wE = 0.25 (potential consequence)
wU = 0.25 (uncertainty density)
wC = 0.15 (graph centrality)
wS = 0.10 (evidence staleness)
Heuristics
P = min(1, log10(1 + deployments)/log10(1 + 100))
U = sum of flags, capped at 1.0:
+0.30 if no provenance anchor
+0.25 if version_range
+0.20 if conflicting_feeds
+0.15 if missing_vector
+0.10 if unreachable source advisory
S = min(1, age_days / 14)
Band Assignment
Score ≥ 0.70 → HOT (immediate rescan + VEX escalation)
0.40 ≤ Score < 0.70 → WARM (scheduled rescan 12-72h)
Score < 0.40 → COLD (weekly batch)
4.4 Node ID Computation (.NET)
Primary (IL-based)
nodeId = SHA256(MVID + ":" + metadataToken + ":" + arity + ":" + signatureShape)
Fallback (source-only)
nodeId = SHA256(projectPath + ":" + file + ":" + span + ":" + symbolDisplayString)
External nodes
nodeId = SHA256("ext:" + artifactKey + ":" + symbolKey)
4.5 Canonical Symbol Key Format
{Namespace}.{TypeName}[`Arity][+Nested]::{MethodName}[`Arity]({ParamType1},{ParamType2},...)
Rules:
- Use
System.*full names for BCL types - Use
+for nested types (metadata style) - Use backtick arity for generic type/method definitions
- Arrays:
System.String[] - Byref:
System.String&
4.6 Reachability Cache Algorithm
public readonly record struct ReachKey(
string AlgoSig, // e.g., "RTA@sha256:…"
string InputsHash, // SBOM slice + policy + versions
string CallPathHash // normalized query graph
);
public sealed class ReachCache {
private readonly ConcurrentDictionary<ReachKey, Lazy<Task<ReachResult>>> _memo = new();
public Task<ReachResult> GetOrComputeAsync(
ReachKey key,
Func<Task<ReachResult>> compute,
CancellationToken ct)
{
var lazy = _memo.GetOrAdd(key, _ => new Lazy<Task<ReachResult>>(
() => compute(), LazyThreadSafetyMode.ExecutionAndPublication));
return lazy.Value.ContinueWith(t => {
if (t.IsCompletedSuccessfully) return t.Result;
_memo.TryRemove(key, out _);
throw t.Exception ?? new Exception("reachability failed");
}, ct);
}
}
Operational rules
- Canonical everything: sort nodes/edges, normalize paths
- Cache scope: per-scan, per-workspace, or per-feed version
- TTL: 15-60 minutes or evict after pipeline completes
- Max-entries cap
- Concurrency:
Lazy<Task<>>coalesces duplicate in-flight calls
4.7 Proof Spine Construction
1. Sbomer produces SBOM_SLICE segment, DSSE-signs it
2. Scanner produces MATCH segment
3. Reachability produces REACHABILITY segment
4. Guard Analyzer produces GUARD_ANALYSIS segment
5. Vexer evaluates lattice, produces POLICY_EVAL segment
6. ProofSpineBuilder:
- Sorts segments by predetermined order
- Chains PrevSegmentHash
- Computes RootHash = hash(concat of segment hashes)
- Stores ProofSpine with deterministic SpineId
5. API CONTRACTS
5.1 Scanner Ingestion Endpoints
POST /api/scans
Returns: scanId
POST /api/scans/{scanId}/callgraphs
Body: CallGraph.v1.json
Header: Content-Digest (for idempotency)
POST /api/scans/{scanId}/runtimeevidence
Body: RuntimeEvidence.v1.json
POST /api/scans/{scanId}/sbom
Body: CycloneDX/SPDX
POST /api/scans/{scanId}/compute-reachability
Idempotent trigger
5.2 Query Endpoints
GET /api/scans/{scanId}/reachability/components?purl=...
GET /api/scans/{scanId}/reachability/findings?cve=...
GET /api/scans/{scanId}/reachability/explain?cve=...&purl=...
Returns: why[], path witness, sample refs
5.3 Export Endpoints
GET /api/scans/{scanId}/exports/sarif
GET /api/scans/{scanId}/exports/cdxr # CycloneDX reachability extension
GET /api/scans/{scanId}/exports/openvex
5.4 Proof Spine Endpoints
GET /graph/runtime/{podId}/lineage
GET /graph/image/{digest}/vex
GET /spines/{spineId}
Returns: ProofSpine with all segments
6. .NET IMPLEMENTATION PATTERNS
6.1 .NET Worker (Roslyn + IL) Required Features
Call Graph Extraction
- Direct invocation edges:
InvocationExpressionSyntax - Object creation edges: constructors
- Delegate invocation: record heuristic edge when target unresolved
- Virtual/interface dispatch: record
virtual_calledge to declared method - Async/await: connect logical caller → awaited method
Entrypoint Discovery
Program.Main(classic)- ASP.NET Core:
- Controllers:
[ApiController], route attributes, action methods - Minimal APIs:
MapGet/MapPost/MapMethodspatterns - gRPC:
MapGrpcService<T>()and service methods - Hosted services:
IHostedService,BackgroundService.ExecuteAsync
- Controllers:
Reflection and DI Heuristics
Type.GetType("…"),Assembly.GetType,GetMethod("…"),Invokeservices.AddTransient<IFoo,Foo>()/AddScoped/AddSingletonActivator.CreateInstance,ServiceProvider.GetService- Produce heuristic edges with
reason = di_bindingorreflection_string
6.2 NuGet Dependencies
<!-- Roslyn / MSBuild -->
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="5.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="5.0.0" />
<PackageReference Include="Microsoft.Build.Locator" Version="*" />
<!-- IL + metadata -->
<!-- Use System.Reflection.Metadata (BCL) -->
<!-- Optional: Mono.Cecil for faster IL traversal -->
<!-- CLI + JSON -->
<PackageReference Include="System.CommandLine" Version="*" />
<PackageReference Include="System.Text.Json" Version="*" />
6.3 Roslyn IL Opcodes for Call Detection
Recognize as "calls":
- call
- callvirt
- newobj
- jmp
- ldftn
- ldvirtftn
6.4 MSBuild Workspace Loading Pattern
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;
var ws = MSBuildWorkspace.Create();
var sln = await ws.OpenSolutionAsync(@"path\to.sln");
foreach (var proj in sln.Projects)
foreach (var doc in proj.Documents)
{
var model = await doc.GetSemanticModelAsync();
var root = await doc.GetSyntaxRootAsync();
foreach (var node in root.DescendantNodes()
.OfType<InvocationExpressionSyntax>())
{
var sym = model.GetSymbolInfo(node).Symbol as IMethodSymbol;
if (sym != null)
{
// record edge: caller -> sym
}
}
}
7. CONFIGURATION PATTERNS
7.1 Crypto Profiles
public interface ICryptoProfile
{
string ProfileId { get; }
byte[] Sign(byte[] data, string keyId);
bool Verify(byte[] data, byte[] signature, string keyId);
}
// Implementations: FipsProfile, GostProfile, EidasProfile, SmProfile, PqcProfile
Profile Metadata
- Algorithm
- Key ID
- Profile name
Key Rotation
- Keys have validity intervals
- Spines keep KeyId in each DSSE signature
- Authority maintains trust table: which keys trusted for which SegmentType and time window
7.2 Offline Bundle Format
Required Contents
- SBOM + feeds + policy bundle + key material
- Manifest with hashes of all contents
- Replay manifest for deterministic rerun
Format
- Zip/tar + manifest
- Each entry content-addressed
7.3 Cache Configuration (appsettings)
{
"Scanner": {
"Reach": {
"Cache": {
"MaxEntries": 10000,
"TtlMinutes": 60,
"EvictOnPipelineComplete": true
}
}
}
}
8. METRICS AND THRESHOLDS
8.1 Performance SLOs (v1)
Medium service (100k LOC .NET) static graph: < 2 minutes
Reachability compute: < 30 seconds
Query GET finding: < 200ms p95
8.2 Quality Metrics
Proof verification
- % verified proofs
- Proof verification failures
- Proof age since last verification
- % entries with valid inclusion proof (Rekor)
Unknowns triage
- Hot/Warm/Cold distribution
- Rescan success rate after N attempts
- Evidence staleness distribution
Drift detection
- Runtime edges not in static graph (above threshold → emit COVERAGE_DRIFT warning)
8.3 Benchmark Metrics (Moat)
| Metric | Target |
|---|---|
| Time-to-evidence: SBOM → signed call-graph | < 5 minutes for 100k LOC service |
| SBOM-diff false positive rate under dependency churn | < 5% change in reachability status for non-code changes |
| Deterministic priority scoring under air-gap replay | Bit-identical results given same inputs |
| Proof verification time | < 200ms p95 |
9. TESTING PATTERNS
9.1 Golden Corpus Requirements
Mandatory Test Cases
- Minimal ASP.NET controller with reachable endpoint → vulnerable lib call
- Vulnerable lib present but never called → unreachable
- Reflection-based activation → "possible" unless runtime proves
- BackgroundService job case
- Version range ambiguity
- Mismatched epoch/backport
- Missing CVSS vector
- Conflicting severity vendor/NVD
- Unanchored filesystem library
Assertions per Test
- Reachability status
- At least one
why[]reason - Deterministic confidence within ±0.01
- Segments with expected status (verified/partial/invalid)
9.2 Replay Manifest Tests
Given manifest containing:
- feed hashes
- rules version
- normalization logic
- lattice rules
Assert: ranking/reachability recomputes identically (byte-for-byte)
9.3 Signature Tampering Tests
- Flip byte in DSSE payload → UI must show
invalid - Mark key untrusted → segments show
untrusted-key - Entire spine marked as compromised
10. SPECIFICATION COMPLIANCE
10.1 SBOM Standards
CycloneDX
- Version: 1.6 (ECMA-424) and 1.7 (current)
- Media type: include version parameter
- Ingest: validate against ECMA-424/1.7 schemas
SPDX
- Version: 3.0.1
- Validate against canonical spec
Ingestion Rules
- Accept only
*.cdx.jsonand*.spdx.json - Hard fail others
- Store: raw bytes + parsed form + normalized canonical form
10.2 VEX Standards
OpenVEX
- Minimal, SBOM-agnostic
- Predicate type:
https://openvex.dev/ns/v0.2.0
CSAF VEX
- Alternative format for interoperability
Required VEX Fields
- status:
not_affected|affected|fixed|under_investigation - justification
- timestamp
- author
- link to supporting evidence
10.3 Attestation Standards
DSSE (Dead Simple Signing Envelope)
- Use for all signed artifacts
- Payload: canonical JSON
- Envelope: signature + key metadata + profile
in-toto
- Statement structure
- Predicate types:
- SBOM:
https://spdx.dev/Document - VEX: OpenVEX predicate URI
- Custom: reachability predicates
- SBOM:
Cosign Integration
cosign attest --yes --type https://spdx.dev/Document \
--predicate sbom.spdx.json \
--key cosign.key \
"${IMAGE_DIGEST}"
10.4 Rekor Integration
CLI Verification
rekor-cli verify --rekor_server https://rekor.sigstore.dev \
--signature artifact.sig \
--public-key cosign.pub \
--artifact artifact.bin
Persistence per Entry
- Rekor UUID
- Log index
- Integrated time
- Inclusion proof data
11. CLI COMMANDS
11.1 Worker CLI
# Artifacts-first scan
stella-worker-dotnet scan \
--scanKey 00000000-0000-0000-0000-000000000000 \
--assemblies ./artifacts/bin/Release \
--out ./callgraph.json
# Build-and-scan
stella-worker-dotnet scan \
--scanKey ... \
--sln ./src/MySolution.sln \
--configuration Release \
--tfm net10.0 \
--buildMode build \
--out ./callgraph.json
# Upload to scanner.webservice
stella-worker-dotnet scan \
--scanKey ... \
--assemblies ./artifacts/bin/Release \
--upload https://scanner/api/scans/{scanId}/callgraphs \
--apiKey $STELLA_API_KEY
11.2 Replay CLI
stellaops scan \
--replay-manifest <id-or-file> \
--artifact <image-digest> \
--vuln <cve> \
--explain
11.3 Reachability Query CLI
stella scan graph --lang dotnet --sln path.sln --out graph.scc.json
stella scan runtime --target pod/myservice --duration 30s --out stacks.json
stella reachability join \
--graph graph.scc.json \
--runtime stacks.json \
--sbom bom.cdx.json \
--out reach.cdxr.json
12. DEVELOPER CHECKLIST
12.1 Per-Feature Definition of Done
For any feature touching scans, VEX, or evidence:
- Deterministic: input manifest defined, canonicalization applied, golden fixture(s) added
- Evidence: outputs DSSE-wrapped and linked
- Reachability/Lattice: runs only in allowed services, records algorithm IDs
- Crypto: calls through profile abstraction, tests for ≥2 profiles
- Graph: lineage edges added, node/edge IDs stable and queryable
- UX/API: API to retrieve structured evidence
- Tests: unit + golden + integration test with full SBOM → scan → VEX chain
12.2 Determinism Checklist
- Input manifest type defined and versioned
- Canonicalization applied before hashing/signing
- Output stored with
inputsDigestandalgoDigest - At least one golden fixture proves determinism
- No environment variables in core algorithm
- No machine-local files
- No system clock inside algorithms
12.3 Reachability Implementation Checklist
- Reachability algorithms only in Scanner.WebService
- Cache lazy and keyed by deterministic inputs
- Output includes explicit evidence pointers
- UI endpoints expose reachability state in structured form
- All modifiers recorded in
why[]
12.4 Crypto-Sovereign Checklist
- No direct crypto calls in feature code; only via profile layer
- All attestations carry algorithm + key id + profile
- Offline bundle type exists for this workflow
- Tests for at least 2 different crypto profiles
12.5 Policy/Lattice Checklist
- Facts and policies serialized separately
- Lattice code in allowed services only
- Merge strategies named and versioned
- Artifacts record which lattice algorithm used
12.6 Proof-Linked VEX Checklist
- VEX schema includes pointers to all upstream artifacts (sbomDigest, scanId, reachMapDigest, policyDigest, signerKeyId)
- No duplication of SBOM/scan content inside VEX
- DSSE used as standard envelope type
12.7 Unknowns Triage Checklist
- Persist all traces for deterministic replay
- Ranking depends only on manifest-declared parameters
- All uncertainty factors are explicit flags
- Scoring reproducible under identical inputs
- Scheduler decision table deterministic and tested
- API exposes full reasoning
Document Version: 1.0 Target Platform: .NET 10, PostgreSQL ≥16, Angular v17