cd /news/ai-agents/solving-the-erasure-receipt-trilemma… · home › topics › ai-agents › article
[ARTICLE · art-167451] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Solving the Erasure / Receipt Trilemma in AI Memory and RAG

A developer built Ember (ember-custody), an open-source memory and RAG custody layer that wraps existing vector stores and agent memory systems such as Mem0, Chroma, Qdrant, and SQLite to make GDPR Article 17 erasure verifiable. Ember uses salted, length-prefixed RFC 6962 Merkle documents so a subject's leaves can be redacted while other users' provenance receipts still verify, plus a zero-plaintext append-only ledger with two-tier AES-256-GCM crypto-shredding that destroys per-subject and per-record keys before calling vendor delete(). The project also proposes two-direction benchmarks to counter zombie re-ingestion and the trivial 0-leak metrics that reward wiping bystanders' memories.

by read4 min views1 publishedNov 11, 2026

Why delete_all(user_id=...) breaks GDPR compliance in practice — and how length-prefixed salted Merkle documents, two-tier AES-256-GCM crypto-shredding, and two-direction benchmarks close the gap.

Most vector stores (Qdrant, Chroma, Pinecone, pgvector) and agent memory layers (Mem0, Letta, LangMem) make storing facts and scoping simple queries by user_id straightforward. When a user invokes GDPR Article 17 ("Right to be Forgotten") or an enterprise client demands verifiable offboarding, three failure modes appear silently:

Failure 1: The Erasure / Receipt Trilemma

Imagine an onboarding call transcript or clinical intake note containing facts about two people:

"Priya Raman joined Acme in 2019 as a logistics analyst. Marcus Webb owns a bookshop in Leeds."

Your RAG pipeline indexes that transcript and gives Marcus a cryptographic provenance receipt binding his fact to the document's flat SHA-256 hash and UTF-8 byte offsets.

Now Priya requests erasure. A flat document hash forces an impossible trilemma:

Redact or delete the transcript -> Priya's data is gone, but Marcus's SHA-256 receipt breaks forever because both the document digest and every byte offset shifted.

Keep the transcript intact so Marcus's receipt verifies -> Priya's PII stays on disk permanently.

Failure 2: Derived & Cross-Bucket Memory Leaks

Suppose an agent synthesizes a weekly summary:

"Riverside handoff: triage routing pairs with pharmacy inventory."

Because summaries belong to "team_acme" rather than "priya", calling delete_all(user_id="priya") deletes Priya's raw memories — and leaves derived summaries, graph links, and append-only audit logs surfacing her context under a team namespace.

Failure 3: Zombie Re-Ingestion and Fake Compliance Metrics

Even after deletion runs cleanly:

Zombie syncs (webhook retries, backup imports, stale ETL jobs) re-ingest Priya minutes later under slightly different normalization ("Priya Raman" vs "priya").

Trivial 0-leak metrics: Any benchmark that only measures "leak rate" rewards wiping everything — destroying innocent bystanders' memories alongside the erased subject gives 0 leaks on paper while corrupting your store.

Ember (ember-custody) wraps an existing store (Mem0, LangChain/Chroma/Qdrant vector stores, or SQLite) without rewriting your retrieval model:

A. Salted Length-Prefixed RFC 6962 Merkle Documents (merkle.py)

Instead of hashing the whole document flatly, Ember splits a source into sentence/line/custom leaves, generates a fresh 128-bit random nonce per leaf, and hashes:

leaf_hash  = SHA-256(0x00 || uint32_be(len(nonce)) || nonce || leaf_bytes)

node_hash  = SHA-256(0x01 || left_32 || right_32)

Length-prefixing nonce prevents boundary ambiguity between (nonce, text) and ("", nonce + text).

RFC 6962 0x00 vs 0x01 domain separation + strict positional proof-walk checks block second-preimage tree-geometry spoofing.

On erasure: Ember strips Priya's leaf text and nonce, retaining only Priya's leaf_hash. The tree root stays identical, offline dictionary confirmation on common sentences fails (nonce is gone), and Marcus's receipt still verifies bit-for-bit against the redacted document using zero external dependencies (verify.py).

B. Zero-Plaintext Append-Only Ledger + Two-Tier Crypto-Shredding (keystore.py, vault.py) Append-only SQLiteLedger (WAL, synchronous=FULL) hashes an unbroken SHA-256 chain over encrypted subjects, text, quote, and caller metadata (AES-256-GCM bound via AAD to (tenant_id, item_id, field, key_ref)).

Direct records encrypt under an opaque subject CEK (subject:subj_).

Shared and derived_from records automatically compute the transitive ancestor set of all contributors and encrypt under a tracked per-record DEK (record:) indexed under every contributing subject.

Erasing Priya redacts shared source leaves and destroys both Priya's CEK and every derived/shared DEK before calling external vendor delete() (so even a network timeout never leaves local decryption keys alive, and retries safely sweep pending IDs).

From-zero ledger replay remains 100% tamper-evident while yielding [erased] and {} for all of Priya's items — leaving innocent bystanders decrypted and retrievable.

C. Keyed Tombstones & Two-Direction Calibration (reducer.py, audit.py)

Vault-keyed HMAC-SHA256 tombstones block zombie re-ingestion with TombstonedSubjectError unless an explicit reconsent_id is recorded.

erase() probes the raw backing store directly (adapter.search()) and refuses to issue an Ed25519 ErasureCertificate (ErasureIncomplete) if any residue still surfaces.

The built-in adversarial suite tests 12 subjects × 7 attack categories (204 probes) while co-gating bystander retrieval survival and redacted Merkle receipt verification:

Naive user_id-only baseline: 204/204 probes leak

Ember wrapper: 0/204 probes leak, 100% bystander memories survive, 100% bystander receipts verify offline, 100% from-zero replays stay content-free.

Cryptography cannot erase data you already leaked out-of-band. Every certificate explicitly records trust boundaries (trust_boundary in ErasureCertificate):

Separate your keys from ledger backups: Crypto-shredding only protects pre-existing snapshots if key_dir (or your KMS/HSM KeyStore) was never backed up alongside ledger.db.

External timestamp anchoring: Without configuring a TimestampAnchor (RFC 3161 TSA or public transparency log), a malicious root operator holding both ledger.db and ed25519.json can rewrite history coherently. Unanchored certificates explicitly declare externally_timestamped: false.

Unlinked copy-paste residue: Structural lineage catches everything written via subjects and derived_from plus optional leaf_predicate sweeps; unlinked copies still trigger fail-closed rejection via probes.

── more in #ai-agents 4 stories · sorted by recency
── more on @ember 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/solving-the-erasure-…] indexed:0 read:4min 2026-11-11 · —