Skip to content

Revoke a document

Evidence changes. A contract is superseded, a source is retracted, a data subject asks to be forgotten. Revocation removes one document and every artifact derived from it, so it is no longer retrievable and no longer citable — while every other document stays intact and answerable.

Python’s delete() (alias revoke()) is the exact inverse of ingest() and unwinds the whole store. Go and JavaScript have no facade, so revocation is whichever seam holds your evidence: the in-memory corpus, or the vector store.

rag.ingest(text="The employee shall not disclose…", document_id="nda-2021")
rag.ingest(text="Employees accrue twenty days of leave…", document_id="leave")
result = rag.delete("nda-2021") # or rag.revoke("nda-2021")
print(result.status, result.n_units) # deleted 1
# nda-2021 is gone — not retrieved, not citable
print(rag.ask("Can the employee disclose confidential information?").evidence.decision)
# refused → "I can't answer that from the available evidence."
print(rag.ask("How many days of annual leave?").evidence.decision)
# answered → every other document still answers

When the port does hold your evidence in a store, revocation is a store call — DeleteDocument / deleteDocument, the row-level primitive the Python facade is built on. Both tabs below run against the repo’s local pgvector container (docker compose --profile postgres up -d postgres).

result = rag.delete("nda-2021")
print(result)
# DeleteResult(document_id='nda-2021', status='deleted', removed_eu_ids=('nda-2021::0::0',))

The facade drives the store for you — vector rows, structure, images, the raw blob, graph, wiki, and the manifest entry (see the table below).

A single ingest() writes several artifacts; Python’s delete() unwinds all of them for that document_id:

Artifact Removed
Vector rows (the retrievable Evidence Units) ✅ all rows carrying the document_id
Structure index (knowledge/…/structure/{id}.json)
Per-document image blobs (raw/…/images/{id}/)
Content-addressed raw blob (raw/…/{checksum}) only if no other document shares those bytes
Graph (graph/…/graph.json) ✅ rebuilt to contain nothing derived from the doc — when the graph signal is on
Wiki page + index entry ✅ page dropped, index rewritten — when the wiki signal is on
Etag-manifest entry ✅ removed last (the commit point)

The lexical (BM25) index needs no separate step — it is derived from the vector rows and stops matching the document the moment its rows are gone.

The port stores unwind only the vector rows (that is all they own); anything else your application derived from the document — a structure index you built with buildStructure, a graph you built with buildComentionGraph — you rebuild or drop yourself.

delete() is safe to call twice and safe to interrupt:

print(rag.delete("nda-2021").status) # deleted — existed, removed
print(rag.delete("nda-2021").status) # absent — nothing left to do, no error
print(rag.delete("never-ingested").status) # absent

The etag-manifest entry is written last. While it is present the document is considered logically present, so a revoke interrupted after some artifacts are removed but before the manifest entry is forgotten simply re-runs cleanly — it finishes removing what remains and forgets the entry, with no orphaned, still-retrievable evidence.

A revoke fires the on_delete lifecycle hook (the mirror of on_ingest), observe-only and never fatal — the same contract as every other hook:

from citenexus import CiteNexus, Hooks
rag = CiteNexus(store, embedder=, generator=,
hooks=Hooks(on_delete=lambda r: audit_log(r.document_id, r.status)))

Revocation reaches down to the storage seam in every port at parity. The Python facade orchestrates the full unwind; the Go, JS, and Rust cores expose the row-level primitive it is built on:

Port Surface
Python rag.delete(document_id) / rag.revoke(document_id) — full orchestration
Rust core LanceStore::delete_document(&self, document_id) (C-ABI citenexus_store_delete_document)
Go PostgresVectorStore.DeleteDocument(documentID string) error — plus LanceVectorStore behind the citenexus_ffi build tag
JavaScript PostgresVectorStore.deleteDocument(documentId): Promise<void> — plus the Lance store on the @muthuishere/citenexus/ingest subpath