import type { Kysely } from 'kysely'; import type { AuditLogRow, Database, User } from '../db/schema.js'; /** * Who did what. * * Append-only: nothing here updates or deletes, and nothing else should either. A log that can be * tidied by whoever it embarrasses is not a log. The one exception is retention, which is a * deliberate, dated sweep rather than a targeted delete — see `purgeAuditLogBefore`. * * Writes are **best-effort and never block the action they describe**. Failing a publish because * the log write failed would trade a real capability for a record of it, and an editor cannot act * on "audit log unavailable". A failure is reported to the server console, where it belongs. */ export type AuditSubjectType = 'item' | 'content_type' | 'user' | 'media' | 'taxonomy' | 'reusable_block' | 'redirect' | 'release' | 'api_key' | 'webhook'; export interface AuditEntryInput { /** Dotted verb: `item.published`, `user.two_factor_cleared`. Past tense — it already happened. */ action: string; subjectType: AuditSubjectType; subjectId?: string | null; /** What it was called at the time, so the entry still reads after the subject is gone. */ subjectLabel?: string | null; /** The user responsible, or null for something the system did — the scheduler, say. */ actor?: Pick | null; detail?: Record | null; } export declare function recordAuditEntry(db: Kysely, input: AuditEntryInput): Promise; export interface AuditEntry extends Omit { detail: Record | null; } export interface ListAuditOptions { action?: string; actorId?: string; subjectType?: AuditSubjectType; subjectId?: string; limit?: number; offset?: number; } export declare function listAuditEntries(db: Kysely, options?: ListAuditOptions): Promise<{ entries: AuditEntry[]; total: number; }>; /** The distinct actions present, so a filter can offer what exists rather than a fixed list. */ export declare function listAuditActions(db: Kysely): Promise; /** * Retention: drop everything older than a date. * * The only deletion this module offers, and deliberately blunt — a sweep by age rather than * anything that can be aimed. "Delete entries about me" and "delete entries from last Tuesday" are * the two capabilities an audit log must not have. */ export declare function purgeAuditLogBefore(db: Kysely, before: Date, /** * Most rows to remove in one call, or omitted for all of them. * * A bound rather than a throttle: the first sweep after retention is switched on may face a table * that has grown since the deployment was built, and one unbounded delete over hundreds of * thousands of rows is a statement long enough to hit a runtime limit on the one path that runs * unattended. `purgeExpiredLogs` passes it; a caller doing this by hand need not. */ limit?: number): Promise;