save development progress
This commit is contained in:
@@ -52,6 +52,8 @@ Common codes:
|
||||
Query params:
|
||||
|
||||
* `showMuted` (bool, default false)
|
||||
* `showHidden` (bool, default false) — include gated findings in results
|
||||
* `gatingReason` (optional, enum) — filter by specific gating reason
|
||||
* `lane` (optional, enum)
|
||||
* `search` (optional string; searches asset, purl, cveId)
|
||||
* `page` (int, default 1)
|
||||
@@ -66,7 +68,17 @@ Response 200:
|
||||
"page": 1,
|
||||
"pageSize": 50,
|
||||
"total": 12345,
|
||||
"actionableCount": 847,
|
||||
"mutedCounts": { "reach": 1904, "vex": 513, "compensated": 18 },
|
||||
"gatedBuckets": {
|
||||
"unreachableCount": 1904,
|
||||
"policyDismissedCount": 234,
|
||||
"backportedCount": 456,
|
||||
"vexNotAffectedCount": 513,
|
||||
"supersededCount": 12,
|
||||
"userMutedCount": 18,
|
||||
"totalHiddenCount": 3137
|
||||
},
|
||||
"rows": [
|
||||
{
|
||||
"id": "uuid",
|
||||
@@ -77,7 +89,9 @@ Response 200:
|
||||
"vex": "affected",
|
||||
"exploit": "YES",
|
||||
"asset": "prod/api-gateway:1.2.3",
|
||||
"updatedAt": "2025-12-16T01:02:03Z"
|
||||
"updatedAt": "2025-12-16T01:02:03Z",
|
||||
"gatingReason": null,
|
||||
"isHiddenByDefault": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -328,7 +342,149 @@ Event payload includes:
|
||||
* inputsHash
|
||||
* links to `/cases/{caseId}`
|
||||
|
||||
## 8. Gating Explainability
|
||||
|
||||
### 8.1 GatingReason enum
|
||||
|
||||
Reason why a finding is hidden by default in quiet-by-design triage:
|
||||
|
||||
| Value | Description |
|
||||
|-------|-------------|
|
||||
| `none` | Not gated - visible in default view |
|
||||
| `unreachable` | Not reachable from any application entrypoint |
|
||||
| `policy_dismissed` | Waived or tolerated by policy rules |
|
||||
| `backported` | Patched via distro backport |
|
||||
| `vex_not_affected` | VEX statement declares not affected with sufficient trust |
|
||||
| `superseded` | Superseded by newer advisory |
|
||||
| `user_muted` | Explicitly muted by user |
|
||||
|
||||
### 8.2 GatedBucketsSummary
|
||||
|
||||
```json
|
||||
{
|
||||
"unreachableCount": 1904,
|
||||
"policyDismissedCount": 234,
|
||||
"backportedCount": 456,
|
||||
"vexNotAffectedCount": 513,
|
||||
"supersededCount": 12,
|
||||
"userMutedCount": 18,
|
||||
"totalHiddenCount": 3137
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 VEX Trust Scoring
|
||||
|
||||
VEX statements include trust scoring for policy-driven acceptance:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "not_affected",
|
||||
"justification": "vulnerable_code_not_in_execute_path",
|
||||
"issuedBy": "vendor.example",
|
||||
"issuedAt": "2025-12-15T10:00:00Z",
|
||||
"trustScore": 0.85,
|
||||
"policyTrustThreshold": 0.80,
|
||||
"meetsPolicyThreshold": true,
|
||||
"trustBreakdown": {
|
||||
"authority": 0.90,
|
||||
"accuracy": 0.85,
|
||||
"timeliness": 0.80,
|
||||
"verification": 0.85
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Trust score components:
|
||||
* **Authority** (0-1): Issuer reputation and category
|
||||
* **Accuracy** (0-1): Historical correctness
|
||||
* **Timeliness** (0-1): Response speed
|
||||
* **Verification** (0-1): Signature validity
|
||||
|
||||
### 8.4 Finding gating fields
|
||||
|
||||
Extended fields on finding response:
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `gatingReason` | string | Why this finding is hidden (null if visible) |
|
||||
| `isHiddenByDefault` | boolean | True if gated by default view |
|
||||
| `subgraphId` | string | Link to reachability subgraph |
|
||||
| `deltasId` | string | Link to delta comparison |
|
||||
| `gatingExplanation` | string | Human-readable explanation |
|
||||
|
||||
## 9. Unified Evidence
|
||||
|
||||
### 9.1 Get unified evidence
|
||||
|
||||
`GET /findings/{findingId}/evidence`
|
||||
|
||||
Returns all evidence tabs in one call.
|
||||
|
||||
Response 200:
|
||||
|
||||
```json
|
||||
{
|
||||
"findingId": "uuid",
|
||||
"cveId": "CVE-2024-1234",
|
||||
"componentPurl": "pkg:npm/lodash@4.17.20",
|
||||
"sbom": { ... },
|
||||
"reachability": { ... },
|
||||
"vexClaims": [ ... ],
|
||||
"attestations": [ ... ],
|
||||
"deltas": { ... },
|
||||
"policy": { ... },
|
||||
"manifests": {
|
||||
"artifactDigest": "sha256:...",
|
||||
"feedDigest": "sha256:...",
|
||||
"policyDigest": "sha256:...",
|
||||
"manifestDigest": "sha256:..."
|
||||
},
|
||||
"verification": {
|
||||
"status": "verified",
|
||||
"hashesMatch": true,
|
||||
"signaturesValid": true,
|
||||
"isFresh": true
|
||||
},
|
||||
"replayCommand": "stella scan replay --artifact sha256:abc...",
|
||||
"generatedAt": "2025-12-16T01:02:03Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 9.2 Export evidence bundle
|
||||
|
||||
`GET /findings/{findingId}/evidence/export?format=zip`
|
||||
|
||||
Downloads complete evidence package as archive (ZIP or TAR.GZ).
|
||||
|
||||
Response headers:
|
||||
* `Content-Type`: application/zip or application/gzip
|
||||
* `Content-Disposition`: attachment; filename="evidence-{findingId}.zip"
|
||||
* `X-Archive-Digest`: sha256:{digest}
|
||||
|
||||
### 9.3 Get replay command
|
||||
|
||||
`GET /findings/{findingId}/replay-command`
|
||||
|
||||
Returns copy-ready CLI command for deterministic reproduction.
|
||||
|
||||
Response 200:
|
||||
|
||||
```json
|
||||
{
|
||||
"fullCommand": "stella scan replay --artifact sha256:abc... --manifest sha256:def...",
|
||||
"shortCommand": "stella replay snapshot --verdict V-12345",
|
||||
"bundleDownloadUrl": "/v1/triage/findings/uuid/evidence/export",
|
||||
"inputHashes": {
|
||||
"artifactDigest": "sha256:...",
|
||||
"manifestHash": "sha256:...",
|
||||
"feedSnapshotHash": "sha256:...",
|
||||
"policyHash": "sha256:..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: 1.0
|
||||
**Document Version**: 1.1
|
||||
**Updated**: 2025-12-24 (Sprint 9200 - Gating Explainability)
|
||||
**Target Platform**: .NET 10, PostgreSQL >= 16
|
||||
|
||||
Reference in New Issue
Block a user