The trust layer
Who reviewed this,
and how sure were they?
Agents made code cheap; the scarce resource is now
trust. attest records a
commit-keyed answer (reviewer, verdict, confidence) and stores it in
git notes so the record
travels with the repo. Signing is optional; a policy in
.attest.json turns the ledger
into a CI gate.
$ attest keygen
attest · wrote private key to ~/.config/attest/key
# Record who reviewed this commit, signed
$ attest sign --commit HEAD \
--reviewer human:you --confidence 0.9 --tests-passed --sign
attest · recorded human:you on 77fe5ac11c (signed)
# Gate CI on the trust policy
$ attest verify --commit HEAD --policy .attest.json
attest verify · [ok] PASS (1 commit checked)
- 11
- policy rules
- all optional, permissive defaults
- 0
- services
- stored in git notes: no DB, no backend
- 1
- key, optional
- Ed25519; unsigned records still valid
- 5
- subcommands
- sign · verify · log · export · keygen
The trust primitive
A portable record of what vetted a change.
When an agent lands a change, there is no native record of which agent or human vetted it, and that context is lost the moment the PR merges. attest is that missing primitive: a durable, optionally-signed fact CI and agents can gate on.
A record, keyed to a commit
AttestationEach attestation answers who or what reviewed this SHA, and at what confidence: a reviewer (agent:claude, human:leif), a confidence in 0...1, an optional verdict, tests-passed and human-approved flags, a timestamp, an optional note, bound to the exact commit.
Stored in git notes
refs/notes/attestThe ledger lives in refs/notes/attest, so the trust record travels with the repository across every git host. No database, no service, no extra infra. Sync it with git push origin "refs/notes/*".
Signing is optional
attest keygenAn unsigned attestation is still a valid record, so attest works with zero setup. Run attest keygen once and pass --sign to attach an Ed25519 signature over a deterministic canonical serialization anyone can verify.
Policy gates CI
.attest.json.attest.json declares what a commit must carry: an attestation, passing tests, a signature, a human sign-off above a verdict. attest verify exits non-zero when the policy is not met, the contract a CI job or agent loop gates on.
Fed by augur
--from-augurattest sign --from-augur - ingests an augur verdict and risk score straight from its JSON, so the trust record captures the risk assessment that informed it: a risk-45 diff becomes a 0.55-confidence attestation.
Auditable trail
attest exportattest log reads the ledger for a commit; attest export emits the whole history as one stable JSON document for compliance. The trail is portable, append-only, and verifiable offline.
The record
One attestation, fully spelled out.
An attestation is a small, signed (or unsigned) fact bound to a commit. Multiple attestations can accrue on one commit: an agent's verdict and a human's separate sign-off both count. Every record is machine-readable, so agents and tooling parse it directly.
- commit
- The SHA this record is bound to.
- reviewer
- Who or what vetted it: agent:claude, human:leif.
- confidence
- How sure they were, in 0...1.
- verdict
- Optional: proceed, review, or block.
- testsPassed
- Whether the change's tests passed.
- humanApproved
- Whether a human signed off.
- signature
- Optional Ed25519 signature, base64.
- publicKey
- The signing key, so a verifier can check it.
attest log --commit HEAD --json
"commit": "9f2c1a7b04...",
"reviewer": "agent:claude",
"confidence": 0.92,
"verdict": "proceed",
"testsPassed": true,
"humanApproved": false,
"signature": "base64...",
"publicKey": "base64...",
"timestamp": 1700000000
}
The CLI
Five subcommands. The whole surface.
Record, verify, read, export, sign. Each command that touches a repo takes
--path /
-C to point elsewhere, and
--json for machine output.
Every flag is in the CLI reference.
Record an attestation for a commit, written to git notes.
--commit, --reviewer, --confidence, --from-augur, --sign
Gate a commit or range against .attest.json; exit non-zero on a violation.
--range, --commit, --policy, --json
List the recorded ledger, newest-first. The default subcommand.
--range, --commit, --json
Emit the complete provenance trail as one stable JSON audit document.
--range, --policy, --pretty
Create the Ed25519 key used to sign attestations.
--force
exit code is the contract
attest verify exits
0 when every commit passes and
1 on any violation. That non-zero
exit is what a CI job or agent loop gates on.
The policy
Eleven rules, all plain JSON.
.attest.json starts permissive and
tightens as a repo accumulates attestations. Every field defaults to lenient, so an
empty {} requires only one
attestation per commit. A misspelled rule or a missing explicit policy path is a hard
error, never a silent pass.
See the full policy reference.
Evidence rules: what was claimed
- requireAttestation
- The commit has no attestations.
- requireTestsPassed
- No attestation reports testsPassed.
- minimumConfidence
- The highest recorded confidence is below the floor.
- requireHumanApprovalWhenVerdictAtLeast
- A verdict is at/above the level but no record is humanApproved.
- requireSignatureWhenVerdictAtLeast
- A verdict is at/above the level but no record is validly signed.
- requireTestsPassedWhenVerdictAtLeast
- A verdict is at/above the level but no record reports passing tests.
- maxAgeDays
- The newest attestation is older than this many whole days.
Identity rules: who vouched
- requireSignature
- No valid signed attestation exists.
- allowedReviewers
- Any reviewer falls outside the allow-list (exact, or a prefix when it ends with
:). - trustedKeys
- Any signed record carries a key not in the trusted set (does not force signing).
- signerPinning
- A pinned reviewer is unsigned or signed with the wrong key. This is what stops a spoofed human:leif.
{
"requireAttestation": true,
"requireTestsPassed": false,
"minimumConfidence": 0.6,
"requireHumanApprovalWhenVerdictAtLeast": "block"
}
Trust model: read this before you rely on a gate
A gate is only as strong as the rule that ties a record to a key.
requireSignature
alone proves only that some key signed, not whose: an
attacker can sign with their own key while claiming
reviewer: human:leif.
To actually stop reviewer spoofing, pin identity to a key with
signerPinning, or pair
trustedKeys with
requireSignature.
Confidence and tests-passed gates are satisfied by any record on the commit, so bind them to
allowedReviewers or
signerPinning too.
The pipeline
augur scores the risk. attest records the trust.
augur answers how risky is this diff, and should a human look?, but that verdict is ephemeral. attest makes it durable: a portable, optionally-signed record of what vetted a change. Together they give an agent loop a stop condition a human can audit later.
An agent gates itself, recording provenance as it goes
$ augur check --range main..HEAD --json \
| attest sign --commit HEAD --reviewer agent:claude --from-augur -
# Then gate; escalate to a human on a violation
$ attest verify --commit HEAD \
|| echo "trust not satisfied, escalating"
How the score becomes confidence
--from-augur copies
augur's verdict and maps its risk score (0…100) to
confidence = 1 − riskScore/100:
a risk-45 review diff becomes a
0.55-confidence attestation. Explicit
--verdict /
--confidence flags
override the augur-derived values.
Audit and CI
A trail you can archive, a gate you can drop in.
attest export emits a single, stable JSON
document covering the complete trail across a range (sorted keys, commits oldest-first), so
it diffs cleanly and is suitable for compliance archival. In CI, run the binary directly or
drop in the GitHub Action, which installs a prebuilt attest for the runner: no Swift
toolchain required.
attest export: deterministic audit document
--policy .attest.json --no-pretty > audit.json
# every commit, every record, with verification
{ "version": 1, "allPassed": true,
"commitCount": 1, "records": [ … ] }
.github/workflows: the trust gate
with: { fetch-depth: 0 }
- uses: CorvidLabs/attest@v0
with:
range: origin/main..HEAD
policy: .attest.json
Pin @v0 to track the
latest 0.x, or an exact tag to lock a version. Prebuilt binaries cover GitHub-hosted macOS and
Linux x86_64 runners.
Where it ships
- Language
- Swift 6 (AttestKit library + CLI)
- Crypto
- swift-crypto (Ed25519), signing optional
- Storage
- git notes (refs/notes/attest)
- Platforms
- macOS universal + Linux x86_64
- Action
- CorvidLabs/attest@v0 (composite, prebuilt binary)
- License
- MIT
v0.4.0 is live
v0.4.0 shipped 4 days ago (Jun 11, 2026).
See how it fits with spec-sync, fledge, and augur in the toolchain onboarding.