consolidation of some of the modules, localization fixes, product advisories work, qa work

This commit is contained in:
master
2026-03-05 03:54:22 +02:00
parent 7bafcc3eef
commit 8e1cb9448d
3878 changed files with 72600 additions and 46861 deletions

View File

@@ -0,0 +1,134 @@
Heres a compact, plugandplay blueprint for making **“unknown” a firstclass, auditable state** in your VEX pipeline (fits StellaOps nicely).
# Why this matters (quick)
VEX (OpenVEX/CSAF) often forces binary “affected/not_affected.” In practice, evidence is missing, conflicting, or stale. Treating **unknown** as a deliberate, signed, and replayable decision keeps you compliant (CRA/NIS2/DORA) and operationally honest.
# Lifecycle & precedence
```
unvalidated
→ evidence_ingested
→ proof_anchored
→ merge_candidate
→ merged_outcome { affected | not_affected | unknown }
→ scored
→ triage
```
* **Default unknown at ingest** if anything is missing/ambiguous.
* **Precedence:** latest valid timestamp wins; hard tie → **lexicographic source_id** tiebreak.
* Carry a **provenance bundle** with every hop: `{source_id, timestamp, proof_hash}`.
* Every **merged outcome** and **score** is **DSSEwrapped** and **Rekoranchored**.
# Four readiness gates (fail fast)
1. **ingest_validation**
* Schemavalid OpenVEX/CSAF + DSSE envelope present.
* Reject → `unvalidated` (record reasons).
2. **proof_anchor**
* Rekor entry (UUID) + inclusion proof persisted.
* Reject if no inclusion proof or log not reachable (offline mode: queue + mark `unknown`).
3. **merge_precheck**
* Deterministic timestamp precedence; evidence sufficiency (at least one attestation + SBOM ref).
* Reject if conflicts unresolved → stay at `proof_anchored` and set target outcome `unknown`.
4. **scoring_precondition**
* `replay_success_ratio` (e.g., ≥0.95) on verification of DSSE/rekor bundles + provenance presence.
* Reject if below threshold or provenance gaps → do not score; outcome remains `unknown`.
# Deterministic merge rules
* Normalize identifiers (CVE, package PURL, image digest).
* Collapse equivalent justifications (OpenVEX) and product trees (CSAF).
* If any required justification absent or conflicting → **merged_outcome = unknown** with rationale snapshot.
* Merge is **idempotent**: same inputs → byteidentical output and provenance trace.
# API surface (minimal)
```
POST /v1/vex/ingest
Body: DSSE-envelope { payload: OpenVEX|CSAF, signatures:[] }
Resp: { state: "evidence_ingested"|"unvalidated", provenance_bundle, rekor_hint? }
POST /v1/vex/merge
Body: { product_ref, candidates:[{openvex_or_csaf_ref, provenance_bundle}], strategy:"timestamp_lexi_tiebreak" }
Resp: { merged_outcome, provenance_trace[], dsse_signed_merged }
POST /v1/score
Body: { merged_outcome_ref, policy_id, replay_window }
Resp: { signed_score_dsse, replay_verification:{ratio, failures[]}, gate_passed:boolean }
GET /v1/triage?outcome=unknown
Resp: [{ product_ref, vuln_id, last_timestamp, missing_evidence[], next_actions[] }]
```
# Evidence & storage
* **EvidenceLocker** (your module) keeps: raw docs, DSSE envelopes, Rekor inclusion proofs, SBOM/attestation refs, provenance bundles.
* Hash all decision artifacts; store `{artifact_hash → Rekor UUID}` map.
* Offline/airgap: stage to local transparency log; when online, **bridge** to Rekor and backfill inclusion proofs.
# Scoring model (example)
* Base score source (e.g., CVSS/CVSSSR).
* Dampener if outcome=`unknown`: apply policy (e.g., cap at 6.9 or bump to triage queue).
* Require `replay_success_ratio ≥ threshold` and `provenance.complete=true` before emitting scores.
# Acceptance tests (mustpass)
1. **missing_evidence_defaults_unknown**
* Ingest CSAF missing justification → merged outcome is `unknown` with rationale.
2. **dsse_anchor_presence**
* Attempt score without Rekor inclusion → gate fails.
3. **timestamp_precedence_tiebreak**
* Two equal timestamps from different sources → lexicographic `source_id` decides, deterministic.
4. **merge_idempotence**
* Rerun merge with same inputs → identical `dsse_signed_merged` hash.
5. **scoring_gate_replay_success**
* Corrupt one signature in replay set → `replay_success_ratio` drops; scoring blocked.
# CLI hints (nice DX)
```
stella vex ingest --file advisories/openvex.json --sign key.pem --rekor-url $REKOR
stella vex merge --product my/image:sha256:… --inputs dir:./evidence
stella score --policy default --replay-window 30d
stella triage --outcome unknown --limit 50
```
# UI touchpoints (lean)
* **Evidence Ingest**: file drop (OpenVEX/CSAF), DSSE status, Rekor anchor badge.
* **Merge Review**: sidebyside justifications, conflicts, deterministic decision summary.
* **Scoring Gate**: replay bar (ratio), provenance checklist.
* **Triage (unknown)**: prioritized queue with “missing evidence” chips and oneclick requests.
# Dropin for StellaOps modules
* **Concelier**: orchestrates gates.
* **Attestor**: DSSE wrap/verify.
* **EvidenceLocker**: storage + provenance.
* **AdvisoryAI**: explanation/triage suggestions (surfacing unknowns first).
* **ReleaseOrchestrator**: policy “block if unknown>0 and critical path”.
If you want, I can generate:
* a ready OpenAPI spec for the 4 endpoints,
* the DSSE/Rekor wiring stubs (C#) and a minimal SQLite/Postgres schema,
* a Playwright test suite implementing the five acceptance tests.