up
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
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
This commit is contained in:
311
docs/replay/replay-manifest-v2-acceptance.md
Normal file
311
docs/replay/replay-manifest-v2-acceptance.md
Normal file
@@ -0,0 +1,311 @@
|
||||
# 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
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": "2.0",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Hash Algorithm Declaration
|
||||
|
||||
All hash fields now include explicit algorithm:
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
1. Verify all `casUri` references resolve to existing CAS objects
|
||||
2. Verify hash matches CAS content
|
||||
3. Verify DSSE envelope exists for all graph references
|
||||
4. Fail manifest creation if any reference is missing
|
||||
|
||||
### 3.3 Validation API
|
||||
|
||||
```csharp
|
||||
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
|
||||
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
```json
|
||||
{
|
||||
"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):
|
||||
|
||||
```json
|
||||
{
|
||||
"reachability": {
|
||||
"graphs": [
|
||||
{"casUri": "cas://reachability/graphs/blake3:zzzz...", "kind": "framework"},
|
||||
{"casUri": "cas://reachability/graphs/blake3:aaaa...", "kind": "static"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Expected output (sorted):
|
||||
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
```csharp
|
||||
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 `ReplayManifest` record with v2 fields
|
||||
- [ ] Add `hashAlg` to all hash-bearing types
|
||||
- [ ] Implement sorting in `ReachabilityReplayWriter`
|
||||
- [ ] Add CAS registration validation
|
||||
- [ ] Create test fixtures
|
||||
- [ ] Update `DETERMINISTIC_REPLAY.md` section 3
|
||||
- [ ] Wire into RecordModeService
|
||||
|
||||
---
|
||||
|
||||
_Last updated: 2025-12-13. See Sprint 0401 GAP-REP-004 for implementation._
|
||||
Reference in New Issue
Block a user