feat(audit): comprehensive logging — auth events, severity, source, IP
Audit log was previously silent on authentication and on background work. This wires: - Login (success + failed) and logout via a wrapper around better-auth's [...all] handler. Failed logins are severity 'warning' and carry the attempted email so brute-force attempts surface in the inspector. - New severity (info|warning|error|critical) and source (user|auth| system|webhook|cron|job) columns on audit_logs. permission_denied defaults to 'warning', hard_delete to 'critical'. - Webhook delivery success/failure/DLQ/retry now write audit rows alongside the webhook_deliveries detail table. - IP address is now visible as a column in the inspector (was already captured at the helper level). - Audit UI: severity badges per row, severity + source dropdowns, IP column, expanded action filter covering hard-delete, webhook events, job/cron events. Migration 0044 adds the two columns + their port-scoped indexes. 1175/1175 vitest passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,9 @@ interface AuditEntry {
|
||||
newValue: Record<string, unknown> | null;
|
||||
metadata: Record<string, unknown> | null;
|
||||
ipAddress: string | null;
|
||||
userAgent?: string | null;
|
||||
severity?: 'info' | 'warning' | 'error' | 'critical';
|
||||
source?: 'user' | 'system' | 'auth' | 'webhook' | 'cron' | 'job';
|
||||
createdAt: string;
|
||||
actor: { id: string; email: string; name: string } | null;
|
||||
}
|
||||
@@ -110,11 +113,19 @@ export function AuditLogCard({ entry }: AuditLogCardProps) {
|
||||
</span>
|
||||
</p>
|
||||
|
||||
{/* Timestamp meta line */}
|
||||
{/* Timestamp + IP meta line */}
|
||||
<div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-muted-foreground">
|
||||
<ListCardMeta icon={<Clock className="h-3 w-3" />}>
|
||||
{formatDistanceToNow(new Date(entry.createdAt), { addSuffix: true })}
|
||||
</ListCardMeta>
|
||||
{entry.ipAddress ? (
|
||||
<span className="font-mono text-[11px]">{entry.ipAddress}</span>
|
||||
) : null}
|
||||
{entry.severity && entry.severity !== 'info' ? (
|
||||
<span className="uppercase font-semibold tracking-wide text-[10px]">
|
||||
{entry.severity}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{/* Action badge + changed-fields chips */}
|
||||
|
||||
Reference in New Issue
Block a user