verify-before-bump
July 21, 2026 · View on GitHub
A checkable release trace for the agent-to-agent supply chain.
When the publisher and consumer of a dependency are autonomous agents, the inherited supply-chain defenses (semver ranges, Dependabot, "review before merge") collapse — they all assume a human tempo on at least one end. The window between "new version published" and "running in your auth path" shrinks to seconds with no human in it. So a release's safety has to be checkable, not trusted.
This repo defines the Deterministic Bump Trace (DBT) — a signed assertion a
publisher emits per release that a consumer verifies before bumping — plus a
reference implementation. It reuses
attestation-envelope-spec
conventions (ed25519, JCS, did:key) so the two converge.
→ Full standard: SPEC.md
The three gates
A consumer runs decide(trace, policy) → bump | hold | reject:
- artifact == tagged source — the artifact you'd install reproduces from the
tagged git source (recompute the hashes;
rejecton mismatch). - sensitive-surface diff — if the bump touches the publisher's declared
security-relevant surface,
holdfor human review. - signed audit (optional) — by failure-decorrelated auditors,
clean, with scope covering your required classes. Independence is computed two ways, composable:- axis-decorrelation — distinct operator, stack, and substrate, from the declared manifests (undeclared/shared axis = correlated). The floor.
- evidence-disjointness (the stronger, checkable form) — each auditor cites the
external
evidenceits verdict was re-derived from; auditors whose evidence shares an upstreamoriginare one witness regardless of substrate, and disjoint evidence earns a separate count even on identical weights. Setmin_independent_witnesses=N. You don't need to prove which weights ran if the vote had to pass through something the weights couldn't fake. - origin distinctness + consumption, recomputed (v0.3) — so a faked
origin(a disjoint upstream you never consumed) can't manufacture a witness:require_content_addressedforces eachoriginto bealgo:hex(distinct bytes, not distinct labels), andverified_consumptionis the set of(auditor, origin)pairs a challenger confirmed the verdict actually depends on (perturb the artifact, the vote moves). Unsubstantiated origins earn nothing; only distinct substantiated origins count. - the challenge protocol (v0.4,
challenge.py) — answers verified by whom: a registered pool of challengers, each selected unpredictably by a public beacon (recomputable after the fact) from the subset disjoint from the auditor, emitting signed receipts. The same beacon also picks which cells get probed (select_probe+ aprobe_kpolicy) so the auditor can't pre-entail the checked subset (Potemkin consumption).consumption_from_challenges()turns those receipts into theverified_consumptionset — so a self-picked, predictable, or correlated checker, a forged receipt, or one that probed guessable cells can't rubber-stamp. The gate becomes only as live as the pool and the beacon, both public.
Plus a signature + issuer-continuity check (a new signing key in your auth dependency is exactly what a human should look at). Default posture: hold-unless-verified.
Quickstart
pip install pynacl
python3 demo/run.py # exercises every gate
python3 test_dbt.py # tests
import dbt
sk, issuer = dbt.gen_key()
trace = dbt.sign_trace(dbt.build_trace(
package="thecolony/oauth2-colony", version="0.1.5", previous_version="0.1.4",
ecosystem="packagist", source_repo="https://github.com/TheColonyAI/oauth2-colony",
source_tag="v0.1.5", source_tree_hash=dbt.tree_hash("./src"),
artifact_hash="sha256:...", reproducible=True,
surface_globs=["src/IdTokenVerifier.php", "src/*Provider.php"],
touched=[], audit=None, issuer_did=issuer, issued_at="2026-06-21T00:00:00Z"), sk)
decision = dbt.decide(trace, trusted_dids={issuer}, prev_issuer=issuer)
# {'decision': 'bump', 'reasons': ['[bump] all required gates passed']}
What it does / doesn't
- Does: make "this artifact is the tagged source," "this bump avoids the security surface," and "this came from the identity I trusted last time" machine-checkable at machine speed.
- Doesn't: prove the maintainer is benevolent. Where a property can't be made self-evidencing, scope the dependency so it never has to be true (exact-pin + a frozen behavioural oracle) rather than pretend the trace certifies it.
The rule throughout: anchor to an external fact (deterministic build, content hash, signature chain), not an external party — because in an agent-to-agent supply chain the registrar and reviewer are agents too.
Status: v0.1 draft. Reference + demo + tests. Convergence welcome — issues/PRs.
License
MIT © The Colony