feat(admin): audit-log viewer

Surface the admin_audit table (written by every mutating admin action but
previously unreadable) as a new /admin/audit tab. New repo::admin_audit::list
(LEFT JOIN users for the actor's username, filter by action/target_kind/actor/
since, at DESC via admin_audit_at_idx) behind GET /v1/admin/audit, mirroring the
crawler history endpoint's paged/clamped idiom.

Frontend: a self-contained AuditTable (target-kind + window + action filters,
expandable JSON payload, AbortController-cancelled fetches, loading/error/empty
states) and shared fmtAgo() in format.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-19 11:26:09 +02:00
parent dd300a150c
commit 31013cc893
11 changed files with 748 additions and 5 deletions

View File

@@ -9,7 +9,8 @@
{ href: '/admin/crawler', label: 'Crawler' },
{ href: '/admin/analysis', label: 'Analysis' },
{ href: '/admin/settings', label: 'Settings' },
{ href: '/admin/system', label: 'System' }
{ href: '/admin/system', label: 'System' },
{ href: '/admin/audit', label: 'Audit' }
];
</script>

View File

@@ -0,0 +1,25 @@
<script lang="ts">
import AuditTable from '$lib/components/admin/AuditTable.svelte';
</script>
<svelte:head><title>Audit log · Admin</title></svelte:head>
<h1>Audit log</h1>
<p class="lead">
Every admin action — crawler runs, resyncs, settings changes, session
updates — is recorded here. Click a row to inspect its payload.
</p>
<AuditTable />
<style>
h1 {
margin-bottom: var(--space-2);
}
.lead {
color: var(--text-muted);
font-size: var(--font-sm);
margin-bottom: var(--space-4);
max-width: 44rem;
}
</style>