Files
git.stella-ops.org/docs/contracts/change-trace-schema.md
2026-01-12 12:24:17 +02:00

448 lines
11 KiB
Markdown

# Change-Trace JSON Schema Contract
> **Version:** 1.0.0
> **Status:** Draft
> **Last Updated:** 2026-01-12
---
## Overview
This document defines the JSON schema for Change-Trace artifacts (`trace.cdxchange.json`). All implementations must conform to this schema for interoperability.
---
## Schema Identifier
```
Schema URI: stella.change-trace/1.0
File Extension: .cdxchange.json
MIME Type: application/vnd.stella.change-trace+json
```
---
## Root Object
```json
{
"$schema": "https://stella-ops.org/schemas/change-trace/1.0/schema.json",
"schema": "stella.change-trace/1.0",
"subject": { ... },
"deltas": [ ... ],
"summary": { ... },
"analyzedAt": "2026-01-12T14:30:00.000Z",
"algorithmVersion": "1.0"
}
```
### Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `schema` | string | Yes | Schema version identifier. Must be `stella.change-trace/1.0` |
| `subject` | object | Yes | Subject of the comparison |
| `deltas` | array | Yes | Array of package deltas (may be empty) |
| `summary` | object | Yes | Aggregated summary metrics |
| `analyzedAt` | string | Yes | ISO 8601 timestamp (UTC) |
| `algorithmVersion` | string | No | Algorithm version used (default: "1.0") |
---
## Subject Object
```json
{
"imageRef": "docker.io/library/nginx:1.25.3",
"fromDigest": "sha256:abc123...",
"toDigest": "sha256:def456...",
"fromScanId": "scan-12345",
"toScanId": "scan-67890"
}
```
### Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `imageRef` | string | Yes | Container image reference |
| `fromDigest` | string | Yes | SHA-256 digest of source image |
| `toDigest` | string | Yes | SHA-256 digest of target image |
| `fromScanId` | string | No | Source scan identifier |
| `toScanId` | string | No | Target scan identifier |
---
## PackageDelta Object
```json
{
"purl": "pkg:deb/debian/libssl3@3.0.9-1",
"fromVersion": "3.0.9-1",
"toVersion": "3.0.9-1+deb12u3",
"changeType": "patched",
"symbols": [ ... ],
"bytes": [ ... ],
"trustDelta": { ... }
}
```
### Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `purl` | string | Yes | Package URL (RFC 3986 compliant) |
| `fromVersion` | string | No | Source version (null if added) |
| `toVersion` | string | No | Target version (null if removed) |
| `changeType` | enum | Yes | Type of change |
| `symbols` | array | No | Symbol-level deltas (if available) |
| `bytes` | array | No | Byte-level deltas (if enabled) |
| `trustDelta` | object | Yes | Trust impact calculation |
### ChangeType Enum
| Value | Description |
|-------|-------------|
| `unchanged` | No change detected |
| `added` | Package added in target |
| `removed` | Package removed in target |
| `upgraded` | Version increased |
| `downgraded` | Version decreased |
| `patched` | Security patch applied (same base version) |
| `rebuilt` | Same version, different build |
---
## SymbolDelta Object
```json
{
"symbolName": "ssl3_get_record",
"changeType": "patched",
"sizeDelta": -24,
"cfgBlockDelta": 2,
"confidence": 0.97,
"matchMethod": "CFGHash+ChunkMatch",
"explanation": "Function patched: 2 basic blocks changed"
}
```
### Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `symbolName` | string | Yes | Symbol/function name |
| `changeType` | enum | Yes | Type of symbol change |
| `sizeDelta` | integer | No | Size change in bytes |
| `cfgBlockDelta` | integer | No | CFG basic block count change |
| `confidence` | number | No | Match confidence (0.0-1.0) |
| `matchMethod` | string | No | Method used for matching |
| `explanation` | string | No | Human-readable explanation |
### SymbolChangeType Enum
| Value | Description |
|-------|-------------|
| `unchanged` | No change detected |
| `added` | Symbol added in target |
| `removed` | Symbol removed in target |
| `modified` | Symbol modified (general) |
| `patched` | Security patch detected |
---
## ByteDelta Object
```json
{
"offset": 4096,
"size": 2048,
"fromHash": "sha256:abc123...",
"toHash": "sha256:def456...",
"section": ".text",
"context": "Function: ssl3_get_record"
}
```
### Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `offset` | integer | Yes | Byte offset in binary |
| `size` | integer | Yes | Size of changed region |
| `fromHash` | string | Yes | SHA-256 hash of source bytes |
| `toHash` | string | Yes | SHA-256 hash of target bytes |
| `section` | string | No | Binary section name |
| `context` | string | No | Context hint (e.g., function name) |
**Privacy Note:** Raw byte content is never included; only hashes are stored.
---
## TrustDelta Object
```json
{
"score": -0.27,
"beforeScore": 0.65,
"afterScore": 0.92,
"reachabilityImpact": "reduced",
"exploitabilityImpact": "down",
"proofSteps": [
"CVE-2026-12345 affects ssl3_get_record",
"Version changed: 3.0.9-1 -> 3.0.9-1+deb12u3",
"Patch verified via CFG match: 97% confidence",
"Reachable call paths: 3 -> 0 after patch",
"DSSE attestation present",
"Verdict: risk_down (-0.27)"
]
}
```
### Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `score` | number | Yes | Trust delta value (-1.0 to +1.0) |
| `beforeScore` | number | Yes | Trust score before change |
| `afterScore` | number | Yes | Trust score after change |
| `reachabilityImpact` | enum | Yes | Impact on code reachability |
| `exploitabilityImpact` | enum | Yes | Impact on exploitability |
| `proofSteps` | array | Yes | Human-readable proof steps |
### ReachabilityImpact Enum
| Value | Description |
|-------|-------------|
| `unchanged` | No change in reachability |
| `introduced` | Path now reachable |
| `eliminated` | Path no longer reachable |
| `reduced` | Fewer reachable paths |
| `increased` | More reachable paths |
### ExploitabilityImpact Enum
| Value | Description |
|-------|-------------|
| `unchanged` | No change in exploitability |
| `introduced` | New exploitability concern |
| `eliminated` | Exploitability eliminated |
| `up` | Increased exploitability |
| `down` | Decreased exploitability |
---
## Summary Object
```json
{
"packagesChanged": 5,
"packagesAdded": 1,
"packagesRemoved": 0,
"symbolsChanged": 23,
"bytesChanged": 8192,
"trustDelta": -0.15,
"overallVerdict": "risk_down"
}
```
### Properties
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `packagesChanged` | integer | Yes | Total packages with changes |
| `packagesAdded` | integer | Yes | Packages added |
| `packagesRemoved` | integer | Yes | Packages removed |
| `symbolsChanged` | integer | Yes | Total symbols with changes |
| `bytesChanged` | integer | Yes | Total bytes changed |
| `trustDelta` | number | Yes | Aggregate trust delta |
| `overallVerdict` | string | Yes | Overall verdict |
### Verdict Values
| Value | Trust Delta Range | Description |
|-------|-------------------|-------------|
| `risk_down` | < -0.3 | Risk decreased significantly |
| `neutral` | -0.3 to +0.3 | No significant risk change |
| `risk_up` | > +0.3 | Risk increased significantly |
| `inconclusive` | N/A | Unable to determine |
---
## Full Example
```json
{
"$schema": "https://stella-ops.org/schemas/change-trace/1.0/schema.json",
"schema": "stella.change-trace/1.0",
"subject": {
"imageRef": "docker.io/library/nginx:1.25.3",
"fromDigest": "sha256:abc123def456...",
"toDigest": "sha256:789ghi012jkl...",
"fromScanId": "scan-20260112-001",
"toScanId": "scan-20260112-002"
},
"deltas": [
{
"purl": "pkg:deb/debian/libssl3@3.0.9-1",
"fromVersion": "3.0.9-1",
"toVersion": "3.0.9-1+deb12u3",
"changeType": "patched",
"symbols": [
{
"symbolName": "ssl3_get_record",
"changeType": "patched",
"sizeDelta": -24,
"cfgBlockDelta": 2,
"confidence": 0.97,
"matchMethod": "CFGHash+ChunkMatch",
"explanation": "Function patched: 2 basic blocks changed"
}
],
"bytes": [
{
"offset": 4096,
"size": 2048,
"fromHash": "sha256:abc...",
"toHash": "sha256:def...",
"section": ".text"
}
],
"trustDelta": {
"score": -0.27,
"beforeScore": 0.65,
"afterScore": 0.92,
"reachabilityImpact": "reduced",
"exploitabilityImpact": "down",
"proofSteps": [
"CVE-2026-12345 affects ssl3_get_record",
"Version changed: 3.0.9-1 -> 3.0.9-1+deb12u3",
"Patch verified via CFG match: 97% confidence",
"Reachable call paths: 3 -> 0 after patch",
"DSSE attestation present",
"Verdict: risk_down (-0.27)"
]
}
}
],
"summary": {
"packagesChanged": 1,
"packagesAdded": 0,
"packagesRemoved": 0,
"symbolsChanged": 1,
"bytesChanged": 2048,
"trustDelta": -0.27,
"overallVerdict": "risk_down"
},
"analyzedAt": "2026-01-12T14:30:00.000Z",
"algorithmVersion": "1.0"
}
```
---
## Serialization Rules
### Determinism Requirements
1. **Key ordering**: Object keys must be sorted alphabetically
2. **Array ordering**:
- `deltas`: Sorted by `purl` (lexicographic)
- `symbols`: Sorted by `symbolName` (lexicographic)
- `bytes`: Sorted by `offset` (numeric ascending)
- `proofSteps`: Preserve generation order
3. **Number formatting**: No trailing zeros, no exponent notation
4. **String escaping**: Minimal escaping per RFC 8785
5. **Timestamps**: ISO 8601 with milliseconds, UTC (`Z` suffix)
### RFC 8785 Compliance
All JSON output must conform to [RFC 8785](https://datatracker.ietf.org/doc/html/rfc8785) (JSON Canonicalization Scheme) for digest computation.
---
## Validation
### JSON Schema
The formal JSON Schema is available at:
```
https://stella-ops.org/schemas/change-trace/1.0/schema.json
```
### Validation Command
```bash
stella change-trace verify trace.cdxchange.json
```
### Required Fields
The following fields are required for a valid trace:
- `schema`
- `subject.imageRef`
- `subject.fromDigest`
- `subject.toDigest`
- `deltas` (may be empty array)
- `summary.*` (all summary fields)
- `analyzedAt`
---
## CycloneDX Integration
### Embedded Mode
When embedded in CycloneDX, the change trace is attached as a `component-evidence` extension:
```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.7",
"components": [
{
"purl": "pkg:deb/debian/libssl3@3.0.9-1+deb12u3",
"evidence": {
"extensions": [
{
"extensionType": "stella-change-trace",
"extension": {
"schema": "stella.change-trace/1.0",
"changeType": "patched",
"trustDelta": { ... },
"symbols": [ ... ]
}
}
]
}
}
]
}
```
### Standalone Mode
Export as separate file: `<basename>.cdxchange.json`
---
## Version History
| Version | Date | Changes |
|---------|------|---------|
| 1.0.0 | 2026-01-12 | Initial release |
---
## References
- [Architecture Document](../modules/scanner/design/change-trace-architecture.md)
- [Trust-Delta Contract](./change-trace-trust-delta.md)
- [RFC 8785 - JSON Canonicalization Scheme](https://datatracker.ietf.org/doc/html/rfc8785)
- [Package URL Specification](https://github.com/package-url/purl-spec)
---
*Document Version: 1.0.0*
*Last Updated: 2026-01-12*