Campaign-Action Audit-Trail Integrity Automation: A Security History That Recorded Nothing About Real Money

A blank security history and a healthy one look identical from the screen showing them
A Security or Activity screen that shows an empty or sparse history doesn't announce whether that's because very little actually happened, or because the mechanism recording what happened has been silently failing the entire time. Both states render the exact same way — a short list, or none at all — and there is no visual signal on the screen itself distinguishing "nothing significant occurred" from "everything that occurred failed to be recorded." Confirming which one is true requires checking, directly and specifically, whether a KNOWN real event that should be present in the history actually is.
How the underlying problem shows up before you fix it
An audit or activity table's actual column structure has changed or was always different from what several separate pieces of code assume when writing to it — each writer sends field names that don't match the real columns.
A database insert that references a column the target table doesn't have is rejected, but the specific rejection is never surfaced anywhere a person would see it.
Error-handling code around a write operation is structured to silently discard both the success and the failure outcome of that operation — a pattern indistinguishable, from the outside, from a system that genuinely doesn't need to react to failure.
More than one independent piece of code writes to what should be the same logical record, but they disagree — one group targets the wrong table entirely, sharing it with many unrelated parts of the platform, using a column name that table stopped having some time ago.
A screen built specifically to show a security or activity history has never been directly tested against a KNOWN, deliberately triggered real event to confirm that event actually appears.
Why five independent, correctly-intentioned writers can all fail the same way
Multiple pieces of code writing to the same logical audit table, built at different times, naturally drift from the table's actual current structure if nothing enforces agreement between them — each writer is reasonably confident it knows the right column names, and nothing in a normal successful request path ever forces that assumption to be checked against reality. A database's own behavior compounds the problem: rejecting an insert that references a nonexistent column is a normal, correct response, but if the calling code's error handling doesn't specifically inspect and act on that rejection, the failure disappears as completely as if the write had never been attempted — leaving behind an audit table that looks merely quiet, not visibly broken.
How Centriu Maestro found and closed a completely silent, months-long gap
This gap was found and fixed as part of the same production security review that closed Maestro's OAuth token exposure (covered on this pillar's companion page) — the review didn't stop at credentials; it also directly measured whether the Security screen's own displayed history reflected reality. It didn't. Two specific, quoted database queries settled the question: counting rows in the platform-wide shared audit table for the exact actions ("platform connected," "campaign updated") that real Maestro usage should have produced returned zero, and listing every distinct action value actually present in Maestro's own dedicated audit table returned only login events and one unrelated system's events — nothing whatsoever about connecting a platform, pausing a campaign, changing a budget, or publishing an ad.
The root cause split into two independent failures. Five separate edge functions — covering the ad-account hierarchy, the ad-management actions, suggestion application, campaign control, and token refresh — were all writing audit events using a flat set of column names (a user identifier, an action name, a severity level, a details field, a timestamp) that simply didn't match the audit table's real, current shape: an identifier, a tenant identifier, and a single structured JSON field holding everything else. Every one of those inserts was rejected by the database as invalid — and three of the five functions were specifically built with a promise-handling pattern that reacts identically whether the write succeeds or fails, discarding the outcome either way. A sixth function, handling the OAuth connection callback, wrote to an entirely different table — the platform's own general-purpose audit table, shared across roughly thirty unrelated parts of the product — using a column name that table had stopped having some time before, after an earlier, unrelated schema change elsewhere in the platform.
The fix consolidates every one of these six call sites onto a single, shared write function that constructs its insert using the audit table's actual, current column structure — matched precisely to what the Security screen's own reading code expects, so a write that succeeds is guaranteed to actually display correctly. That function deliberately never allows a write failure to interrupt the real operation that triggered it — a failed audit write must never block someone from actually pausing a campaign or disconnecting a platform, since the operation people came to perform matters more than the record of having performed it. But it changes the failure's visibility completely: where the old code discarded the outcome entirely, the new function specifically logs any failure to the system's own error output — the exact silence that had let the entire audit trail sit empty for an unmeasured stretch of time is what the fix directly targets, not merely the six broken inserts themselves.
A further, deliberate detail: the shared function includes its own dedicated redaction step, checking every field name inside an event's structured details — at any nesting depth — against a list of terms associated with secrets (tokens, passwords, credentials, authorization headers, and similar), replacing the value with an explicit placeholder wherever a match is found, by name rather than by trusting whichever code is calling it to have already excluded anything sensitive. The reasoning recorded directly alongside that redaction step is worth stating plainly: an audit trail exists specifically for the moments something goes wrong upstream of it, which makes it the wrong place to assume every caller will always get it right — a centralized, name-based safety net catches what any individual caller might miss.
What is actually built today
A single, shared audit-write function used by all six of the previously affected edge functions, constructing its insert to match the audit table's real, current column structure exactly.
A write path that never allows an audit failure to block or interrupt the real operation that triggered it — pausing a campaign always succeeds or fails on its own merits, independent of whether the accompanying record was written.
Genuine, visible logging of any audit-write failure to the system's own error output, replacing error-handling code that previously discarded both success and failure outcomes identically.
A dedicated redaction step scanning every field name inside an event's structured details, at any nesting depth, against a list of secret-associated terms — applied centrally, rather than trusted to each individual caller.
Every one of the six previously affected call sites — spanning ad-account hierarchy, ad management, suggestion application, campaign control, token refresh, and the OAuth connection callback — now writing through the same verified path.
Confirmed today via direct inspection: this shared function remains the only write path into the audit table across all six call sites.
A paused campaign that finally leaves a record (illustrative scenario, not a real client)
Someone pauses a real, active ad campaign through Maestro's campaign-control screen. Before the fix, that action would succeed exactly as expected from the campaign's own perspective — but the Security screen's history would show nothing about it, because the accompanying audit write had been silently rejected by the database. After the fix, the same pause action succeeds identically, and the Security screen's history now genuinely reflects that it happened, with the record's details already checked for anything resembling a secret before being stored.
What changes operationally
A person reviewing Maestro's Security screen to understand what happened to a client's advertising accounts — who connected a platform, who paused a campaign, who changed a budget — is now looking at a record that genuinely reflects those events, rather than a history that had been silently empty for real, money-moving actions since the six affected functions were first written. And because any future write failure is now visibly logged rather than discarded, a similar gap opening again would be far more likely to be noticed.
When this is not the right fit
This fix restores and verifies the integrity of Maestro's own audit-trail writes for the six specific call sites it covers — it does not retroactively reconstruct any historical events that went unrecorded before the fix, since that data was never written anywhere to begin with. A team specifically needing a complete historical record predating this fix will not find one; what this guarantees is that events from this point forward are genuinely captured.
A quiet audit table vs. a verified one
An audit table that displays only a handful of unrelated events can look, at a glance, like a system that simply hasn't had much happen — nothing about a sparse or empty history visually distinguishes it from one where the writing mechanism has been silently broken the entire time. Centriu Maestro's fix was confirmed the only way that actually settles the question: by directly querying for a known category of real event the audit trail should contain, and finding it genuinely absent, before treating a mismatched column name as the true root cause rather than assuming the low activity was simply real.
Related systems
Main system: Centriu Maestro.
What it does NOT do
- Does not allow an audit-write failure to block or interrupt the real operation that triggered it — pausing a campaign, disconnecting a platform, or any other real action always proceeds independent of the audit write's own outcome.
- Does not discard the outcome of an audit write silently — any failure is now genuinely logged to the system's own error output, rather than handled identically to a success.
- Does not trust each individual calling function to have already excluded sensitive values from an event's details — a shared, name-based redaction step checks every field at any nesting depth before the record is written.
- Does not write to the platform-wide shared audit table for Maestro-specific events — the OAuth connection callback, previously misdirected there, now writes to Maestro's own dedicated audit table like every other call site.
- Does not reconstruct or backfill any historical event that went unrecorded before this fix — data that was never successfully written cannot be recovered retroactively.
- Does not use more than one write path into the audit table across the six affected functions — all six now share exactly one verified function.
Security and governance
Every audit event written through the shared function has its structured details checked, by field name, for anything resembling a secret before being stored, and no audit-write failure can block the real operation it accompanies. Any personal or business data referenced in a recorded event remains subject to Brazil's LGPD (Law No. 13,709/2018). Full detail on access control lives at /governanca and /iso.
Pricing and contracting
Available by monthly subscription, with tiered plans. Values and terms come from the official pricing table at /precos (Centriu's central source — never restated here).
Frequently asked questions
How was it confirmed that the audit trail was genuinely empty, and not just quiet?
By directly querying the database for a specific, known category of real event — counting rows for actions like "platform connected" and "campaign updated" — and finding zero, rather than assuming a sparse-looking history reflected genuinely low activity.
Why did the audit writes fail without anyone noticing?
Five functions sent column names that didn't match the table's real structure, so the database rejected every insert — and three of those five had error handling that discarded both success and failure outcomes identically, so the rejection was never surfaced anywhere.
What was different about the sixth affected function?
It wrote to an entirely different, shared table used across roughly thirty unrelated parts of the platform, using a column name that table had stopped having after an earlier, unrelated schema change.
Can a failed audit write ever block a real action, like pausing a campaign?
No — the shared write function deliberately never lets an audit failure interrupt the real operation that triggered it; the two are handled independently by design.
Does the fix protect against a caller accidentally logging a secret in an audit event?
Yes — a dedicated redaction step scans every field name inside an event's details, at any nesting depth, against a list of secret-associated terms, applied centrally rather than trusted to each caller.
What does Centriu Maestro cost?
It is sold by subscription with a published starting price — exact current values are on the central pricing page.
See how Centriu Maestro keeps a genuine record of what happened to ad accounts
Reach our commercial team directly, or leave your details below — we'll follow up with guidance for your case.