feat(receipt): show what the signature actually binds, and stop dropping the amount - #11
Merged
Merged
Conversation
…ing the amount
A verified receipt printed six lines, none of which said what had been verified.
The signed payload of the production receipt used for the sales demo carries the
whole chain — policy id and policy hash, authorization id, decision record id,
artifact hash, certificate id, transaction id, Stripe PaymentIntent, settlement
state and time, amount, currency, rail, agent, purpose — and the tool showed
none of it.
That is the wrong failure for this tool in particular. The pitch is "do not
trust our dashboard, verify it yourself", and the verifier answered with an
unsupported VALID, leaving the substance to be taken on trust anyway.
Everything now printed is read from the payload that has already passed BOTH
the signature and the payload-hash check, so nothing is displayed as bound by a
signature that does not cover it. A tampered payload still fails before any of
it is shown. Absent fields are omitted rather than invented.
Also fixes a silent data bug found while wiring this up: production emits
`amount` as a STRING ("99"), and the code tested `typeof p.amount === "number"`.
Every real receipt therefore verified with no amount at all. Both forms are now
accepted; a non-numeric value is dropped rather than coerced.
`bindings` is exposed on ReceiptVerifyResult so library consumers get the same
fields without re-parsing the payload.
98 tests (was 93). The new ones cover the binding surface, both amount forms,
non-numeric amounts, absent bindings, and that a post-signing tamper fails
before anything is reported as bound.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The demo artifact carries the whole story and the tool was showing none of it.
Before
After
That is real output from the live production receipt, not a mockup.
Why this is the right failure to fix
The pitch is "don't trust our dashboard, verify it yourself." The verifier was answering with an unsupported
VALIDand leaving the substance — which policy, which artifact, which decision, which settlement — to be taken on trust anyway. The signature was only as interesting as what it bound, and the tool never said.Safety: everything printed is read from the payload that has already passed both the signature and payload-hash checks, so nothing is displayed as bound by a signature that does not cover it. A post-signing tamper fails before any of it renders. Absent fields are omitted rather than invented.
A silent data bug found while wiring this up
Production emits
amountas a string ("99"). The code testedtypeof p.amount === "number", so every real receipt verified with no amount displayed at all. Both forms now work; a non-numeric value is dropped rather than coerced into something wrong.Verified against production
Each binding was confirmed to dereference before being surfaced:
fb914a90…709519fd…df033885…Tests
98, up from 93. New coverage: the binding surface, both amount forms, non-numeric amounts, absent bindings reported as null rather than invented, and that a post-signing tamper fails before anything is reported as bound.
Version bumped to 0.1.1.
🤖 Generated with Claude Code