Contracts¶
Authoritative reference for algorithm assignments across the autonomy.lock.json schema and the supply-chain pipeline.
Hash Roles¶
Two hash algorithms are used in this codebase. They serve different purposes and must never be confused or substituted for each other.
Field / purpose |
Algorithm |
Prefix |
Hex length |
Canonical source |
|---|---|---|---|---|
|
BLAKE3 |
|
64 |
|
|
SHA-256 |
|
64 |
OCI registry manifest |
|
SHA-256 |
|
64 |
OCI registry manifest |
|
SHA-256 or BLAKE3 |
|
64 |
caller-supplied |
|
SHA-256 or BLAKE3 |
|
64 |
caller-supplied |
Policy bundle |
SHA-256 |
|
64 |
|
TOML lock CI golden gate |
SHA-256 |
(none — raw hex) |
64 |
|
BLAKE3 — behavioral_fingerprint¶
behavioral_fingerprint is computed entirely in-process over the canonical
JSON bytes of the lock file (with the behavioral_fingerprint field itself
omitted to keep the computation self-consistent).
canon = CanonicalBytes(lock) // JSON, keys sorted, fingerprint excluded
digest = blake3.Sum256(canon) // 32 bytes
stored = "blake3:" + hex(digest) // stored in lock.behavioral_fingerprint
VerifyFingerprint rejects any stored value that does not carry the blake3:
prefix (forward-compat algorithm check). There is no fallback to SHA-256.
BLAKE3 is used here (not SHA-256) because:
It is faster for in-process computation over arbitrary-length JSON.
Its output is prefix-tagged, making the algorithm unambiguous at a glance.
It is deliberately distinct from SHA-256 to prevent callers from accidentally treating a registry OCI digest as a behavioral fingerprint or vice versa.
SHA-256 — OCI digests¶
OCI image manifests are content-addressed by SHA-256 (OCI Image Layout
Specification). The registry computes and returns sha256: digests for all
pushed content. The lock file records these values verbatim:
agent_artifact.digest = sha256:<hex> ← registry manifest digest
policy_bundle.digest = sha256:<hex> ← bundle layer digest
autonomy verify step 2 resolves the live digest from the registry and
compares it byte-for-byte with the lock field. Using BLAKE3 for OCI digests
would produce a value the registry does not know, so only SHA-256 is used here.
What cosign signs¶
cosign signs the OCI manifest at its SHA-256 subject digest. The cosign
signature payload embeds the sha256: digest of the image manifest as the
signed subject. The behavioral_fingerprint (BLAKE3) is not directly
covered by the cosign signature; it is verified separately in step 3 of
the supply-chain pipeline (lock.VerifyFingerprint).
Supply-chain verification: algorithm assignment per step¶
Step 1 — Signatures cosign verify → SHA-256 subject digest (registry standard)
Step 2 — OCI digests live SHA-256 digest vs lock.agent_artifact.digest
SHA-256(bundle bytes) vs lock.policy_bundle.digest
Step 3 — Fingerprint BLAKE3(canonical JSON) vs lock.behavioral_fingerprint
Step 4 — Semver string comparison — no hashing
Each step has a distinct sentinel error so callers can distinguish failures:
Error |
Step |
Algorithm involved |
|---|---|---|
|
1 |
cosign / SHA-256 OCI digest |
|
2 |
SHA-256 |
|
3 |
BLAKE3 |
|
4 |
n/a |
Schema enforcement¶
The JSON Schema at lock/schema/lock.schema.json encodes the algorithm
contract as regex patterns:
"behavioral_fingerprint": { "pattern": "^blake3:[a-f0-9]{64}$" }
"agent_artifact.digest": { "pattern": "^(sha256:|blake3:)[a-f0-9]{64}$" }
"policy_bundle.digest": { "pattern": "^(sha256:|blake3:)[a-f0-9]{64}$" }
behavioral_fingerprint accepts only the blake3: prefix. OCI digest
fields accept sha256: or blake3: (forward-compatible), though sha256:
is the only value produced in practice by today’s OCI registries.
Canonical MVP artifacts¶
These are the artifacts the CI acceptance gates validate end-to-end.
Artifact |
Canonical format |
Canonical location |
|---|---|---|
Behavioral lock file |
|
|
Policy bundle |
|
output of |
OCI lock sidecar |
JSON blob at |
pushed by |
OCI policy sidecar |
|
pushed by |
Telemetry WAL |
Append-only JSONL ( |
|
OCI attachment strategy¶
The autonomy oci commands probe the registry on first use and cache the
result per registry host:
OCI Referrers API (preferred) — OCI 1.1 manifest with a
subjectfield. Supported by GitHub Container Registry, Zot, Harbor 2.x, AWS ECR.Sidecar tag fallback — derived tags
<image>-lockand<image>-policy. Used byregistry:2(local dev and CI).
Both modes produce byte-identical content on pull. The OCI sidecar CI gate
(ci/test_oci_attach_verify.sh) asserts this with diff -q.
Policy bundle manifest¶
The canonical bundle format is a .tar.gz archive containing manifest.json.
The field policy_bundle_version in manifest.json drives the Step 4 semver
check (sign.ErrSemverIncompat). The legacy manifest.toml format is no
longer supported in the verification path; bundles produced by autonomy policy build always emit manifest.json.
What is explicitly NOT MVP-gating¶
The following are supported by the codebase but are not hard CI gates. They must not be promoted to gating status without an explicit decision.
Item |
Status |
Rationale |
|---|---|---|
|
Legacy / dev-only |
Superseded by |
|
Removed |
No longer read by the verification path; |
cosign signatures |
Required for |
|
OCI Referrers API mode |
Preferred but not required |
CI uses |
|
Optional |
Enforced only when |
TOML lock SHA-256 fingerprint |
Legacy / non-gating |
|
Canonical CI gate matrix¶
CI gate |
Script |
Hard/soft |
|---|---|---|
BLAKE3 determinism |
|
Hard |
Policy enforcement (allow/deny) |
|
Hard |
OCI sidecar byte-identity |
|
Hard |
WAL durability (offline→drain) |
|
Hard |
cosign sign + verify |
|
Soft — skipped if cosign absent |
TOML canonicalize utility |
GitHub Actions |
Soft — utility correctness, not format gate |
The Go unit tests backing the hard BLAKE3 gate are:
lock/lock_test.go::TestJSONFingerprintGolden ← stored BLAKE3 matches recomputed (primary gate)
lock/lock_test.go::TestFingerprintAlgorithmIsBLAKE3 ← algorithm contract (not SHA-256)
lock/lock_test.go::TestCanonicalBytesRepeatable ← canonical JSON bytes deterministic (100 runs)
lock/lock_test.go::TestComputeFingerprintDeterministic ← BLAKE3 stable across 10 independent calls