import { all, run } from "./db"; import { randomId } from "./crypto"; export type AdminAuditEntry = { id: string; actor_id: string | null; actor_name: string | null; action: string; target_kind: string; target_id: string; reason: string | null; created_at: number; }; export type AdminAuditInput = { actorId: string; action: string; targetKind: string; targetId: string; reason?: string | null; }; const MAX_REASON = 1000; /** Appends one site-admin action to the audit log. */ export async function recordAdminAction(input: AdminAuditInput): Promise { await run( `INSERT INTO admin_audit_log (id, actor_id, action, target_kind, target_id, reason, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, randomId(), input.actorId, input.action, input.targetKind, input.targetId, input.reason?.trim().slice(0, MAX_REASON) || null, Date.now(), ); } export async function listAdminAudit( filter: { targetKind?: string; targetId?: string; before?: number } = {}, limit = 100, ): Promise { return all( `SELECT l.id, l.actor_id, a.name AS actor_name, l.action, l.target_kind, l.target_id, l.reason, l.created_at FROM admin_audit_log l LEFT JOIN accounts a ON a.id = l.actor_id WHERE (?1 IS NULL OR l.target_kind = ?1) AND (?2 IS NULL OR l.target_id = ?2) AND (?3 IS NULL OR l.created_at < ?3) ORDER BY l.created_at DESC LIMIT ?4`, filter.targetKind ?? null, filter.targetId ?? null, filter.before ?? null, limit, ); }