add advisories
This commit is contained in:
@@ -0,0 +1,576 @@
|
||||
Here’s a tight, practical blueprint to turn your SBOM→VEX links into an auditable “proof spine”—using signed DSSE statements and a per‑dependency trust anchor—so every VEX verdict can be traced, verified, and replayed.
|
||||
|
||||
# What this gives you
|
||||
|
||||
* A **chain of evidence** from each SBOM entry → analysis → VEX verdict.
|
||||
* **Tamper‑evident** DSSE‑signed records (offline‑friendly).
|
||||
* **Deterministic replay**: same inputs → same verdicts (great for audits/regulators).
|
||||
|
||||
# Core objects (canonical IDs)
|
||||
|
||||
* **ArtifactID**: digest of package/container (e.g., `sha256:…`).
|
||||
* **SBOMEntryID**: stable ID for a component in an SBOM (`sbomDigest:package@version[:purl]`).
|
||||
* **EvidenceID**: hash of raw evidence (scanner JSON, reachability, exploit intel).
|
||||
* **ReasoningID**: hash of normalized reasoning (rules/lattice inputs used).
|
||||
* **VEXVerdictID**: hash of the final VEX statement body.
|
||||
* **ProofBundleID**: merkle root of {SBOMEntryID, EvidenceID[], ReasoningID, VEXVerdictID}.
|
||||
* **TrustAnchorID**: per‑dependency anchor (public key + policy) used to validate the above.
|
||||
|
||||
# Signed DSSE envelopes you’ll produce
|
||||
|
||||
1. **Evidence Statement** (per evidence item)
|
||||
|
||||
* `subject`: SBOMEntryID
|
||||
* `predicateType`: `evidence.stella/v1`
|
||||
* `predicate`: source, tool version, timestamps, EvidenceID
|
||||
* **Signers**: scanner/ingestor key
|
||||
|
||||
2. **Reasoning Statement**
|
||||
|
||||
* `subject`: SBOMEntryID
|
||||
* `predicateType`: `reasoning.stella/v1` (your lattice/policy inputs + ReasoningID)
|
||||
* **Signers**: “Policy/Lattice Engine” key (Authority)
|
||||
|
||||
3. **VEX Verdict Statement**
|
||||
|
||||
* `subject`: SBOMEntryID
|
||||
* `predicateType`: CycloneDX or CSAF VEX body + VEXVerdictID
|
||||
* **Signers**: VEXer key (or vendor key if you have it)
|
||||
|
||||
4. **Proof Spine Statement** (the spine itself)
|
||||
|
||||
* `subject`: SBOMEntryID
|
||||
* `predicateType`: `proofspine.stella/v1`
|
||||
* `predicate`: EvidenceID[], ReasoningID, VEXVerdictID, ProofBundleID
|
||||
* **Signers**: Authority key
|
||||
|
||||
# Trust model (per‑dependency anchor)
|
||||
|
||||
* **TrustAnchor** (per package/purl): { TrustAnchorID, allowed signers (KMS refs, PKs), accepted predicateTypes, policy version, revocation list }.
|
||||
* Store anchors in **Authority** and pin them in your graph by SBOMEntryID→TrustAnchorID.
|
||||
* Optional: PQC mode (Dilithium/Falcon) for long‑term archives.
|
||||
|
||||
# Verification pipeline (deterministic)
|
||||
|
||||
1. Resolve SBOMEntryID → TrustAnchorID.
|
||||
2. Verify every DSSE envelope’s signature **against the anchor’s allowed keys**.
|
||||
3. Recompute EvidenceID/ReasoningID/VEXVerdictID from raw content; compare hashes.
|
||||
4. Recompute ProofBundleID (merkle root) and compare to the spine.
|
||||
5. Emit a **Receipt**: {ProofBundleID, verification log, tool digests}. Cache it.
|
||||
|
||||
# Storage layout (Postgres + blob store)
|
||||
|
||||
* `sbom_entries(entry_id PK, bom_digest, purl, version, artifact_digest, trust_anchor_id)`
|
||||
* `dsse_envelopes(env_id PK, entry_id, predicate_type, signer_keyid, body_hash, envelope_blob_ref, signed_at)`
|
||||
* `spines(entry_id PK, bundle_id, evidence_ids[], reasoning_id, vex_id, anchor_id, created_at)`
|
||||
* `trust_anchors(anchor_id PK, purl_pattern, allowed_keyids[], policy_ref, revoked_keys[])`
|
||||
* Blobs (immutable): raw evidence, normalized reasoning JSON, VEX JSON, DSSE bytes.
|
||||
|
||||
# API surface (clean and small)
|
||||
|
||||
* `POST /proofs/:entry/spine` → submit or update spine (idempotent by ProofBundleID)
|
||||
* `GET /proofs/:entry/receipt` → full verification receipt (JSON)
|
||||
* `GET /proofs/:entry/vex` → the verified VEX body
|
||||
* `GET /anchors/:anchor` → fetch trust anchor (for offline kits)
|
||||
|
||||
# Normalization rules (so hashes are stable)
|
||||
|
||||
* Canonical JSON (UTF‑8, sorted keys, no insignificant whitespace).
|
||||
* Strip volatile fields (timestamps that aren’t part of the semantic claim).
|
||||
* Version your schemas: `evidence.stella/v1`, `reasoning.stella/v1`, etc.
|
||||
|
||||
# Signing keys & rotation
|
||||
|
||||
* Keep keys in your **Authority** module (KMS/HSM; offline export for air‑gap).
|
||||
* Publish key material via an **attestation feed** (or Rekor‑mirror) for third‑party audit.
|
||||
* Rotate by **adding** new allowed_keyids in the TrustAnchor; never mutate old envelopes.
|
||||
|
||||
# CI/CD hooks
|
||||
|
||||
* On SBOM ingest → create/refresh SBOMEntry rows + attach TrustAnchor.
|
||||
* On scan completion → produce Evidence Statements (DSSE) immediately.
|
||||
* On policy evaluation → produce Reasoning + VEX, then assemble Spine.
|
||||
* Gate releases on `GET /proofs/:entry/receipt` == PASS.
|
||||
|
||||
# UX (auditor‑friendly)
|
||||
|
||||
* **Proof timeline** per entry: SBOM → Evidence tiles → Reasoning → VEX → Receipt.
|
||||
* One‑click “Recompute & Compare” to show deterministic replay passes.
|
||||
* Red/amber flags when a signature no longer matches a TrustAnchor or a key is revoked.
|
||||
|
||||
# Minimal dev checklist
|
||||
|
||||
* [ ] Implement canonicalizers (Evidence, Reasoning, VEX).
|
||||
* [ ] Implement DSSE sign/verify (ECDSA + optional PQC).
|
||||
* [ ] TrustAnchor registry + resolver by purl pattern.
|
||||
* [ ] Merkle bundling to get ProofBundleID.
|
||||
* [ ] Receipt generator + verifier.
|
||||
* [ ] Postgres schema + blob GC (content‑addressed).
|
||||
* [ ] CI gates + API endpoints above.
|
||||
* [ ] Auditor UI: timeline + diff + receipts download.
|
||||
|
||||
If you want, I can drop in a ready‑to‑use JSON schema set (`evidence.stella/v1`, `reasoning.stella/v1`, `proofspine.stella/v1`) and sample DSSE envelopes wired to your .NET 10 stack.
|
||||
Here’s a focused **Stella Ops Developer Guidelines** doc, specifically for the pipeline that turns **SBOM data into verifiable proofs** (your SBOM → Evidence → Reasoning → VEX → Proof Spine).
|
||||
|
||||
Feel free to paste this into your internal handbook and tweak names to match your repos/services.
|
||||
|
||||
---
|
||||
|
||||
# Stella Ops Developer Guidelines
|
||||
|
||||
## Turning SBOM Data Into Verifiable Proofs
|
||||
|
||||
---
|
||||
|
||||
## 1. Mental Model: What You’re Actually Building
|
||||
|
||||
For every component in an SBOM, Stella must be able to answer, *“Why should anyone trust our VEX verdict for this dependency, today and ten years from now?”*
|
||||
|
||||
We do that with a pipeline:
|
||||
|
||||
1. **SBOM Ingest**
|
||||
Raw SBOM → validated → normalized → `SBOMEntryID`.
|
||||
|
||||
2. **Evidence Collection**
|
||||
Scans, feeds, configs, reachability, etc. → canonical evidence blobs → `EvidenceID` → DSSE-signed.
|
||||
|
||||
3. **Reasoning / Policy**
|
||||
Policy + evidence → deterministic reasoning → `ReasoningID` → DSSE-signed.
|
||||
|
||||
4. **VEX Verdict**
|
||||
VEX statement (CycloneDX / CSAF) → canonicalized → `VEXVerdictID` → DSSE-signed.
|
||||
|
||||
5. **Proof Spine**
|
||||
`{SBOMEntryID, EvidenceIDs[], ReasoningID, VEXVerdictID}` → merkle bundle → `ProofBundleID` → DSSE-signed.
|
||||
|
||||
6. **Verification & Receipts**
|
||||
Re-run verification → `Receipt` that proves everything above is intact and anchored to trusted keys.
|
||||
|
||||
Everything you do in this area should keep this spine intact and verifiable.
|
||||
|
||||
---
|
||||
|
||||
## 2. Non‑Negotiable Invariants
|
||||
|
||||
These are the rules you don’t break without an explicit, company-level decision:
|
||||
|
||||
1. **Immutability of Signed Facts**
|
||||
|
||||
* DSSE envelopes (evidence, reasoning, VEX, spines) are append‑only.
|
||||
* You never edit or delete content inside a previously signed envelope.
|
||||
* Corrections are made by **superseding** (new statement pointing at the old one).
|
||||
|
||||
2. **Determinism**
|
||||
|
||||
* Same `{SBOMEntryID, Evidence set, policyVersion}` ⇒ same `{ReasoningID, VEXVerdictID, ProofBundleID}`.
|
||||
* No non-deterministic inputs (e.g., “current time”, random IDs) in anything that affects IDs or verdicts.
|
||||
|
||||
3. **Traceability**
|
||||
|
||||
* Every VEX verdict must be traceable back to:
|
||||
|
||||
* The precise SBOM entry
|
||||
* Concrete evidence blobs
|
||||
* A specific policy & reasoning snapshot
|
||||
* A trust anchor defining allowed signers
|
||||
|
||||
4. **Least Trust / Least Privilege**
|
||||
|
||||
* Services only know the keys and data they need.
|
||||
* Trust is always explicit: through **TrustAnchors** and signature verification, never “because it’s in our DB”.
|
||||
|
||||
5. **Backwards Compatibility**
|
||||
|
||||
* New code must continue to verify **old proofs**.
|
||||
* New policies must **not rewrite history**; they produce *new* spines, leaving old ones intact.
|
||||
|
||||
---
|
||||
|
||||
## 3. SBOM Ingestion Guidelines
|
||||
|
||||
**Goal:** Turn arbitrary SBOMs into stable, addressable `SBOMEntryID`s and safe internal models.
|
||||
|
||||
### 3.1 Inputs & Formats
|
||||
|
||||
* Support at least:
|
||||
|
||||
* CycloneDX (JSON)
|
||||
* SPDX (JSON / Tag-Value)
|
||||
* For each ingested SBOM, store:
|
||||
|
||||
* Raw SBOM bytes (immutable, content-addressed)
|
||||
* A normalized internal representation (your own model)
|
||||
|
||||
### 3.2 IDs
|
||||
|
||||
* Generate:
|
||||
|
||||
* `sbomDigest` = hash(raw SBOM, canonical form)
|
||||
* `SBOMEntryID` = `sbomDigest + purl + version` (or equivalent stable tuple)
|
||||
* `SBOMEntryID` must:
|
||||
|
||||
* Not depend on ingestion time or database IDs.
|
||||
* Be reproducible from SBOM + deterministic normalization.
|
||||
|
||||
### 3.3 Validation & Errors
|
||||
|
||||
* Validate:
|
||||
|
||||
* Syntax (JSON, schema)
|
||||
* Core semantics (package identifiers, digests, versions)
|
||||
* If invalid:
|
||||
|
||||
* Reject the SBOM **but** record a small DSSE “failure attestation” explaining:
|
||||
|
||||
* Why it failed
|
||||
* Which file
|
||||
* Which system version
|
||||
* This still gives you a proof trail for “we tried and it failed”.
|
||||
|
||||
---
|
||||
|
||||
## 4. Evidence Collection Guidelines
|
||||
|
||||
**Goal:** Capture all inputs that influence the verdict in a canonical, signed form.
|
||||
|
||||
Typical evidence types:
|
||||
|
||||
* SCA / vuln scanner results
|
||||
* CVE feeds & advisory data
|
||||
* Reachability / call graph analysis
|
||||
* Runtime context (where this component is used)
|
||||
* Manual assessments (e.g., security engineer verdicts)
|
||||
|
||||
### 4.1 Evidence Canonicalization
|
||||
|
||||
For every evidence item:
|
||||
|
||||
* Normalize to a schema like `evidence.stella/v1` with fields such as:
|
||||
|
||||
* `source` (scanner name, feed)
|
||||
* `sourceVersion` (tool version, DB version)
|
||||
* `collectionTime`
|
||||
* `sbomEntryId`
|
||||
* `vulnerabilityId` (if applicable)
|
||||
* `rawFinding` (or pointer to it)
|
||||
* Canonical JSON rules:
|
||||
|
||||
* Sorted keys
|
||||
* UTF‑8, no extraneous whitespace
|
||||
* No volatile fields beyond what’s semantically needed (e.g., you might include `collectionTime`, but then know it affects the hash and treat that consciously).
|
||||
|
||||
Then:
|
||||
|
||||
* Compute `EvidenceID = hash(canonicalEvidenceJson)`.
|
||||
* Wrap in DSSE:
|
||||
|
||||
* `subject`: `SBOMEntryID`
|
||||
* `predicateType`: `evidence.stella/v1`
|
||||
* `predicate`: canonical evidence + `EvidenceID`.
|
||||
* Sign with **evidence-ingestor key** (per environment).
|
||||
|
||||
### 4.2 Ops Rules
|
||||
|
||||
* **Idempotency:**
|
||||
Re-running the same scan with same inputs should produce the same evidence object and `EvidenceID`.
|
||||
* **Tool changes:**
|
||||
When tool version or configuration changes, that’s a *new* evidence statement with a new `EvidenceID`. Do not overwrite old evidence.
|
||||
* **Partial failure:**
|
||||
If a scan fails, produce a minimal failure evidence record (with error details) instead of “nothing”.
|
||||
|
||||
---
|
||||
|
||||
## 5. Reasoning & Policy Engine Guidelines
|
||||
|
||||
**Goal:** Turn evidence into a defensible, replayable reasoning step with a clear policy version.
|
||||
|
||||
### 5.1 Reasoning Object
|
||||
|
||||
Define a canonical reasoning schema, e.g. `reasoning.stella/v1`:
|
||||
|
||||
* `sbomEntryId`
|
||||
* `evidenceIds[]` (sorted)
|
||||
* `policyVersion`
|
||||
* `inputs`: normalized form of all policy inputs (severity thresholds, lattice rules, etc.)
|
||||
* `intermediateFindings`: optional but useful — e.g., “reachable vulns = …”
|
||||
|
||||
Then:
|
||||
|
||||
* Canonicalize JSON and compute `ReasoningID = hash(canonicalReasoning)`.
|
||||
* Wrap in DSSE:
|
||||
|
||||
* `subject`: `SBOMEntryID`
|
||||
* `predicateType`: `reasoning.stella/v1`
|
||||
* `predicate`: canonical reasoning + `ReasoningID`.
|
||||
* Sign with **Policy/Authority key**.
|
||||
|
||||
### 5.2 Determinism
|
||||
|
||||
* Reasoning functions must be **pure**:
|
||||
|
||||
* Inputs: SBOMEntryID, evidence set, policy version, configuration.
|
||||
* No hidden calls to external APIs at decision time (fetch feeds earlier and record them as evidence).
|
||||
* If you need “current time” in policy:
|
||||
|
||||
* Treat it as **explicit input** and record it inside reasoning under `inputs.currentEvaluationTime`.
|
||||
|
||||
### 5.3 Policy Evolution
|
||||
|
||||
* When policy changes:
|
||||
|
||||
* Bump `policyVersion`.
|
||||
* New evaluations produce new `ReasoningID` and new VEX/spines.
|
||||
* Don’t retroactively apply new policy to old reasoning objects; generate new ones alongside.
|
||||
|
||||
---
|
||||
|
||||
## 6. VEX Verdict Guidelines
|
||||
|
||||
**Goal:** Generate VEX statements that are strongly tied to SBOM entries and your reasoning.
|
||||
|
||||
### 6.1 Shape
|
||||
|
||||
* Target standard formats:
|
||||
|
||||
* CycloneDX VEX
|
||||
* or CSAF
|
||||
* Required linkages:
|
||||
|
||||
* Component reference = `SBOMEntryID` or a resolvable component identifier from your SBOM normalize layer.
|
||||
* Vulnerability IDs (CVE, GHSA, internal IDs).
|
||||
* Status (`not_affected`, `affected`, `fixed`, etc.).
|
||||
* Justification & impact.
|
||||
|
||||
### 6.2 Canonicalization & Signing
|
||||
|
||||
* Define a canonical VEX body schema (subset of the standard + internal metadata):
|
||||
|
||||
* `sbomEntryId`
|
||||
* `vulnerabilityId`
|
||||
* `status`
|
||||
* `justification`
|
||||
* `policyVersion`
|
||||
* `reasoningId`
|
||||
* Canonicalize JSON → `VEXVerdictID = hash(canonicalVexBody)`.
|
||||
* DSSE-envelope:
|
||||
|
||||
* `subject`: `SBOMEntryID`
|
||||
* `predicateType`: e.g. `cdx-vex.stella/v1`
|
||||
* `predicate`: canonical VEX + `VEXVerdictID`.
|
||||
* Sign with **VEXer key** or vendor key (depending on trust anchor).
|
||||
|
||||
### 6.3 External VEX
|
||||
|
||||
* When importing vendor VEX:
|
||||
|
||||
* Verify signature against vendor’s TrustAnchor.
|
||||
* Canonicalize to your internal schema but preserve:
|
||||
|
||||
* Original document
|
||||
* Original signature material
|
||||
* Record “source = vendor” vs “source = stella” so auditors see origin.
|
||||
|
||||
---
|
||||
|
||||
## 7. Proof Spine Guidelines
|
||||
|
||||
**Goal:** Build a compact, tamper-evident “bundle” that ties everything together.
|
||||
|
||||
### 7.1 Structure
|
||||
|
||||
For each `SBOMEntryID`, gather:
|
||||
|
||||
* `EvidenceIDs[]` (sorted lexicographically).
|
||||
* `ReasoningID`.
|
||||
* `VEXVerdictID`.
|
||||
|
||||
Compute:
|
||||
|
||||
* Merkle tree root (or deterministic hash) over:
|
||||
|
||||
* `sbomEntryId`
|
||||
* sorted `EvidenceIDs[]`
|
||||
* `ReasoningID`
|
||||
* `VEXVerdictID`
|
||||
* Result is `ProofBundleID`.
|
||||
|
||||
Create a DSSE “spine”:
|
||||
|
||||
* `subject`: `SBOMEntryID`
|
||||
* `predicateType`: `proofspine.stella/v1`
|
||||
* `predicate`:
|
||||
|
||||
* `evidenceIds[]`
|
||||
* `reasoningId`
|
||||
* `vexVerdictId`
|
||||
* `policyVersion`
|
||||
* `proofBundleId`
|
||||
* Sign with **Authority key**.
|
||||
|
||||
### 7.2 Ops Rules
|
||||
|
||||
* Spine generation is idempotent:
|
||||
|
||||
* Same inputs → same `ProofBundleID`.
|
||||
* Never mutate existing spines; new policy or new evidence ⇒ new spine.
|
||||
* Keep a clear API contract:
|
||||
|
||||
* `GET /proofs/:entry` returns **all** spines, each labeled with `policyVersion` and timestamps.
|
||||
|
||||
---
|
||||
|
||||
## 8. Storage & Schema Guidelines
|
||||
|
||||
**Goal:** Keep proofs queryable forever without breaking verification.
|
||||
|
||||
### 8.1 Tables (conceptual)
|
||||
|
||||
* `sbom_entries`: `entry_id`, `bom_digest`, `purl`, `version`, `artifact_digest`, `trust_anchor_id`.
|
||||
* `dsse_envelopes`: `env_id`, `entry_id`, `predicate_type`, `signer_keyid`, `body_hash`, `envelope_blob_ref`, `signed_at`.
|
||||
* `spines`: `entry_id`, `proof_bundle_id`, `policy_version`, `evidence_ids[]`, `reasoning_id`, `vex_verdict_id`, `anchor_id`, `created_at`.
|
||||
* `trust_anchors`: `anchor_id`, `purl_pattern`, `allowed_keyids[]`, `policy_ref`, `revoked_keys[]`.
|
||||
|
||||
### 8.2 Schema Changes
|
||||
|
||||
Always follow:
|
||||
|
||||
1. **Expand**
|
||||
|
||||
* Add new columns/tables.
|
||||
* Make new code tolerant of old data.
|
||||
|
||||
2. **Backfill**
|
||||
|
||||
* Idempotent jobs that fill in new IDs/fields without touching old DSSE payloads.
|
||||
|
||||
3. **Contract**
|
||||
|
||||
* Only after all code uses the new model.
|
||||
* Never drop the raw DSSE or raw SBOM blobs.
|
||||
|
||||
---
|
||||
|
||||
## 9. Verification & Receipts
|
||||
|
||||
**Goal:** Make it trivial (for you, customers, and regulators) to recheck everything.
|
||||
|
||||
### 9.1 Verification Flow
|
||||
|
||||
Given `SBOMEntryID` or `ProofBundleID`:
|
||||
|
||||
1. Fetch spine and trust anchor.
|
||||
2. Verify:
|
||||
|
||||
* Spine DSSE signature against TrustAnchor’s allowed keys.
|
||||
* VEX, reasoning, and evidence DSSE signatures.
|
||||
3. Recompute:
|
||||
|
||||
* `EvidenceIDs` from stored canonical evidence.
|
||||
* `ReasoningID` from reasoning.
|
||||
* `VEXVerdictID` from VEX body.
|
||||
* `ProofBundleID` from the above.
|
||||
4. Compare to stored IDs.
|
||||
|
||||
Emit a **Receipt**:
|
||||
|
||||
* `proofBundleId`
|
||||
* `verifiedAt`
|
||||
* `verifierVersion`
|
||||
* `anchorId`
|
||||
* `result` (pass/fail, with reasons)
|
||||
|
||||
### 9.2 Offline Kit
|
||||
|
||||
* Provide a minimal CLI (`stella verify`) that:
|
||||
|
||||
* Accepts a bundle export (SBOM + DSSE envelopes + anchors).
|
||||
* Verifies everything without network access.
|
||||
|
||||
Developers must ensure:
|
||||
|
||||
* Export format is documented and stable.
|
||||
* All fields required for verification are included.
|
||||
|
||||
---
|
||||
|
||||
## 10. Security & Key Management (for Devs)
|
||||
|
||||
* Keys live in **KMS/HSM**, not env vars or config files.
|
||||
* Separate keysets:
|
||||
|
||||
* `dev`, `staging`, `prod`
|
||||
* Authority vs VEXer vs Evidence Ingestor.
|
||||
* TrustAnchors:
|
||||
|
||||
* Edit via Authority service only.
|
||||
* Every change:
|
||||
|
||||
* Requires code-reviewed change.
|
||||
* Writes an audit log entry.
|
||||
|
||||
Never:
|
||||
|
||||
* Log private keys.
|
||||
* Log full DSSE envelopes in plaintext logs (log IDs and hashes instead).
|
||||
|
||||
---
|
||||
|
||||
## 11. Observability & On‑Call Expectations
|
||||
|
||||
### 11.1 Metrics
|
||||
|
||||
For the SBOM→Proof pipeline, expose:
|
||||
|
||||
* `sboms_ingested_total`
|
||||
* `sbom_ingest_errors_total{reason}`
|
||||
* `evidence_statements_created_total`
|
||||
* `reasoning_statements_created_total`
|
||||
* `vex_statements_created_total`
|
||||
* `proof_spines_created_total`
|
||||
* `proof_verifications_total{result}` (pass/fail reason)
|
||||
* Latency histograms per stage (`_duration_seconds`)
|
||||
|
||||
### 11.2 Logging
|
||||
|
||||
Include in structured logs wherever relevant:
|
||||
|
||||
* `sbomEntryId`
|
||||
* `proofBundleId`
|
||||
* `anchorId`
|
||||
* `policyVersion`
|
||||
* `requestId` / `traceId`
|
||||
|
||||
### 11.3 Runbooks
|
||||
|
||||
You should maintain runbooks for at least:
|
||||
|
||||
* “Pipeline is stalled” (backlog of SBOMs, evidence, or spines).
|
||||
* “Verification failures increased”.
|
||||
* “Trust anchor or key issues” (rotation, revocation, misconfiguration).
|
||||
* “Backfill gone wrong” (how to safely stop, resume, and audit).
|
||||
|
||||
---
|
||||
|
||||
## 12. Dev Workflow & PR Checklist (SBOM→Proof Changes Only)
|
||||
|
||||
When your change touches SBOM ingestion, evidence, reasoning, VEX, or proof spines, check:
|
||||
|
||||
* [ ] IDs (`SBOMEntryID`, `EvidenceID`, `ReasoningID`, `VEXVerdictID`, `ProofBundleID`) remain **deterministic** and fully specified.
|
||||
* [ ] No mutation of existing DSSE envelopes or historical proof data.
|
||||
* [ ] Schema changes follow **expand → backfill → contract**.
|
||||
* [ ] New/updated TrustAnchors reviewed by Authority owner.
|
||||
* [ ] Unit tests cover:
|
||||
|
||||
* Canonicalization for any new/changed predicate.
|
||||
* ID computation.
|
||||
* [ ] Integration test covers:
|
||||
|
||||
* SBOM → Evidence → Reasoning → VEX → Spine → Verification → Receipt.
|
||||
* [ ] Observability updated:
|
||||
|
||||
* New paths emit logs & metrics.
|
||||
* [ ] Rollback plan documented (especially for migrations & policy changes).
|
||||
|
||||
---
|
||||
|
||||
If you tell me which microservices/repos map to these stages (e.g. `stella-sbom-ingest`, `stella-proof-authority`, `stella-vexer`), I can turn this into a more concrete, service‑by‑service checklist with example API contracts and class/interface sketches.
|
||||
Reference in New Issue
Block a user