Skip to content

fix(cli): pass expected_origin through verify-proof - #137

Merged
b7n0de merged 1 commit into
mainfrom
fix/verify-proof-expected-origin
Aug 16, 2026
Merged

fix(cli): pass expected_origin through verify-proof#137
b7n0de merged 1 commit into
mainfrom
fix/verify-proof-expected-origin

Conversation

@b7n0de

@b7n0de b7n0de commented Aug 15, 2026

Copy link
Copy Markdown
Owner

verify_tlog_proof has taken an expected_origin argument since the release-review origin-acceptance fix, but the argparse parser for verify-proof carried no flag and the command never passed one. A relying party at the command line could therefore not demand that a validly signed checkpoint came from the log it actually meant to trust. The signature check passes, and without the origin constraint nothing else looks wrong. The library path was already covered by tests/test_anchors_markovian_log.py, so the gap was the command line alone.

This adds --expected-origin, passes it through to verify_tlog_proof, and names the expectation on the human-readable output so a FAIL cannot be misread as a broken signature. The default stays None, meaning the origin is unconstrained, so every existing invocation keeps exactly the verdict it had.

Five tests in tests/test_verify_proof_expected_origin.py pin the pass-through against the frozen markovianprotocol.com/log leaf 7271 fixture. They cover that the flag is discoverable in --help, that a matching origin does not change the verdict, that a mismatching origin fails closed with exit code 1 while inclusion and the reported origin stay intact, that the default leaves the origin unconstrained, and that the text output names the expectation. No network and no optional extra is needed, since Ed25519 verification rides on cryptography, which is a hard dependency.

Found while closing out the markovian log strand, where it was listed as open point five.

verify_tlog_proof has taken expected_origin since the release-review origin-acceptance fix, but the argparse parser carried no flag and the command never passed one. A relying party at the command line could therefore not reject a validly signed checkpoint issued by a different log than the one it meant to trust: the signature check passes, and without the origin constraint nothing else looks wrong. The library path was already covered by tests/test_anchors_markovian_log.py; the gap was the CLI.

Adds --expected-origin (default None, so every existing invocation keeps its verdict), passes it through to verify_tlog_proof, and names the expectation on the human-readable path so a FAIL cannot be misread as a broken signature.

Five tests in tests/test_verify_proof_expected_origin.py pin the pass-through against the frozen markovianprotocol.com/log leaf 7271 fixture. No network, no optional extra.

Found while closing out the markovian log strand, open point five in kraxo/02_proofbundle_berichte/standbericht_markovian_log_proof7271_20260814.md.
@b7n0de
b7n0de merged commit 9e46d23 into main Aug 16, 2026
22 checks passed
@b7n0de
b7n0de deleted the fix/verify-proof-expected-origin branch August 16, 2026 09:47
b7n0de pushed a commit that referenced this pull request Aug 16, 2026
Bringt die drei heute gelandeten PRs (#137 expected-origin in der CLI,
#138 der gemessene ML-DSA-Grund, #135 Dependabot) auf den 3.7.1-Zweig.

Ein Konflikt, in .github/workflows/release.yml, und keine Seite hatte allein
recht:

  - `id: provenance` stammt vom Zweig und wird gebraucht — Zeile 102 liest
    `steps.provenance.outputs.bundle-path`. Ohne die id ist der Ausdruck leer.
  - `actions/attest-build-provenance` pinnt main auf 4d101475 (v4.2.2), der
    Zweig auf 0f67c3f4 (v4.1.1). Die neuere Fassung gewinnt, sie kam aus #135.

Aufgeloest als beides: id behalten, Version von main uebernehmen.
b7n0de pushed a commit that referenced this pull request Aug 16, 2026
… audit grades

The pre-tag falsification pass was pointed at its own output. It found four
defects in this release candidate, all of them mine, and two of them in the
paragraph that justifies the version number.

CHANGELOG, claim 1 -- RETRACTED. "this repository has never shipped a new
user-facing CLI flag in a patch release (measured over sixteen patch releases)"
is false. Measured by diffing `add_argument("--...")` in src/proofbundle/cli.py
across the release tags: four patch releases shipped ten such flags.
  v3.1.0 -> v3.1.1  --expected-root-file --issuer-key --output --policy-id --valid-until
  v3.1.2 -> v3.1.3  --checkpoint-vkey --trusted-checkpoint --verification-time
  v3.2.1 -> v3.2.2  --require-derived-subject
  v3.2.2 -> v3.2.3  --eat (plus the `evalcard` subcommand)
The earlier reasoning had found `--strict` in 3.2.3, correctly established that
it sits on scripts/rust_parity_gate.py rather than the shipped CLI, and then
stopped -- without reading the rest of the same `### Added` section, where
`evalcard` and `show-eval --eat` stand, and without looking at 3.1.1, 3.1.3 or
3.2.2 at all. One explained-away hit was taken for a completed search.

The version number does not change, but its justification does, and the new one
is stronger than the old one was even when the old one was believed: SemVer
2.0.0 section 7 requires MINOR for new backward-compatible functionality in the
public API, `proofbundle` is a console entry point, so a new option on the
shipped CLI is exactly that. The project binds itself to SemVer in three places
(CHANGELOG header, GOVERNANCE.md, README.md). MINOR follows from the rule. The
precedent points the other way and no longer carries the argument; the cost
asymmetry (a `~=3.7.0` pin silently acquires a new capability under 3.7.1)
reinforces it rather than founding it.

CHANGELOG, claim 2 -- CORRECTED. "`verify_tlog_proof` has accepted
`expected_origin` since 3.6" is false; it has since 1.3.0. Measured:
`git show v1.3.0:src/proofbundle/tlogproof.py | grep -c expected_origin` -> 3,
continuous through v3.7.0, never removed and re-added. The v1.3.0 source carries
the release-review comment inline at line 155. PRE-EXISTING FINDING, REPORTED NOT
FIXED HERE: the same wrong wording sits in shipped source on main at
src/proofbundle/cli.py:949, from 911fd5c (PR #137, merged). The test file states
it correctly without a version number.

FALSIFICATION_F1_F7, grade F7 -- REGRADED holds -> FELL. The row claimed "a
repo-wide grep finds 3.8.0 in exactly the three enforced files and nowhere else".
False on its own digest: four files at f64d35e (the CHANGELOG too), seven at
f1e9cea. Worse, the target asked whether a FOURTH place carries a version, and
one does: pre_tag_audit_gate.py::_version_token computes `audit_artifacts/380/`
from the version at run time. Measured consequence -- the gate exits 1 and
TestF7PreTagAudit is the single red test in an otherwise green suite (1 failed,
1970 passed, 116 skipped), while main at ac0688c is green across 13 CI jobs.

FALSIFICATION_F1_F7, grade F6 -- REGRADED holds -> FELL. The target was "the
CHANGELOG claims something the tree does not do". It was answered by checking
that the named commits and files EXIST, which they do -- and the status paragraph
above them, carrying both false claims, was never read.

THE CLASS, because both regrades share it: a computed coupling is invisible to a
literal search. `audit_artifacts/380/` is version-coupled without the string
"3.8.0" occurring in it, so a grep for the version number is not a weak test of
that coupling but a structurally blind one. F7 was the target written to catch
exactly this, and it was answered with the grep.

Also corrected in the section: "for one reason only" / "genau ein Commit". Two
commits touch src/ (911fd5c and the release commit), MANIFEST.in grafts tests,
scripts, schemas, examples, conformance, formal and docs/readiness_pack into the
sdist where 27 files over 13 commits changed, and the dev extra narrows
ruff>=0.5 to <0.17 and mypy>=1.8 to <3. None of it is public API, so the verdict
stands, but the sentence was not accurate.

NEAR MISS, recorded because it would have been the worst outcome here: the first
draft of the retraction used the words "pre-tag adversarial audit" on a
non-negated line. pre_tag_audit_gate scans the [3.8.0] CHANGELOG section for
exactly that marker, so the sentence admitting the audit was incomplete would
have certified it as complete. Reworded, then MEASURED rather than reasoned:
gate ok=false, zero marker lines in the section, zero positive markers in all
three audit_artifacts/380 files. The gate stays red until a real verdict exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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