Skip to content

Data handling & retention

What the Dashboard's local store holds, how long it keeps it, what's exposed in a backup, and the limits on deletion. The short version: the store holds operator-attributed activity and presentation state — never platform secrets — and two tables (audit log and launch history) currently grow without automatic pruning.

What the store holds

Everything is in the dashboard state store (SQLite by default, or Postgres). Grouped by sensitivity:

Data Contains Operator-identifying? Free-text / sensitive?
Sessions opaque id → operator identity · role · timestamps yes (identity) no
Audit log operator · action · environment · target · outcome · timestamp yes no (structured fields)
Launch history spec_path · label · content-digest · env · run_id · created_by (reference-only — no inline spec since 0.4.0) yes (created_by) label is free text
Annotations / tags run_id → note body + tags + created_by yes (created_by) body is free operator text
Saved filters named RunFilters blobs + created_by yes no
Config › Connections env → kneo-client profile ref + free-text label no label is free text
Config › Access role → capability map + per-role env grants no no
Config › Pricing blended per-1,000-token rate no no
Config › Preferences keyed by the operator's identity → an opaque preferences blob + created_by yes (identity) opaque JSON blob

Not in the store — by design:

  • Platform API keys live in the kneo-client profile store, never here (Connections stores only a profile reference).
  • OIDC client secret + session signing key live in BFF config / env, never the store.
  • Credential inventory surfaces references + presence metadata only — secret values are never read into the BFF or the browser.
  • Run inputs/outputs / traces are the platform's data (kneo-serv), fetched live and not persisted by the Dashboard.

Retention

Data Retention today
Sessions auto-purged — a background loop removes expired rows (KNEO_DASH_SESSION_PURGE_INTERVAL_SECONDS), plus absolute + idle expiry; logout deletes immediately
Audit log append-only; no automatic prune by design — retention is the operator-safe kneo-dash prune CLI (0.8.0): export-before-delete + a self-audit record
Launch history the UI shows the recent ~20 (an MRU read cap); old rows persist until an operator runs kneo-dash prune (0.8.0)
Annotations · saved filters · config kept until an operator edits/deletes them (ordinary CRUD)

Metering + retention pruning (0.8.0)

Audit-log and launch-history rows accumulate on disk (append-only by design). Since 0.8.0, bound them with the operator-safe kneo-dash prune CLI — export-before-delete (versioned + checksummed) with a self-audit record — and watch growth via kneo_dash_store_state_bytes plus the row-count gauges kneo_dash_store_rows{table="audit_log"|"launches"} (deployment › state-store growth).

The audit log is best-effort, not compliance-grade

The local audit log is best-effort: an append that fails is counted and swallowed, and the action still completes — so the log can have gaps under store pressure and is not a lossless/compliance-grade record. It exists for per-operator attribution (kneo-serv only sees the shared service account), not as a legal audit of record. Exact coverage + the failure signal (kneo_dash_audit_write_failures_total) are the normative audit contract (ADR-012). Alert on the failure counter if attribution completeness matters to you.

Backups & deletion

  • A backup captures the whole store — operator identities, annotation text, and the audit trail included (but no secrets — those aren't in it). Protect backups accordingly; see Backup & recovery.
  • Deletion limits. Annotations and saved filters are deletable through the app (ordinary CRUD). Among config, only Connections has an in-app delete; Access, Pricing, and Preferences are edit/overwrite-only (no delete route) — you change their values, you don't remove the row. The audit log is append-only — there is no in-app delete path for audit rows (deliberate, for attribution integrity); launch history likewise has no in-app delete. Purging either today is a direct DB operation against the store.
  • Right-to-erasure / operator offboarding that must remove an identity's audit/launch rows is a manual DB task today (no app affordance) — plan for it if your compliance regime requires it.
  • State store — design — the full schema + the normative audit contract.
  • Security hardening — auth, sessions, and the capability model.
  • Backup & recovery — backing up + restoring the store.
  • Deployment — sizing the state volume.