Repository navigation
The audit log is an in-memory rolling buffer — entries are lost on restart and silently evicted under load #224
Description
Priority: Medium · Area: Audit logging / durability · Est. effort: 7–10 h
📌 Problem
src/middleware/auditLog.ts describes itself as a "rolling buffer, so operators can see recent write activity", implemented as an in-process array:
history.push(redactSensitiveData(entry)); // auditLog.ts:103Exposed at GET /api/v1/audit per src/openapi.ts:35.
As a debugging aid this is reasonable. As an audit log it has two disqualifying properties:
- No durability. A restart destroys the record of every write the service performed. There is no other copy.
- Silent eviction. A rolling buffer drops the oldest entries once full. Under sustained write activity — exactly when an audit trail matters most — the earliest evidence is discarded first, with no signal that it happened.
The redaction step (redactSensitiveData) shows the entries are considered sensitive enough to filter, which reinforces that they are meant to be a real record.
🎯 Design decision required
State and defend:
- What this is. Decide whether it is an operator convenience or a genuine audit trail, and make the code and docs say so unambiguously. If it stays a convenience buffer,
GET /api/v1/auditand its documentation must stop implying completeness. Either answer is acceptable; ambiguity is not. - Durability, if it is an audit trail. Structured stdout for external collection, or the database (tracked separately — the service currently has no persistence)? Structured logging is cheap and needs no schema; a table gives queryability. Argue one.
- Eviction visibility. However it ends up, dropping an entry must be observable — a counter, a warning, or a gap marker — not silent.
🧩 Requirements and context
redactSensitiveDatamust apply to any new sink. Verify what it actually redacts and report whether the coverage is adequate — anything reaching a durable sink is far harder to retract than something in a ring buffer.- The
GET /api/v1/auditresponse shape should stay stable unless you argue otherwise. - Tests must run with no external dependency.
- Do not silently increase the buffer size and call it fixed.
src/middleware/auditLog.test.tsexists — extend it.
🛠️ Suggested execution
- Read
redactSensitiveDataand report its actual coverage. - Write a test proving entries are lost on eviction and that nothing reports it.
- Implement your decision.
- Add a test for eviction/overflow visibility.
- Update
src/openapi.tsif the endpoint's guarantees change.
✅ Acceptance criteria
- The PR states whether this is a convenience buffer or an audit trail, and the code and docs agree.
- A test proves the current silent-eviction behaviour.
- Eviction or overflow is observable after the change, with a test.
-
redactSensitiveDatacoverage is reported, with any gap called out. - If it became durable, the sink is documented for operators.
-
GET /api/v1/auditdocumentation matches actual guarantees. -
npm run lint,npm run buildandnpm testpass.
🚫 Out of scope
- Building a log-shipping pipeline.
- The persistence layer — separate issue, though you may build on it.
- Adding new audited events.
🧪 Verification
npm ci
npm test src/auditLog.test.ts src/middleware/auditLog.test.ts
npm run lint && npm run build && npm test📤 What your PR must include
- What
redactSensitiveDataactually covers, and any gap. - Your convenience-vs-audit-trail decision.
- Your durability choice and its reasoning.
- The eviction-visibility test.
Closes #<n>.
🔒 Security notes
An audit log that silently discards its oldest entries under load fails exactly when it is needed: sustained anomalous write activity is both the thing worth investigating and the thing that evicts the evidence of how it started. If the log becomes durable, redaction becomes materially more important — a sensitive value in a ring buffer disappears on its own, whereas one written to a durable sink persists and propagates.
📋 Guidelines
- Minimum 95% test coverage on changed lines
- Clear documentation
- Timeframe: 96 hours from assignment
- One logical change per commit; no merge commits
💬 Join our community
Working on this, or want to sanity-check your approach before you start? Come and ask — the maintainers are there and happy to help.
Telegram: https://t.me/Grainlify
Activity
Jagadeeshftw commentedon Aug 21, 2026
Assignment update — durable audit logging
Welcome, @martinshub-tech, and good luck with the audit-log persistence issue. Start by reading the complete issue description and trace its restart-loss and bounded-buffer requirements through the current service design. Your PR needs to address every stated acceptance criterion, include robust tests for persistence and eviction behavior, and present a clean, reviewable solution with no hidden data-loss path.
Please submit a PR within 48 hours of this assignment. If no PR is opened within that period, the issue may be unassigned to make room for another contributor. Please join our Telegram group for coordination: https://t.me/+u5qmu35nZ7I0OTU1
grantfox-oss commentedon Aug 21, 2026
🦊 GrantFox — @martinshub-tech has been assigned to this issue as part of the Third Campaign campaign!
Next steps:
Closes #224)Good luck! Track your progress on GrantFox.
grantfox-oss commentedon Aug 29, 2026
🎉 This issue has been marked as completed on GrantFox as part of the Third Campaign campaign!
@martinshub-tech's PR #233 was approved and merged by @Jagadeeshftw.
🏆 @martinshub-tech: You earned 40 FoxPoints for this contribution! Your current tier: Builder (2,343 total points). Track your full progress on GrantFox.
👏 Great work, @martinshub-tech! Keep contributing to AnchorNet-Org.