test
This commit is contained in:
250
docs/modules/snapshot/merge-preview.md
Normal file
250
docs/modules/snapshot/merge-preview.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# Policy Merge Preview
|
||||
|
||||
## Overview
|
||||
|
||||
The **Policy Merge Preview** shows how VEX statements from different sources combine using lattice logic. This visualization helps analysts understand:
|
||||
|
||||
1. What each source contributes
|
||||
2. How conflicts are resolved
|
||||
3. What evidence is missing
|
||||
4. The final merged status
|
||||
|
||||
## Merge Semantics
|
||||
|
||||
StellaOps uses a three-layer merge model:
|
||||
|
||||
```
|
||||
vendor ⊕ distro ⊕ internal = final
|
||||
```
|
||||
|
||||
Where ⊕ represents the lattice join operation.
|
||||
|
||||
### Layer Hierarchy
|
||||
|
||||
| Layer | Description | Typical Trust |
|
||||
|-------|-------------|---------------|
|
||||
| **Vendor** | Software vendor's VEX statements | 0.95-1.0 |
|
||||
| **Distro** | Distribution maintainer's assessments | 0.85-0.95 |
|
||||
| **Internal** | Organization's own assessments | 0.70-0.90 |
|
||||
|
||||
### Lattice Operations
|
||||
|
||||
Using K4 (Kleene's 4-valued logic):
|
||||
|
||||
| Status | Lattice Position |
|
||||
|--------|-----------------|
|
||||
| Affected | Top (Both) |
|
||||
| UnderInvestigation | Unknown (Neither) |
|
||||
| Fixed | True |
|
||||
| NotAffected | False |
|
||||
|
||||
Join table (⊕):
|
||||
```
|
||||
| Affected | Under... | Fixed | NotAffected
|
||||
---------+----------+----------+-------+------------
|
||||
Affected | A | A | A | A
|
||||
Under... | A | U | U | U
|
||||
Fixed | A | U | F | F
|
||||
NotAff | A | U | F | N
|
||||
```
|
||||
|
||||
## API Endpoint
|
||||
|
||||
### GET /policy/merge-preview/{cveId}
|
||||
|
||||
**Parameters:**
|
||||
- `cveId`: CVE identifier
|
||||
- `artifact`: Artifact digest (query param)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"cveId": "CVE-2024-1234",
|
||||
"artifactDigest": "sha256:abc...",
|
||||
"contributions": [
|
||||
{
|
||||
"layer": "vendor",
|
||||
"sources": ["lodash-security"],
|
||||
"status": "NotAffected",
|
||||
"trustScore": 0.95,
|
||||
"statements": [...],
|
||||
"mergeTrace": {
|
||||
"explanation": "Vendor states not affected due to version"
|
||||
}
|
||||
},
|
||||
{
|
||||
"layer": "distro",
|
||||
"sources": ["redhat-csaf"],
|
||||
"status": "Affected",
|
||||
"trustScore": 0.90,
|
||||
"statements": [...],
|
||||
"mergeTrace": {
|
||||
"explanation": "Distro states affected without context"
|
||||
}
|
||||
},
|
||||
{
|
||||
"layer": "internal",
|
||||
"sources": [],
|
||||
"status": null,
|
||||
"trustScore": 0,
|
||||
"statements": [],
|
||||
"mergeTrace": null
|
||||
}
|
||||
],
|
||||
"finalStatus": "NotAffected",
|
||||
"finalConfidence": 0.925,
|
||||
"missingEvidence": [
|
||||
{
|
||||
"type": "internal-assessment",
|
||||
"description": "Add internal security assessment",
|
||||
"priority": "medium"
|
||||
}
|
||||
],
|
||||
"latticeType": "K4",
|
||||
"generatedAt": "2024-12-22T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
When sources disagree, resolution follows:
|
||||
|
||||
1. **Trust Weight**: Higher trust wins
|
||||
2. **Lattice Position**: If trust equal, higher lattice position wins
|
||||
3. **Freshness**: If still tied, more recent statement wins
|
||||
4. **Tie**: First statement wins
|
||||
|
||||
### Resolution Trace
|
||||
|
||||
Each merge includes explanation:
|
||||
```json
|
||||
{
|
||||
"leftSource": "vendor:lodash",
|
||||
"rightSource": "distro:redhat",
|
||||
"leftStatus": "NotAffected",
|
||||
"rightStatus": "Affected",
|
||||
"leftTrust": 0.95,
|
||||
"rightTrust": 0.90,
|
||||
"resultStatus": "NotAffected",
|
||||
"explanation": "'vendor:lodash' has higher trust weight than 'distro:redhat'"
|
||||
}
|
||||
```
|
||||
|
||||
## UI Components
|
||||
|
||||
### Layer Cards
|
||||
|
||||
Each layer shows:
|
||||
- Source names
|
||||
- Current status badge
|
||||
- Trust score bar
|
||||
- Statement count
|
||||
|
||||
### Merge Flow Diagram
|
||||
|
||||
Visual representation:
|
||||
```
|
||||
┌─────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐
|
||||
│ Vendor │ ──⊕─│ Distro │ ──⊕─│ Internal │ ──=─│ Final │
|
||||
│ NotAff. │ │ Affected│ │ — │ │ NotAff. │
|
||||
│ (0.95) │ │ (0.90) │ │ │ │ (0.925) │
|
||||
└─────────┘ └─────────┘ └──────────┘ └─────────┘
|
||||
```
|
||||
|
||||
### Missing Evidence CTA
|
||||
|
||||
Prominent call-to-action for missing evidence:
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ ⚠ Improve Confidence │
|
||||
│ │
|
||||
│ [+] Add internal security assessment │
|
||||
│ Increases confidence by ~5% │
|
||||
│ │
|
||||
│ [+] Add reachability analysis │
|
||||
│ Determines if code is called │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Merge Traces (Expandable)
|
||||
|
||||
Detailed explanation of each merge:
|
||||
```
|
||||
▼ Merge Details
|
||||
|
||||
Vendor layer:
|
||||
Sources: lodash-security
|
||||
Status: NotAffected (trust: 95%)
|
||||
|
||||
Distro layer:
|
||||
Sources: redhat-csaf
|
||||
Status: Affected (trust: 90%)
|
||||
Merge: 'lodash-security' has higher trust weight
|
||||
|
||||
Internal layer:
|
||||
No statements
|
||||
|
||||
Final: NotAffected (confidence: 92.5%)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Trust Weights
|
||||
|
||||
Configure in `trust.yaml`:
|
||||
```yaml
|
||||
sources:
|
||||
vendor: 1.0
|
||||
distro: 0.9
|
||||
nvd: 0.8
|
||||
internal: 0.85
|
||||
community: 0.5
|
||||
unknown: 0.3
|
||||
```
|
||||
|
||||
### Lattice Type
|
||||
|
||||
Configure lattice in `policy.yaml`:
|
||||
```yaml
|
||||
lattice:
|
||||
type: K4 # or Boolean, 8-state
|
||||
joinStrategy: trust-weighted
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### 1. Understanding Disagreement
|
||||
|
||||
When vendor says "not affected" but NVD says "affected":
|
||||
- View merge preview
|
||||
- See trust scores
|
||||
- Understand why vendor wins
|
||||
- Decide if internal assessment needed
|
||||
|
||||
### 2. Adding Internal Context
|
||||
|
||||
When external sources lack context:
|
||||
- View missing evidence
|
||||
- Click "Add evidence"
|
||||
- Submit internal VEX statement
|
||||
- See confidence increase
|
||||
|
||||
### 3. Audit Documentation
|
||||
|
||||
For compliance:
|
||||
- Export merge preview
|
||||
- Include in audit report
|
||||
- Document decision rationale
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Review Conflicts**: When layers disagree, investigate why
|
||||
2. **Add Internal Context**: Your reachability data often resolves conflicts
|
||||
3. **Trust Calibration**: Adjust trust weights based on source accuracy
|
||||
4. **Document Decisions**: Use merge preview in exception justifications
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [VEX Trust Scoring](../excititor/scoring.md)
|
||||
- [Lattice Configuration](../policy/implementation_plan.md)
|
||||
- [REPLAY.yaml Specification](./replay-yaml.md)
|
||||
295
docs/modules/snapshot/replay-yaml.md
Normal file
295
docs/modules/snapshot/replay-yaml.md
Normal file
@@ -0,0 +1,295 @@
|
||||
# REPLAY.yaml Manifest Specification
|
||||
|
||||
## Overview
|
||||
|
||||
The **REPLAY.yaml** manifest defines the complete set of inputs required to reproduce a StellaOps evaluation. It is the root document in a `.stella-replay.tgz` bundle.
|
||||
|
||||
## File Location
|
||||
|
||||
```
|
||||
.stella-replay.tgz
|
||||
├── REPLAY.yaml # This manifest
|
||||
├── sboms/
|
||||
├── vex/
|
||||
├── reach/
|
||||
├── exceptions/
|
||||
├── policies/
|
||||
├── feeds/
|
||||
├── config/
|
||||
└── SIGNATURE.sig # Optional DSSE signature
|
||||
```
|
||||
|
||||
## Schema Version
|
||||
|
||||
Current schema version: `1.0.0`
|
||||
|
||||
```yaml
|
||||
version: "1.0.0"
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
```yaml
|
||||
version: "1.0.0"
|
||||
|
||||
snapshot:
|
||||
id: "snap-20241222-abc123"
|
||||
createdAt: "2024-12-22T12:00:00Z"
|
||||
artifact: "sha256:abc123..."
|
||||
previousId: "snap-20241221-xyz789"
|
||||
|
||||
inputs:
|
||||
sboms:
|
||||
- path: "sboms/cyclonedx.json"
|
||||
format: "cyclonedx-1.6"
|
||||
digest: "sha256:def456..."
|
||||
- path: "sboms/spdx.json"
|
||||
format: "spdx-3.0.1"
|
||||
digest: "sha256:ghi789..."
|
||||
|
||||
vex:
|
||||
- path: "vex/vendor-lodash.json"
|
||||
source: "vendor:lodash"
|
||||
format: "openvex"
|
||||
digest: "sha256:jkl012..."
|
||||
trustScore: 0.95
|
||||
- path: "vex/redhat-csaf.json"
|
||||
source: "distro:redhat"
|
||||
format: "csaf"
|
||||
digest: "sha256:mno345..."
|
||||
trustScore: 0.90
|
||||
|
||||
reachability:
|
||||
- path: "reach/api-handler.json"
|
||||
entryPoint: "/api/handler"
|
||||
digest: "sha256:pqr678..."
|
||||
nodeCount: 42
|
||||
edgeCount: 57
|
||||
|
||||
exceptions:
|
||||
- path: "exceptions/exc-001.json"
|
||||
exceptionId: "exc-001"
|
||||
digest: "sha256:stu901..."
|
||||
|
||||
policies:
|
||||
bundlePath: "policies/bundle.tar.gz"
|
||||
digest: "sha256:vwx234..."
|
||||
version: "2.1.0"
|
||||
rulesHash: "sha256:yza567..."
|
||||
|
||||
feeds:
|
||||
- feedId: "nvd"
|
||||
name: "National Vulnerability Database"
|
||||
version: "2024-12-22T00:00:00Z"
|
||||
digest: "sha256:bcd890..."
|
||||
fetchedAt: "2024-12-22T06:00:00Z"
|
||||
- feedId: "ghsa"
|
||||
name: "GitHub Security Advisories"
|
||||
version: "2024-12-22T01:00:00Z"
|
||||
digest: "sha256:efg123..."
|
||||
fetchedAt: "2024-12-22T06:15:00Z"
|
||||
|
||||
lattice:
|
||||
type: "K4"
|
||||
configDigest: "sha256:hij456..."
|
||||
|
||||
trust:
|
||||
configDigest: "sha256:klm789..."
|
||||
defaultWeight: 0.5
|
||||
|
||||
outputs:
|
||||
verdictPath: "verdict.json"
|
||||
verdictDigest: "sha256:nop012..."
|
||||
findingsPath: "findings.ndjson"
|
||||
findingsDigest: "sha256:qrs345..."
|
||||
|
||||
seeds:
|
||||
rng: 12345678
|
||||
sampling: 87654321
|
||||
|
||||
environment:
|
||||
STELLAOPS_POLICY_VERSION: "2.1.0"
|
||||
STELLAOPS_LATTICE_TYPE: "K4"
|
||||
|
||||
signature:
|
||||
algorithm: "ecdsa-p256"
|
||||
keyId: "signing-key-prod-2024"
|
||||
value: "MEUCIQDx..."
|
||||
```
|
||||
|
||||
## Field Reference
|
||||
|
||||
### snapshot
|
||||
|
||||
Metadata about the snapshot itself.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| id | string | Yes | Unique snapshot identifier |
|
||||
| createdAt | datetime | Yes | ISO 8601 timestamp |
|
||||
| artifact | string | Yes | Artifact digest being evaluated |
|
||||
| previousId | string | No | Previous snapshot for diff |
|
||||
|
||||
### inputs.sboms
|
||||
|
||||
SBOM documents included in bundle.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| path | string | Yes | Path within bundle |
|
||||
| format | string | Yes | `cyclonedx-1.6` or `spdx-3.0.1` |
|
||||
| digest | string | Yes | Content digest |
|
||||
|
||||
### inputs.vex
|
||||
|
||||
VEX documents from various sources.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| path | string | Yes | Path within bundle |
|
||||
| source | string | Yes | Source identifier (vendor:*, distro:*, etc.) |
|
||||
| format | string | Yes | `openvex`, `csaf`, `cyclonedx-vex` |
|
||||
| digest | string | Yes | Content digest |
|
||||
| trustScore | number | Yes | Trust weight (0.0-1.0) |
|
||||
|
||||
### inputs.reachability
|
||||
|
||||
Reachability subgraph data.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| path | string | Yes | Path within bundle |
|
||||
| entryPoint | string | Yes | Entry point identifier |
|
||||
| digest | string | Yes | Content digest |
|
||||
| nodeCount | integer | No | Number of nodes |
|
||||
| edgeCount | integer | No | Number of edges |
|
||||
|
||||
### inputs.exceptions
|
||||
|
||||
Active exceptions at snapshot time.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| path | string | Yes | Path within bundle |
|
||||
| exceptionId | string | Yes | Exception identifier |
|
||||
| digest | string | Yes | Content digest |
|
||||
|
||||
### inputs.policies
|
||||
|
||||
Policy bundle reference.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| bundlePath | string | Yes | Path to policy bundle |
|
||||
| digest | string | Yes | Bundle digest |
|
||||
| version | string | No | Policy version |
|
||||
| rulesHash | string | Yes | Hash of compiled rules |
|
||||
|
||||
### inputs.feeds
|
||||
|
||||
Advisory feed versions at snapshot time.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| feedId | string | Yes | Feed identifier |
|
||||
| name | string | No | Human-readable name |
|
||||
| version | string | Yes | Feed version/timestamp |
|
||||
| digest | string | Yes | Feed content digest |
|
||||
| fetchedAt | datetime | Yes | When feed was fetched |
|
||||
|
||||
### inputs.lattice
|
||||
|
||||
Lattice configuration for merge semantics.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| type | string | Yes | `K4`, `Boolean`, `8-state` |
|
||||
| configDigest | string | Yes | Configuration hash |
|
||||
|
||||
### inputs.trust
|
||||
|
||||
Trust weight configuration.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| configDigest | string | Yes | Configuration hash |
|
||||
| defaultWeight | number | No | Default trust weight |
|
||||
|
||||
### outputs
|
||||
|
||||
Evaluation outputs for verification.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| verdictPath | string | Yes | Path to verdict file |
|
||||
| verdictDigest | string | Yes | Verdict content digest |
|
||||
| findingsPath | string | No | Path to findings file |
|
||||
| findingsDigest | string | No | Findings content digest |
|
||||
|
||||
### seeds
|
||||
|
||||
Random seeds for deterministic evaluation.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| rng | integer | No | Random number generator seed |
|
||||
| sampling | integer | No | Sampling algorithm seed |
|
||||
|
||||
### environment
|
||||
|
||||
Environment variables captured (non-sensitive).
|
||||
|
||||
Key-value pairs of environment configuration.
|
||||
|
||||
### signature
|
||||
|
||||
DSSE signature over manifest.
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| algorithm | string | Yes | Signing algorithm |
|
||||
| keyId | string | Yes | Signing key identifier |
|
||||
| value | string | Yes | Base64-encoded signature |
|
||||
|
||||
## Digest Format
|
||||
|
||||
All digests use the format:
|
||||
```
|
||||
sha256:<64-char-hex>
|
||||
```
|
||||
|
||||
Example:
|
||||
```
|
||||
sha256:a1b2c3d4e5f6...
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Bundle validation checks:
|
||||
1. REPLAY.yaml exists at bundle root
|
||||
2. All referenced files exist
|
||||
3. All digests match content
|
||||
4. Schema validates against JSON Schema
|
||||
5. Signature verifies (if present)
|
||||
|
||||
## CLI Usage
|
||||
|
||||
```bash
|
||||
# Create bundle
|
||||
stella snapshot export --output snapshot.stella-replay.tgz
|
||||
|
||||
# Verify bundle
|
||||
stella snapshot verify snapshot.stella-replay.tgz
|
||||
|
||||
# Replay from bundle
|
||||
stella replay --bundle snapshot.stella-replay.tgz
|
||||
|
||||
# View manifest
|
||||
stella snapshot manifest snapshot.stella-replay.tgz
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Knowledge Snapshot Model](./knowledge-snapshot.md)
|
||||
- [Merge Preview](./merge-preview.md)
|
||||
- [Replay Engine](../../modules/policy/implementation_plan.md)
|
||||
Reference in New Issue
Block a user