# provenance — guide
> **Class:** `guide` · audience: someone checking build provenance / SLSA / Scorecard. The
> *what* is in [`provenance-design.md`](provenance-design.md).
## f0 — require an attestation
```rust
use modgunn::provenance::{Attestation, ProvenanceRequirement};
let req = ProvenanceRequirement {
require_min_slsa: 3,
trusted_signers: vec!["release-bot@example.com".into()],
expected_source_repo: Some("https://codeberg.org/nordisk/modgunn".into()),
};
let att = Attestation::signed_by("release-bot@example.com", 3);
let (provenance, findings) = req.evaluate(Some(&att)); // findings empty ⇒ satisfied
```
Feed `provenance` into a `scan::Artifact` so Engine A's `provenance_finding` folds it into the
verdict (see [`verdict-guide.md`](verdict-guide.md)). `req.evaluate(None)` scores a missing
attestation against `ProvenancePolicy`.
## f2 — detect a provenance change
```rust
let deltas = modgunn::provenance::attestation_delta(Some(&old_att), Some(&new_att));
// non-empty ⇒ signer / source-repo / presence changed (A25) — review before promoting
```
## f3 — Scorecard signals
```rust
use modgunn::provenance::{parse_scorecard, ScorecardSignals};
// Ingest a raw OpenSSF Scorecard report (`scorecard --format json`) offline:
let sc = parse_scorecard(json)?; // → ScorecardSignals { subject, overall, … }
// …or hand-build the signals directly:
let sc = ScorecardSignals { subject: "some-crate".into(), overall: 4.2, maintained: true,
branch_protection: false, signed_releases: false,
dangerous_workflow: true };
for f in sc.findings() { /* low score / unmaintained / dangerous workflow / no branch protection */ }
```
`parse_scorecard` reads Scorecard's 0..=10 check scale (higher = better; `-1` = inconclusive):
a check passes at `score >= 5`, and **Dangerous-Workflow is inverted** (a present score in
`0..10` means a dangerous CI pattern was found → a High finding). Persist with
`Warehouse::append_scorecard(&[sc])`; read the latest-per-subject with `load_scorecard()`.
Or drive the whole flow from the CLI:
```text
# parse + print the signals and their findings (offline, no catalog):
modgunn scorecard --path report.json
# …and persist into the shared warehouse (append→load path):
modgunn scorecard --path report.json --subject acme/widget --warehouse <root>
# read the persisted signals + findings back out:
modgunn warehouse provenance-log --warehouse <root>
```
## Gotchas
- `evaluate` returns *both* a `Provenance` and findings — use the `Provenance` for the artifact
and surface the findings; don't discard either.
- Scorecard signals are advisory features (A14/A24), not hard blocks — they inform, they don't
by themselves force a `Block`.