Skip to content

feat(cli): one install answers all three registry questions, and lead with it - #75

Merged
imran-siddique merged 2 commits into
mainfrom
trace-verify-cli-parity
Sep 12, 2026
Merged

feat(cli): one install answers all three registry questions, and lead with it#75
imran-siddique merged 2 commits into
mainfrom
trace-verify-cli-parity

Conversation

@imran-siddique

Copy link
Copy Markdown
Member

The problem

pip install trace-verify answered one of the three questions a reader can ask of this registry.

Question Before After
Is my claim anchored? trace-verify --claim ... unchanged
Does the registry's own history hold? Python API, no command trace-verify chain ...
Does an outside witness agree? not in the package at all trace-verify receipt ...

The second and third were reachable only by cloning this repository, which is the wrong ask for a public accountability layer. The README made it worse by leading with git clone while the trace-spec tutorial led with pip install.

The substantive half

verify_against_raw_entries moves from tools/verify_checkpoint_chain.py into trace_verify._checkpoint as verify_chain_against_entries, and is exported.

That function is the check that catches a quiet edit to an already-anchored entry. Such an edit leaves every checkpoint record's own math self-consistent, so the chain-consistency check still passes and only the recompute fails. It existed here and nowhere a pip user could reach it. Verified by editing one field outside mmr_checkpoint in the September entry:

chain consistency: passes (as expected, that is the point)
recompute:         root 5da32203... != claimed 3af8ddf2... -- altered after it was checkpointed

Compatibility

The inclusion check keeps its bare-flag form, so every invocation written against 0.3.x runs unchanged. Only the two literal tokens chain and receipt route; anything else falls through to the inclusion parser, which also means an argument typo is reported by the parser the caller was actually using. Tested.

cbor2 and scitt-cose stay imported inside verify(), so import trace_verify still works with no CBOR stack installed, and a test asserts no top-level import of either creeps back. They arrive through a new extra, pip install "trace-verify[witness]"; without it, receipt names the extra instead of raising ImportError. Both tools/ scripts stay, re-exporting rather than reimplementing, because the evidence packets cite them by path.

Two defects found on the way

The published CLI reported the wrong version. trace-verify 0.3.0 and 0.3.1 both answer --version with 0.1.0__version__ had not moved since #19 and nothing compared it to anything. A bug reporter was handing us a string naming neither their release nor the code in it. The publish workflow now refuses a release whose tag disagrees with the packaged version, or whose __version__ disagrees with pyproject.toml. Checked against this tree: v0.4.0 passes, v0.3.1 fails.

pyproject's own comment said to undo it. It read "Do not point any of these back at trace-registry until that repository is public." The repo is public. Homepage, Bug Tracker and Changelog come back; Documentation and Anchor format stay at trace-spec, where the normative text belongs. A test asserts any URL naming a file in this tree names one that exists, since the previous breakage went unnoticed for a week.

Verification

276 tests pass, up from 263. CI smoke-tests all three commands the way a reader who only ran pip install runs them. All three were also run from a clean venv against a built wheel, plus a base install without the extra to confirm chain still works and receipt explains itself. sha256sum -c passes on all eight files of the September 7 packet.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X2GDChXjA7BAdDNzCAmBJv

imran-siddique and others added 2 commits September 11, 2026 21:27
Until now `pip install trace-verify` answered one of the three questions a
reader can ask of this registry. Inclusion had a CLI. Chain verification was a
Python API with no command. Witness-receipt verification was not in the package
at all. The other two were reachable only by cloning this repository, which is
the opposite of what a public accountability layer should ask of a third party.

  trace-verify --claim C.json --proof P.json --entry E.ndjson   (unchanged)
  trace-verify chain E.ndjson [MORE...]
  trace-verify receipt --checkpoint CP.json --response POST.json \
      --registry-key HEX --witness-key HEX --expected-log-id ID

The inclusion check keeps its bare-flag form, so every invocation written
against 0.3.x runs unchanged. Only the two literal tokens route; anything else
falls through to the inclusion parser, which also means an argument typo is
reported by the parser the caller was actually using.

verify_against_raw_entries moves from tools/verify_checkpoint_chain.py into
trace_verify._checkpoint as verify_chain_against_entries and is exported. This
is the substantive half. That function is the check that catches a quiet edit to
an already-anchored entry: such an edit leaves every checkpoint record's own
math self-consistent, so the chain check still passes and only the recompute
fails. It was the one check a pip user could not reach. Verified by editing a
single field outside mmr_checkpoint in the September entry: chain consistency
passes, the recompute reports root 5da32203 against the claimed 3af8ddf2.

tools/verify_witness_receipt.py moves to trace_verify._witness. cbor2 and
scitt-cose stay imported inside verify(), so `import trace_verify` still works
for the inclusion-only reader, and a test asserts no top-level import of either
creeps back. The witness extra carries them: pip install "trace-verify[witness]".
Without it, `receipt` names the extra rather than raising ImportError.

Both tools/ scripts stay, re-exporting rather than reimplementing, because the
evidence packets cite them by path and a second copy of a verifier is exactly
what should not exist.

CI smoke-tests all three commands the way a reader who only ran pip install runs
them. 273 tests pass, up from 263.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X2GDChXjA7BAdDNzCAmBJv
The README told a reader to clone this repository and run
tools/verify_inclusion.py, while the trace-spec tutorial told them to
pip install trace-verify. Two front doors, and the repository's own one was the
longer path. It now opens on one install and three commands, and says plainly
that answering the first question needs no clone at all, because --entry-url
fetches an entry over https from an allowlisted host.

pyproject's URL block carried the instruction "Do not point any of these back at
trace-registry until that repository is public." That condition has been met.
Homepage, Bug Tracker and Changelog come back here, where the code, the issues
and the changelog actually are. Documentation and Anchor format stay at
trace-spec: those are normative spec documents that describe this
implementation, not documents about this package. A test asserts that any URL
naming a file in this tree names one that exists, so a rename fails in CI rather
than silently on PyPI, which is how the previous breakage lasted a week.

The publish workflow now refuses to build a release whose tag disagrees with the
packaged version, or whose __version__ disagrees with pyproject. Both 0.3.0 and
0.3.1 shipped answering --version with 0.1.0, so a bug reporter was handing us a
string that named neither their release nor the code in it. The guard is
checked against the current tree: v0.4.0 passes, v0.3.1 fails.

Also: the bug template asks for the installed command first, docs/mmr-checkpoint
names `trace-verify chain` before the clone form, and the September 7 evidence
packet gains the no-clone invocation beside its existing one, with SHA256SUMS
moved to match and sha256sum -c passing on all eight files.

276 tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X2GDChXjA7BAdDNzCAmBJv
@imran-siddique
imran-siddique requested a review from a team as a code owner September 12, 2026 04:32
@imran-siddique
imran-siddique merged commit e638f8c into main Sep 12, 2026
3 checks passed
@imran-siddique
imran-siddique deleted the trace-verify-cli-parity branch September 12, 2026 04:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant