
Company News
Free Business Plan Upgrades for Open Source Maintainers
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.
@graneth/verify
Advanced tools
Offline verifier for Graneth's signed governance receipts — checks the Ed25519 signature against a public key you already have. Zero network calls, zero runtime dependencies.
Offline verifier for Graneth's signed governance receipts. Recomputes the
canonical bytes and checks the Ed25519 signature against a public key you
already have — no network calls, no account, no dependencies beyond Node's
built-in crypto/fs.
npx @graneth/verify receipt.json --key graneth-key.json
Don't have the key yet? Download it once (this tool won't fetch it for you):
curl -o graneth-key.json https://graneth.com/.well-known/graneth-attestation-key.json
--key accepts either that key document or a raw PEM public key.
| Exit | Word | What it means |
|---|---|---|
0 | PASS | The signature was checked, and it is valid. |
1 | FAIL | The signature was checked, and the file does not match it — the document was altered after it was signed. |
2 | UNCHECKED | Nothing was checked, and the obstacle is on your side: a missing or wrong key, an unreadable file, a mistake in the command. This one says nothing about the receipt. |
3 | MALFORMED | This is not a well-formed Graneth receipt — no signature, or a signed field removed since it was issued. Not evidence of anything. |
Only 0 means verified.
Forgetting --key, pointing at a key file that isn't there, or using a key
document downloaded before the signing key was rotated are all mistakes on the
reader's side — and a verifier that answers them with the same word it uses for
a forgery is telling the reader something false about a receipt that may be
perfectly good.
2 and 3 are separated for the opposite reason, and the line between them is
load-bearing. UNCHECKED is the one state a reader is explicitly reassured
about, so anyone who can steer a document into it gets to choose the sentence
the reader sees.
The line is drawn once, by artifact rather than by case:
Before the tool holds bytes claimed to be a receipt — no path, no file, an unreachable URL, a mistyped command — the obstacle is yours, and
UNCHECKEDis honest. Once it holds those bytes, a defect in them is the document's, and it isMALFORMED.
Not because we can tell who damaged the bytes: because one corrupted byte is indistinguishable, from in here, from an edited one — and the person editing a receipt is the one who benefits from the doubt. The default side is the one whose sentence is not a lie under either reading, and "this is not a well-formed Graneth receipt" is true even when you simply pointed at the wrong file.
Your copy of the key stays your artifact end to end, so every defect in it —
unreadable, not JSON, no matching key — is UNCHECKED. The same unparseable
file is therefore MALFORMED when passed as a receipt and UNCHECKED when
passed with --key.
Whether a file is a well-formed receipt is a property of that file, so it is
answered without a key at all: graneth-verify receipt.json with no --key
still reports MALFORMED for a document that is not one. (In 0.2.0 those
checks sat behind key resolution, so the same file answered MALFORMED with a
key and UNCHECKED without — under a sentence that blamed the reader. Fixed in
0.2.1.)
Two consequences of the same rule: every receipt Graneth issues names its
signing key inside the signature, so a document declaring a version and an
algorithm but no keyId has had that field removed and is MALFORMED; and the
copy of keyId in the receipt envelope is never consulted for a verdict,
because no signature covers it.
--help also exits 2, because exit 0 is reserved for a receipt that verified.
Programmatically, verifyReceipt() returns outcome: "valid" | "mismatch" | "malformed" | "unverifiable" alongside the original valid boolean, which still
means exactly outcome === "valid".
PASS — Ed25519 signature is valid.
scan #4821 acme-corp/payments-api
verdict: PASSED (critical 0, warnings 2)
keyId: 3ed76e31c05aecdb
The signature covers the object it was given, so a receipt can be validly signed and still not state a repository or a verdict. When that happens the tool says so rather than printing a blank:
PASS — Ed25519 signature is valid.
scan #4821
NOT ATTESTED: repository, verdict — the signature is valid, but
this receipt's signed object does not carry those facts.
Exit code is still 0 in that case: the signature really is valid, and scripts key on that. What changes is that the human reading it is not left to assume the receipt attested to more than it did.
NOT ATTESTED is a different axis from PASS/FAIL/UNCHECKED: it describes what a
valid signature covers, not whether a check happened.
Programmatic use: import { verifyReceipt } from "@graneth/verify".
MIT
FAQs
Offline verifier for Graneth's signed governance receipts — checks the Ed25519 signature against a public key you already have. Zero network calls, zero runtime dependencies.
The npm package @graneth/verify receives a total of 446 weekly downloads. As such, @graneth/verify popularity was classified as not popular.
We found that @graneth/verify demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Open source maintainers are under more pressure than ever. We're raising our open source program from the Team plan to the Business plan, free.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.