Security
Governance receipts
A review row says what happened. A receipt answers a different question, and it is the one an auditor is actually asking: has this record been altered since it was written?
“Trust our database” is not an answer to that. So receipts are append-only and hash-chained.
Verifiable offline
garboard receipt verify <bundle>
Verification does not call us. The chain is checked locally against the signature, so the evidence stands on its own — which is the only kind of evidence worth having in an audit, because an auditor who has to ask the vendor whether the vendor’s records are genuine has learned nothing.
Signing
GARBOARD_RECEIPT_KEY holds the signing seed; garboard receipt keygen generates one. GARBOARD_RECEIPT_RETIRED_KEYS lets you retire a key without invalidating receipts already signed with it.
An unsigned receipt is never reported as verified. An install with no signing key still writes receipts, and they are honestly labelled as unsigned rather than quietly presented as checked.
What is in a bundle
An exported evidence bundle contains what the gate decided and what it chose not to say:
pr_events.csv— every delivery we saw. This is the coverage denominator: it lets you ask “did you look at everything?” rather than only “what did you find?”suppressions.csv— findings that were recorded and shown to nobody: muted rules, shadow rules. With the actor and the timestamp.
Those two files answer different questions and both are needed. Coverage without suppressions tells you what was reviewed but not what was hidden; suppressions without coverage tells you what was hidden but not whether anything was missed.
Suppression is not deletion
A muted or shadowed finding is suppressed from the comment, not erased. It is recorded, it is counted, and it is in the bundle.
Silence towards a pull request author is not silence towards an auditor. A tool where “mute” meant “delete” would let an organisation quietly launder its own findings, and the evidence bundle would be worth nothing.
Review.suppressed_total carries the true count, so a client showing fewer than that must say its copy is partial — a cap a reader cannot see is indistinguishable from a smaller estate.
The audit log
Decisions in this family are audited with the actor, the rule and the repo#pr: dismissals, mutes, adoptions, break-glass, SSO configuration changes. Retention is GARBOARD_AUDIT_RETENTION_DAYS, defaulting to forever, with an organisation-scoped pruner.
