Skip to content

Activity & Audit

KubeManta keeps two complementary records: a live Activity feed of what's happening in the cluster and the platform, and a tamper-evident audit trail of every request and privileged action — with a unified, filterable, exportable timeline for compliance.


Activity feed

The Activity tab is a real-time feed that merges:

  • Kubernetes Warning events streamed into cluster_events (CrashLoopBackOff, OOMKilled, and similar)
  • Platform activity — agent and terminal session open/close, autonomous investigations

Filter by namespace, level, and time range. Retention for the feed is configurable at runtime via the admin activity_retention_days setting (default 7 days; env seed CLUSTER_EVENTS_RETENTION_DAYS).


The unified audit timeline

Every audited action is written to one of four SQLite tables, and GET /audit/unified merges them into a single normalized timeline. All audit routes are admin-only and read-only.

Source table What it records
audit_log Every HTTP request + every audited write (actor, action, scrubbed detail, status).
agent_sessions Autonomous alert-investigation transcripts.
terminal_audit Terminal session open/close.
ai_prompt_log Scrubbed AI prompt + response (only when Prompt Audit is enabled).

Rows are _scrub-redacted at write time and passed through _scrub again on the way out, so a source that stored raw text can never leak a secret through this layer.

Filtering & pagination

GET /audit/unified supports:

  • category facet (repeatable): http, write, ai_decision, ai_executed, terminal, auth
  • actor, namespace, action (prefix), outcome
  • from / to ISO timestamps, q free-text over action + detail
  • Keyset pagination via cursor (ts|id) and limit (max 500)

GET /audit/unified/{event_id} returns one event plus best-effort correlated siblings (same actor, ±5-minute window).


Tamper-evident hash-chain

The audit_log table is hash-chained: each row's SHA-256 covers the previous row plus its own payload. Any edit to an existing row or any interior deletion breaks the chain and is detectable — no configuration required.

# Verify the chain (admin)
curl -s https://kubemanta.example.com/api/agent/audit/verify-chain \
  -H "Cookie: km_session=<token>" | jq .

GET /audit/verify-chain recomputes the chain (oldest-first) and reports whether it is intact. If not, first_break names the first row whose content was edited (row_hash_mismatch) or whose predecessor was deleted (linkage_break).

Closing the last gap — WORM export

The in-DB chain detects edits and interior deletions but cannot detect trimming the newest rows. For that, enable the optional off-box WORM export (audit.worm): every audit row is also written as one immutable object into your own S3 (or S3-compatible) bucket that has Object Lock with a default retention, so even an account-root actor cannot alter it within the window. The bucket is yours — data residency is preserved. See Helm Values → Audit.


Export

GET /audit/unified/export?format=csv|json returns the same filtered timeline — CSV for spreadsheets, JSON for SIEM ingestion. This is the first read/export path for ai_prompt_log (previously write-only). Every export carries the applied filters and a generated-at timestamp.

For streaming forwarding rather than pull, set audit.webhookUrl (+ optional audit.webhookToken) to POST every audited request to your collector as it happens.


Retention

Append-only audit tables prune themselves on their own insert path — cheap, indexed, no sweep job to schedule:

Table Default retention Env override
audit_log 365 days AUDIT_LOG_RETENTION_DAYS
terminal_audit 180 days TERMINAL_AUDIT_RETENTION_DAYS
agent_sessions 180 days AGENT_SESSIONS_RETENTION_DAYS
ai_prompt_log 30 days (compliance.prompt_retention_days) via AI Guardrails
cluster_events 7 days (runtime activity_retention_days) CLUSTER_EVENTS_RETENTION_DAYS
alert_history / alert_firings 180 days ALERT_HISTORY_RETENTION_DAYS / ALERT_FIRINGS_RETENTION_DAYS

User-authored content (saved bundles, runbooks, alert rules, settings) is never auto-pruned — only operational/activity logs are.

A manual purge also exists independently: POST /kubemanta/db/purge (admin) force-purges audit_log / alert_history by age or keep-last-N on demand.