Skip to content

Activity & Audit

A live cluster and platform activity feed alongside a tamper-evident, hash-chained audit trail, unified into one filterable, exportable timeline for compliance.

Tier: Free


What it does

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.

The Activity feed is a real-time feed that merges Kubernetes Warning events — CrashLoopBackOff, OOMKilled, and similar — with platform activity such as agent and terminal session open/close and autonomous investigations. It can be filtered by namespace, level, and time range. Its retention defaults to 7 days; see Setup for changing it.

Each row carries its own age (4m ago, 3d ago) rather than only a timestamp, so how current the feed is readable at a glance.

Filters on the audit timeline survive leaving it. They live in the page's URL, not in the browser's private storage, so switching tabs or reloading brings the same filtered view back, the back button steps through them, and you can send someone a link to exactly what you are looking at. Whenever any filter is on, the timeline says Filtered above the list: a restored filter plus an empty result is otherwise indistinguishable from a broken feed.

The unified audit timeline merges every audited action from seven separate tables into a single normalized view: the general audit log, which records every write, every denial or error, and reads of sensitive surfaces — identity and credential endpoints, the terminal, settings, licensing, the purge endpoint — with actor, action, scrubbed detail, and status; agent session transcripts, from autonomous alert-investigation; terminal session audit, which carries the session-close record; terminal commands, the captured shell history described below; the AI prompt log, scrubbed prompt and response pairs, recorded only when Prompt Audit is enabled; cluster events, the Kubernetes Warning and platform-outcome rows behind the Activity feed; and alert firings. A terminal session's OPEN is recorded in the general audit log as terminal_session_start. Routine read polling does not enter this trail at all — it is written to a separate access log kept 7 days, which stays out of the timeline and is reachable only by naming category=access on an export. Every audit read route is admin-only and read-only; the one write on this surface is the manual purge described below, which is itself audited before and after. Rows are redacted at write time and passed through redaction again on the way out, so a source that stored raw text can never leak a secret through this layer.

Importing a pod's logs into the Log Workspace is recorded as its own event, logs.import, naming the namespace and the pod that was read, under the Data reads category — shown by default, so "who read which pod's logs, and when" is answered without enabling the HTTP filter.

The unified endpoint supports filtering by category (repeatable — http, write, read, ai_decision, ai_executed, terminal, auth, login, cluster_event, alert, plus access on the export only), severity (repeatable — info, warning, critical), actor, namespace, an action prefix, and outcome; by ISO timestamp range and free-text search over action and detail; and keyset pagination for scrolling through large result sets. A single-event lookup also returns best-effort correlated siblings — events from the same actor within a five-minute window — which is useful for reconstructing what else happened around a specific action.

The general audit log table is hash-chained: each row's hash covers the previous row plus its own payload, so any edit to an existing row, or any interior deletion, breaks the chain and is detectable with no configuration required. A verify-chain endpoint recomputes the chain oldest-first and reports whether it's intact; if not, it checks every remaining row anyway and lists each one whose content was edited, which does not follow the row before it, or which carries no hash at all, together with a count of all breaks found. The in-database chain detects edits and interior deletions but cannot detect trimming the newest rows off the end — for that, an optional off-box WORM export writes every audit row as an immutable object into your own S3 or S3-compatible bucket with Object Lock and a default retention, so even a root-level actor can't alter it within the window, while the bucket itself stays yours for data residency.

Export returns the same filtered timeline as CSV for spreadsheets or JSON for SIEM ingestion, and includes the AI prompt log when Prompt Audit is enabled. The JSON export embeds the applied filters and a generated-at timestamp in its envelope. The CSV carries neither: they travel only as response headers (X-Generated-At, X-Total-Matched, X-Truncated), which a saved .csv does not retain. A capped CSV does record that in the file, as a truncation banner in cell A1. For streaming forwarding rather than pull, configuring a webhook URL (with an optional token) POSTs every audited request to your own collector as it happens.

Append-only audit tables prune themselves on their own insert path — cheap, indexed, and requiring no separate sweep job to schedule. The general audit log defaults to 365 days retention, terminal audit, captured terminal commands and agent session transcripts to 180 days, and the activity feed's cluster events to 7 days by default though runtime-adjustable; the alert history (one record per firing) defaults to 180 days. Those windows all take environment-variable overrides for operators who want a different one; the terminal command window is also the Helm value terminal.commandCapture.retentionDays. The AI prompt log is the exception: its window is a runtime setting under Admin → AI → Guardrails (prompt_retention_days, default 30 days), and no environment variable changes it. User-authored content — saved bundles, runbooks, alert rules, settings — is never auto-pruned, only operational and activity logs are. A manual purge also exists independently, letting an admin force-purge the audit log and alert history by age or keep-last-N on demand.

Terminal commands

Every command submitted in a browser terminal session is recorded with the account, timestamp, session and namespace. Reads of that history are themselves audited, and admin-only. Capture is on by default; an install that sets terminal.commandCapture.enabled=false records no command lines, and still records who opened and closed each session and when.

Commands come from bash's own history rather than from raw keystrokes, so a command recalled with the arrow keys is stored as what it ran, and a tab completion is stored completed.

OUTPUT IS NEVER STORED. It routinely contains secrets, tokens and kubeconfig dumps that scrolled past, and keeping it would turn the audit trail into the most sensitive store in the product. Commands are redacted before storage with the standard rules plus command-line-specific ones (--password=, --from-literal, access-key patterns).

The honest limit: this is in-shell instrumentation, so an operator can turn their own history off — the gap is visible in the record. Closing it entirely would need privileged host access that KubeManta deliberately does not take.

The Tasks tray — background work that follows you

Some work takes long enough that nobody waits for it. A vulnerability scan of a real namespace runs for tens of minutes, so people start one and go back to what they were doing. Tasks is the control in the top bar that tells them how it ended, wherever they happen to be.

It has two halves. The tray is the ledger — what is running now, and what recently finished. A toast is the interrupt, shown once, at the moment something ends. Every toast is a view of a tray row, which is what makes hiding one safe: dismissing the pop-up never removes the outcome.

Rows are shared and attributed. One admin's scan is every admin's context — seeing that a colleague already started the scan you were about to start is most of the value. Only two things are personal: whether you have looked (the badge) and whether you want pop-ups (mute).

A task that stops reporting is not a task that finished. If a scan's pod is evicted or the agent restarts mid-run, the row shows an amber hexagon and says Stopped reporting rather than quietly showing as complete. Rendering it as finished would send someone looking for findings that were never produced — the failure this surface exists to prevent.

A failure says what happened and what it cost. The row carries the reason (OOMKilled, DeadlineExceeded), the detail in plain words, and the consequence — that nothing was produced, so what is on screen is still the previous result. A timeout is presented as a failure, not a warning, because the outcome is the same: time spent, nothing to show.

Three ways to get it out of your way, none of which loses anything. Dismiss a single toast with ✕ and it never comes back. Several finishing at once collapse into one summary instead of stacking up the corner. Mute finish pop-ups in the tray footer silences the pop-ups for you entirely — and deliberately leaves the badge, the rows and the audit record alone, so a failure can never be muted into looking like a success. The badge clears one way only: you open the tray.

Each row has a small hexagon beside its status word: it breathes while the task is running and is still once it has finished, failed or stopped reporting.

Returning after a while shows a badge, never a replay. Pop-ups fire only from live events, so signing in tomorrow does not greet you with a day of old news.

Tasks is admin-only, like the rest of this page and for the same reason: the rows carry other operators' work.

Setup

Both records live on one tab, Activity Feed, and that tab is admin-only — like the Tasks tray on it, and for the same reason: every feed behind it merges captured terminal commands and AI transcripts with the cluster warnings, so the rows are other operators' work. A viewer is not shown the tab at all, rather than being shown a page that then refuses everything on it.

Viewers still see the Kubernetes warnings, which are the part of this that is about the cluster rather than about people: they are on the Network tab's event list and on each resource's own detail view.

Older #audit links redirect to Activity Feed. The Activity feed's retention window comes from CLUSTER_EVENTS_RETENTION_DAYS, 7 days unless a value has been stored through the admin-only POST /activity/retention, which overrides it. The optional WORM export and streaming webhook forwarding are both configured via Helm values, since they extend the deployment rather than being toggled purely at runtime.

Troubleshooting

If verify-chain reports a break, the response names each affected row and whether it's a content edit, a linkage break (a deleted predecessor or an inserted row) or a row with no hash — treat this as a genuine integrity finding rather than a transient error, since the chain is specifically designed not to produce false positives from ordinary operation. Remember the chain can only catch edits and interior deletions; it cannot by itself prove the newest rows weren't trimmed off the end, which is exactly what the optional WORM export closes. Two exceptions apply to a trail written by an earlier version. An account-recovery command run inside the pod (recorded as admin_recovery, mfa_reset or user_password_reset, with a pod-exec: actor) at the same moment as other activity could leave a linkage break with nothing edited or removed; if a break sits directly beside such a row, that is the likely cause. And re-enabling password login from inside the pod (recorded as local_login_enable) wrote its row without a hash, which is reported as an unchained row. Current versions produce neither, but a break already in the trail continues to be reported. Because verification covers the whole trail and counts every break, note the count: a later change to the trail shows up as an additional break rather than hiding behind the existing one. If an export or the unified timeline seems to be missing recent events, check the applied filters first — category, actor, and time-range filters are easy to leave narrower than intended, and a filtered-out event is indistinguishable from a missing one until you check.


Generated from KubeManta 1.5.0 — this page is rendered from the product's own documentation, so it cannot drift from what ships. Manifest built 2026-11-03T12:53:14Z.