@vextlabs/stoa-verifier
v0.1.1
Published
Standalone verifier for Stoa receipts. Re-derive the Merkle inclusion proof and check the ES256 signature on any signed receipt, offline, without trusting Vext Labs. From Vext Labs.
Maintainers
Readme
@vextlabs/stoa-verifier
A standalone verifier for Stoa receipts. Re-derive the Merkle inclusion proof and check the ES256 signature on any signed receipt, offline, without trusting Vext Labs.
Stoa is the open audit substrate underneath every Theron capability call. Each call is signed with ES256 over a canonical envelope, then anchored daily into a SHA-256 Merkle root. This package lets any third party prove a receipt is authentic, and falsify a tampered one.
Apache-2.0. Zero runtime dependencies. Node 18+, browsers, and Workers.
Verify from the command line (no install)
The fastest way to check a receipt is to point the CLI at it. Nothing to install — npx fetches and runs the package:
# Verify a receipt saved to disk.
npx @vextlabs/stoa-verifier ./receipt.json
# Or pipe a receipt straight from the API.
curl -s https://tryvext.com/api/stoa/receipt/<id> | npx @vextlabs/stoa-verifierThe CLI re-derives the Merkle inclusion proof and (when a public JWK is present) checks the ES256 signature, then prints a clear summary:
Stoa receipt verification
receipt b2c3d4e5f6a7…f0a1b2c3
root fa559146e9f5b87a…
✓ Merkle inclusion proof reconstructs the anchored daily root
✓ ES256 signature verifies against the supplied public key
✓ VALID — this receipt is authentic.Tamper with the id, a proof node, the root, or the signature and it tells you exactly which check sank it and exits non-zero:
✗ Merkle inclusion reconstructed root does not match the expected daily root
✗ INVALID (failed: Merkle proof) — do not trust this receipt.Exit code is 0 for a valid receipt and 1 for an invalid one or a parse error, so it drops straight into CI or a pre-commit hook. To also check the signature, include a publicJwk field in the bundle (one entry of /.well-known/stoa-edge/keys.json) or pass --key <jwk.json>. Run npx @vextlabs/stoa-verifier --help for the full input shape.
Why a portable receipt matters
A Stoa receipt is offline-falsifiable: a stranger with neither our weights nor our servers can re-derive the Merkle root and check the signature, and so can break a forged one. The verifier is open (Apache-2.0) so nobody has to take our word for what it checks. This is the kind of tamper-evident logging the EU AI Act asks of high-risk AI systems — automatic record-keeping over the system's lifetime (Art. 12), which becomes applicable on 2 August 2026 — except the records are independently verifiable rather than self-attested.
Install (library)
npm install @vextlabs/stoa-verifierVerify a real receipt
import { verifyReceipt } from '@vextlabs/stoa-verifier';
// 1. Pull the proof bundle for a receipt.
const bundle = await fetch('https://tryvext.com/api/stoa/receipt/<id>')
.then((r) => r.json())
.then((j) => ({
receiptId: j.data.id,
jws: j.data.jws,
proof: {
sibling_path: j.data.proof.sibling_path,
daily_root: j.data.proof.daily_root,
},
}));
// 2. Pull the public signing key.
const { keys } = await fetch('https://tryvext.com/.well-known/stoa-edge/keys.json').then((r) => r.json());
// 3. Verify inclusion AND signature, locally.
const result = await verifyReceipt(bundle, keys[0]);
console.log(result.valid); // true only if the chain reconciles and the signature checks outverifyReceipt returns { valid, inclusion, signature }. Inclusion is checked even without a key; pass the public JWK to also check the ES256 signature.
Falsify a tampered receipt
The whole point of a receipt is that you can break it. Flip one character of the receipt id, mutate a proof node, or swap the root, and the reconstructed Merkle root no longer matches the anchored one:
import { buildMerkleTree, getInclusionProof, findLeafIndex, verifyInclusionProof } from '@vextlabs/stoa-verifier';
const ids = ['<receipt-a>', '<receipt-b>', '<receipt-c>'];
const tree = await buildMerkleTree(ids);
const i = await findLeafIndex(tree, ids[1]);
const proof = getInclusionProof(tree, i);
// Authentic: passes.
await verifyInclusionProof({ receiptId: ids[1], proof, root: tree.root });
// → { valid: true, ... }
// Tampered id: rejected.
await verifyInclusionProof({ receiptId: ids[1].replace(/^./, 'f'), proof, root: tree.root });
// → { valid: false, reason: 'reconstructed root does not match the expected daily root' }The test suite (npm test) exercises tamper rejection for the id, a proof node, and the root.
How it works
- Leaf —
sha256(sha256(receiptId)). Each hash is over the UTF-8 bytes of the previous hex string. This matches exactly how the Stoa anchor builds the tree, so your locally-derived leaf reconciles with the published proof. - Walk — for each step in the sibling path,
R:<h>meanscurrent = sha256(current + h)andL:<h>meanscurrent = sha256(h + current). - Compare — the reconstructed value must equal the
daily_rootpublished in the signed daily-root document at/.well-known/stoa-edge/daily-roots/<YYYY-MM-DD>.json. - Signature — the receipt body is signed as a compact ES256 JWS. Verify it against the public JWK at
/.well-known/stoa-edge/keys.json.
API
| Export | Purpose |
|---|---|
| verifyReceipt(bundle, jwk?) | High-level: inclusion + (optional) signature. |
| verifyInclusionProof({ receiptId, proof, root }) | Re-derive and check the Merkle inclusion proof. |
| verifyJws(jws, jwk) | Verify a compact ES256 JWS against a public JWK. |
| buildMerkleTree(ids) / getInclusionProof(tree, i) / findLeafIndex(tree, id) | Rebuild the tree and proofs yourself. |
| sha256Hex(s) / leafHash(id) / canonicalize(v) | The underlying hash primitives. |
The same checks are available as a binary: stoa-verifier <receipt.json> (or pipe a bundle on stdin). See Verify from the command line.
What is open vs proprietary
Open: the Stoa wire spec (Apache-2.0), the public receipt corpus (CC-BY-4.0), the Vext Eval SDK (MIT), and this verifier (Apache-2.0). Proprietary: Theron's model weights, the Hive orchestration layer, and the serving/training infrastructure. You never need any of the proprietary pieces to verify a receipt — that is the design.
Links
- Open source hub: https://tryvext.com/open-source
- Public receipt browser: https://tryvext.com/stoa/receipts
- Proof surface: https://tryvext.com/proof
- Source: https://github.com/Vext-Labs-Inc/stoa-verifier
License
Apache-2.0.
