TAMPER
SIGNAL
← Docs home

Help

FAQ

The questions people actually ask, answered the way the rest of this project talks: confident about the mechanism, scrupulously honest about the limits. The shortest true answer to most of them is "it proves continuity, not correctness."

The one claim, up front. Tamper Signal can prove nobody changed your data between the export and the dashboard. It cannot tell you the export was right. Everything below is downstream of that line.

The basics

What is Tamper Signal?

Tamper Signal puts a signed receipt on every stage of a data pipeline and reduces the whole chain to one verdict: a green, yellow, or red light. It proves the numbers on your dashboard descend from the original export through a known sequence of code, unchanged. It is open source, installs with pip or npm, and needs no database, server, or metadata catalog.

What problem does it solve?

Vibe-coded pipelines fail silently. AI-written transform scripts work most of the time, and when they do not, they do not crash: they drop rows, double-count, or coerce a column wrong and quietly shift a total, while the dashboard still renders. Tamper Signal is the missing verification layer that catches the change, or proves nothing changed. The longer version is on the blog.

What does "vibe-coded" mean?

A pipeline someone built quickly by describing what they wanted to an AI assistant, rather than engineering it with a warehouse, an orchestrator, and tests. It names the audience's reality without judging it. These are the pipelines with no safety net, and the ones Tamper Signal is built for.

What it proves, and what it does not

Does Tamper Signal make sure my data is correct?

No, and it never claims to. It proves continuity, not correctness. It can prove nobody changed your data between the export and the dashboard, but it cannot tell you the export was right in the first place. If the source is wrong, the chain faithfully verifies wrong numbers. Checking the source is still your job.

What does "continuity, not correctness" mean?

Continuity is the property that a result descends from the original source through a known sequence of code, unchanged. Correctness is whether the source itself is true. Tamper Signal proves the first and deliberately makes no claim about the second. It is the one line the whole product is held to.

Is Tamper Signal a blockchain?

No. It is a hash chain: signed files on disk that link because each stage's input fingerprint must match the previous stage's output. There is no consensus, no network, no tokens, no ledger. Just receipts, like the shoebox under your bed, except these check themselves.

How it works

What is a receipt, and what is a chain?

A receipt is a signed record one pipeline stage emits: a fingerprint of the data it received, the code it ran, the data it produced, and that stage's control totals. A chain is the ordered sequence of receipts, verified link by link. A chain has exactly two honest endpoints: intact, or broken at an exact link. The full vocabulary is in Core concepts.

What do green, yellow, and red mean?

Green: every link verifies and every signature checks, so the data is intact. Yellow: the chain verifies but carries a caveat a human should look at, such as a coverage gap, an unrecognized signing key, or declared drift. Red: the chain is broken at a specific link, reported with the exact stage and the control-totals delta. Yellow never blames; red points rather than panics.

What is the difference between the evidence hash and the semantic hash?

The evidence hash fingerprints an artifact's raw bytes, taken once at ingest, anchoring the original file exactly as exported. The semantic hash fingerprints the canonicalized data content, stable across format round-trips, so an xlsx ingest still verifies against a CSV copy of the same data. One answers "is this the same file," the other "is this the same data."

Using it

Does it work with Python and JavaScript?

Yes. pip install tamper-signal gives a Python CLI (receipts) and library; npm install tamper-signal gives a Node CLI (tamper-signal) and API. The chains are interchangeable across the two stacks, proven byte-for-byte by golden vectors, so a chain signed in Python verifies in Node and the reverse.

What file formats can it read?

ingest and verify accept .xlsx, .csv, .tsv, .json (an array of objects), and .ndjson. The semantic hash is identical across formats, so the format you store in does not move the verdict. Spreadsheets go through the Python CLI; the JavaScript stack reads the text formats.

How do I add it to my own project?

Point your coding agent at the repository and say "add tamper signal." AGENTS.md is the full integration runbook: install, generate keys, ingest the source, wrap your transforms with the receipt decorator, mount the signal, and verify. By hand, the Quickstart takes you from pip install to a green light in about five minutes.

How do I put the light in my dashboard?

Mount one of the browser surfaces and point it at your chain file. The inline status light, the badge, the Data tab, and the inspector console each re-verify the whole chain in the viewer's browser with Web Crypto, no server-side trust. They ship for plain HTML, React, and any framework via a custom element. See Mounting the signal, or the case for a verified table in Show your work.

Can I take the data out, with the proof?

Yes, that is the point. receipts export --bundle writes a verified bundle: a zip of the data file plus chain.json and its receipts, kept byte for byte, so whoever receives it runs receipts verify chain.json and gets the same light, offline. The Data tab's "Take your data" control does the same in the browser, as a bundle or a bare rows-only file (csv/tsv/json/ndjson; spreadsheets go through the Python CLI). A rows-only file is the data without its receipt, and the tab marks it unverified at the point you pick it. Because the semantic hash is format-agnostic, a CSV you export re-verifies as JSON and the light stays green. One caveat: numeric-looking text canonicalizes to its number, so leading zeros and trailing decimals do not survive a round trip.

How do I bring an updated file back in?

receipts ingest --as replace (the default) re-signs a fresh chain from the file and archives the prior one. --as period continues the chain's run history as the next period, judged against prior runs through the prior run's signed tolerance band. A period continues only under a trusted signer (pass --pub to trust a key other than the chain's); an untrusted signer is refused rather than appended silently, because re-attestation is never silent.

Trust and security

Where does the signing key live?

On your machine. Day to day, that local Ed25519 keypair is the root of trust, and anyone holding it can sign a fresh, internally consistent chain. For the moments that matter, anchoring closes that gap by witnessing the chain in a public log under your identity.

What is anchoring?

An optional step that records the exact bytes of your chain in a public transparency log under your identity (a browser login locally, automatic in CI). It proves this exact chain existed at a point in time, independent of the signing key, closing the gap where whoever holds the key could quietly re-sign everything.

Scope and alternatives

How is this different from dbt, Great Expectations, or OpenLineage?

Those model lineage and quality at the warehouse and orchestration layer, and assume that infrastructure exists. Tamper Signal is narrower and lighter: a signed, file-based receipt chain you drop in front of an ad-hoc xlsx-to-dashboard pipeline with no database, server, or catalog. It is a complement for the gap before those tools are in place, not a replacement.

What are tolerance bands?

A signed declaration, made at ingest, of how much a period normally moves day over day, plus a settling window. Recurring refreshes then stay green when recent data drifts within the band and turn yellow when settled data moves or a recent bucket breaches the band. It keeps the light believable on a pipeline that refreshes every morning, which is the whole story behind 1.6.0.

Is it free, and what are the requirements?

Yes, open source under the MIT license. It needs Python 3.11+ or Node 18.17+. There is no paid tier, no account, and no server to run.