BuildGate

For administrators

The exception queue

Bubble’s own version history is reconciled against BuildGate’s records, and anything unaccounted for becomes a dated finding somebody has to close. This is the layer that makes the control defensible.

What reconciliation does

On a schedule, BuildGate reads Bubble's own version history and compares it with what it recorded. A deploy that skipped the gate does not become silence — it becomes a finding with a name, a date and a queue entry.

This is the detective layer, and it is the strongest thing in the product. A browser extension can be disabled; a reconciliation that notices it was is what turns "we have a control" into something an auditor can test.

An unreviewed exception queue is worse evidence than no queue at all. It shows a control that detects and an organization that does not respond. Put a review cadence on this screen and keep to it.

What the findings mean

The name says what happened, because the remediation is different for each:

FindingWhat it means
unlogged_deployA deploy appears in Bubble's history with no matching request. Somebody went around a gate that exists
unapproved_deployA request existed but was never approved, or was rejected
bypass_usedA break-glass code was used. The stated reason is on the finding, and whether the code was recognised
gate_not_enforcingBubble's live deploy timestamp advanced with nothing to account for it. This says the gate itself has stopped working — most likely Bubble renamed an endpoint — rather than that one person went around it
unlogged_restoreA restore appears in Bubble's change log. Restores are not gated, so every one of these is unaccounted for by construction. Only raised for apps where restore observation is switched on
observation_failedBubble's history could not be read at all. Recorded so that "we cannot see" is never reported as "nothing happened"
deployed_content_mismatchWhat shipped is not what was reviewed: the change moved on between the approval and the deploy. There was an approval and the gate did work — what is in question is whether it was an approval of this

The four that mean the control has stopped working — gate_not_enforcing, unlogged_deploy, unapproved_deploy and bypass_used — are sent to owners and admins as they are raised, and a daily digest covers whatever is still open. Both need a notification channel: with neither Slack nor email configured the queue is still there, but nobody is told about it.

Reviewing and closing one

Clicking a finding opens it: its history, the change in Bubble that provoked it, the deploy request it belongs to where there is one, and a box to write in. Reviewers can comment while they work it, and closing one appends the note and the closer to the chain.

Resolving deletes nothing. The finding, the note and the name stay, and the resolution is appended to the record — you are not clearing a row, you are writing down what you checked. Neither a comment nor a resolution can be edited afterwards, which is what makes "we looked into this and here is why it was fine" worth reading a year later.

Approvers can also work this queue from their own tooling over MCP, with a separate pair of scopes from the approval ones: an agent allowed to see what is pending has not thereby been allowed to read, or close, the record of every time the gate was evaded.

A note on restores

BuildGate cannot stop a restore. The endpoint that performs one is undocumented and unknown to this system, so restore observation is exactly that — observation — and every observed restore is a finding by construction.

It is off by default, because turning it on for an app that is restored routinely fills the queue with findings nobody asked for. The consequence is worth stating plainly: with it off, an empty queue says nothing about restores. The Evidence screen's gate health card names the apps that are in that position, so the gap is visible rather than assumed.