joule-code: close the two gaps its conformance gate cannot see #97

Open
dcharlot wants to merge 1 commit from ci/joule-code-pack into main
Owner

Corrected after opening. This PR originally claimed joule-code's pack was
verified by nothing. That was wrong — joule-code-conformance.yml runs the
verifier on every PR touching joule-code/**. My survey grepped *.rs and
never looked in .github/workflows/. The real gaps are narrower and are what
this now closes.

joule-code-conformance ships a complete pack verifier, and a dedicated
workflow already runs it. The pack is not unchecked. This closes the two
gaps that gate cannot see.

1. It cannot tell a verified pack from a skipped one

The gate is grep -Eq '0 failed' over the summary line, and verify_pack is
documented to let SKIPs pass. Run the possible summaries through the gate's own
expression:

summary line gate
24 passed, 0 failed, 0 skipped ✅ passes
1 passed, 0 failed, 23 skipped ✅ passes
0 passed, 0 failed, 24 skipped ✅ passes

A pack where every vector was skipped, or which shrank to a single vector,
clears the existing gate. This pins the count at 24 and requires skip == 0 —
the distinction the grep cannot draw. Pinned rather than bounded, because
>= 24 would let a case be deleted as long as another was added.

2. It is paths:-filtered, and this crate reaches outside the filter

joule-code-conformance.yml is scoped to joule-code/**. But:

joule-code-conformance   -> jcp-schema, jcp-grant, jcp-receipt   (../../../../jcp/...)
joule-code-joulecontract -> joulecontract-schema

A change in jcp to canonical CBOR or the receipt preimage would change the
op_ids and signatures this pack pins — and would not touch
joule-code/**, so that workflow would not run. (PR #98 in this same series
edits jcp-receipt and does not trigger it.) standards-build.yml carries a
deliberate "NO paths: filter" and runs cargo test --workspace, so hosting
the call in tests/pack.rs covers the cross-standard case. Confirmed with that
exact command:

     Running tests/pack.rs (target/debug/deps/pack-166f00c1bcdb19a2)
test the_published_pack_still_verifies ... ok
test a_tampered_pack_is_not_reported_as_passing ... ok

The tamper test

A verifier that reports PASS on a pack it never really read is worse than no
verifier, because it manufactures confidence — a tampered copy of map's pack
once still reported 15/15. So the tamper case does not trust the report: it
flips one hex digit of a signature in a scratch copy and requires the verifier
to notice. (It does; verify_pack also returns Err on a missing file rather
than a vacuous zero-count pass.)

Falsified

change result
corrupt a published signature ✅ verify test fails
claim 25 vectors ✅ expected 25 vectors to be checked, 24 were
neuter the flip to a no-op ✅ the verifier is not checking what it publishes

Pack restored afterwards, byte-identical to main.

One honest limit: I could not force a SKIP to confirm that assertion fires.
Unlike the other three it is reasoned, not falsified.

Also

Corrects the workflow comment claiming nothing in CI validates the published
conformance/v1 files on disk — no longer true with the tests/pack.rs suites
— and records that a missing conformance: key is not evidence a pack is
unchecked. joule-code and sandbox are both covered without one.

🤖 Generated with Claude Code

> **Corrected after opening.** This PR originally claimed joule-code's pack was > verified by nothing. That was wrong — `joule-code-conformance.yml` runs the > verifier on every PR touching `joule-code/**`. My survey grepped `*.rs` and > never looked in `.github/workflows/`. The real gaps are narrower and are what > this now closes. `joule-code-conformance` ships a complete pack verifier, and a dedicated workflow already runs it. The pack is **not** unchecked. This closes the two gaps that gate cannot see. ### 1. It cannot tell a verified pack from a skipped one The gate is `grep -Eq '0 failed'` over the summary line, and `verify_pack` is documented to let SKIPs pass. Run the possible summaries through the gate's own expression: | summary line | gate | |---|---| | `24 passed, 0 failed, 0 skipped` | ✅ passes | | `1 passed, 0 failed, 23 skipped` | ✅ **passes** | | `0 passed, 0 failed, 24 skipped` | ✅ **passes** | A pack where every vector was skipped, or which shrank to a single vector, clears the existing gate. This pins the count at 24 and requires `skip == 0` — the distinction the grep cannot draw. Pinned rather than bounded, because `>= 24` would let a case be deleted as long as another was added. ### 2. It is `paths:`-filtered, and this crate reaches outside the filter `joule-code-conformance.yml` is scoped to `joule-code/**`. But: ``` joule-code-conformance -> jcp-schema, jcp-grant, jcp-receipt (../../../../jcp/...) joule-code-joulecontract -> joulecontract-schema ``` A change in `jcp` to canonical CBOR or the receipt preimage would change the `op_id`s and signatures this pack pins — and would **not** touch `joule-code/**`, so that workflow would not run. (PR #98 in this same series edits `jcp-receipt` and does not trigger it.) `standards-build.yml` carries a deliberate "NO `paths:` filter" and runs `cargo test --workspace`, so hosting the call in `tests/pack.rs` covers the cross-standard case. Confirmed with that exact command: ``` Running tests/pack.rs (target/debug/deps/pack-166f00c1bcdb19a2) test the_published_pack_still_verifies ... ok test a_tampered_pack_is_not_reported_as_passing ... ok ``` ### The tamper test A verifier that reports PASS on a pack it never really read is worse than no verifier, because it manufactures confidence — a tampered copy of `map`'s pack once still reported 15/15. So the tamper case does not trust the report: it flips one hex digit of a signature in a scratch copy and requires the verifier to notice. (It does; `verify_pack` also returns `Err` on a missing file rather than a vacuous zero-count pass.) ### Falsified | change | result | |---|---| | corrupt a published signature | ✅ verify test fails | | claim 25 vectors | ✅ `expected 25 vectors to be checked, 24 were` | | neuter the flip to a no-op | ✅ `the verifier is not checking what it publishes` | Pack restored afterwards, byte-identical to main. **One honest limit:** I could not force a SKIP to confirm that assertion fires. Unlike the other three it is reasoned, not falsified. ### Also Corrects the workflow comment claiming nothing in CI validates the published `conformance/v1` files on disk — no longer true with the `tests/pack.rs` suites — and records that a missing `conformance:` key is not evidence a pack is unchecked. `joule-code` and `sandbox` are both covered without one. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
joule-code: run the pack verifier that CI was never invoking
All checks were successful
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 1m29s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 1m35s
standards workspaces build + test / aac-rs (pull_request) Successful in 33s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 35s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m48s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 33s
standards workspaces build + test / map-rs (pull_request) Successful in 28s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m22s
standards workspaces build + test / mesh-rs (pull_request) Successful in 26s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m20s
standards workspaces build + test / openpay (pull_request) Successful in 1m14s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m12s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 2m7s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 1m52s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m7s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m48s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m29s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m51s
36a9acff3c
`joule-code-conformance` already shipped a complete verifier. `verify_pack`
reads all six files of `joule-code/conformance/v1`, recomputes every derived
field — each `op_id` is BLAKE3 over canonical CBOR of its `CodingOp`, each
binding and receipt signature a real Ed25519 signature over the spec's
preimage — and returns a FAIL count that `main()` turns into a non-zero exit.

Nothing ran it. No test calls `verify_pack`, and the `joule-code-rs` matrix
entry carries no `conformance:` key, so the twenty-four published vectors
were checked by a human typing the command and by nothing else.

It was missed for a specific reason. The other five conformance binaries take
no arguments, so CI invokes them as `cargo run -p <crate> --bin <crate>`. This
one requires `verify <pack-dir>` and, given nothing, prints usage and exits
FAILURE. A survey looking for "a main() CI does not run" found the other five
and walked past this one, because wiring it up needed a different shape of
step. Hosting the call in `tests/pack.rs` removes the argument problem: the
existing `cargo test --workspace` step runs it, confirmed by running that
exact command rather than reasoning about it.

The second test is the load-bearing one. A verifier reporting PASS on a pack
it never read is worse than none, because it manufactures confidence — a
tampered copy of `map`'s pack once still reported 15/15. So the tamper case
does not trust the report: it flips one hex digit of a signature in a scratch
copy and requires the verifier to notice. The offset is found by scanning to
the value's opening quote, since the pack is column-aligned and the run of
spaces is not something a test should depend on.

Falsified, each assertion separately: corrupting a published signature fails
the verify test; claiming 25 vectors fails the count; neutering the flip to a
no-op fails the tamper test with "the verifier is not checking what it
publishes". The pack was restored afterwards and is byte-identical to main.

The vector count is pinned, not bounded — `>= 24` would let a case be deleted
as long as another was added. `skip` is pinned at 0 for the same reason: a SKIP
is a published-but-unverified vector, and the verifier is documented to let
skips pass, so reintroducing a placeholder should be a deliberate edit here.
One honest limit: I could not force a SKIP to confirm that assertion fires,
so unlike the other three it is reasoned rather than falsified.

Also corrects the workflow comment claiming nothing in CI validates the
published `conformance/v1` files on disk. That stopped being true with the
`tests/pack.rs` suites, and a missing `conformance:` key is no longer evidence
that a standard's pack is unchecked.

Co-Authored-By: Claude Opus 5 <[email protected]>
dcharlot force-pushed ci/joule-code-pack from 36a9acff3c
All checks were successful
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 1m29s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 1m35s
standards workspaces build + test / aac-rs (pull_request) Successful in 33s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 35s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m48s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 33s
standards workspaces build + test / map-rs (pull_request) Successful in 28s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m22s
standards workspaces build + test / mesh-rs (pull_request) Successful in 26s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m20s
standards workspaces build + test / openpay (pull_request) Successful in 1m14s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m12s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 2m7s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 1m52s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m7s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m48s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m29s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m51s
to b8006b9b00
All checks were successful
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 1m29s
standards workspaces build + test / aac-rs (pull_request) Successful in 31s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 33s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 32s
standards workspaces build + test / map-rs (pull_request) Successful in 28s
standards workspaces build + test / mesh-rs (pull_request) Successful in 22s
standards workspaces build + test / openpay (pull_request) Successful in 1m15s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 1m30s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m49s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m3s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m19s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m56s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m4s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m8s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m57s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m30s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m59s
2026-09-19 05:24:02 -04:00
Compare
dcharlot changed title from joule-code: run the pack verifier that CI was never invoking to joule-code: close the two gaps its conformance gate cannot see 2026-09-19 05:24:27 -04:00
All checks were successful
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 1m29s
standards workspaces build + test / aac-rs (pull_request) Successful in 31s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 33s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 32s
standards workspaces build + test / map-rs (pull_request) Successful in 28s
standards workspaces build + test / mesh-rs (pull_request) Successful in 22s
standards workspaces build + test / openpay (pull_request) Successful in 1m15s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 1m30s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m49s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m3s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m19s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m56s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m4s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m8s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m57s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m30s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m59s
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin ci/joule-code-pack:ci/joule-code-pack
git switch ci/joule-code-pack

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff ci/joule-code-pack
git switch ci/joule-code-pack
git rebase main
git switch main
git merge --ff-only ci/joule-code-pack
git switch ci/joule-code-pack
git rebase main
git switch main
git merge --no-ff ci/joule-code-pack
git switch main
git merge --squash ci/joule-code-pack
git switch main
git merge --ff-only ci/joule-code-pack
git switch main
git merge ci/joule-code-pack
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!97
No description provided.