Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions scripts/validate-reviewer-routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Path("docs/reviewer-brief.md"),
Path("docs/repo-scope-map.md"),
Path("docs/risk-model-boundary.md"),
Path("tools/sbom-diff-and-risk/docs/report-schema.md"),
Path("tools/sbom-diff-and-risk/docs/reviewer-path.md"),
Path("projects/precipitation-anomaly-diagnostics/docs/reviewer-path.md"),
Path("projects/precipitation-anomaly-diagnostics-lab/docs/reviewer-path.md"),
Expand Down Expand Up @@ -69,6 +70,13 @@
"tools/sbom-diff-and-risk/src/sbom_diff_risk/models.py",
"tools/sbom-diff-and-risk/src/sbom_diff_risk/risk.py",
},
Path("tools/sbom-diff-and-risk/docs/report-schema.md"): {
"tools/sbom-diff-and-risk/docs/policy-decision-ci-cookbook.md",
"tools/sbom-diff-and-risk/docs/policy-decision-explainability.md",
"tools/sbom-diff-and-risk/docs/summary-json-ci-cookbook.md",
"tools/sbom-diff-and-risk/examples/sample-report.json",
"tools/sbom-diff-and-risk/examples/sample-summary.json",
},
Path("tools/sbom-diff-and-risk/docs/reviewer-path.md"): {
".github/workflows/reviewer-route-contract-ci.yml",
"docs/risk-model-boundary.md",
Expand Down Expand Up @@ -171,6 +179,16 @@
"suspicious_source",
"not_evaluated",
),
Path("tools/sbom-diff-and-risk/docs/report-schema.md"): (
"evidence_confidence",
"local_manifest_only",
"sbom_present",
"policy_matched",
"enrichment_mocked",
"enrichment_live",
"not a package safety verdict",
"not a CVE result",
),
Path("tools/sbom-diff-and-risk/docs/reviewer-path.md"): (
"Artifact evidence map",
"Reviewer route contract",
Expand All @@ -183,6 +201,7 @@
"every tracked reviewer-surface Markdown file is covered",
"python scripts/validate-reviewer-routes.py",
"No network",
"summary.evidence_confidence",
"not current PyPI package truth",
"not current repository reputation",
"It does not decide whether a dependency is safe.",
Expand Down
28 changes: 23 additions & 5 deletions tools/sbom-diff-and-risk/docs/report-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ JSON reports currently use this top-level structure:

| Field | Description |
| --- | --- |
| `summary` | Compact count-only run summary for deterministic machine consumption. |
| `summary` | Compact run summary for deterministic machine consumption. |
| `evidence_confidence` | Highest evidence-confidence level represented by this report. |
| `components` | Added, removed, and changed component records. |
| `risks` | Heuristic risk findings generated from the diff. |
| `policy_evaluation` | Policy evaluation details when policy state is represented in the report. |
Expand All @@ -28,7 +29,7 @@ JSON reports currently use this top-level structure:
| `scorecard_summary` | OpenSSF Scorecard evidence summary when available from report presentation. |
| `enrichment_metadata` | Top-level enrichment metadata used by trust-signal report sections. |
| `trust_signal_notes` | Review notes for provenance and Scorecard trust signals. |
| `metadata` | Run metadata such as input formats, generation time, strict mode, policy state, and enrichment state. |
| `metadata` | Run metadata such as input formats, generation time, strict mode, policy state, evidence confidence, and enrichment state. |
| `notes` | Additional report notes. |

When provenance policy fields are relevant, reports may also include
Expand Down Expand Up @@ -94,8 +95,9 @@ locks the standalone policy sidecar shape for a strict policy example.
## Summary contract

`summary` is the stable, compact entry point for automation that needs counts
without walking the full report. The `--summary-json PATH` CLI option writes
only this stable `report.json["summary"]` object.
and evidence-level labels without walking the full report. The
`--summary-json PATH` CLI option writes only this stable
`report.json["summary"]` object.

The checked-in [../examples/sample-summary.json](../examples/sample-summary.json)
artifact is the summary-only output for the default CycloneDX example and
Expand All @@ -112,11 +114,25 @@ Base `summary` fields:
| `removed` | Number of components present only in the before input. |
| `changed` | Number of components present in both inputs with a detected change. |
| `risk_counts` | Map of risk bucket name to count. |
| `evidence_confidence` | Highest evidence-confidence level represented by this report. |

There is intentionally no `unchanged` field. The current diff model does not
track unchanged components, so reporting an unchanged count would imply a model
guarantee that does not exist.

`evidence_confidence` is a reviewer-facing evidence label. It explains what
kind of evidence the report contains; it is not a package safety verdict and is
not a CVE result. The same value appears at top level, in `summary`, and in
`metadata.evidence_confidence`.

| Value | Meaning |
| --- | --- |
| `local_manifest_only` | The report was produced from local manifest-style inputs without SBOM input, policy matches, or enrichment evidence. |
| `sbom_present` | At least one input is an SBOM format such as CycloneDX JSON or SPDX JSON. |
| `policy_matched` | Local policy evaluation produced at least one blocking, warning, or suppressed policy match. |
| `enrichment_mocked` | Enrichment-shaped evidence is present without recorded live network access, or the report explicitly marks constructed snapshot evidence as mocked. |
| `enrichment_live` | Opt-in enrichment recorded live network access for PyPI provenance or OpenSSF Scorecard evidence. |

`summary.policy` appears only when a policy is applied. Absence of
`summary.policy` means policy was not used, not that policy evaluation failed.

Expand Down Expand Up @@ -153,7 +169,9 @@ stable for tests and downstream consumers.
- The schema is conservative and additive where possible.
- Missing `summary.policy` means policy was not applied.
- Missing `summary.enrichment` means PyPI and Scorecard enrichment were not used.
- Runtime details remain in the fuller report fields; `summary` stays count-only.
- Runtime details remain in the fuller report fields; `summary` stays compact.
- `evidence_confidence` describes evidence source level only; it does not rank
dependency safety.

## Non-claims

Expand Down
2 changes: 2 additions & 0 deletions tools/sbom-diff-and-risk/docs/reviewer-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ Then read:
Look for these reviewer anchors:

- `summary` is the compact machine-readable entry point
- `summary.evidence_confidence` labels the highest evidence level represented
by the report
- `summary.policy` appears only when policy evaluation runs
- `summary.enrichment` appears only when enrichment evidence exists
- policy findings explain `decision_reason`, `policy_rule`,
Expand Down
7 changes: 7 additions & 0 deletions tools/sbom-diff-and-risk/docs/summary-json-ci-cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ added = summary["added"]
removed = summary["removed"]
changed = summary["changed"]
risk_counts = summary["risk_counts"]
evidence_confidence = summary["evidence_confidence"]

print(f"added={added} removed={removed} changed={changed}")
print(f"risk_counts={risk_counts}")
print(f"evidence_confidence={evidence_confidence}")

max_new_packages = 2
if risk_counts.get("new_package", 0) > max_new_packages:
Expand All @@ -61,9 +63,11 @@ $added = $summary.added
$removed = $summary.removed
$changed = $summary.changed
$newPackageCount = $summary.risk_counts.new_package
$evidenceConfidence = $summary.evidence_confidence

Write-Output "added=$added removed=$removed changed=$changed"
Write-Output "new_package=$newPackageCount"
Write-Output "evidence_confidence=$evidenceConfidence"

$maxNewPackages = 2
if ($newPackageCount -gt $maxNewPackages) {
Expand All @@ -75,6 +79,9 @@ if ($newPackageCount -gt $maxNewPackages) {

- `summary.policy` appears only when policy evaluation is applied.
- `summary.enrichment` appears only when PyPI or Scorecard enrichment is used.
- `summary.evidence_confidence` is always present and can be
`local_manifest_only`, `sbom_present`, `policy_matched`,
`enrichment_mocked`, or `enrichment_live`.
- `unchanged` is absent because unchanged components are not modeled.
- Absence of `summary.policy` or `summary.enrichment` means the feature was
not used, not that it failed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
"suspicious_source": 0,
"not_evaluated": 2
},
"evidence_confidence": "policy_matched",
"policy": {
"status": "fail",
"blocking": 3,
"warning": 1,
"suppressed": 0
}
},
"evidence_confidence": "policy_matched",
"components": {
"added": [
{
Expand Down Expand Up @@ -700,6 +702,7 @@
},
"exit_code": 1
},
"evidence_confidence": "policy_matched",
"enrichment": {
"mode": "offline_default",
"pypi_enabled": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added: 1
- Removed: 0
- Version changes: 1
- Evidence confidence: policy_matched

## Risk buckets
- new_package: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
"suspicious_source": 0,
"not_evaluated": 2
},
"evidence_confidence": "policy_matched",
"policy": {
"status": "warn",
"blocking": 0,
"warning": 1,
"suppressed": 0
}
},
"evidence_confidence": "policy_matched",
"components": {
"added": [
{
Expand Down Expand Up @@ -553,6 +555,7 @@
},
"exit_code": 0
},
"evidence_confidence": "policy_matched",
"enrichment": {
"mode": "offline_default",
"pypi_enabled": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added: 1
- Removed: 0
- Version changes: 1
- Evidence confidence: policy_matched

## Risk buckets
- new_package: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"suspicious_source": 0,
"not_evaluated": 0
},
"evidence_confidence": "enrichment_mocked",
"policy": {
"status": "fail",
"blocking": 2,
Expand All @@ -32,6 +33,7 @@
}
}
},
"evidence_confidence": "enrichment_mocked",
"components": {
"added": [
{
Expand Down Expand Up @@ -744,6 +746,7 @@
},
"exit_code": 1
},
"evidence_confidence": "enrichment_mocked",
"enrichment": {
"mode": "opt_in_pypi",
"pypi_enabled": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added: 2
- Removed: 0
- Version changes: 1
- Evidence confidence: enrichment_mocked

## Risk buckets
- new_package: 2
Expand Down
5 changes: 4 additions & 1 deletion tools/sbom-diff-and-risk/examples/sample-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
"stale_package": 0,
"suspicious_source": 0,
"not_evaluated": 2
}
},
"evidence_confidence": "sbom_present"
},
"evidence_confidence": "sbom_present",
"components": {
"added": [
{
Expand Down Expand Up @@ -480,6 +482,7 @@
},
"exit_code": 0
},
"evidence_confidence": "sbom_present",
"enrichment": {
"mode": "offline_default",
"pypi_enabled": false,
Expand Down
1 change: 1 addition & 0 deletions tools/sbom-diff-and-risk/examples/sample-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added: 1
- Removed: 0
- Version changes: 1
- Evidence confidence: sbom_present

## Risk buckets
- new_package: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
"stale_package": 0,
"suspicious_source": 0,
"not_evaluated": 2
}
},
"evidence_confidence": "local_manifest_only"
},
"evidence_confidence": "local_manifest_only",
"components": {
"added": [
{
Expand Down Expand Up @@ -416,6 +418,7 @@
},
"exit_code": 0
},
"evidence_confidence": "local_manifest_only",
"enrichment": {
"mode": "offline_default",
"pypi_enabled": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added: 1
- Removed: 0
- Version changes: 1
- Evidence confidence: local_manifest_only

## Risk buckets
- new_package: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"suspicious_source": 0,
"not_evaluated": 0
},
"evidence_confidence": "enrichment_mocked",
"policy": {
"status": "warn",
"blocking": 0,
Expand All @@ -31,6 +32,7 @@
}
}
},
"evidence_confidence": "enrichment_mocked",
"components": {
"added": [
{
Expand Down Expand Up @@ -573,6 +575,7 @@
},
"exit_code": 0
},
"evidence_confidence": "enrichment_mocked",
"enrichment": {
"mode": "opt_in_scorecard",
"pypi_enabled": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added: 2
- Removed: 0
- Version changes: 1
- Evidence confidence: enrichment_mocked

## Risk buckets
- new_package: 2
Expand Down
3 changes: 2 additions & 1 deletion tools/sbom-diff-and-risk/examples/sample-summary.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
"stale_package": 0,
"suspicious_source": 0,
"not_evaluated": 2
}
},
"evidence_confidence": "sbom_present"
}
Loading