npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@stackmerthh/receipt-verifier

v1.1.0

Published

Verify TokenOS DeAI inference receipts offline. Ed25519 over canonical-JSON serialization, no network calls, no platform trust required. Supports receipt-format spec v1.0 + v1.1.

Downloads

90

Readme

@stackmerthh/receipt-verifier

Verify TokenOS DeAI inference receipts offline. Ed25519 over canonical-JSON serialization, no network calls after the one-time pubkey fetch, no platform trust required at verification time.

  • ~140 LOC, single TypeScript file
  • One runtime dependency: tweetnacl (pure-JS ed25519, works in browsers + Node + workers)
  • Spec: RECEIPT_FORMAT_v1.md
  • Supports: receipt v1.0 and v1.1 (field-agnostic canonical algorithm)
  • License: MIT

What is a TokenOS DeAI receipt?

Every billable inference call made through the TokenOS DeAI platform produces a tamper-evident, ed25519-signed JSON record. The receipt proves:

  1. The platform metered this exact call (model, tokens, cost, served-at time).
  2. The receipt body has not been modified since signing.
  3. The signing key is one the platform has published.

Receipts survive the platform: even if the issuer disappeared, anyone holding the receipt + the published public key can verify it years later from cold storage. They are the unit of trust between buyer / operator / platform / external auditor.

This package is the reference verifier: byte-for-byte identical to the canonicalizer the platform uses to issue receipts, so issuing and verifying can never drift.


Install

npm install @stackmerthh/receipt-verifier
# or
pnpm add @stackmerthh/receipt-verifier
# or
yarn add @stackmerthh/receipt-verifier

Requires Node 18+ (or any modern browser).


Quick start

import { verifyReceipt } from '@stackmerthh/receipt-verifier'

// 1. Fetch the platform's published key set (cache aggressively — pubkeys
//    only change on rotation).
const keys = await fetch('https://a2e-api.onrender.com/.well-known/tokenos-keys.json')
  .then(r => r.json())

// 2. Look up the pubkey for this receipt's signing key.
const pubkeyHex = keys.keys[receipt.signedBy]?.pubkeyHex
if (!pubkeyHex) throw new Error('Unknown signing key — refusing to verify')

// 3. Verify.
const result = verifyReceipt(receipt, pubkeyHex)
if (result.valid) {
  console.log('Receipt is genuine')
} else {
  console.error(`Receipt invalid: ${result.reason}`)
}

That's the whole API. The verification is synchronous, pure, and does no I/O after the one-time fetch for the key set.


API

verifyReceipt(receipt, pubkeyHex): VerifyResult

Returns a discriminated result:

type VerifyResult =
  | { valid: true }
  | { valid: false; reason: string }

Possible reason values when invalid:

| Reason | Meaning | |---|---| | missing_signature | receipt.signature is missing or empty | | malformed_hex | receipt.signature or pubkeyHex is not valid hex | | wrong_length | Pubkey is not 32 bytes OR signature is not 64 bytes | | signature_mismatch | Bytes don't verify — the receipt was tampered with, signed by a different key, or your canonicalization disagrees |

isReceiptValid(receipt, pubkeyHex): boolean

Same as verifyReceipt but returns a plain boolean. For callers that don't care about the failure reason.

canonicalizeReceipt(receipt): string

Returns the canonical JSON string (the bytes that get signed/verified). Useful when you need to compute the canonical form yourself, e.g. when building a custom issuer or debugging signature drift.


CLI

A one-shot verifier ships with the package:

# Verify a receipt JSON file using the live published key set.
npx tokenos-verify-receipt path/to/receipt.json

# Or with a specific pubkey hex (skip the network call).
npx tokenos-verify-receipt path/to/receipt.json --pubkey 67a161...

# Or with a custom keys endpoint (useful for testing).
npx tokenos-verify-receipt path/to/receipt.json --keys-url https://staging.tokenos.ai/.well-known/tokenos-keys.json

Exits 0 on valid, 1 on invalid. Prints a discriminated result for piping.


How it works (short version)

  1. The platform signs every receipt with ed25519 over the canonical JSON of the receipt body. The body excludes signature (chicken-and-egg) and signedBy (so key rotation doesn't invalidate old receipts).
  2. Canonical JSON = recursive alphabetic key sort + no whitespace + Date to ISO-8601 string. The algorithm is field-agnostic, so receipts with new fields in future spec minor versions verify with no code change.
  3. To verify: fetch the published key set once, look up the pubkey by the receipt's signedBy, re-canonicalize the body, run ed25519_verify.

The complete spec is in RECEIPT_FORMAT_v1.md. A JSON Schema for receipt validation lives at receipt-format-v1.schema.json.


Key rotation

The platform's published key set is a map: every key id ever used maps to its pubkey hex + a retiredAt timestamp (null for the active key).

{
  "active": "platform-key-v1",
  "keys": {
    "platform-key-v1": {
      "id": "platform-key-v1",
      "pubkeyHex": "67a16103...",
      "retiredAt": null
    }
    // ...future retired keys live here too with non-null retiredAt
  }
}

Always look up the pubkey by receipt.signedBy — never assume the active key signed the receipt. Old receipts are signed by retired keys; they still verify correctly because retired keys remain in the map.

If the platform's signing key is compromised, it will be retired with its retiredAt set to the compromise time. Verifiers SHOULD refresh the key set periodically (24-hour cadence is reasonable) and treat receipts signed by a compromised key AFTER its retiredAt as untrusted.


Versioning

The package version tracks the receipt-format spec it supports:

| Package version | Supports receipt versions | |---|---| | 1.0.x | v1.0.0 | | 1.1.x | v1.0.0 + v1.1.0 (adds servedAtTier) |

The canonical algorithm is field-agnostic, so a 1.0.x verifier handed a v1.1.0 receipt will compute the right canonical bytes anyway — the version column above tracks the spec version the package was intentionally designed against.

Major-version bumps (2.0.0 etc.) will only happen if the canonical algorithm itself changes; minor-version bumps are additive.


Limitations + non-goals

  • Not a replay detector. Receipts are tamper-evident, not transferable bearer tokens. A verifier that wants to detect replay must compare inferenceRequestId against its own audit log.
  • Not an attestation verifier. Phase 3.2 of the TokenOS roadmap adds attestationProofRef chasing — verifying that the CONFIDENTIAL-tier receipt was actually served on attested TEE hardware. That logic will ship in a separate companion package.
  • No CRL. Key revocation is via the retiredAt field in the published set. There is no separate CRL endpoint.

Contributing + spec changes

The package lives in the TokenOS monorepo at packages/receipt-verifier. Spec changes are coordinated with package releases — see RECEIPT_FORMAT_v1.md §12.

Compatible implementations in other languages (Rust, Go, Python, Java) are welcomed; the canonical algorithm is small enough that a faithful port is straightforward. Open an issue with a link to your implementation and we'll list it here.


License

MIT. See LICENSE.