Skip to content
EvalBook

Retention, export and deletion

Retention per content class with purge receipts and tombstones, JSONL trace exports with a manifest and digest, and deletion requests that remove every derived row and withdraw exports.

Three mechanisms remove or hand over trace data, and each leaves a record. Retention purges by content class on the schedule the project sets. Exports write an authorized JSONL bundle of the traces that matched frozen filters at a moment in time. Deletions remove named traces whole, leave a tombstone so they cannot come back, and withdraw exports that may hold them. Exports and deletions are on Traces → Exports; retention is in the project's retention settings.

Status (25 October 2026). The traces component is built in the application (ingestion, explorer, settings, exports and deletions pages are live in the shell); its requirements EV-002 to EV-009 are not yet marked implemented in the requirements ledger and are being verified now. Nothing on this page is marked verified.

Retention by content class

Retention is set per project as days per content class; null means keep. The traces component enforces two classes:

Class What the purge does
raw_bodies span bodies received before the cutoff are cleared; the payload row stays, marked purged, so the explorer says purged rather than showing nothing; their files at Bookbag SSO are removed; exports that may hold them are withdrawn
traces traces whose last data arrived before the cutoff are deleted whole — spans, attributes, events, links, payloads, rollups — with a tombstone each; receipts and counters older than the cutoff go too

The other classes (results, cost_records, audit_metadata) belong to other components, and the settings page says which classes have no purger yet. A purge runs in the background, in chunks, and writes deletion receipts (DECISIONS A16).

Exports

An export needs trace.export; including bodies needs trace.read_body as well, and the caller is checked again on every download. Choose the filters (started from and until, environment, status, error type — the same rows as the explorer) and whether to include bodies. The filters and the moment (as_of) are frozen, the traces.export job writes the file to SSO's file store, and the page lists it with Download.

The bundle is one JSON object per line:

{ "type": "manifest", "schema": "evalbook.trace-export/v1", "export_id", "project_id", "filters", "as_of", "include_bodies", "capture_mode" }
{ "type": "trace", "trace": { … }, "spans": [ { …, "attributes", "events", "links", "bodies"? } ] }   × N
{ "type": "summary", "traces", "spans", "bodies", "omitted": { "bodies_not_captured", "bodies_purged", "bodies_without_permission" }, "digest" }

digest is sha256 over every line before it. Traces are in start order and spans in tree order, so the same filters and as_of against the same data give the same bytes. Bodies are only ever what the capture policy stored, and anything not included says why. An export holds at most 20,000 traces and 200 MB — narrow the filters otherwise — and is kept 7 days, after which it is withdrawn and its file removed. Its states are queued → running → completed → withdrawn, with failed from the first two. Each download is audited.

Deletion requests

A deletion needs trace.delete and the project's exact name, typed, checked on the server (CONFIRMATION_MISMATCH otherwise). The request is the ledger entry: who asked, for what, why, and — once the traces.delete job has run — what was removed.

A selector is one of:

  • trace_ids — up to 1,000 trace ids or public ids;
  • time_range — started from and until, optionally in one environment;
  • attribute — an attribute key equals a value (user.id = …), optionally within a range and an environment.

Preview what would be deleted answers how many traces match now (capped) and a sample of them. The selector is evaluated again when the job runs, in chunks of 200, until nothing matches — a trace that arrives inside the range before then is deleted too.

For each trace the job removes spans, attributes, events, links, retrieval documents, payloads and their redaction markers, the SSO files of bodies over the inline cap, and the usage rollups; then the trace itself, leaving a tombstone. Later spans for that trace id are refused at ingestion with TRACE_DELETED. Exports completed before the deletion finished are withdrawn, and an export whose writing overlapped the deletion is discarded, so a deleted body is reachable through nothing: not search, not saved views, not exports. Error groups are computed from spans and lose the occurrences by construction.

The ledger keeps only a digest of an attribute value it was asked to delete by, not the value. States are requested → running → completed, with failed retried into running. The page lists requests newest first with what was asked, status and what was removed.

What a deletion does not reach

A candidate curated from a span was copied into a dataset's working copy under the datasets component's own rules; deleting the trace does not remove it. Review it there (Curation and synthetic data). Offboarding an organization revokes API keys, runner tokens and peer links and produces a receipt (DECISIONS A16); see Security model.