import { useDeferredValue, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { listAuditLogs } from '@/lib/api-client'; import { useDemoMode } from '@/lib/demo-mode'; import { formatDate, formatRelative } from '@/lib/time'; import { DemoRestricted } from '@/shared/components'; import { ScrollText, ChevronLeft, ChevronRight, Loader2 } from 'lucide-react'; const PAGE_SIZE = 50; const rangeOptions = [ { value: '', label: 'All time' }, { value: '24h', label: 'Last 24 hours', ms: 24 * 60 * 60 * 1000 }, { value: '7d', label: 'Last 7 days', ms: 7 * 24 * 60 * 60 * 1000 }, { value: '30d', label: 'Last 30 days', ms: 30 * 24 * 60 * 60 * 1000 }, ] as const; const inputClass = 'h-9 px-3 rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--surface-muted)] text-sm text-[var(--text-primary)] placeholder:text-[var(--text-muted)] focus:border-[var(--accent-primary)] focus:ring-1 focus:ring-[var(--accent-primary)] transition-all'; export function AuditLogsPage() { const isDemoMode = useDemoMode(); const [resource, setResource] = useState(''); const [action, setAction] = useState(''); const [actor, setActor] = useState(''); const [range, setRange] = useState(''); const [page, setPage] = useState(1); const deferredResource = useDeferredValue(resource); const deferredAction = useDeferredValue(action); const deferredActor = useDeferredValue(actor); const filters = { resource: deferredResource.trim() || undefined, action: deferredAction.trim() || undefined, actor: deferredActor.trim() || undefined, page, limit: PAGE_SIZE, }; const logsQuery = useQuery({ queryKey: ['audit-logs', filters, range], queryFn: () => { const option = rangeOptions.find((o) => o.value === range); const since = option && 'ms' in option ? new Date(Date.now() - option.ms).toISOString() : undefined; return listAuditLogs({ ...filters, since }); }, enabled: !isDemoMode, }); if (isDemoMode) { return ; } const logs = logsQuery.data ?? []; const hasNext = logs.length === PAGE_SIZE; const hasFilters = Boolean(resource || action || actor || range); const resetFilters = () => { setResource(''); setAction(''); setActor(''); setRange(''); setPage(1); }; return (

Audit Logs_

Every authenticated action recorded by the platform

{ setResource(e.target.value); setPage(1); }} placeholder="service, project…" className={`${inputClass} w-44`} />
{ setAction(e.target.value); setPage(1); }} placeholder="create, deploy…" className={`${inputClass} w-44`} />
{ setActor(e.target.value); setPage(1); }} placeholder="user email" className={`${inputClass} w-52`} />
{hasFilters && ( )}
{logsQuery.isLoading ? ( ) : logsQuery.isError ? ( ) : logs.length === 0 ? ( ) : ( logs.map((log) => ( )) )}
Time Actor Resource Action Resource ID IP Details
Failed to load audit logs.

No audit events{hasFilters ? ' match these filters' : ' recorded yet'}.

{log.createdAt ? formatRelative(log.createdAt) : '—'} {log.userEmail || (log.userId ? log.userId.slice(0, 8) : 'system')} {log.resource} {log.action} {log.resourceId || '—'} {log.ipAddress || '—'} {log.details && log.details !== '{}' ? log.details : '—'}

Page {page}{logs.length > 0 ? ` — ${logs.length} entries` : ''}

); }