JSPM

@runback/verify

1.0.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 8
  • Score
    100M100P100Q61774F
  • License MIT

Verify tamper-evidence and integrity of Runback audit cassettes (runback.cassette/v1). No account required.

Package Exports

  • @runback/verify

Readme

@runback/verify

Verify the tamper-evidence and integrity of runback.cassette/v1 audit records. No account required. Pure Node.js — zero external dependencies.

Every AI agent decision captured by Runback is sealed in a hash-chained, HMAC-signed cassette. This package lets anyone verify the record independently — without Runback software, without a Runback account.

Install

npm install @runback/verify
# or
npx @runback/verify cassette.json

CLI

# Verify a cassette file
runback-verify cassette.json

# Verify from stdin
cat cassette.json | runback-verify -

# Verify the signature (if the record is signed)
runback-verify cassette.json --key <signing-key>

Output:

runback.cassette/v1 — VALID
  run_id        loan-approval-agent-2026-07-01
  generated_at  2026-07-01T09:14:22.000Z
  events        6

  ✓  chain     — event hashes form an unbroken SHA-256 chain
  ✓  digest    — manifest.content_digest matches terminal chain hash
  ✓  cassette  — oracle-stream digest matches manifest.replay.cassette_digest
  –  signature — HMAC-SHA256 (record not signed)

  spec      https://runback.dev/spec

Exit code 0 = valid. Exit code 1 = invalid or error.

Library

import { verify, verifyJson } from '@runback/verify';

// From a parsed object
const result = verify(cassette);

// From raw JSON string
const result = verifyJson(jsonString);

// With signing key
const result = verify(cassette, process.env.AUDIT_SIGNING_KEY);

console.log(result.valid);         // true / false
console.log(result.checks.chain);  // true / false
console.log(result.checks.digest); // true / false
console.log(result.checks.cassette); // true / false
console.log(result.checks.signature); // "valid" | "invalid" | "unsigned" | "no-key"

What it verifies

Three required checks, one optional:

Check What it proves
chain Every event._hash matches SHA-256(h_{i-1} + canonical(event)). Tampering with any event breaks the chain at that point and every hash after it.
digest manifest.content_digest equals the terminal chain hash — a single value covering all events.
cassette manifest.replay.cassette_digest equals the oracle-stream digest — proving the recording IS the deterministic input stream of the agent run, not a post-hoc reconstruction.
signature HMAC-SHA256(key, content_digest:cassette_digest) — optional. Proves the record came from a holder of the signing key.

Algorithm

# Event chain
h_0 = ""
h_i = SHA-256( h_{i-1} + canonical( event_i_without_hash ) )
canonical = JSON.stringify with all keys sorted recursively

# Oracle stream (cassette digest)
For each event sorted by seq:
  if type === "llm":  entry = { kind: "llm",  key: SHA-256("llm:{model_id}:{canonical(request)}"),  output: response }
  if type === "tool": entry = { kind: "tool", key: SHA-256("tool:{tool_name}:{canonical(input)}"), output: output }
  if type === "env":  entry = { kind: e.kind, key: e.key, output: e.output }
  else: skip
  chain_hash = SHA-256( prev_hash + canonical(entry) )

Full specification: runback.dev/spec

Online verifier

Paste a cassette at runback.dev/verify — runs entirely in your browser, the cassette never leaves your machine.

License

MIT