diff --git a/CHANGELOG.md b/CHANGELOG.md index aeeb545..6309217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.1] - 2026-10-12 + +### Fixed + +- **Receipts from Pipelock parallel receipt chains now verify.** `verify()` and + `verify_chain()` accept the optional `group_binding` object that Pipelock signs + into `session_open` when `flight_recorder.receipt_chains` is greater than 1. + Before this release every shard of a grouped run failed with an unknown signed + field error. The binding is part of the signed projection in Go field order. + This is per-receipt and per-chain compatibility only: whole-group verification + (signed open and close manifests, shard membership, missing shards, the link to + a previous group and recovery tails) still needs Pipelock's own group verifier. + Receipts from single-chain runs verify as before. + +### Documentation + +- **The README states what a valid result does not prove.** It no longer says exit codes match `pipelock verify-receipt` or that the package mirrors the Go verifier without qualification. A valid chain is not proof that its end is present, a valid shard is not proof that a parallel-chain group is complete, and entries other than ActionReceipt v1 in a recorder file are not checked. + ## [0.4.0] - 2026-07-30 ### Added diff --git a/README.md b/README.md index d182737..4cd03c8 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ **Python verifier for [Pipelock](https://github.com/luckyPipewrench/pipelock) receipts.** Supports **ActionReceipt v1** chains and individual **EvidenceReceipt v2** envelopes for contract-aware lifecycle events. Verifies Ed25519 signatures, v1 chain linkage, v2 payload schemas, key-purpose authority, and flight-recorder wrapping. -Mirrors the Go reference implementation byte-for-byte. The conformance golden files in `tests/conformance/` are generated by Pipelock's Go code and verified identically by both sides. +Mirrors the Go reference implementation's signature, chain-linking and canonical-form checks byte-for-byte. The conformance golden files in `tests/conformance/` are generated by Pipelock's Go code and verified identically by both sides. It does not implement the end-of-chain proof or the whole-group verification that newer Pipelock releases add; see the section "What a valid result does and does not prove" below. [Install](#install) · [Usage](#usage) · [EvidenceReceipt v2](#evidencereceipt-v2) · [Well-known directory](#well-known-directory) · [What gets verified](#what-gets-verified) · [Spec](https://pipelab.org/learn/action-receipt-spec/) · [Go reference](https://github.com/luckyPipewrench/pipelock) @@ -116,7 +116,13 @@ python -m pipelock_verify evidence.jsonl \ --rotation-endorsement receipt-rotation-2026-07-30.json ``` -Exit codes match `pipelock verify-receipt`: 0 on success, 1 on failure. +Exit codes: 0 on success, 1 on failure. In Pipelock releases that add end-of-chain proofs, `pipelock verify-receipt` also exits 3 for a valid chain whose end is not proven. This package has no such state. + +### What a valid result does and does not prove + +`CHAIN VALID` means every ActionReceipt v1 extracted from the file has a valid signature, the signer matches, and each receipt links to the one before it. Other entries in a flight-recorder file are not checked here: altering the signature on a wrapped EvidenceReceipt v2 entry still returns `CHAIN VALID`, while Pipelock's own `pipelock verify-receipt` rejects the recorder. It also does not prove the chain ends where it should. A chain cut off after a receipt still verifies, because this package has no end-of-chain proof. The exception is a chain verified with a rotation endorsement: cutting it before the rotation boundary leaves the endorsement unused, and that is rejected. In Pipelock releases that add end-of-chain proofs, `pipelock verify-receipt` reports a chain with no proven end as `VALID PREFIX, END UNPROVEN`. Use it when a missing tail matters. + +Parallel receipt chains (`flight_recorder.receipt_chains` greater than 1) write one chain per shard. Each shard verifies on its own with this package, but a valid shard does not show that the group is complete. Shard membership, missing shards, the signed group open and close, and the link to a previous group still need Pipelock's own group verifier. ## EvidenceReceipt v2 diff --git a/pipelock_verify/__init__.py b/pipelock_verify/__init__.py index 24a5475..05fb007 100644 --- a/pipelock_verify/__init__.py +++ b/pipelock_verify/__init__.py @@ -65,7 +65,7 @@ verify_chain, ) -__version__ = "0.4.0" +__version__ = "0.4.1" __all__ = [ "PAYLOAD_AUTHORITY", diff --git a/pipelock_verify/__main__.py b/pipelock_verify/__main__.py index e5752b7..75f5853 100644 --- a/pipelock_verify/__main__.py +++ b/pipelock_verify/__main__.py @@ -1,8 +1,9 @@ """Command-line interface for ``python -m pipelock_verify``. Verifies a single receipt JSON file or a flight recorder JSONL chain. -Exit code 0 on success, 1 on failure — same convention as the Go -``pipelock verify-receipt`` command. +Exit code 0 on success, 1 on failure. Pipelock releases that add end-of-chain +proofs also exit 3 from ``pipelock verify-receipt`` for a valid chain whose end +is not proven; this CLI has no such state. """ from __future__ import annotations diff --git a/pyproject.toml b/pyproject.toml index 1553924..2c50099 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pipelock-verify" -version = "0.4.0" +version = "0.4.1" description = "Verify Pipelock receipts: ActionReceipt v1 chains and individual EvidenceReceipt v2 envelopes." readme = "README.md" license = "Apache-2.0"