Skip to main content

gbverify

Verify the integrity of a Greenbar evidence packet in one command.

gbverify is a small, dependency-free, MIT-licensed tool that recomputes the SHA-256 manifest hash printed on every Greenbar evidence-packet PDF and reports whether it matches the record. It runs entirely on your machine — no network call, no Greenbar account.

If the hash matches, you have cryptographic evidence that the AI-assisted review record on the accompanying PDF is bit-for-bit identical to the record sealed at approval time in Greenbar's database. If it doesn't match, the packet was modified after sealing.

gbverify isn't tied to one Greenbar product. It verifies any packet whose schemaVersion it recognizes (currently evidence.v2 — see "Schema versioning" below), regardless of which Greenbar tool sealed it.

Install

npm install -g @greenbarsystemsllc/gbverify   # Node ≥ 18
pipx install gbverify                         # Python ≥ 3.8

Or run it once without installing:

npx @greenbarsystemsllc/gbverify packet.json

Use

$ gbverify packet.json
✓  manifest hash valid
   computed: d7096a4ba450756b3f251b34c83ddada35e5e22f2fe7c3c1a0f676e2686b08f2
   recorded: d7096a4ba450756b3f251b34c83ddada35e5e22f2fe7c3c1a0f676e2686b08f2
   schema:   evidence.v2

Also verify the source PDF the AI extracted from:

$ gbverify --document invoice.pdf packet.json
✓  manifest hash valid
✓  source document hash matches

Machine-readable output:

$ gbverify --json packet.json
{"manifest":{"ok":true,"computedManifestHash":"d709…","recordedManifestHash":"d709…", …}}

Try it

sample/packet.json is a real (synthetic) evidence packet. sample/tampered.json is the same packet with extractedInvoice.total changed after sealing — everything else, including the recorded manifestHash, is untouched:

$ gbverify sample/packet.json
✓  manifest hash valid
   computed: d7096a4ba450756b3f251b34c83ddada35e5e22f2fe7c3c1a0f676e2686b08f2
   recorded: d7096a4ba450756b3f251b34c83ddada35e5e22f2fe7c3c1a0f676e2686b08f2
   schema:   evidence.v2

$ gbverify sample/tampered.json
✗  manifest hash INVALID
   computed: 0468a89c02135b62561ba36bdf6cc31016783a278ceddc4b4aa0acc972cd1bdb
   recorded: d7096a4ba450756b3f251b34c83ddada35e5e22f2fe7c3c1a0f676e2686b08f2
   schema:   evidence.v2

Problems:
  - manifestHash mismatch

Exit code is 0 for the first, 1 for the second — the recorded hash never changes, only what it's checked against.

What a passing verification proves

  • The record is untampered. The invoice, line items, AI briefing card, deterministic risk score inputs, validation findings, approver attestation, and any blocking-finding override were bit-for-bit identical to what was sealed at approval time.
  • The source PDF is the one the AI reviewed. With --document, the SHA-256 of the file on disk matches the source-document hash recorded in the packet at ingest time.

What it does not prove

  • Whether the approver's judgment was correct.
  • Whether the vendor is legitimate.
  • Whether the AI's extraction was accurate.

These are review questions. The packet is the evidence you use to ask them, not the answer.

How the hash is computed

The manifest hash is a SHA-256 over the manifest JSON, serialized with recursively sorted object keys and no incidental whitespace (canonical JSON). The current source-of-truth implementation of this algorithm lives at src/lib/evidence/assemble.ts in the Greenbar-Pay repository. test.sh checks that gbverify's own Node and Python implementations agree with each other on every change; it does not check them against a live copy of assemble.ts. Today, the two repos stay in sync by convention, not by an automated cross-repo test.

You do not need this tool to verify — a five-line Python script or a short shell pipeline will produce the same hash:

import json, hashlib
p = json.load(open("packet.json"))["gbEvidencePacket"]
s = json.dumps(p["manifest"], sort_keys=True, ensure_ascii=False,
               separators=(",", ":"))
assert hashlib.sha256(s.encode("utf-8")).hexdigest() == p["manifestHash"]

Exit codes

Code Meaning
0 Hash valid (and document hash matches if --document was given)
1 Manifest hash INVALID — packet modified after sealing
2 Usage error / unreadable input
3 --document mismatch (manifest was valid but the PDF is not the sealed one)

Schema versioning

gbverify refuses to verify a packet with an unknown schemaVersion. This prevents silent mis-hashing when Greenbar changes the canonical-JSON contract. If you receive a packet with a newer schema, upgrade gbverify; if you receive one with an older schema, use the matching older gbverify release.

Currently supported: evidence.v2.

License

MIT. Contributions welcome. Report canonicalization bugs at github.com/GreenbarSystems/gbverify/issues.

Release files for gbverify 0.3.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gbverify 0.3.3
File Size Uploaded
gbverify-0.3.3.tar.gz 7.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gbverify 0.3.3
File Interpreter ABI Platform
gbverify-0.3.3-py3-none-any.whl Python 3 none any Details

Total release size: 15.5 kB

Release files / gbverify-0.3.3.tar.gz

Download URL gbverify-0.3.3.tar.gz
Size 7.7 kB
Tags Source
SHA-256 checksum
How to use checksums
dc1a980f112cde7a1224f4a30f21df693fcc531faf157fc451066180563a23f4
BLAKE2b-256 checksum
How to use checksums
a3a6b9ba60e3d69f83237fa5b0ff0b48596f4123084a696073134d2046e71bdc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.

Transparency log

Release files / gbverify-0.3.3-py3-none-any.whl

Download URL gbverify-0.3.3-py3-none-any.whl
Size 7.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1380b437678266cd5edd8ad0907ab742d7a688d8efb7c855c67654a1bb2c9eb0
BLAKE2b-256 checksum
How to use checksums
7bb9e1caf82a687dde6511af231140d2e7e5f0f69610bb1421eee2be64fb9faf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.3 This release

2 release files

0.3.2

2 release files

0.3.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page