Tamper
Signal

✓ signed · ed25519

A verification layer for AI-built data pipelines. Each stage leaves a signed receipt, and one command tells you whether the chain held.

I built all of it: concept, code, docs, demo.

The numbers in front of the boss are wrong, and nothing says so.

A social team exports a month of TikTok performance data. Someone builds a dashboard on it in an afternoon with an AI assistant, and it looks great. Then a transform quietly drops 22 rows and the numbers are wrong. Nothing in that workflow catches it. Nobody is going to re-check 48,000 rows by hand.

Seal every stage, and a break has an address.

Each stage gets a receipt for what went in and what came out: an evidence hash, a semantic hash, and control totals a person can actually read. Ed25519 signatures link the receipts into a chain. Run one command. You get back intact, or the exact stage where the chain stopped and by how much. The receipts are files on disk, so there is nothing to stand up first.

123tiktok.xlsx48,212 ROWSclean.pySTAGE 1report.pySTAGE 2dashboard48,190 ROWSRECEIPTRECEIPTRECEIPTRECEIPTSIGNEDSIGNEDMINUS 22 ROWSVERIFYWALKS THE CHAINHUMANSTOP AND LOOKROWS −22 · VIEWS −24,889ONE LIGHT, NOT48,000 ROWS
A signed receipt under every stage. This proves the dashboard descends from the export. It does not prove the export was right.
  1. 1Every stage signs for what came in and what went out.
  2. 2The receipts chain to each other. Break one link and the chain names it.
  3. 3A person is handed a verdict, not a spreadsheet.

The verdict lives where the numbers live.

The pill sits in the dashboard header, beside the date range, where a person is already looking. It cycles green, yellow, red. When the chain breaks it outlines the one metric that stopped descending from the source: total views, 1.26M, the number somebody was about to read out loud.

A TikTok creator analytics dashboard with a dark pill in the header reading BROKEN, hash mismatch. The Total Views tile, 1.26M, is outlined in red and flagged as an unverified value.
The badge in a dashboard header640 × 360
Green earns silence.

The break lands on a link, not a file.

The verification console. Four signed stages run left to right, tiktok.xlsx at 48,212 rows, clean.py, report.py, dashboard, with a red break between clean.py and report.py. The log below reads chain broken at link 1 to 2, expected 6617_f3, found bb30_43, delta rows minus 22 and views minus 24,889.123
The Console · one command640 × 360
  1. 01

    The console draws the run as a row of signed stages and puts the break between the two it belongs to.

  2. 02

    The log underneath gives the hash it expected, the hash it found, and the damage: 22 rows gone, 24,889 views gone.

  3. 03

    Everything downstream is marked unverifiable rather than wrong. That is enough to know which script to open.

The dashboard flips to a dark Data tab showing the raw attested table, with the pipeline stages listed across the top and the views column highlighted in red where the chain broke.
The Data tab, re-hashed in the browser640 × 360

Click the pill and the table opens underneath.

The dashboard has a Data tab, beside the charts. It shows the attested rows, re-hashed in your own browser against the final receipt, with the stages across the top, so you can see what the number came through. The break shows up in one column. This is a drawer in the dashboard you already have, and it comes with the badge, with nothing extra to install.

It is open source, on PyPI and npm.

The Python and the JavaScript canonicalize byte for byte the same, and there are attach helpers for Flask, FastAPI, Express and Streamlit. No team has it in a pipeline yet. The demo at tampersignal.com re-verifies a real committed receipt chain in your own browser and catches the tampered run at the exact link: 48,212 rows down to 48,190.

The live demo: one receipt chain verified intact in green, and the same chain after tampering, broken at the aggregate stage with the row-count delta printed in red.
tampersignal.com — verified, then tampered880 × 780