Search the complete documentation

Try idempotency, proposal lifecycle, authentication, or ordering.

Navigate Open
繁體中文
Browse documentation

Relay · Governance

Data lifecycle and audit

Relay separates conversation history, user offboarding, tenant shutdown, and operational audit. These are different actions with different guarantees. Every endpoint on this page requires the deployment admin token.

Message lifecycle

ActionImmediate resultLater cleanup
RetractKeeps the message row and channel seq, clears the body, and emits msg:retractedNo retention-based hard deletion is scheduled
Admin deleteKeeps the row and seq, clears the body, hides the message from normal reads and search, tombstones linked attachments, and emits msg:deletedThe message row is hard-deleted after deleted_message_days
Message auditRecords send, edit, retract, and delete events inside the tenant schemaAudit rows remain after deleted message rows are purged

A retract is a conversation action available to the sender. It does not mean erasure. Administrative deletion is the data-governance path:

DELETE /api/admin/messages/{message_id}?tenant_id={tenant_id}
X-Admin-Token: <admin-token>

The delete transaction clears the message body, tombstones linked attachments, records the audit event, and writes durable post-commit effects together. Object deletion runs asynchronously and can retry independently.

Per-tenant retention

Read the active policy:

GET /api/admin/tenants/{tenant_id}/data_retention
X-Admin-Token: <admin-token>

Replace the complete policy:

PUT /api/admin/tenants/{tenant_id}/data_retention
X-Admin-Token: <admin-token>
Content-Type: application/json

{
  "deleted_message_days": 30,
  "post_commit_handoff_days": 7,
  "host_webhook_dead_letter_days": 14,
  "user_export_days": 1
}

All four values are required positive integers. These are the current defaults, and a deployment can configure different defaults. The policy controls scheduled cleanup of soft-deleted messages, terminal post-commit handoffs, webhook dead letters, and export records and files.

Retention workers are asynchronous. A configured number of days is a cleanup threshold, not proof that every copy disappears at that exact second. Operators must monitor worker and object-deletion queues.

Export a user’s data

An export is an asynchronous admin operation:

POST /api/admin/users/{user_id}/exports?tenant_id={tenant_id}
X-Admin-Token: <admin-token>

The response returns a job_id with status queued. Poll the tenant-scoped job:

GET /api/admin/user_exports/{job_id}?tenant_id={tenant_id}
X-Admin-Token: <admin-token>

A completed job includes a short-lived, application-signed download_url and expires_at. Downloads return JSON with Cache-Control: no-store, private. An expired download returns 410; an unknown job or invalid token returns 404.

Export format v1 contains chat-core data only: channels, messages, memberships, reactions, read cursors, and external identities. This format version is independent of the unversioned server API. It does not claim to export host business data, webhook history, operational handoffs, or data owned by Activity and Govern.

Delete a user

DELETE /api/admin/users/{user_id}?tenant_id={tenant_id}
X-Admin-Token: <admin-token>

User deletion runs in one database transaction. Relay:

  • replaces the sender and audit actor on historical messages with the tenant’s tombstone user;
  • deletes memberships, reactions, read cursors, and external identities;
  • tombstones attachments uploaded by the user and queues object deletion;
  • deletes user-attributed post-commit handoffs and webhook dead letters.

Historical message bodies remain so shared conversations keep their sequence and context. Channel-level infrastructure rows without a principal user are not removed by user deletion. Retention or tenant removal handles those rows.

Disable a tenant

POST /api/admin/tenants/{tenant_id}/disable
X-Admin-Token: <admin-token>

Disabling is immediate and idempotent. New JWT verification and host credential sync fail closed after disabled_at is set. It does not delete the tenant schema or retained operational data.

Relay has an internal hard-delete operation that first disables traffic, removes public-schema artifacts, drops the tenant schema, and deletes the tenant registry row. It is deliberately not exposed as a public HTTP endpoint or supported operator command. A customer-facing tenant erasure workflow, completion receipt, and recovery window remain product work.

Audit surfaces

Control-plane events:

GET /api/admin/tenant_audit_events?tenant_id={tenant_id}&event=user_deleted&limit=50
X-Admin-Token: <admin-token>

Message lifecycle events:

GET /api/admin/message_audit_events?tenant_id={tenant_id}&message_id={message_id}&limit=50
X-Admin-Token: <admin-token>

Both endpoints return newest-first results, clamp limit to 1 through 200, and do not expose cursor pagination. Tenant audit rows include tenant_id, event, source_ip, user_agent, and occurred_at. Message audit rows include message_id, actor_id, event, source, request metadata, and occurred_at.

Evidence boundary

Relay audit records prove that Relay accepted and recorded a transport or control-plane action. They do not prove the host’s business authorization, the truth of message content, human review, or execution in another system.

The current audit tables are queryable records, not a tamper-evident ledger. They have no hash chain, external witness, immutable archive, export signature, or public retention policy for message audit rows. If a compliance program requires those properties, the host must export events into its evidence system or wait for a stronger Relay audit contract.

Related: Deployment and operations · Limits and errors · Relay overview