feat: audit log campaign scoping, coverage, admin UI, pruning (#120) #200
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/120-audit-log"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #120. First issue of v3.8.0 Privacy & Data Lifecycle — the audit foundation the sibling issues (#117/#118/#119) log into.
Backend (
b2633b8)AuditLoggains nullablecampaign_id(indexed),target_type,target_id+ composite index(campaign_id, created_at). Migrationa1c2d3e4f5a6(round-trips). Backward-compatible — new columns nullable, the existing 7 log sites keep working.log_event/get_recent_eventsgaincampaign_id/target/since/until/offset; newcount_eventsfor pagination totals.GET /admin/audit-loggainssince/until/campaign_id/offsetfilters +X-Total-Count; response carries the new fields.campaign.deleted(hard delete) +admin.settings.backup.updated;campaign_id/targetbackfilled on the existing archive/restore/member-removed sites. (AI settings share the already-logged bot-settings handler; no admin platform-link-recovery endpoint exists — both correctly left alone rather than inventing sites.)audit_log_retention_yearssetting (default 2, clamp 1–2) + a monthlyprune_audit_logBeat task — state-driven, idempotent, and not self-audited.Frontend (
<head>)X-Total-Countpagination (reuses the existingrequestListhelper); per-row expandablecontextJSON; "system" for null actors.Tests
test_audit_log.py(new columns, filters/pagination/X-Total-Count, coverage sites with secret redaction, idempotent non-self-auditing pruning). Full suite 541 pass; migration round-trip verified.Notes
since/untilcome fromdatetime-localinputs (naive → treated as UTC by asyncpg for the timestamptz comparison); a minor admin filter.🤖 Generated with Claude Code