Repository navigation
feat(audit): activity audit log + skills UI improvements - #10
Merged
Merged
Conversation
Audit log capturing per-interaction detail (prompt, response, error, duration, resource) for admin review, plus configurable retention from central settings. Backend: - migration 000036: audit_events table (content + metadata, distinct from the metrics-only chat_events) - models.AuditEvent + AuditEventFilter, postgres repo (Insert/List/Cleanup), repository.AuditEventRepository interface - audit.RecordEvent helper: truncates content to a configurable limit and inserts asynchronously (never blocks the hot-path) - captured on the MCP facade (Claude/Cursor/Codex): agent chat, MCP tool, skill read, group debate - settings: observability_retention_days (migrated from YAML), audit_retention_days, audit_max_content_chars — all editable in Admin → General Configuration; cleanup job now reads retention from settings for both chat_events and audit_events - GET /api/admin/audit with filters (range, user, group, category, request_id, paging) Web: - /admin/audit page: activity table with expandable rows (prompt/response/error), filters and pagination; nav entry - skills reader: wider panel, proper scroll, collapsible sidebar section, frontmatter stripped from displayed content
Instrument the web/API surfaces with the same audit.RecordEvent helper used by the MCP facade: agent proxy chat (proxy.go), MCP chat single + multi (mcp.go), and group debate turns (group_chat.go). Audit repo injected into ProxyHandler and MCPHandler via setters (both already use a variadic chatEventRepo).
…ges, Max selector - drop the request_id filter (not populated yet) - time range options: 30m/1h/6h/12h/24h/7d - add a Max results selector (50/100/250/500); repo limit cap raised to 1000
…calls - migration 000037: add client, session_id, token_usage, llm_model columns - AuditEvent gains Client, SessionID, ToolCalls (name+args+result), TokenUsage, LLMModel - facade captures the MCP client (user-agent) and agent session_id - web surfaces capture session_id, tool calls with args/result, and (MCP chat) token usage + LLM model - audit UI shows client on the row and a metadata line + expandable tool calls in the detail view
- backend: filter audit events by session_id (?session=) - UI: Session column (click a session id to filter by it) + Session search box
- time range options are generated up to the configured audit retention (audit_retention_days), always ending with a full-window option; if retention is raised to 90 days the range reaches 90 days - replace prev/next with numeric pagination (First « ‹ 1 2 3 … N › Last »), page-size selector relabeled 'Per page'
Show the Error section whenever status is error (with error_type and the message, or 'Unknown error' when the message is empty) instead of only when a message exists.
HIGH: - truncate tool-call arguments/result to audit_max_content_chars too (not just prompt/response), so the privacy/size limit actually bounds all stored content - MCP group tool: audit failures too and measure real wall-clock duration (auditStart) instead of the 15s-granularity progress counter - add tests for the audit helper (truncation, no-op guards) and the admin audit handler (filter parsing, empty result) MEDIUM: - group-debate web events now capture the prompt sent to each agent - populate user_groups on web-surface events (proxy/mcp/group) so the group filter matches them, not only facade events - drop the never-populated request_id and ttfb_ms fields/column/index (YAGNI)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an Audit section under
/admin: a detailed log of user activity — who ran what, the prompt sent, the response returned, errors, duration, and which agent/MCP/skill/group was used — with retention configurable from the central admin settings. Also bundles the requested skills reader UI improvements.Distinct from Observability (
chat_events), which stores only aggregate metrics with no content. Audit stores content (truncated) for review/compliance.Backend
audit_eventstable (migration 000036): content + metadata, own retention.models.AuditEvent+ filter, postgres repo (Insert/List/Cleanup),repository.AuditEventRepository.audit.RecordEventhelper: truncates prompt/response to a configurable limit and inserts asynchronously (never blocks the request hot-path).observability_retention_days(migrated from YAML),audit_retention_days,audit_max_content_chars. The cleanup job now reads retention from settings for bothchat_eventsandaudit_events.GET /api/admin/auditwith filters (range, user, group, category, request_id) + offset pagination.Web
/admin/audit: activity table with expandable rows (prompt / response / error), filters (range, member, category, request ID) and pagination; nav entry.Test plan
Verified end-to-end against the Docker dev stack:
audit_eventstable)source=mcp,skill_read, content)source=web,agent,chat, prompt+response)GET /api/admin/auditreturns events with filters/paginationGET /api/admin/settings(observability + audit + max content)go build,go vet,go test ./internal/{handlers,mcpserver,models,settings}green; webnpm run lint0 errors/admin/auditand the skills reader (browser extension not connected during dev; pages compile and build)Notes
🤖 Generated with Claude Code