Prove personal data is gone.
When someone asks a company to delete their data, the law gives it 30 days to remove every trace. In practice that request lands on one engineer with a checklist, because personal data is never in one place — it is in Postgres, in an S3 export, in Stripe, in the support inbox, in an analytics table, in last night's backup, and increasingly inside a vector index built from a support ticket eight months ago.
Lethe does that job end to end:
- Find every trace of the subject across all connected systems.
- Simulate the deletion against a shadow snapshot and measure exactly what it would break.
- Ask a human to sign off — showing them the measured consequence, not a raw tool call.
- Execute the erasure only after approval.
- Prove it, by re-running discovery against live systems and issuing a signed Certificate of Erasure.
The premise: erasure is not an action, it is a proof. Marking a row deleted is not deletion, and "we called the delete API" is not evidence.
Processing an erasure request means reading your customers' personal data. Routing that through a third-party agent runtime makes that vendor a new data processor, triggers a DPA amendment, and — if they are hosted in another jurisdiction — a cross-border transfer assessment.
So Lethe runs entirely on infrastructure you own, against an agent harness you own, with your own model keys. Nothing leaves your perimeter.
The component that finds your data cannot delete it. Discovery connects to every system with read-only credentials and a read-only toolset. Deletion is not merely gated for the discovery agent — the capability is absent. Writes live in a separate executor whose every destructive tool requires human approval.
Approval is a briefing, not a button. Asking a human to approve delete_user(id=4471) produces rubber-stamping, because nobody can evaluate a consequence they cannot see. Lethe never requests approval for an action; it requests approval for a consequence it has already measured against a snapshot:
ERASURE PLAN — subject: [redacted], request #DSR-118
Measured against a shadow snapshot. Nothing has been touched.
DELETE 1,247 rows across 9 tables
DELETE 3 objects in s3://acme-exports/
DELETE 1 Stripe customer + 4 payment methods
PURGE 218 vectors in the support-ticket index
(requires compaction; soft-delete leaves them recoverable)
ANONYMISE orders.customer_id (14 rows)
hard delete violates order_items_customer_fk and would orphan
41 order lines. Retained under Art.17(3)(b), tax obligation.
DRY RUN: 0 constraint violations, 0 traces remaining on snapshot.
Refusing is part of the job. Some data must legally be retained — tax records, data held for legal claims. An erasure tool that deletes everything it is pointed at is a compliance failure in the other direction. Lethe cites the exemption it is relying on and leaves that data in place.
Every case is auditable. The full event history of a request — every query, every finding, the plan, who approved it and when — is replayable, and the certificate is derived from it rather than written alongside it.
Five commands from clone to a walked erasure request. Requires Node 20+,
Docker, a running TrueForge
harness with a model key, and a read-only Postgres connector named
acme-postgres pointed at the demo estate.
npm install
docker compose -f demo/docker-compose.yml up -d # the demo estate
./demo/verify.sh # prove it contains the hard cases
TRUEFORGE_BASE_URL=http://localhost:8790 npm run smoke # first live contact
TRUEFORGE_BASE_URL=http://localhost:8790 npm run case -- DSR-1 ada@example.invalidThe last command walks one request end to end at the terminal: discovery
fans out, the plan is measured against a copy, the erasure-plan card renders
with every figure on it measured rather than estimated, and nothing is
destroyed until you type sign. Refusing records the refusal — a refused
erasure is itself a compliance event. After execution, a second sweep proves
the erasure before the certificate is written.
src/
domain/ subjects, findings, retention law, plans, certificates
agents/ agent specifications — capability separation lives here
connectors/ verifying declared bindings against the live tool list
harness/ protocol, event assembly, SSE, the wire format
discovery/ the fan-out, and adversarial parsing of what comes back
simulation/ measuring the plan against a copy before anyone signs
review/ the plan card, and reconciling calls against the signed plan
execution/ running the plan, answering gates mechanically
verification/ the proving sweep, and certificate issuance
suppression/ the ledger that stops a backup restore undoing an erasure
lifecycle/ the case file and its legal state machine
cli/ the runbook
smoke/ first-contact diagnostics against a live harness
demo/ a seeded estate shaped around what makes erasure hard
npm run typecheck # tests included; a test that does not compile proves nothing
npm test # 380+ tests, all against injected fakes — no network, no Docker
npm run build # emits dist/ without the testsEvery substantive change reached main through a pull request, each with a description stating the decisions worth arguing with and the failure mode being prevented — the merged PR history is the count of record. Qodo Merge reviews pull requests on this repository.
Qodo Code Review Evidence: PR #26 (Qodo-reviewed). Representative merged PRs showing how the project came together: #12 — a verification pass that found a real rule-ordering bug, #20 — closing the loop, where tests caught two privacy leaks on the certificate, #17 — four wire-format assumptions falsified against the API reference.
MIT — see LICENSE.