Spec: Admin Audit Logs
Overview​
Admin-only feature that allows administrators to browse, search, and export all conversations and full message content across all users, gated by the AUDIT_LOGS_ENABLED environment variable (disabled by default).
Motivation​
Platform administrators need visibility into all chat conversations for compliance, auditing, and support purposes. Without this, there is no way for admins to review what users are discussing with the AI agents, investigate issues reported by users, or audit platform usage at the conversation level.
Scope​
In Scope​
- Environment variable toggle (
AUDIT_LOGS_ENABLED=true) to enable the feature - Admin API endpoints for listing conversations, reading messages, exporting to CSV, and searching owners
- Admin UI tab with search, filtering, and pagination
- Searchable owner email dropdown with typeahead autocomplete
- Conversation detail dialog showing full message content with scrollable layout
- Conversation UUID display with direct chat link and copy-to-clipboard
- CSV export of audit logs (respects active filters, up to 10,000 rows)
- Server-side enforcement of the feature flag (API returns 403 when disabled)
Out of Scope​
- Exporting to external SIEM systems
- Real-time streaming of new conversations/messages
- Editing or deleting conversations from the audit view
- Per-message audit trail (who viewed what)
- Retention policies for audit data
Design​
Architecture​
The feature adds a new "Audit Logs" tab to the existing admin dashboard, backed by four API endpoints that query the existing MongoDB conversations and messages collections. No new collections or data models are introduced — the feature provides a read-only cross-user view over existing data.
The feature is double-gated:
AUDIT_LOGS_ENABLED=trueenv var must be set (disabled by default)- User must be a full admin (
requireAdmin) — read-only admin viewers cannot access audit logs
Data Models​
The feature introduces two types in ui/src/types/mongodb.ts:
AuditConversation— extendsConversationwithmessage_count,last_message_at, andstatus(derived via aggregation pipeline)AuditLogFilters— describes the filter parameters:owner_email,search,date_from,date_to,include_deleted,status
API Endpoints​
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/admin/audit-logs | GET | requireAdmin | List all conversations with filters and pagination |
/api/admin/audit-logs/[id]/messages | GET | requireAdmin | Get paginated messages for a specific conversation |
/api/admin/audit-logs/export | GET | requireAdmin | Download filtered conversations as CSV (up to 10,000 rows) |
/api/admin/audit-logs/owners | GET | requireAdmin | Search distinct conversation owner emails (typeahead) |
List Endpoint Filters​
| Parameter | Type | Description |
|---|---|---|
owner_email | string | Filter by conversation owner (case-insensitive substring) |
search | string | Search in conversation titles (case-insensitive substring) |
date_from | ISO date | Conversations created on or after this date |
date_to | ISO date | Conversations created on or before this date |
status | enum | active, archived, or deleted |
include_deleted | boolean | Include soft-deleted conversations (default: false) |
page | number | Page number (default: 1) |
page_size | number | Items per page (default: 20, max: 100) |
Components Affected​
- Agents (
ai_platform_engineering/agents/) - Multi-Agents (
ai_platform_engineering/multi_agents/) - MCP Servers
- Knowledge Bases (
ai_platform_engineering/knowledge_bases/) - UI (
ui/)ui/src/lib/config.ts—auditLogsEnabledconfig flagui/src/types/mongodb.ts—AuditConversation,AuditLogFilterstypesui/src/app/api/admin/audit-logs/route.ts— list conversations endpointui/src/app/api/admin/audit-logs/[id]/messages/route.ts— conversation messages endpointui/src/app/api/admin/audit-logs/export/route.ts— CSV export endpointui/src/app/api/admin/audit-logs/owners/route.ts— searchable owners endpointui/src/app/(app)/admin/page.tsx— conditional Audit Logs tabui/src/components/admin/AuditLogsTab.tsx— filter/search/table component with export and owner searchui/src/components/admin/ConversationDetailDialog.tsx— message viewer dialog with scrollingui/.env.example— documentedAUDIT_LOGS_ENABLEDenv var
- Documentation (
docs/) - Tests (
ui/src/)ui/src/app/api/__tests__/admin-audit-logs.test.ts— 52 tests covering all 4 endpointsui/src/app/api/__tests__/admin-audit-access.test.ts— 8 tests forrequireConversationAccessadmin audit accessui/src/lib/__tests__/config.test.ts— 4 tests forauditLogsEnabledenv-var behavior
- Helm Charts (
charts/)
Acceptance Criteria​
- Feature is disabled by default (no env var = tab hidden, API returns 403)
- Setting
AUDIT_LOGS_ENABLED=trueshows the Audit Logs tab in admin dashboard - Admins can search conversations by owner email, title, date range, and status
- Owner email field provides searchable autocomplete with typeahead
- Admins can view full message content for any conversation
- Conversation detail dialog has proper scrolling for long conversations
- Conversation UUID is visible with copy-to-clipboard and direct chat link
- Admins can download filtered audit logs as CSV
- API enforces
requireAdminauthorization on all endpoints (full admin only, not read-only viewers) - API enforces feature flag server-side (not just UI hiding)
- Pagination works for both conversation list and message detail
- No write operations are exposed (read-only audit view)
- CSV export includes proper headers, escaping, and
Cache-Control: no-store - All 52 unit tests pass (API endpoints)
- All 4 config env-var tests pass (
auditLogsEnabled) - All 8 admin audit access tests pass
-
AUDIT_LOGS_ENABLEDdocumented inui/.env.example - Documentation updated (spec + ADR)
Implementation Plan​
Phase 1: Core Feature​
- Add
auditLogsEnabledto Config interface, DEFAULT_CONFIG, and getServerConfig() - Add
AuditConversationandAuditLogFilterstypes - Create
GET /api/admin/audit-logswith aggregation pipeline - Create
GET /api/admin/audit-logs/[id]/messagesfor conversation detail - Create
AuditLogsTabcomponent with filters and results table - Create
ConversationDetailDialogcomponent for message viewing - Add conditional tab to admin page
Phase 2: Enhancements​
- Add CSV export endpoint (
GET /api/admin/audit-logs/export) - Add Download CSV button to AuditLogsTab UI
- Add searchable owner email dropdown with
GET /api/admin/audit-logs/owners - Add conversation UUID display, copy-to-clipboard, and direct chat link
- Implement scrollable message content in ConversationDetailDialog
Phase 3: Quality & Documentation​
- Create comprehensive test suite (52 API tests + 4 config tests + 8 access tests = 64 total)
- Add
AUDIT_LOGS_ENABLEDtoui/.env.example - Create spec in
.specify/specs/ - Create ADR in
docs/docs/changes/
Testing Strategy​
- Config tests (4 tests in
config.test.ts):- Default false when unset
truewhenAUDIT_LOGS_ENABLED=truefalsewhenAUDIT_LOGS_ENABLED=falsefalsefor non-"true"values ("1","banana","TRUE")
- API tests (52 tests in
admin-audit-logs.test.ts):- Auth: 401 unauthenticated, 403 non-admin, 403 readonly admin, 503 MongoDB not configured
- Feature flag: 403 when
auditLogsEnabledis false (all 4 endpoints) - List: filter propagation (owner, search, date range, status), pagination, aggregation pipeline
- List edge cases: archived filter, include_deleted, date-only filters, combined filters, default pagination, sort order
- Messages: 404 not found, conversation metadata, paginated messages, empty conversations, has_more pagination
- Export: CSV headers, Content-Type/Content-Disposition, data rows, CSV escaping, filter propagation
- Export edge cases: no tags, empty results, status filters
- Owners: distinct owners, search query,
$groupaggregation, result limit, null filtering
- Access tests (8 tests in
admin-audit-access.test.ts):requireConversationAccessreturnsadmin_auditaccess level for admin sessions- Non-admin/non-owner users get 403
- Conversation not found returns 404
- Manual verification:
- Set
AUDIT_LOGS_ENABLED=true, verify tab appears - Unset env var, verify tab is hidden and API returns 403
- Search by owner email using autocomplete dropdown
- Click conversation to view full messages with scrolling
- Download CSV and verify contents
- Copy conversation UUID and open direct chat link
- Set
Rollout Plan​
- Merge PR to main
- Feature is off by default — no impact on existing deployments
- Operators enable via
AUDIT_LOGS_ENABLED=truein their environment - Document env var in deployment guides
Related​
- ADR: 2026-03-03-admin-audit-logs
- PR: #894 (initial implementation)
- Tests:
ui/src/app/api/__tests__/admin-audit-logs.test.ts(52 tests) - Tests:
ui/src/app/api/__tests__/admin-audit-access.test.ts(8 tests) - Tests:
ui/src/lib/__tests__/config.test.ts(4auditLogsEnabledtests) - Existing admin dashboard:
ui/src/app/(app)/admin/page.tsx - Config system:
ui/src/lib/config.ts