Files
git.stella-ops.org/docs/VEX_CONSENSUS_GUIDE.md

189 lines
8.0 KiB
Markdown

# VEX Consensus and Issuer Trust
This document consolidates the VEX concepts StellaOps relies on: ingesting upstream VEX without rewriting it, correlating evidence across sources, and producing a deterministic, explainable "effective" status for a component-vulnerability pair.
## Scope
- VEX ingestion and provenance (what is stored and why)
- Correlation (linksets) versus consensus (effective status)
- Issuer trust and offline operation
This is not an API reference; module dossiers define concrete schemas and endpoints.
## Vocabulary (Minimal)
- **VEX statement:** a claim about vulnerability status for a product/component (for example: `affected`, `fixed`, `not_affected`, `under_investigation`).
- **Observation:** an immutable record of a single upstream VEX document as received (including provenance and raw payload).
- **Linkset:** a deterministic correlation group that ties together statements that refer to the same `(vulnerabilityId, productKey)` across providers.
- **Consensus decision (effective VEX):** the platform's deterministic result after policy rules evaluate available VEX/advisory/reachability evidence.
## Observation Model (Link, Not Merge)
StellaOps treats upstream VEX as append-only evidence.
An observation records:
- **Provenance:** tenant, provider/issuer identity, receive timestamps (UTC), signature status, and content hash.
- **Raw payload:** stored losslessly so auditors and operators can retrieve exactly what was ingested.
- **Derived tuples:** extracted `(vulnerabilityId, productKey, status, justification?, version hints, references)` used for correlation and UI presentation.
An observation is never mutated. If upstream publishes a revision, StellaOps stores a new observation and records a supersedes relationship.
## Linksets (Correlation Without Consensus)
Linksets exist to make multi-source evidence explainable without collapsing it:
- Group statements that likely refer to the same product-vulnerability pair.
- Preserve conflicts (status disagreements, justification divergence, version range clashes) as first-class facts.
- Provide stable IDs generated from canonical, sorted inputs (deterministic hashing).
Linksets do not invent consensus; they only align evidence so downstream layers (Policy/Console/Exports) can explain what is known and what disagrees.
## Consensus (Effective Status)
The effective VEX status is computed by policy evaluation using:
- Correlated VEX evidence (observations + linksets)
- Advisory evidence (observations/linksets from Concelier)
- Optional reachability and other signals
Key properties:
- **Deterministic:** the same inputs yield the same output.
- **Explainable:** the decision includes an explanation trace and evidence references.
- **Uncertainty-aware:** when critical evidence is missing or conflicts are unresolved, the result can remain `under_investigation` instead of implying safety.
## Aggregation-Only Guardrails (AOC)
To avoid hidden rewriting of upstream data, the platform enforces:
- **Raw-first storage:** upstream payloads are stored as received; normalized projections are derived but do not replace raw data.
- **No merge of sources:** each provider's statements remain independently addressable.
- **Provenance is mandatory:** missing provenance or unverifiable signatures are surfaced as ingestion failures or warnings (policy-driven).
- **Idempotent writes:** identical content hashes do not create duplicate observations.
- **Deterministic outputs:** stable ordering and canonical hashing for linksets and exports.
## Issuer Directory and Trust
Issuer trust is a first-class input:
- Issuers are identified by stable provider IDs and, where applicable, cryptographic identity (certificate chain, key id, transparency proof).
- The issuer directory defines which issuers are trusted per tenant/environment and how they are weighted/accepted by policy.
- Offline sites carry required trust material (roots and allowlists) inside the Offline Kit so verification does not require network access.
## Console Integration
The Console uses these concepts to keep VEX explainable:
- VEX views show provider provenance, signature/issuer status, and snapshot timestamps.
- Conflicts are displayed as conflicts (what disagrees and why), not silently resolved in the UI.
- The effective VEX status shown in triage views links back to underlying observations/linksets and the policy explanation.
See `docs/UI_GUIDE.md` for the operator workflow perspective.
## Anchor-Aware Mode (v1.1)
> **Sprint:** SPRINT_20260112_004_BE_policy_determinization_attested_rules
Anchor-aware mode enforces cryptographic attestation requirements on VEX proofs used for allow decisions.
### VexProofGate Options
| Option | Type | Default | Strict Mode |
|--------|------|---------|-------------|
| `AnchorAwareMode` | bool | `false` | `true` |
| `RequireVexAnchoring` | bool | `false` | `true` |
| `RequireRekorVerification` | bool | `false` | `true` |
| `RequireSignedStatements` | bool | `false` | `true` |
| `RequireProofForFixed` | bool | `false` | `true` |
| `MaxAllowedConflicts` | int | `5` | `0` |
| `MaxProofAgeHours` | int | `168` | `72` |
### Strict Anchor-Aware Preset
For production environments requiring maximum security:
```csharp
var options = VexProofGateOptions.StrictAnchorAware;
// Enables: RequireVexAnchoring, RequireRekorVerification,
// RequireSignedStatements, RequireProofForFixed
// Sets: MinimumConfidenceTier=high, MaxAllowedConflicts=0, MaxProofAgeHours=72
```
### Metadata Keys
When passing VEX proof context through policy evaluation:
| Key | Type | Description |
|-----|------|-------------|
| `vex_proof_anchored` | bool | Whether proof has DSSE anchoring |
| `vex_proof_envelope_digest` | string | DSSE envelope sha256 digest |
| `vex_proof_rekor_verified` | bool | Whether Rekor transparency verified |
| `vex_proof_rekor_log_index` | long | Rekor log index if verified |
### Failure Reasons
| Reason | Description |
|--------|-------------|
| `vex_not_anchored` | VEX proof requires DSSE anchoring but is not anchored |
| `rekor_verification_missing` | VEX proof requires Rekor verification but not verified |
## VEX Change Events
> Sprint: SPRINT_20260112_006_EXCITITOR_vex_change_events
Excititor emits deterministic events when VEX statements change, enabling policy reanalysis.
### Event Types
| Event | Description | Policy Trigger |
|-------|-------------|----------------|
| `vex.statement.added` | New statement ingested | Immediate reanalysis |
| `vex.statement.superseded` | Statement replaced | Immediate reanalysis |
| `vex.statement.conflict` | Status disagreement detected | Queue for review |
| `vex.status.changed` | Effective status changed | Immediate reanalysis |
### Conflict Detection
Conflicts are detected when multiple providers report different statuses for the same vulnerability-product pair:
| Conflict Type | Description |
|---------------|-------------|
| `status_mismatch` | Different status values (e.g., affected vs not_affected) |
| `trust_tie` | Equal trust scores with different recommendations |
| `supersession_conflict` | Disagreement on which statement supersedes |
### Event Ordering
Events follow deterministic ordering:
1. Ordered by timestamp (ascending)
2. Conflict events after related statement events
3. Same-timestamp events sorted by provider ID
### Integration with Policy
Subscribe to VEX events for automatic reanalysis:
```yaml
subscriptions:
- event: vex.statement.*
action: reanalyze
filter:
trustScore: { $gte: 0.7 }
```
See [Excititor Architecture](docs/modules/excititor/architecture.md#33-vex-change-events) for full event schemas.
## Offline / Air-Gap Operation
- VEX observations/linksets are included in Offline Kit snapshots with content hashes and timestamps.
- Verification workflows (signatures, issuer trust) must work offline using bundled trust roots and manifests.
- The Console should surface snapshot identity and staleness budgets when operating offline.
## Related Docs
- `docs/modules/excititor/architecture.md`
- `docs/modules/vex-lens/architecture.md`
- `docs/ARCHITECTURE_OVERVIEW.md`
- `docs/OFFLINE_KIT.md`