Appearance
ADR 0002 — Append-only enforcement of agent_audit_log at the DB layer
Status
Accepted — 2026-04-17.
Context
The agent_audit_log collection records every auth event, admin action, and data change that touches agent or member records starting in Phase 5. HIPAA §164.312(b) requires audit controls that record and examine activity on systems containing ePHI. CMS EDE Audit Program Appendix A § 9 requires access-control logging with a retention window. SOC 2 CC7.2 asks the entity to detect anomalies — which only works if the log cannot be tampered with after the fact.
The naive implementation would grant the agent portal's Mongo user readWrite on agent_audit_log and rely on application code to never call updateOne or deleteOne against it. That leaves two failure modes:
- A future code path (or a LLM-written migration) silently mutates the log.
- A compromised app-layer credential lets an attacker rewrite their own trail.
Both defeat the audit function.
Decision
Mutability of agent_audit_log is blocked at the database permission layer, not in application code. The Mongo roles that write to the collection (role_writer_agents, role_admin_agents) hold only FIND and INSERT privileges on it — no UPDATE, no REMOVE. Reads for compliance use role_audit_reader which has FIND only.
No Mongo user issued to the application can mutate or delete from the audit log. The only way to tamper is to escalate to an Atlas-admin credential, which is not held by any app-tier user and is not stored in any env file.
Consequences
Positive:
- Tamper-resistance is a property of the schema permission model, independent of application code correctness.
- Reviewers (SOC 2, HIPAA, EDE) can verify the property by reading the Atlas role JSON, not by reading every app route.
- Bugs in application code cannot accidentally corrupt the log.
Accepted costs:
- Probe rows written during verification cannot be cleaned up without revoking the append-only guarantee. We leave them; they age out with the collection's retention window (target 6-10 years, to be enforced via TTL index in Phase 5).
- Schema evolution of the log (e.g. adding a new field to historic records) requires an Atlas-admin credential, which is an intentional break-glass operation.
Alternatives considered
- App-layer enforcement only — rejected; see Context.
- Write the audit trail to an external immutable store (CloudWatch, S3 Object Lock, Atlas App Services) — viable and complementary, not a replacement. Will be revisited when the AWS migration completes; at that point we may mirror
agent_audit_loginserts into CloudWatch Logs with a retention lock for defense in depth. This ADR does not preclude that.
References
- Issue #56 — MongoDB permissioned users setup
- ADR 0003 — Narrow-scoped MongoDB users per Issue #56
- HIPAA 45 CFR §164.312(b) — Audit controls
- CMS EDE Audit Program Appendix A § 9 — Access Control Logging
- SOC 2 TSC 2017 — CC7.2