Skip to main content
Back to blog

ZopNight's Audit Trail Logs Assistant Reads for Compliance

Riya Mittal
Riya Mittal Engineer · Zop.Dev
6 min read
ZopNight's Audit Trail Logs Assistant Reads for Compliance

ZopNight’s Audit Trail Logs Assistant Reads for Compliance

An AI assistant connected to your infrastructure through MCP reads far more than it writes. It checks a resource’s state, looks up a cost figure, or lists a team’s permissions many times over for every change it actually proposes. An audit log that records only mutations captures the rare write and misses the entire investigation that led up to it, which means most of what the assistant actually did was invisible to anyone running a compliance review.

ZopNight’s audit trail now logs those reads too. Every lookup an AI assistant makes over MCP shows up as a clearly labeled “Read…” entry, next to the actions that changed something.

Reads Show Up as Labeled Entries, With a Filter to Manage the Noise

A read entry and a mutation entry now sit in the same log, but they’re not treated as the same kind of event. A new source filter lets you narrow the view to all sources, MCP activity specifically, or platform activity specifically. That keeps a read-heavy assistant session from burying the mutations you actually care about reviewing. Identical repeated lookups collapse into a single line instead of repeating the same entry dozens of times, which is exactly the pattern an assistant produces when it re-checks the same resource across several steps of one task.

Entry typeWhat it representsHow it’s grouped
MutationAn action that changed somethingShown individually, as before
Read (new)A lookup that changed nothingLabeled “Read…”, repeated identical lookups collapsed into one line

The release notes say this plainly: with reads now included, the log gets busier. That’s the honest tradeoff of visibility. A quieter log that only shows mutations is easier to skim and tells you less; a busier one that shows reads too is harder to skim at a glance and tells you what actually happened.

Every tools/call Is Logged Now, Not Just the Mutating Ones

The mechanism behind this is a change to what the audit gate considers loggable. It used to log mutating tool calls only. It now logs every tools/call, with reads stamped method=GET so they’re distinguishable from mutations in the same table. There’s no sampling and no allowlist deciding which reads make it into the log: every one does.

Architecture diagram

That’s a meaningfully different guarantee than “we log the reads we think matter.” A sampled or allowlisted approach would require deciding in advance which lookups are worth keeping. Any assistant behavior nobody anticipated when writing that allowlist would fall outside it silently. Logging everything sidesteps that guessing game entirely.

What Gets Stored, and What Deliberately Doesn’t

A read row never stores the response body, only the request. That’s a deliberate boundary: the audit log records that a lookup happened and what was asked for, not a full copy of whatever data came back. A new ErrorMessage field preserves the failure detail for a read that errored out, without needing to persist the response payload to explain what went wrong.

Supporting that volume of new rows without slowing down the log itself needed a new index. It was added on audit_logs(source, created_at, tool), specifically for the rollup queries this feature depends on. The existing audit-failure counters were adjusted at the same time to exclude the new read rows, so a spike in read volume doesn’t get mistaken for a spike in failures on a dashboard that was built before reads existed in this table at all.

The Security Fix Hiding Inside a Visibility Feature

One more change shipped folded into this release, and it’s worth separating out because it’s not really a visibility improvement, it’s a gap closing. An MCP tool call that didn’t map to a known tool, or carried no org_id, used to get shadow-forwarded anyway and logged as if it were a harmless read. That’s a quiet way for an unclassified call to slip through: it gets treated as safe by default rather than rejected for being something the system couldn’t identify.

That path is now rejected outright instead of forwarded. The two changes in this release are connected more tightly than they look. Logging every read only tells you the truth if every call actually gets classified as a read or a mutation in the first place; a call the system can’t identify was never a “harmless read” to log, it was a gap in classification that happened to log something reassuring. Closing that gap and turning on read-logging are one fix looked at from two angles, not two separate improvements that happened to ship together.

Tagged
Riya Mittal

Riya Mittal

Engineer · Zop.Dev

Riya is an AI engineer at ZopDev, working on production LLM pipelines behind the company's content and account-intelligence platforms. She works on the engineering that makes these systems reliable and repeatable, from multi-provider orchestration and structured output validation to evals, idempotent pipelines, and automated recovery. She writes about what it takes to make AI systems reliable enough to run in production.

Stop watching the waste.
Start cutting it.

See. Find. Fix. Automatic.

Connect your first cloud account in under 5 minutes. See your first remediation in under 7. No credit card required.

CDCR connect detect classify remediate
full audit every action traceable
read-only default access
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·