10 KiB
Change-Trace Architecture
Module: Scanner / ChangeTrace Version: 1.0.0 Status: Draft Last Updated: 2026-01-12
Overview
The Change-Trace feature provides deterministic comparison of binary artifacts across versions, producing a "trust-delta" view that explains what changed, why (backport, rebuild, upgrade), and what it means for security risk.
Strategic Value
- Differentiating capability: Explains backports and security patches that competitors flag as "version mismatch"
- Audit trail: Produces verifiable evidence for every version change decision
- Reduced review time: Pre-computed deltas with proof steps eliminate manual investigation
- Compliance support: Generates attestations suitable for regulatory frameworks
Architecture Diagram
+------------------+
| CLI / API |
| (entry points) |
+--------+---------+
|
+-------------+v+-------------+
| ChangeTraceBuilder |
| (orchestrates comparison) |
+---+-----+-----+-----+------+
| | | |
+------------+ | | +------------+
| | | |
v v v v
+-------+------+ +------+-----+------+ +-------+------+
| ScanResult | | BinaryIndex | | VexLens |
| Loader | | DeltaSigMatcher | | Consensus |
+--------------+ +-------------------+ +--------------+
| | |
v v v
+-------+------+ +------+-----+------+ +------+-------+
| PackageDelta | | SymbolDelta | | TrustDelta |
| Generator | | + ByteDelta | | Calculator |
+--------------+ +-------------------+ +--------------+
| | |
+------------------+----------------------+
|
+---------v----------+
| ChangeTrace |
| (output model) |
+--------------------+
|
+------------------+------------------+
| | |
v v v
+-------+------+ +------+-----+------+ +--+-------------+
| JSON Export | | DSSE Attestation | | CycloneDX |
| (standalone) | | (signing) | | (embedded) |
+--------------+ +-------------------+ +----------------+
Data Flow
1. Input Stage
Scan1 (from) Scan2 (to)
| |
v v
+----+----+ +----+----+
| SBOM | | SBOM |
| Findings| | Findings|
| Binary | | Binary |
| Sigs | | Sigs |
+---------+ +---------+
2. Comparison Stage
Package Comparison:
- Match by PURL
- Detect: Added, Removed, Upgraded, Downgraded, Patched, Rebuilt
Symbol Comparison (via BinaryIndex):
- CFG hash matching
- Instruction hash matching
- Semantic hash matching
- Chunk-level similarity
Byte Comparison (optional):
- Rolling hash windows (2KB)
- Per-section analysis
- Delta identification
3. Trust Scoring Stage
For each PackageDelta:
1. Get VEX consensus (from, to)
2. Query reachability (from, to)
3. Apply patch verification bonus
4. Compute trust delta
Formula:
TrustDelta = (AfterTrust - BeforeTrust) / max(BeforeTrust, 0.01)
4. Output Stage
ChangeTrace JSON
-> Standalone export (.cdxchange.json)
-> DSSE attestation (stella.ops/changetrace@v1)
-> CycloneDX embedded (component-evidence extension)
Component Responsibilities
ChangeTraceBuilder
Location: src/Scanner/__Libraries/StellaOps.Scanner.ChangeTrace/
Orchestrates the comparison workflow:
- Loads scan results
- Coordinates package, symbol, and byte comparisons
- Aggregates results into
ChangeTracemodel - Ensures deterministic output (stable ordering, UTC timestamps)
SymbolChangeTracer
Location: src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.DeltaSig/
Performs binary-level comparison:
- Compares
SymbolSignatureobjects - Identifies change type (Added, Removed, Modified, Patched)
- Computes similarity metrics
- Generates human-readable explanations
TrustDeltaCalculator
Location: src/Scanner/__Libraries/StellaOps.Scanner.ChangeTrace/Scoring/
Computes risk impact:
- Integrates with VexLens for consensus scores
- Integrates with ReachGraph for reachability data
- Applies patch verification bonus
- Generates proof steps
ByteLevelDiffer
Location: src/Scanner/__Libraries/StellaOps.Scanner.ChangeTrace/ByteDiff/
Performs byte-level analysis:
- Rolling hash window comparison
- Section-aware diffing (ELF/PE/Mach-O)
- Privacy-preserving output (hashes only)
Key Models
ChangeTrace (Root)
public sealed record ChangeTrace
{
public const string SchemaVersion = "stella.change-trace/1.0";
public string Schema { get; init; } = SchemaVersion;
public required ChangeTraceSubject Subject { get; init; }
public ImmutableArray<PackageDelta> Deltas { get; init; } = [];
public required ChangeTraceSummary Summary { get; init; }
public required DateTimeOffset AnalyzedAt { get; init; }
public string AlgorithmVersion { get; init; } = "1.0";
}
PackageDelta
public sealed record PackageDelta
{
public required string Purl { get; init; }
public string? FromVersion { get; init; }
public string? ToVersion { get; init; }
public required ChangeType ChangeType { get; init; }
public ImmutableArray<SymbolDelta> Symbols { get; init; } = [];
public ImmutableArray<ByteDelta> Bytes { get; init; } = [];
public required TrustDelta TrustDelta { get; init; }
}
TrustDelta
public sealed record TrustDelta
{
public double Score { get; init; } // [-1, +1]
public double BeforeScore { get; init; }
public double AfterScore { get; init; }
public ReachabilityImpact ReachabilityImpact { get; init; }
public ExploitabilityImpact ExploitabilityImpact { get; init; }
public ImmutableArray<string> ProofSteps { get; init; } = [];
}
Trust-Delta Formula
Core Formula
TrustDelta = (AfterTrust - BeforeTrust) / max(BeforeTrust, 0.01)
Where:
BeforeTrust = VexConsensus(from) * ReachabilityFactor(from)AfterTrust = VexConsensus(to) * ReachabilityFactor(to) + PatchBonus
Reachability Factor
ReachabilityFactor(callPaths) =
- 1.0 if callPaths > 0 (reachable)
- 0.7 if callPaths == 0 (unreachable, 30% reduction)
- 1.0 if callPaths is null (unknown)
Patch Verification Bonus
PatchBonus =
+ (FunctionMatchWeight * PatchConfidence) // 0.25 weight
+ (SectionMatchWeight * SymbolSimilarity) // 0.15 weight
+ (AttestationWeight * IssuerAuthority) // 0.10 weight (if DSSE present)
Verdict Mapping
| Delta Range | Verdict |
|---|---|
| < -0.3 | risk_down |
| -0.3 to +0.3 | neutral |
| > +0.3 | risk_up |
Integration Points
VexLens Integration
IVexLensClient.GetConsensusAsync(purl, version): Get trust scoreIVexLensClient.GetAdvisoryAsync(cveId): Get CVE details for proof steps
ReachGraph Integration
IReachGraphClient.GetReachabilityAsync(purl, version): Get call path count- Used for reachability impact calculation
BinaryIndex Integration
IDeltaSignatureMatcher.CompareSignaturesAsync(from, to): Symbol comparisonISymbolChangeTracer.CompareSymbols(fromSymbol, toSymbol): Detailed symbol diff
Attestor Integration
IAttestationService.CreateChangeTraceAttestationAsync(trace): DSSE envelope- Predicate type:
stella.ops/changetrace@v1
Determinism Requirements
All outputs must be reproducible:
- Stable ordering: Sort deltas by PURL, symbols by name, bytes by offset
- UTC timestamps: Use
TimeProviderfor all timestamps - Canonical JSON: RFC 8785 compliant serialization
- No randomness: Deterministic ID generation from content hashes
Verification
# Two runs should produce identical output
stella change-trace build --from scan1 --to scan2 > trace1.json
stella change-trace build --from scan1 --to scan2 > trace2.json
diff trace1.json trace2.json # Should be empty
Performance Targets
| Metric | Target |
|---|---|
| Package comparison | < 100ms |
| Symbol comparison | < 100ms per binary |
| Byte-level diffing | < 500ms for binaries < 5MB |
| Full trace build | < 5s for typical container |
| Memory usage | < 500MB peak |
Security Considerations
Privacy
- Byte content is never included in output
- Only hashes, offsets, and sizes are exported
- Symbol names may be sensitive (review before external export)
Integrity
- DSSE attestations provide tamper-evidence
- Signature verification available via
stella change-trace verify
Access Control
- API endpoints require authentication
- Traces inherit visibility from source scans
Future Enhancements
Phase 2
- Function-level heatmap visualization
- Side-by-side disassembly view
- AI-assisted change explanation
Phase 3
- Historical trend analysis
- Anomaly detection for unexpected changes
- Integration with SLSA provenance
References
- Sprint INDEX
- JSON Schema Contract
- Trust-Delta Contract
- BinaryIndex Architecture
- VexLens Architecture
Document Version: 1.0.0 Last Updated: 2026-01-12