Skip to main content

The forget button for AI — provable data-subject deletion for AI memory, with signed deletion certificates.

Project description

Lethe — the forget button for AI

Everyone built AI memory. Nobody built the provable delete. Lethe deletes a person's data from your AI memory (vector store, RAG index, caches, logs) on a GDPR/CCPA request — and hands you a signed certificate proving it happened.

Self-hosted: Lethe runs inside your infrastructure. The tool that erases your data never becomes a new place your data goes.

Status: v0.1, early but real. Connectors: pgvector + Pinecone. The full delete loop is tested end-to-end against real Postgres (pgvector); the Pinecone connector is unit-tested against a mock Index, not live Pinecone. Hardened through four rounds of adversarial self-review (internal, not third-party). Not yet on PyPI.


Why

GDPR Article 17 (right to erasure) covers personal data in agent memory — conversation history, retrieved chunks, and embeddings. Fines reach 4% of global revenue, and the EU's data-protection authorities are actively auditing deletion (the EDPB's 2026 sweep checked 764 organizations and found "lack of automated deletion mechanisms" almost everywhere). Meanwhile no vector database offers provable deletion — teams hand-roll it.

If you sell AI to enterprises, you've probably hit the sharper version: a customer's security review asks "prove you can delete a user's data from your AI," and you can't. Lethe is the answer you hand them.

How it works

tag(subject → record)  →  forget(subject)  →  delete from your stores
                                            →  verify the records are gone
                                            →  signed deletion certificate
                                            →  tamper-evident audit entry

You never have to remember to call tag everywhere: wrap your vector store once and writes tag themselves.

Quickstart (drop-in)

pip install -e .            # from source for now (PyPI soon)
lethe keygen --out lethe_key.bin     # one-time: your signing key (prints the public key)
export DATABASE_URL=...              # your own Postgres
export LETHE_SALT=...                # a secret; pseudonymizes subjects in the ledger
lethe init-db                        # creates Lethe's ledger + audit tables

Wire Lethe to your store, then wrap your vector store so every write is tagged for deletion:

import os, psycopg
from lethe import Lethe
from lethe.ledger import Ledger
from lethe.audit import AuditLog
from lethe.signing import Signer
from lethe.connectors.pgvector import PgVectorConnector
from lethe.integrations.langchain import LetheVectorStore

conn = psycopg.connect(os.environ["DATABASE_URL"])
lethe = Lethe(
    ledger=Ledger(conn),
    audit=AuditLog(conn),
    signer=Signer.from_private_bytes(open("lethe_key.bin", "rb").read()),
    connectors={"pgvector": PgVectorConnector(conn)},
    salt=os.environ["LETHE_SALT"],
)

# Wrap once. Declare which metadata field names the data subject.
store = LetheVectorStore(
    my_vectorstore, lethe,            # any LangChain-style store
    store="pgvector", namespace="docs",
    subject_key="user_id",
    id_key="doc_id",                  # recommended: bind ids from metadata
)

# Use it like a normal vector store — tagging happens automatically.
store.add_documents([Document(page_content="...",
                              metadata={"user_id": "alice@example.com",
                                        "doc_id": "doc-123"})])

When a deletion request comes in:

cert = lethe.forget("alice@example.com")   # deletes everywhere + returns the certificate

Verify a certificate (pin the operator's published public key — a certificate that vouches for itself proves nothing):

from lethe.certificate import verify_certificate
assert verify_certificate(cert, trusted_public_key=PUBLISHED_PUBKEY)

The certificate

Ed25519-signed, tamper-evident, independently verifiable (schema lethe.cert/2). It states exactly what happened and scopes its claim honestly"deleted across these retrieval layers and verified absent," never "perfectly erased everywhere" (backups and model weights are out of scope by definition). verified_absent means Lethe re-queried the configured endpoint immediately after deleting and saw the records gone at issue time — it is not a guarantee against read replicas, query caches, or asynchronous propagation (notably Pinecone, whose deletes are eventually consistent).

The v2 certificate carries the evidence, not just the boolean:

  • valid_until — the absence is asserted from issued_at up to this time; a deletion cert is not eternal, so re-verify past it (the underlying index can change). Set the window with Lethe(cert_validity=…) or forget(valid_for=…).
  • declared_scope — the stores Lethe was configured to sweep, so a reader can see what was in scope and infer what was not checked.
  • per-layer residual_count + verify_method — how many records the post-delete re-query still found (0 backs verified_absent) and the exact query that produced it. index_version is a nullable slot for a store-native index fingerprint. Older lethe.cert/1 certificates still verify.
{
  "schema": "lethe.cert/2",
  "all_verified": true,
  "records_deleted": 2,
  "valid_until": "2026-07-21T00:00:00+00:00",
  "declared_scope": ["pgvector", "pinecone"],
  "layers": [{"store": "pgvector", "namespace": "docs",
              "deleted_count": 2, "verified_absent": true, "erased": true,
              "residual_count": 0,
              "verify_method": "pgvector: SELECT count(*) WHERE id = ANY(:ids); n_ids=2",
              "index_version": null}],
  "claim": "Deleted across the listed retrieval layers and verified absent ...",
  "signature": "…", "public_key": "…"
}

CLI

Command Purpose
lethe keygen --out KEY Create the Ed25519 signing key (prints the public key to publish)
lethe init-db Create Lethe's ledger + audit tables in your Postgres
lethe forget SUBJECT Delete a subject everywhere; prints the signed certificate
lethe verify CERT --public-key PUB Verify a certificate against the operator's published key
lethe audit-head Print the audit-log tip hash (record it out-of-band)
lethe verify-audit --expected-head H Detect tampering/truncation of the audit log

For AI agents (MCP)

Lethe ships an MCP server so autonomous agents can execute provable deletion and verify certificates machine-to-machine:

pip install "lethe-delete[mcp]"
lethe-mcp

Destructive deletes are two-step (preview → confirm token → forget), and any agent can verify a certificate with zero infrastructure (you still need the operator's published public key to pin against). Full guide: docs/m2m.md.

Security model & honest limits

  • Self-hosted. The SDK and the provenance ledger run in your own Postgres. Lethe-the-project never sees your data. The salt stays in your app.
  • No raw PII in the ledger. Subjects are stored as HMAC-SHA256 hashes.
  • Verify with a pinned key. An unpinned certificate check only proves internal consistency; always pin your published public key.
  • verified_absent is a point-in-time re-query, not a replication proof. For eventually-consistent stores (Pinecone) a delete may not have propagated to every replica at issue time. pgvector verifies read-your-writes on one connection; a read-replica DSN would reintroduce the gap.
  • Audit truncation needs an out-of-band head. Mid-chain edits are caught automatically; detecting deletion of the most recent entries requires recording lethe audit-head out-of-band and checking verify-audit --expected-head.
  • Coverage = what flows through Lethe. Writes that bypass the wrapper/tag aren't tracked. Wrap your store, or tag explicitly.
  • Pre-existing data (written before you adopted Lethe) needs retroactive discovery — on the roadmap, not in v0.1.
  • Not erasure from backups or model weights. Out of scope by design; the certificate says so.

Connectors

  • pgvector (and any Postgres table) — PgVectorConnector
  • PineconePineconeConnector (pass your Index). Note: Pinecone deletes are eventually consistent, so verified_absent is asserted at issue time against the queried endpoint, not proven across replicas.
  • Roadmap: Weaviate, Qdrant, Redis, conversation logs.

License

Apache-2.0 — permissive, with an explicit patent grant.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lethe_delete-0.2.0.tar.gz (53.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lethe_delete-0.2.0-py3-none-any.whl (38.1 kB view details)

Uploaded Python 3

File details

Details for the file lethe_delete-0.2.0.tar.gz.

File metadata

  • Download URL: lethe_delete-0.2.0.tar.gz
  • Upload date:
  • Size: 53.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for lethe_delete-0.2.0.tar.gz
Algorithm Hash digest
SHA256 59fdb0c7a8cef4e23b869f48c8f148a7507dea11b4a7aaad854a378b435ad990
MD5 780846b9fde0e2245cc522b5ff4956c7
BLAKE2b-256 70935a77088eaacecd52f022ebe214d12338ef0b4e2803385134c662f5757800

See more details on using hashes here.

File details

Details for the file lethe_delete-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: lethe_delete-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 38.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for lethe_delete-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aac973278f9956654b69b47cc483fb8fc295d94e34a3057a4e961a1f775dd513
MD5 4aef9855af99a51f04a32f49bb302969
BLAKE2b-256 e53e08536c42a085792430ee8f72974ccc52c0bed1892c2bb51d385d90f65a24

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page