Skip to content

feat(api): configurable audit-event retention - #14

Merged
ValgulNecron merged 2 commits into
mainfrom
feat/api-audit-retention
Jun 28, 2026
Merged

ValgulNecron merged 2 commits into
mainfrom
feat/api-audit-retention

Conversation

@ValgulNecron

Copy link
Copy Markdown
Collaborator

What

Closes part of a documented beta limitation — "audit events are stored in the database; there is no … retention policy yet." The audit_events table previously grew unbounded on long-lived installs.

Adds an opt-in retention window: --audit-retention-days (env GAMEPLANE_AUDIT_RETENTION_DAYS), surfaced through the Helm chart as api.audit.retentionDays. Default 0 = keep forever, preserving today's behaviour. When positive, a background sweep deletes events older than the window on API startup and once a day after.

How

  • audit.Prune(ctx, cutoff) — DELETE FROM audit_events WHERE ts < ?. ts is stored as RFC3339 (fixed-width, zero-padded, UTC), so a lexicographic < is also chronological — no per-row time parsing, and the query stays portable across the sqlite/pgx drivers (matching the codebase's existing ?-placeholder convention).
  • audit.RunRetention(ctx, retention, interval, logger) — mirrors the existing telemetry.Run(ctx) goroutine lifecycle: sweeps immediately on start, then every interval, returns on ctx cancel; a non-positive window is an immediate no-op.
  • Wired as a background goroutine in serve() next to telemetry; new envOrInt helper for the int env default.
  • Chart: api.audit.retentionDays renders the flag only when > 0.
  • README known-limitations updated (retention now exists; external sink still deferred).

Tests

audit_test.go: prune boundary (old pruned / recent kept), nothing-older-than-cutoff, disabled-is-no-op, and the start-up sweep. Verified helm template renders the flag at retentionDays=30 and omits it at the 0 default.

Notes

No schema migration (retention is config + delete, not a schema change). No Pencil pass (no dashboard surface). Independent of #13 (disjoint api/ vs operator/ files).

🤖 Generated with Claude Code

ValgulNecron and others added 2 commits June 28, 2026 21:18
Audit events accumulated in the audit_events table with no way to bound
growth — a documented beta limitation ("no retention policy yet"). On a
long-lived install the table grows unbounded.

Add an opt-in retention window: --audit-retention-days (env
GAMEPLANE_AUDIT_RETENTION_DAYS), 0 = keep forever (default, preserves
current behaviour). When positive, a background sweep runs on API
startup and daily thereafter, deleting events older than the window.

- audit.Prune deletes rows whose ts predates a cutoff. ts is stored as
  RFC3339 (fixed-width, zero-padded, UTC), so a lexicographic "ts < ?"
  comparison is also chronological — no per-row parsing and the query
  stays portable across the sqlite/pgx drivers.
- audit.RunRetention mirrors the telemetry goroutine lifecycle: sweeps
  immediately, then every interval, returning on ctx cancel; a
  non-positive window is a no-op.
- Surface it through the Helm chart as api.audit.retentionDays.
- Update the README known-limitations to reflect retention now exists
  (external sink is still deferred).

Tests cover prune boundaries, the disabled no-op, and the start-up sweep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: valgulnecron <39313199+ValgulNecron@users.noreply.github.com>
TestRunRetention_SweepsOnStart cancelled the context before calling
RunRetention, but the start-up sweep's Prune uses that context for the
DELETE — a pre-cancelled context makes the sweep a no-op (correct
shutdown behaviour), so nothing was pruned and the test failed.

Run RunRetention in a goroutine with a live context, poll until the
start-up sweep prunes, then cancel and join. Production code unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: valgulnecron <39313199+ValgulNecron@users.noreply.github.com>
@ValgulNecron
ValgulNecron merged commit 0d51aeb into main Jun 28, 2026
31 of 33 checks passed
@ValgulNecron
ValgulNecron deleted the feat/api-audit-retention branch June 28, 2026 21:48
@ValgulNecron
ValgulNecron restored the feat/api-audit-retention branch June 28, 2026 22:00
@ValgulNecron
ValgulNecron deleted the feat/api-audit-retention branch June 30, 2026 14:26
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.

1 participant