Changelog¶
Unreleased¶
v0.6.2 - 2026-10-02¶
Added¶
- Portable anchor inclusion vectors contributed by dinakarjs: nine valid and eighteen invalid cases, with a Python harness and independent JavaScript cross-check (trace-spec #463; original trace-tests #137).
Changed¶
- Maintain the conformance suite in trace-spec/conformance and publish through its separate conformance publisher. Package name, import and CLI are unchanged.
- Serve conformance documentation under trace.agentrust-io.com/conformance/.
v0.6.1 - 2026-09-26¶
Changed¶
Each change here refuses input that 0.6.0 accepted, so a record that passed on 0.6.0 can fail on 0.6.1. The first two are the ones producers will hit.
- Duplicate member names are refused at load (exit 2) (#124). This covers records, anchor receipts and policy manifests.
json.loadskept the last value, the signature was checked over it, and a consumer whose parser keeps the first read a value no signature covered. RFC 8785 is defined over I-JSON, which forbids duplicates. A producer that emits a repeated key now gets a load error instead of a report. - TR-SIG accepts one spelling of
signatureandcnf.jwk.x(#124): unpadded base64url. The standard alphabet,=padding, characters outside the alphabet and nonzero trailing bits were all accepted before, and since the signature sits outside the body it signs, each was a different record that still verified. A record signed with padded or standard base64 now fails TR-SIG. - Digest,
subjectand receipt hash checks usefullmatch(#124). Python's$matched before a trailing newline, sosha256:<64 hex>passed TR-RTE-002, TR-SCA-002, TR-TXN-001, TR-POL-001 and TR-ENV-003. - TR-ANC-002 refuses claims outside the anchor-leaf profile of registry-anchor-v1 section 1: non-integer numbers and integers outside the safe range, whose leaf bytes differ between implementations (#124).
Fixed¶
- Untrusted input no longer reaches the CLI as a traceback (#124): a non-ASCII
runtime.nonce(TypeErrorfromhmac.compare_digest), a lone surrogate in an object key (UnicodeEncodeErrorfromrfc8785), a non-stringtransparencyinreport --html, and non-UTF-8, over-deep or unreadable input files. Each is now a finding or a load error.
Internal¶
- ClusterFuzzLite targets over the record loader and every module, the signature path and the anchor receipt, run on pull requests and nightly (#124).
- The maintainer approval gate drops the unused
statuses: writescope and runs withcontents: readandpull-requests: read(#125).
v0.6.0 - 2026-09-25¶
Changed¶
- Level 2 now verifies the anchor instead of parsing its URI (#79, closes #70).
TR-ANC-001only ever checked thattransparencywas a well-formed https URI, so any record could clear Level 2 by typing a string. The newTR-ANC-002replays the record's RFC 9162 inclusion proof against the committed Merkle root, offline and standard library only. The receipt is passed with the new--receiptoption onverifyandreport; without one,TR-ANC-002fails. A record that passed Level 2 on 0.5.1 without a receipt will fail it on 0.6.0.
Added¶
TR-ENV-005:cnf.jwkmust carry no private key material (#98). A record carrying its own private key (dand the other private JWK members) passed the whole suite, becauseTR-ENV-004only checked thatktywas present. The packagedschemas/trace-claim.jsoncopy is closed the same way. This is the trace-tests half of GHSA-vc4p-h84j-7qxj; trace-spec#296 fixed the other two schema copies.TR-APR: appraisal well-formedness at every level (#82, closes #63).appraisalis required by the schema and no module read it. Five codes now check the status enum, the verifier URI and appraisal timing. No network, no filesystem, no resolver.TR-POL-003resolvespolicy_uriagainstbundle_hash(#69). Apolicy_resolvercallable onrunner.runand a--policy-diroption on the CLI supply the policy bytes; the check compares their digest to the record.- Machine-readable execution accounting in CLI JSON reports for the bounded
TR-APR-001,TR-POL-003andTR-SCA-002pilot (#93). Accounted findings and accounting come from one immutable execution snapshot; unreconciled accounting is rejected on that path, the operational policy-correspondence rule is separated from supporting schema locators and all carry value digests for comparison against the referenced trace-spec bytes, scheduler non-execution carries a reason, and existing verdict policy and CLI exit behavior are unchanged.
Fixed¶
TR-SIGreports a record with no RFC 8785 canonical form (an integer outside the safe range, a non-finite float) as a finding instead of raising and ending the run (#86).- Malformed arrays or objects in
policy.enforcement_mode,runtime.platform,build_provenance.slsa_levelandcnf.jwk.ktyraisedTypeErrorbefore the runner could return findings; boolean SLSA levels passed as1and0. Both are now findings (#85, closes #84).
Internal¶
- The finding to level failure decision lives in one place, read by both the CLI and the JSON report (#88).
- Release and CI actions pinned to SHAs with a token permissions floor (#97); CI installs from hash-pinned locks (#101); actionlint and a test-environment guard added (#100).
v0.5.1 - 2026-08-22¶
- Level 1 and Level 2 verification now requires a verifier-issued challenge via
--expected-nonceand checks it against the signedruntime.nonceusing constant-time comparison. Previously nonce binding existed only as an assertion over the repository's own pytest fixture; the shipped runner and CLI could report conformance for a fresh signed record containing an attacker-chosen or replayed nonce.
v0.5.0 - 2026-08-09¶
Added¶
trace-tests report: conformance results as an artifact somebody can forward.verifyanswers a question for whoever ran it; a pass/fail in a terminal is useless to an auditor, a counterparty or an acquirer. The new command emits self-contained HTML, a machine-readable JSON document (schema: agentrust-io/trace-tests/report/1), and an SVG level badge.
It runs every level up to --max-level instead of one, because the answer a reader needs is the highest level the record reaches, not whether it cleared the level the person running the tool happened to choose. --fail-under N gates CI on a level; without it the command exits 0, since producing an artifact and enforcing a threshold are different jobs.
The report states that it is not evidence. It is unsigned HTML describing one run of one suite version, and anyone can edit it, so every report carries the record's digest, the suite and authoring-library versions, and the command to reproduce the result - and tells a reader who does not trust the sender to go check the record instead. A conformance report that looks authoritative and cannot be checked is the same shape of thing as a control plane writing its own log, which is the problem this project exists to fix.
Self-contained by construction: no scripts, no external CSS, no fonts, no badge service. A badge served from someone else's infrastructure would add a dependency to an artifact whose whole point is needing none. A test asserts the HTML fetches nothing.
The HTML and the JSON are rendered from one assembled structure so they cannot disagree about the verdict, and unverified findings count as failures from Level 1 up exactly as they do in verify.
v0.4.1 - 2026-08-03¶
Fixed¶
--versionreported the wrong version.__version__was a second hardcoded literal alongsidepyproject.tomland never moved, so it sat at0.2.0through both the 0.3.0 and 0.4.0 releases:trace-tests --versionprinted0.2.0from a 0.4.0 install whileimportlib.metadatacorrectly returned0.4.0. It is now read from installed distribution metadata, so there is one source of truth and the value cannot fall behind a release again.
This mattered more than a wrong string usually would. The v0.2 profile cutover shipped in 0.4.0, and a 0.2.x suite rejects every v0.2 record, so --version is exactly the command someone runs to work out whether their suite matches their producer. It was the one command that could not answer.
v0.4.0 - 2026-07-28¶
Changed¶
- BREAKING: the suite now conforms to TRACE v0.2.
TR-ENVrequires the profiletag:agentrust-io.com,2026:trace-v0.2and fails a record carrying the v0.1 identifier. The v0.1 URI namedagentrust.io, a domain this project never controlled, which RFC 4151 does not permit for a tag URI; see agentrust-io/trace-spec#107. Nothing else about the record format changed, so a producer migrates by updating the profile string and bumpingagentrust-traceto 0.5.0.
This is a deliberate cutover rather than dual acceptance: a conformance suite that passed both identifiers would certify records minted under a domain we do not own. A v0.1 record is checked with the 0.3.x releases of this suite, which stay published.
- Registry, verifier, and documentation hosts moved from
agentrust.iotoagentrust-io.com.
v0.3.0 - 2026-07-21¶
azure-cvm-sev-snpplatform accepted (runtime.platform): Azure confidential VMs run SEV-SNP behind a Hyper-V paravisor (vTPM-rooted). Added to the bundled schema enum and the TR-RTE valid-platform set so Azure TRACE records pass conformance. Matchesagentrust-trace>=0.4.
v0.2.0 - 2026-06-19¶
- DID subject support:
subjectnow acceptsdid:URIs in addition tospiffe://. - Embedded signature verification: plain TRACE records signed with
agentrust-trace sign_record()are now cryptographically verified at all levels. - SLSA Level 0:
build_provenance.slsa_level: 0is now valid for software-only / development records. - Software-only platform:
runtime.platform: "software-only"accepted at Level 0. - Private key leak detection: TR-SIG now fails records that embed a private key (
dmember) incnf.jwk.
v0.1.0 - 2026-05-01¶
- Initial release with 7 test modules: TR-ENV, TR-SIG, TR-RTE, TR-POL, TR-TXN, TR-ANC, TR-SCA.
- Conformance levels 0, 1, 2.