Some checks failed
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
7.5 KiB
7.5 KiB
Replay Manifest v2 Acceptance Contract
Last updated: 2025-12-13. Owner: BE-Base Platform Guild.
This document defines the acceptance criteria and test vectors for replay manifest v2, enabling Task 19 (GAP-REP-004) to proceed with implementation.
1. Overview
Replay manifest v2 introduces:
- BLAKE3 graph hashes: Primary hash algorithm for reachability graphs
- Sorted CAS entries: Deterministic ordering of all CAS references
- hashAlg fields: Explicit algorithm declarations for forward compatibility
- code_id coverage: Coverage metrics for stripped binary handling
2. Schema Changes (v1 → v2)
2.1 Version Field
{
"schemaVersion": "2.0",
...
}
2.2 Hash Algorithm Declaration
All hash fields now include explicit algorithm:
{
"reachability": {
"graphs": [
{
"hash": "blake3:a1b2c3d4e5f6...",
"hashAlg": "blake3-256",
"casUri": "cas://reachability/graphs/blake3:a1b2c3d4..."
}
],
"runtimeTraces": [
{
"hash": "sha256:feedface...",
"hashAlg": "sha256",
"casUri": "cas://reachability/runtime/sha256:feedface..."
}
]
}
}
2.3 Sorted CAS Entries
All arrays must be sorted by deterministic key:
| Array | Sort Key |
|---|---|
reachability.graphs[] |
casUri (lexicographic) |
reachability.runtimeTraces[] |
casUri (lexicographic) |
inputs.feeds[] |
name (lexicographic) |
inputs.tools[] |
name (lexicographic) |
2.4 Code ID Coverage
New field for stripped binary support:
{
"reachability": {
"code_id_coverage": {
"total_nodes": 1247,
"nodes_with_symbol_id": 1189,
"nodes_with_code_id": 58,
"coverage_percent": 100.0
}
}
}
3. CAS Registration Gates
3.1 Required Registration
All referenced artifacts must be registered in CAS before manifest finalization:
| Artifact Type | CAS Path Pattern | Required |
|---|---|---|
| Graph body | cas://reachability/graphs/{hash} |
Yes |
| Graph DSSE | cas://reachability/graphs/{hash}.dsse |
Yes |
| Runtime trace | cas://reachability/runtime/{hash} |
Conditional |
| Edge bundle | cas://reachability/edges/{graph_hash}/{bundle_id} |
Conditional |
3.2 Registration Validation
Before signing a replay manifest:
- Verify all
casUrireferences resolve to existing CAS objects - Verify hash matches CAS content
- Verify DSSE envelope exists for all graph references
- Fail manifest creation if any reference is missing
3.3 Validation API
public interface ICasValidator
{
Task<CasValidationResult> ValidateAsync(string casUri, string expectedHash);
Task<CasValidationResult> ValidateBatchAsync(IEnumerable<CasReference> refs);
}
public record CasValidationResult(
bool IsValid,
string? ActualHash,
string? Error
);
4. Acceptance Test Vectors
4.1 Minimal Valid Manifest v2
{
"schemaVersion": "2.0",
"scan": {
"id": "scan-test-001",
"time": "2025-12-13T10:00:00Z",
"mode": "record",
"scannerVersion": "10.2.0"
},
"subject": {
"ociDigest": "sha256:abc123..."
},
"inputs": {
"feeds": [],
"tools": []
},
"reachability": {
"graphs": [
{
"kind": "static",
"analyzer": "scanner.java@10.2.0",
"hash": "blake3:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"hashAlg": "blake3-256",
"casUri": "cas://reachability/graphs/blake3:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
}
],
"runtimeTraces": [],
"code_id_coverage": {
"total_nodes": 100,
"nodes_with_symbol_id": 100,
"nodes_with_code_id": 0,
"coverage_percent": 100.0
}
},
"outputs": {},
"provenance": {}
}
Expected canonical hash: sha256:e7f8a9b0... (computed from canonical JSON)
4.2 Manifest with Runtime Traces
{
"schemaVersion": "2.0",
"scan": {
"id": "scan-test-002",
"time": "2025-12-13T11:00:00Z",
"mode": "record",
"scannerVersion": "10.2.0"
},
"reachability": {
"graphs": [
{
"kind": "static",
"analyzer": "scanner.java@10.2.0",
"hash": "blake3:1111111111111111111111111111111111111111111111111111111111111111",
"hashAlg": "blake3-256",
"casUri": "cas://reachability/graphs/blake3:1111111111111111111111111111111111111111111111111111111111111111"
}
],
"runtimeTraces": [
{
"source": "eventpipe",
"hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222",
"hashAlg": "sha256",
"casUri": "cas://reachability/runtime/sha256:2222222222222222222222222222222222222222222222222222222222222222",
"recordedAt": "2025-12-13T10:30:00Z"
}
]
}
}
4.3 Sorting Validation Vector
Input (unsorted):
{
"reachability": {
"graphs": [
{"casUri": "cas://reachability/graphs/blake3:zzzz...", "kind": "framework"},
{"casUri": "cas://reachability/graphs/blake3:aaaa...", "kind": "static"}
]
}
}
Expected output (sorted):
{
"reachability": {
"graphs": [
{"casUri": "cas://reachability/graphs/blake3:aaaa...", "kind": "static"},
{"casUri": "cas://reachability/graphs/blake3:zzzz...", "kind": "framework"}
]
}
}
4.4 Invalid Manifest Vectors
| Test Case | Input | Expected Error |
|---|---|---|
| Missing schemaVersion | {} |
REPLAY_MANIFEST_MISSING_VERSION |
| Invalid version | {"schemaVersion": "1.0"} |
REPLAY_MANIFEST_VERSION_MISMATCH (when v2 required) |
| Missing hashAlg | {"hash": "blake3:..."} |
REPLAY_MANIFEST_MISSING_HASH_ALG |
| Unsorted graphs | See 4.3 input | REPLAY_MANIFEST_UNSORTED_ENTRIES |
| Missing CAS reference | {"casUri": "cas://missing/..."} |
REPLAY_MANIFEST_CAS_NOT_FOUND |
| Hash mismatch | CAS content differs | REPLAY_MANIFEST_HASH_MISMATCH |
5. Migration Path
5.1 v1 → v2 Upgrade
public static ReplayManifest UpgradeToV2(ReplayManifest v1)
{
return v1 with
{
SchemaVersion = "2.0",
Reachability = v1.Reachability with
{
Graphs = v1.Reachability.Graphs
.Select(g => g with { HashAlg = InferHashAlg(g.Hash) })
.OrderBy(g => g.CasUri)
.ToList(),
RuntimeTraces = v1.Reachability.RuntimeTraces
.Select(t => t with { HashAlg = InferHashAlg(t.Hash) })
.OrderBy(t => t.CasUri)
.ToList()
}
};
}
5.2 Backward Compatibility
- v2 readers MUST accept v1 manifests with warning
- v2 writers MUST always emit v2 format
- v1 writers deprecated after 2026-03-01
6. Test Fixture Locations
tests/Replay/
fixtures/
manifest-v2-minimal.json
manifest-v2-with-runtime.json
manifest-v2-sorted.json
manifest-v2-code-id-coverage.json
invalid/
manifest-missing-version.json
manifest-unsorted.json
manifest-missing-hashalg.json
golden/
manifest-v2-canonical.golden.json
manifest-v2-hash.golden.txt
7. Implementation Checklist
- Update
ReplayManifestrecord with v2 fields - Add
hashAlgto all hash-bearing types - Implement sorting in
ReachabilityReplayWriter - Add CAS registration validation
- Create test fixtures
- Update
DETERMINISTIC_REPLAY.mdsection 3 - Wire into RecordModeService
Last updated: 2025-12-13. See Sprint 0401 GAP-REP-004 for implementation.