The platform

Audit trail per read

Every gated read writes one row before the answer returns: who asked, what clearance and compartments applied, a preview of the question, and what was surfaced. Here is the row, how to query it, what strict mode changes, and what erasure does to the record.

The row

A read is any retrieval that passed through the gate: a search, a chat turn's retrieval, a document listing, an as-of read, a read by id. Each writes one row to an append-only table, and the write is awaited, not fired and forgotten; the answer does not return before the record exists.

FieldWhat it holds
user_idThe principal who asked, as resolved by the platform (not as the caller phrased it).
principal_clearance, principal_mattersThe classification level and compartments that applied to this read.
query_previewA preview of the question.
surfaced_count, surfacedHow many memories were released, and which: what was shown, not what the asker was cleared for.
identity_source, identity_issuer, token_idasserted or verified; with verified identity, the issuer and token that proved who asked.
thread_id, created_atThe conversation, if any, and the time.

Querying it

GET /api/access/audit?matter=matter:acme&principal=user:maeve&date_from=2026-10-01&date_to=2026-10-22&thread_id=…&limit=500&offset=0
→ {"filters": {...}, "total", "count", "offset", "rows": [...]}

matter returns the reads that surfaced that compartment, which is the question a review actually asks: not who was cleared, but what was shown. A bare date is that day in UTC; a malformed date is a 400. The audit read is on the full surface (a chat-profile key), and it is tenant-scoped: an operator reads the record without reading the memory.

Strict mode

By default a read whose audit write fails still returns, and the failure is logged. With audit_strict on for the tenant, there is no read without a record: the memory API returns 503 and chat answers without memory. Set by the operator; off for most tenants, on for the ones whose regulator will ask.

Decisions are recorded too

The audit of reads sits beside the other ledgers: clearance grants and revocations, grants the conflict graph refused, mandate decisions (action_audit), lifecycle events on every memory, and decision_refused when someone tries to approve their own escalation. All of it is in the tenant export.

Erasure and the record

Ordinary operation never destroys anything; see close and supersede. Destruction is one governed path:

POST /api/access/purge
{"selector": {"principal": "user:maeve"},     // or memory_id | document_id | matter | tenant
 "identity": "ops:dpo", "reason": "erasure request 2026-10-20", "dry_run": true}
→ 200 a content-free plan (counts, labels, what it will and will not reach)
→ 202 escalated to a person, with an escalation id, when the mandate requires it
→ 200 executed, with a receipt and one tombstone row per memory

The plan is resolved first and approved exactly as resolved. Execution removes the points from every store and the side channels, cascades to answers grounded on the erased memory (a paraphrase still holds the personal data), and scrubs the asker's own words from the audit rows and retrieval logs that carried them: the rows stay, the text becomes [erased]. Each erased memory leaves a purged row in the lifecycle ledger. The receipt also says what a purge does not reach: backups are not rewritten, and the report states how many days at most until they expire.

The tenant export

GET /api/access/export            every memory, every ledger row, the entity graph: one NDJSON stream
GET /api/access/export?counts_only=1

Taking the estate is itself a mandated action with an escalation when the mandate requires one. Every erasure proof the platform's own consumers run ends by reading this export, because an erasure that leaves a trace in the export did not happen.

Why this matters. A buyer's security review asks two questions of a RAG system: what did the model see, and can you prove it. The row answers both: Enterprise RAG with access control.

Get a key

Yohanun is in invited beta. Tell us what you are building and we send a key with a developer account; a memory-profile key for your own model, or a chat-profile key if you want the platform to run the model and meter it. There is no card and no self-serve sign-up.

Request an invite