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:
@@ -22,6 +22,10 @@ export interface AuditSearchOptions {
|
||||
entityType?: string;
|
||||
/** Filter by exact entity id (e.g. paste a uuid into search). */
|
||||
entityId?: string;
|
||||
/** Filter by severity ('info' | 'warning' | 'error' | 'critical'). */
|
||||
severity?: string;
|
||||
/** Filter by source ('user' | 'system' | 'auth' | 'webhook' | 'cron' | 'job'). */
|
||||
source?: string;
|
||||
/** Inclusive date range. */
|
||||
from?: Date;
|
||||
to?: Date;
|
||||
@@ -42,6 +46,8 @@ export async function searchAuditLogs(options: AuditSearchOptions = {}): Promise
|
||||
if (options.action) conds.push(eq(auditLogs.action, options.action));
|
||||
if (options.entityType) conds.push(eq(auditLogs.entityType, options.entityType));
|
||||
if (options.entityId) conds.push(eq(auditLogs.entityId, options.entityId));
|
||||
if (options.severity) conds.push(eq(auditLogs.severity, options.severity));
|
||||
if (options.source) conds.push(eq(auditLogs.source, options.source));
|
||||
if (options.from) conds.push(gte(auditLogs.createdAt, options.from));
|
||||
if (options.to) conds.push(lte(auditLogs.createdAt, options.to));
|
||||
if (options.q) {
|
||||
|
||||
@@ -330,7 +330,7 @@ export async function redeliverWebhookDelivery(
|
||||
void createAuditLog({
|
||||
userId: meta.userId,
|
||||
portId,
|
||||
action: 'send',
|
||||
action: 'webhook_retried',
|
||||
entityType: 'webhook_delivery',
|
||||
entityId: next!.id,
|
||||
metadata: { redeliveredFrom: deliveryId, originalStatus: source.status },
|
||||
|
||||
Reference in New Issue
Block a user