Retention, privacy and personal data protection
This page describes the controls of the Navin Platform over the lifetime and confidentiality of data: retention policies, legal holds, erasure of a person, classification, DLP, tokenization and consents. It complements data-protection.md, which covers RAG data protection. Code: services/control-plane/src/eai/domains/retention, services/control-plane/src/eai/domains/privacy, services/control-plane/src/eai/domains/evidence/holds.py.
Version française : ../retention-privacy.md
Data classification
- Five ordered levels:
public,internal,confidential,restricted,secret(eai.auth.CLASSIFICATIONS). Every identity carries a clearance; a policy compares the data classification with that clearance and with the ceiling of the resource (model, agent, tool). POST /v1/privacy/classifydetects the entities of a text or a media and returns the classification, without changing anything.restrictedandsecretRAG chunks are envelope encrypted (data-protection.md).
DLP
| Mode | Effect |
|---|---|
detect | Finds entities, leaves the text unchanged |
mask | Replaces each value with a mask |
tokenize | Replaces each value with a reversible tok_<type>_<digest> token |
block | Refuses the content |
POST /v1/dlp/inspectandPOST /v1/dlp/redactapply DLP to a text;POST /v1/multimodal/dlpto a media. The model gateway and the tool gateway call the same function (eai.domains.privacy.service.inspect).- Tenant rules:
GET /v1/dlp/rules,POST /v1/dlp/rules(tenant_admin,security_officer): name, entity type, pattern (500 characters at most, checked), action, classification, minimum score, enabled. - Streaming output:
EAI_STREAM_DLP_HOLDBACK_CHARScharacters are held back at the end of the stream so a value cut between two chunks is still detected. - A policy may enforce DLP through a
dlpobligation (authentication-authorization.md).
Tokenization
POST /v1/tokenization/tokenizereplaces a value with a deterministic per tenant token; the value is kept encrypted in the token vault.POST /v1/tokenization/detokenizeis reserved totenant_adminandsecurity_officer, goes through a policy decision with the purpose (purpose) and the highest classification of the tokens, and is audited (tokenization.detokenize), denials included.
Retention policies
| Resource type | What is processed |
|---|---|
memory | Agent memory |
sessions | Conversation sessions |
media | Stored media |
usage_raw | Raw payloads of usage events (prompt, response, messages) |
telemetry | Trace summaries |
documents | Knowledge base documents |
realtime | Realtime sessions |
GET /v1/retention/policieslists the policies and the active legal holds.POST /v1/retention/policies(tenant_admin,security_officer,data_steward) setsttl_days(0 to 36500), the action (eraseorarchive) and whether it is enabled.POST /v1/retention/runstarts a run, withdry_runto count without deleting. Theretentionworker job runs it for every tenant (EAI_WORKER_RETENTION_INTERVAL_SECONDS, daily by default).- Platform ceilings:
EAI_TELEMETRY_SPAN_MAX_DAYS(trace summaries),EAI_INBOX_RETENTION_DAYS(consumer inbox),EAI_AUDIT_PAYLOAD_RETENTION_DAYS(encrypted audit payloads),EAI_AUDIT_WORM_RETENTION_DAYS(WORM exports).
Legal holds
Two distinct mechanisms:
| Mechanism | Scope | Set and release | Roles |
|---|---|---|---|
| Retention hold | One resource (resource_type, resource_id) or one person (subject_id) | POST /v1/retention/legal-hold with a reason; active: false and hold_id release it | tenant_admin, security_officer, data_steward |
| Audit hold | A tenant, a case number and an optional event_time range | POST /v1/evidence/holds; released by two distinct approvers with POST /v1/evidence/holds/{hold_id}/release | auditor, security_officer, tenant_admin |
During a hold, the retention purge and the erasure skip the held data and count it in skipped_legal_hold. Every set and release is audited (retention.legal_hold for the retention hold).
Erasure of a person
POST /v1/retention/erase (tenant_admin, security_officer, data_steward) erases the data of a person (subject_id), with dry_run and include_documents. Default reason: gdpr_art_17.
| Result | Meaning |
|---|---|
completed | Memory, media, sessions, ended realtime sessions (and documents when asked) deleted, external stores processed |
incomplete | An external store (Opik traces, ClickHouse rows) failed: the failure is audited, run the erasure again |
blocked_legal_hold | The person is under legal hold: nothing is erased |
dry_run | Count only |
The answer lists what is kept by obligation: the audit chain (append only, hash chained) and the usage events (financial records, raw payloads purged by the usage_raw policy). Encrypted audit payloads expire; the events themselves stay, so the chain and the seals keep verifying.
A real erasure (dry_run: false) is final. Run a dry_run first and check there is no legal hold.
Purge evidence
A purge of audit payloads writes evidence to eai.audit_purge_evidence: counts, sequences and the Merkle root of the digests of the purged ciphertexts, never the contents. Read: GET /v1/evidence/retention/evidence; run: POST /v1/evidence/retention/run.
Consents
- Realtime voice:
POST /v1/realtime/sessions/{session_id}/consentsrecords the consent of a participant (methodsverbal,click,written,api);GET /v1/realtime/sessions/{session_id}/consentslists them;POST /v1/realtime/sessions/{session_id}/consents/{consent_id}/revokewithdraws it. Write roles:tenant_admin,developer,agent. EAI_REALTIME_CONSENT_REQUIRED: unset, consent is required everywhere exceptdevandtest;falseis refused at production startup. Recording always needs consent. Details: ../../operations/en/voice-runtime.md.
Mapping to the control catalogue
| Control | Title | Evidence source |
|---|---|---|
EAI-DATA-01 | Data classification and DLP on prompts, outputs and media | dlp_rules |
EAI-DATA-02 | Retention limits and data subject erasure | retention |
EAI-SEC-01 | Encryption of data at rest with tenant keys and rotation | encryption_keys |
The framework references of these controls are in risk-compliance.md.