Repository navigation
A patch release following 6.3.0, with stricter verification and changed result reporting. Statement validation is reported separately from DSSE signature checks, and reference-check results and executed-outcome evidence levels change as described below. The release also improves handling of specific invalid inputs, extends the inspect_ai adapter and updates repository tools. Review the changed fields and remaining exception paths when upgrading.
python -m pip install --upgrade proofbundle==6.3.1
Highlights
- Statement validation is separate from DSSE signature verification. The eval-result, in-toto and SVR verifiers require the in-toto Statement v1 layer and report
statement_okseparately fromsignature_ok. These and the decision, outcome, relation statement, verification summary, run ledger and trust pack verifiers require subjects that identify artifacts by digest. A successful DSSE signature check alone does not establish that the Statement passes validation. - Reference reporting changes for callers upgrading from 6.3.0.
automation.referencesResolvedisNonewhen no reference was checked;safeForAutomationandautomationBlockersare unchanged. Executed-outcome evidence levels useREFERENCE_WELL_FORMEDfor a well-formed digest reference, orCONTENT_RESOLVEDwhen the evidence resolver confirms it, instead of always reportingCLAIMED.action_outcome_provenandokare unchanged. Review code that depends on these fields. - Stricter validation and more specific errors for the corrected cases. The decision validator rejects JSON null in required fields that do not allow it. The validators named below enforce the corrected digit restrictions and closed
sha256Digestobjects. The corrected error paths return reason codes, blocking verdicts or module-specific errors. Eight public functions remain open for the formatting cases described below, and the twocanonicalprimitives still propagate canonicalization errors. - The inspect extra admits inspect_ai up to 0.3.281. Version 0.3.281 is the latest version measured in a fresh environment. The adapter includes sample counts and early-stopping metadata when supplied by the log, allowing a reported early stop to be distinguished from a completed run. The reported
nis unchanged.
Verify this release yourself
Use the checksums and build provenance to check the downloaded files. To check the signed pre-tag audit receipt, use a clone at the source commit identified by the build attestation. The commands, prerequisites and limits are in Verifying a published release.
What a receipt still does not prove
A valid signature binds the signed content to the signing key. It does not make a reported result true.
Measured on the reference machine
The budget cost axis was measured on the reference machine on 2026-10-21. All 12 axes and all 7 combinations passed, and none was skipped. The calibration factor maschinenfaktor_schnellstes_ende is 1.0, the ratio of the fastest recorded calibration time in this run to the median of the earlier reference recording. The timing limits used the fastest-sample setting, recorded as latte_aus_der_klammer=schnellstes_ende. The measurement record lists every axis and combination.
Details
All 30 entries, one line each, as in the CHANGELOG
Added
- Add ten conformance vectors of the kind
content_root_vectorunderconformance/action_chain_content_roots/. They pin the content root of ADR 0002 as data, andCONTENT_ROOT_CONTRACT.mdstates the contract. The Rust verifierpb_verify_rsrecomputes the eight pinned roots through itscontent-rootsubcommand. - Add
tools/scitt_ccf_external/pr31_strict_reader, a strict reader of a CCF inclusion receipt written to the text of pull request 31 to the CCF receipt profile, with 24 probes and 42 vectors. - Document in
THREAT_MODEL.mdthat a caller's own Python objects passed to the API are code in the same process, outside the verification boundary, and whereRESTRISIKO_620.mdlists the sites where such an object makes a never-raise surface raise.
Changed
automation.referencesResolvedisNone, no longerTrue, when every reference field it reads isNoneor absent, because no reference check ran.safeForAutomationandautomationBlockersdo not change.anchors.receipt_canonical_roottakes its RFC 8785 bytes from the package's one canonicalizer. A value of a subclass ofintorfloat, anIntEnumamong them, is refused withBundleFormatError; each of the 689 JSON objects tracked in the repository keeps its root.- The
inspectextra admitsinspect_aiup to 0.3.281, the last version measured in a fresh environment. - The limit of one run of the mutation gate follows the measured baseline of its selection, 1.5 times the baseline and never less than 3600 s. A run past its limit stays not measurable and counts as a gap.
Fixed
verify_eval_result_dsse,verify_intoto_dsseandverify_svr_dsse, and with themproofbundle intoto --verifyandproofbundle svr --verify, no longer verify a signed statement without the in-toto Statement v1 layer._typemust behttps://in-toto.io/Statement/v1, and every subject entry must carry a digest. The result reports this asstatement_okand the DSSE check alone assignature_ok. Statements written by this package's exporters keep their verdict.- The decision, outcome, relation statement, verification summary, run ledger and trust pack verifiers, and the matching commands of the Rust verifier, no longer accept a signed statement whose subject names no artifact by digest. Their emitters and
emit_agent_reviewraise their own error for a subject override they would not verify, such as asubject_sha256in capitals. The conformance caserelation/target-subject-missingexpectsRELATION_TARGET_MALFORMED. - The decision validator now rejects JSON null in required fields that do not allow null under
schemas/decision-receipt-v0.1.schema.json;decision verify --strictcould previously reportsafeForAutomation=truefor such a receipt. AnotCheckedentry written as a bare string remains accepted as a deprecated form. - The decision, outcome, run ledger, verification summary and trust pack validators correct the affected pattern checks to use ASCII digit classes and reject additional members in
sha256Digestobjects, matching the corresponding schema constraints.verify_trust_packno longer raisesTypeErrorfor a key whosealgis a list. - agent-review v0.1, v0.2 and v0.3 restrict digits in timestamps to ASCII, as required by RFC 3339. Their
schemaVersionchecks also use ASCII digits. By maintainer decision these changes apply to all three existing predicate versions rather than introducing a new version; the receipts and vectors in the repository retain their verdicts. - The eval-result v0.2 checks read the digits of
evaluatedAtas ASCII. verify_decision_receiptreads the evidence level ofactionOutcome.outcomeReffrom the digest inside the reference. A well-formed digest readsREFERENCE_WELL_FORMED, orCONTENT_RESOLVEDwhen the evidence resolver confirms it, where 6.3.0 read every executed outcome asCLAIMED.action_outcome_provenandokdo not change.- The inspect_ai adapter tells a run stopped early from a complete one with the same counts. The signed provenance carries
total_samples,completed_samplesand, from inspect_ai 0.3.266,logged_samples, each only when the log sets it, andearly_stopping_managerandearly_stopped_samples.nis unchanged. - The agent-review verifiers answer a correctly signed receipt that carries a value of the wrong type, a number RFC 8785 cannot represent or a lone surrogate with a reason code or a verdict that blocks, instead of
internal_error. The new reason codes areSTATEMENT_NOT_CANONICALIZABLEandPREDICATE_NOT_OBJECT.emit_agent_reviewraisesAgentReviewErrorfor such a value. - The modules that canonicalize a statement through the package's canonicalizer map its refusal, and the refusal of the structural budget in front of it, to their own typed error, instead of letting a bare
ValueError,BundleFormatErrororBudgetExceededout. The two primitives ofcanonicalpass the refusal on, as documented. - The corrected public entry points handle failures while formatting values for messages, subject names or serialization, including large integers, deeply nested lists and objects whose
__repr__raises. This does not establish a never-raise guarantee for every public API. Eight public functions inintoto,_verdict,sdjwt_issueandevalclaimremain open for these cases and are tracked in the residual-risk record. verify_decision_receiptandverify_outcome_receiptno longer raiseUnboundLocalErrorfor a signed statement whose predicate is not an object under a policy with arelationssection.experimental.attested_inference.binding_presentanswersFalsefor signed material without a JSON form.sdjwt.issuer_key_fingerprintno longer raises for astrsubclass whose hash raises, andagent_review.validate_time_claimanswers anassurancethat cannot be hashed with the error every wrong assurance gets, instead ofTypeError.verify_sdjwt_vcandverify_bundleno longer accept a presentation in which two committed disclosures give the same claim different values. A claim name stands once in its SD-JWT object.- A test-result statement of the verifier block names at least one case. One with all three case lists missing no longer validates, and
join_test_resultno longer reports it asPASSED. - A command-line mode refuses the options it does not read instead of dropping them, among them the writing options of
proofbundle intoto --verify. bundle.load_bundle,emit.load_signerandagent_review.load_policyread a path-like argument once at the call. A__fspath__that raises or answers something else is refused with aProofBundleError; aRecursionErroris raised as it is.load_bundleread__fspath__twice, so the checked file and the opened file could differ.public_transparency.evaluate_public_transparencyasks forvalidateinside its guard.- The data-hash vector tool and the pilot GitHub write profile refuse a duplicated map key or JSON member name, CBOR that is not valid under RFC 8949 Section 5.3.1 and bytes after the value, instead of keeping the last value. The public API does not change.
- Remove the machine-local paths identified in files included in the package.
- Repository tools and checks, outside the installed package. The pilot reads one copy of each input for verification and for judgement. The pre-tag tooling refuses a tree that names a path twice and reads its envelope, the findings register and the readiness self-receipt strictly. The test-manifest gate reads its lock strictly and requires both floors. The audit matrix reads an artifact and its anchor once and recomputes the agreement of the differential cell. Within parsed code and recognized operations, the core-layer gate checks the bindings its analysis identifies within one module, and counts writes to
TYPE_CHECKINGby assignment and through__dict__,vars()andsetattr. Bindings imported from other package modules, writes throughgetattr(module, "__dict__"),module.__setattr__,object.__setattr__or a renamedsetattr, and code it does not parse remain outside that analysis. The Rust parity gate refuses a coverage report that is not evidence, and the pull-request form judges one rendered sequence. - Repository examples and interoperability code. The verdict-contract example pins the key it trusts, reads its JSON strictly and names what its parser accepts. An ACDE-01 claim over members the population does not hold is not supported, and the ACDE-01 report check recomputes conservation. The accumulator refuses a signed empty state whose frontier is not a list.
conformance/common_vocabulary.comparecompares every axis either side fills when both labels are observations. - Repository release and measurement scripts.
scripts/budget_axis_measurement.pyends a successful run with exit 0.scripts/render_release.pyextends its link binding and validation. The memory test for run 11 is updated. - Repository guards. The guard over lookups and writes on constant containers, the membership scanner and the guard against machine-local paths see more spellings of what they look for.
Full changelog · Known limitations for 6.3.1 · Earlier risk record · Release scope · proofbundle.dev
Assisted by little helpers.