raven-verify-js
v0.1.0
Published
Open, dependency-free local verifier for Raven receipt-v1: check a signed on-chain-evidence receipt offline against a published key.
Maintainers
Readme
raven-verify-js
The open, dependency-free local verifier for Raven receipt-v1. Check a signed on-chain-evidence receipt yourself — offline, with zero dependencies, against Raven's published public key. You never have to trust Raven's servers to trust a Raven receipt.
Verification is free and permissionless — forever. Producing a receipt is the metered service; checking one is not. This package contains only verification: no signer, no scanner, no network, no advice. A receipt is signed evidence, not a verdict.
What it does
verifyReceiptV1(receipt, { now?, trustedKeys? }) runs the receipt-v1 verification
procedure and returns:
interface VerifyReceiptResult {
valid: boolean; // gated ONLY by checks 1–5 below
stale: boolean; // freshness — reported, never gates `valid`
reasons: string[]; // stable codes for every failed / noted check
keyTrusted?: boolean; // present only when `trustedKeys` is supplied
}Checks, in order (reasons accumulate; a tampered receipt surfaces every failure):
- Shape — exact field set and types.
- Disclaimer — byte-for-byte exact.
- Forbidden words — defense-in-depth over signed strings (
safe,unsafe,legit,scam-free,approved,guaranteed). - Payload hash + receiptId — recomputed over the canonical preimage.
- Signature — Ed25519 over the domain-separated envelope.
- Key trust (non-fatal) — is
signerPublicKeyin yourtrustedKeysset? - Freshness (non-fatal) —
stale = now − timestamp > maxAgeSeconds.
valid and stale and keyTrusted are independent outputs. A stale receipt is
still authentic; a signature from an untrusted key is still a valid signature. Never
collapse them into one boolean — apply your own policy over the three.
Usage
import { verifyReceiptV1 } from "raven-verify-js";
const trustedKeys = new Set([/* base64 SPKI DER key from /pubkey */]);
const result = verifyReceiptV1(receipt, { now: new Date(), trustedKeys });
if (result.valid && result.keyTrusted && !result.stale) {
// ...then apply YOUR policy over receipt.findings / coverageGaps / scope.
}Cross-language note (for future reference verifiers)
Canonical JSON here sorts object keys with JavaScript's default sort (UTF-16 code-unit order). Receipt object keys are a fixed set of ASCII field names, so byte-order, code-point order, and UTF-16 code-unit order all coincide — a verifier written in Rust/Go/Python may use its native string sort and stay conformant for this schema. Do not add non-ASCII object keys without revisiting this.
Non-goals
This package does not: request or produce receipts, sign anything, access wallets, submit transactions, call the network, evaluate policy, or emit any safe/unsafe/risk judgment. Producing evidence and deciding what to do with it live elsewhere. Raven does not issue safe/unsafe verdicts.
Tests
npm test # builds, then runs the vendored golden vectors offlineThe fixtures under fixtures/receipt-v1/ are the same golden vectors the in-app
verifier is tested against — including a real production-signed BONK receipt — so
this extracted kernel cannot silently diverge from production.
