Skip to content

feat(admin): add system_settings audit history (#3002)#3007

Merged
bokelley merged 1 commit intomainfrom
claude/issue-3002-system-settings-audit
Apr 24, 2026
Merged

feat(admin): add system_settings audit history (#3002)#3007
bokelley merged 1 commit intomainfrom
claude/issue-3002-system-settings-audit

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

Closes #3002

Summary

Adds a complete audit trail for all system_settings changes — the pre-existing gap flagged in the #3000 security review.

Migration 426_system_settings_audit.sql: new append-only system_settings_audit(id, key, old_value JSONB, new_value JSONB NOT NULL, changed_by, changed_at NOT NULL) table with indexes on key, changed_by, and changed_at DESC.

setSetting rewrite: replaced the plain two-query (SELECT + UPSERT) approach with a single writable CTE that atomically captures the pre-update value, runs the UPSERT, and inserts the audit row — one round-trip, no TOCTOU gap.

New getSettingAuditHistory(limit): DB helper with a Math.min/max clamp (1–200) to prevent unbounded queries.

New GET /api/admin/settings/audit endpoint (requireAuth + requireAdmin), returns last 50 entries.

admin-settings.html updates:

  • "Recent changes" section at the bottom of the page renders the audit table (Setting / Changed by / When / New value) on load and refreshes after every save.
  • Added the editorial and announcement channel UI sections that were present in the backend but missing from the frontend.

Non-breaking justification: pure addition — new table, new INSERT side-effect in setSetting (callers are unaffected), new read endpoint, new UI section. No existing field or behavior changed.

Expert consensus: internal-tools-strategist and security-reviewer both reviewed; both approved. Key design requirements from review both incorporated: writable CTE for atomicity (vs. separate SELECT + UPSERT), and NOT NULL on changed_at.

old_value not shown in the UI table: intentional — the "Recent changes" panel is a quick-glance "who changed what" view. Full diff (old vs. new) is available via the API for any admin who needs it; the data is fetched and stored.

Session: https://claude.ai/code/session_01FGtbRG15ixXm4FNtSpaqkg


Generated by Claude Code

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

All contributors have agreed to the IPR Policy. Thank you!
Posted by the CLA Assistant Lite bot.

@bokelley bokelley marked this pull request as ready for review April 24, 2026 11:27
Adds an append-only audit log for system_settings changes:
- Migration 426: system_settings_audit table
- setSetting writes atomically via a writable CTE
- getSettingAuditHistory returns last 50 entries
- GET /api/admin/settings/audit endpoint
- Admin UI: 'Recent changes' card on the settings page

Rebased against current main (3004/3005 had moved admin-settings.html);
HTML audit block + init + per-save refresh calls spliced onto current
main's channel-fetch implementation.

Closes #3002

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bokelley bokelley force-pushed the claude/issue-3002-system-settings-audit branch from e9dab72 to 824bf32 Compare April 24, 2026 11:32
@bokelley bokelley merged commit d9cf62f into main Apr 24, 2026
10 of 11 checks passed
@bokelley bokelley deleted the claude/issue-3002-system-settings-audit branch April 24, 2026 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add audit history to system_settings (pre-existing gap)

1 participant