# Score Replay API Reference **Sprint:** SPRINT_3401_0002_0001 **Task:** SCORE-REPLAY-014 - Update scanner API docs with replay endpoint ## Overview The Score Replay API enables deterministic re-scoring of scans using historical manifests. This is essential for auditing, compliance verification, and investigating how scores change with updated advisory feeds. ## Base URL ``` /api/v1/score ``` ## Authentication All endpoints require Bearer token authentication: ```http Authorization: Bearer ``` Required scope: `scanner:replay:read` for GET, `scanner:replay:write` for POST ## Endpoints ### Replay Score ```http POST /api/v1/score/replay ``` Re-scores a scan using the original manifest with an optionally different feed snapshot. #### Request Body ```json { "scanId": "scan-12345678-abcd", "feedSnapshotHash": "sha256:abc123...", "policyVersion": "1.0.0", "dryRun": false } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `scanId` | string | Yes | Original scan ID to replay | | `feedSnapshotHash` | string | No | Feed snapshot to use (defaults to current) | | `policyVersion` | string | No | Policy version (defaults to original) | | `dryRun` | boolean | No | If true, calculates but doesn't persist | #### Response ```json { "replayId": "replay-87654321-dcba", "originalScanId": "scan-12345678-abcd", "status": "completed", "feedSnapshotHash": "sha256:abc123...", "policyVersion": "1.0.0", "originalManifestHash": "sha256:def456...", "replayedManifestHash": "sha256:ghi789...", "scoreDelta": { "originalScore": 7.5, "replayedScore": 6.8, "delta": -0.7 }, "findingsDelta": { "added": 2, "removed": 5, "rescored": 12, "unchanged": 45 }, "proofBundleRef": "proofs/replays/replay-87654321/bundle.zip", "duration": { "ms": 1250 }, "createdAt": "2025-01-15T10:30:00Z" } ``` #### Example ```bash # Replay with latest feed curl -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"scanId": "scan-12345678-abcd"}' \ "https://scanner.example.com/api/v1/score/replay" # Replay with specific feed snapshot curl -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "scanId": "scan-12345678-abcd", "feedSnapshotHash": "sha256:abc123..." }' \ "https://scanner.example.com/api/v1/score/replay" # Dry run (preview only) curl -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "scanId": "scan-12345678-abcd", "dryRun": true }' \ "https://scanner.example.com/api/v1/score/replay" ``` ### Get Replay History ```http GET /api/v1/score/replays ``` Returns history of score replays. #### Query Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `scanId` | string | - | Filter by original scan | | `page` | int | 1 | Page number | | `pageSize` | int | 50 | Items per page | #### Response ```json { "items": [ { "replayId": "replay-87654321-dcba", "originalScanId": "scan-12345678-abcd", "triggerType": "manual", "scoreDelta": -0.7, "findingsAdded": 2, "findingsRemoved": 5, "createdAt": "2025-01-15T10:30:00Z" } ], "pagination": { "page": 1, "pageSize": 50, "totalItems": 12, "totalPages": 1 } } ``` ### Get Replay Details ```http GET /api/v1/score/replays/{replayId} ``` Returns detailed information about a specific replay. ### Get Scan Manifest ```http GET /api/v1/scans/{scanId}/manifest ``` Returns the scan manifest containing all input hashes. #### Response ```json { "manifestId": "manifest-12345678", "scanId": "scan-12345678-abcd", "manifestHash": "sha256:def456...", "sbomHash": "sha256:aaa111...", "rulesHash": "sha256:bbb222...", "feedHash": "sha256:ccc333...", "policyHash": "sha256:ddd444...", "scannerVersion": "1.0.0", "createdAt": "2025-01-15T10:00:00Z" } ``` ### Get Proof Bundle ```http GET /api/v1/scans/{scanId}/proof-bundle ``` Downloads the proof bundle (ZIP archive) for a scan. #### Response Returns `application/zip` with the proof bundle containing: - `manifest.json` - Signed scan manifest - `ledger.json` - Proof ledger nodes - `sbom.json` - Input SBOM (hash-verified) - `findings.json` - Scored findings - `signature.dsse` - DSSE envelope ## Scheduled Replay Scans can be automatically replayed when feed snapshots change. ### Configuration ```yaml # config/scanner.yaml score_replay: enabled: true schedule: "0 4 * * *" # Daily at 4 AM UTC max_age_days: 30 # Only replay scans from last 30 days notify_on_delta: true # Send notification if scores change delta_threshold: 0.5 # Only notify if delta > threshold ``` ### Trigger Types | Type | Description | |------|-------------| | `manual` | User-initiated via API | | `feed_update` | Triggered by new feed snapshot | | `policy_change` | Triggered by policy version change | | `scheduled` | Triggered by scheduled job | ## Determinism Guarantees Score replay guarantees deterministic results when: 1. **Same manifest hash** - All inputs are identical 2. **Same scanner version** - Scoring algorithm unchanged 3. **Same policy version** - Policy rules unchanged ### Manifest Contents The manifest captures: - SBOM content hash - Rules snapshot hash - Advisory feed snapshot hash - Policy configuration hash - Scanner version ### Verification ```bash # Verify replay determinism curl -H "Authorization: Bearer $TOKEN" \ "https://scanner.example.com/api/v1/scans/{scanId}/manifest" \ | jq '.manifestHash' # Compare with replay curl -H "Authorization: Bearer $TOKEN" \ "https://scanner.example.com/api/v1/score/replays/{replayId}" \ | jq '.replayedManifestHash' ``` ## Error Responses | Status | Code | Description | |--------|------|-------------| | 400 | `INVALID_SCAN_ID` | Scan ID not found | | 400 | `INVALID_FEED_SNAPSHOT` | Feed snapshot not found | | 400 | `MANIFEST_NOT_FOUND` | Scan manifest missing | | 401 | `UNAUTHORIZED` | Invalid token | | 403 | `FORBIDDEN` | Insufficient permissions | | 409 | `REPLAY_IN_PROGRESS` | Replay already running for scan | | 429 | `RATE_LIMITED` | Too many requests | ## Rate Limits - POST replay: 10 requests/minute - GET replays: 100 requests/minute - GET manifest: 100 requests/minute ## Related Documentation - [Proof Bundle Format](./proof-bundle-format.md) - [Scanner Architecture](../modules/scanner/architecture.md) - [Determinism Requirements](../product-advisories/14-Dec-2025%20-%20Determinism%20and%20Reproducibility%20Technical%20Reference.md)