fix(audit): retention TTL on runtime-written audit rows (v0.1.25.15)#108
Merged
Conversation
Runtime's AuditRepository.log() wrote audit:log:{id} keys with no EXPIRE,
so runtime-written rows persisted indefinitely until Redis eviction —
silently failing to participate in the 400-day retention tier admin
applies to authenticated audit rows.
Fix:
- LOG_AUDIT_LUA now reads ARGV[4] as an optional TTL in seconds
(same shape as cycles-server-admin's script, minus sentinel branching).
- audit.retention.days config (default 400, env AUDIT_RETENTION_DAYS).
0 = indefinite retention for legal-hold / archive-store deployments.
- audit.sweep.cron config (default 0 0 3 * * *) — daily @scheduled
sweep of stale ZSET pointers (audit:logs:_all + per-tenant indexes).
Mirrors admin's sweepStaleIndexEntries() so runtime is self-healing
regardless of whether admin is colocated on the same Redis.
Runtime never writes the admin-plane __admin__ / __unauth__ sentinels,
so a single-tier TTL is sufficient (unlike admin's two-tier setup).
Tests:
- New AuditRepositoryTest — 7 cases: TTL passed as ARGV[4],
retention=0 passes "0", logId + timestamp set, log() failure
non-fatal, sweeper removes global + per-tenant pointers, sweeper
no-op when retention=0, sweep failure non-fatal.
- Full data module: 365 / 365 green. Full api module: 152 / 152 green.
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the retention-TTL gap surfaced by the post-v0.1.25.14 alignment audit against
cycles-server-admin. Runtime'sAuditRepository.log()previously wroteaudit:log:{id}keys with noEXPIRE, so runtime-written rows persisted indefinitely until Redis memory-eviction — silently failing to participate in the 400-day retention tier admin applies to authenticated audit rows.LOG_AUDIT_LUAnow readsARGV[4]as an optional TTL in seconds (same shape as admin's Lua, minus sentinel branching).audit.retention.daysconfig (default400, envAUDIT_RETENTION_DAYS).0= indefinite retention for legal-hold / archive-store deployments.audit.sweep.cronconfig (default0 0 3 * * *, envAUDIT_SWEEP_CRON). Daily@Scheduledsweep prunes stale ZSET pointers onaudit:logs:_all+ per-tenant indexes. Mirrors admin'ssweepStaleIndexEntries()so runtime is self-healing regardless of whether admin is colocated.Runtime only writes real-tenant audit rows (never the admin-plane
__admin__/__unauth__sentinels), so a single-tier TTL is sufficient — unlike admin's two-tier setup.No wire change. No API change. Admin's reader is already null-body-tolerant for TTL-expired pointers.
Test plan
AuditRepositoryTest— 7 cases (TTL passed as ARGV[4] = 400×86400, retention=0 passes"0",logId+ timestamp set,log()failure non-fatal, sweeper removes global + per-tenant pointers, sweeper no-op when retention=0, sweep failure non-fatal).redis-cli TTL audit:log:<id>returns a positive integer near34560000(400 × 86400).