The build agent

Approvals and what the agent may run

Unattended remediation is restricted by a fixed allowlist and content-specific checks. Anything unrecognised or able to reach wider host state pauses the deployment for a recorded decision.

Updated 4 min read

Approval is determined by application code, not by the model's wording. Every remediation is classified after schema validation. A small set of operations can run unattended when their complete arguments and content remain within the project boundary. A proposal that is explicitly irreversible, touches broader host state, contains an unrecognised command or cannot be parsed safely is classified as destructive. That term describes the execution gate rather than a prediction that damage will occur. The deployment pauses, records the proposal and waits for an authenticated team member to approve or reject it on the run page.

Commands pass an allowlist, not a denylist

Unattended shell proposals are limited to recognised inspection commands, creation of project-local directories or files, selected Docker inspection and lifecycle commands, selected Docker Compose operations, nginx configuration testing, and Nginx reload or status checks. Every chained segment must be recognised. Absolute paths are confined to /opt/deploy-bridge or /tmp, and Docker flags are checked individually. Inline interpreters, command substitution, decoded payloads, nested shells and variable-built paths are held. An operation does not become safe merely because it avoids a list of familiar destructive words; an unknown command is escalated by default.

Docker content receives argument-level checks

The classifier rejects privileged containers, host namespaces, host devices, additional capabilities, Docker socket access and host paths outside the deployment and temporary directories. Compose is parsed as YAML so flow syntax, anchors and merged values do not bypass line-oriented checks. Bind mounts, external file references, additional build contexts and unknown path-shaped values are traversed. Files that cannot be parsed are held rather than guessed safe. Named volumes and container-side paths remain usable, but proposals that remove volumes or invoke pruning are classified destructive. This gate applies to model-authored remediation, while the platform's own fixed deployment commands follow the implemented runner.

Different edit types have different boundaries

A Dockerfile replacement is treated as project-context work and can run unattended. Compose replacement is allowed only when parsed content remains confined. Nginx edits always require approval because the resulting virtual host is written under /etc and reloads a host service; checks additionally identify sensitive filesystem roots and remote proxy targets. Installing distribution packages also requires approval because package maintainer scripts execute on the host. Environment entries can run unattended only with plain variable names, single-line values and no attempt to configure deployment tooling, shell startup, interpreter injection, Git command hooks or remote Docker behaviour.

A pending proposal parks the run

For destructive classification, Deploy Bridge writes an awaiting-approval action, changes the deployment status and sets Waiting for approval as the current step. The run page shows the diagnosis, proposed fix and detail lines with Approve Fix and Reject Fix controls. The runner polls the recorded decision. It does not continue to later deployment steps while the proposal is unresolved. Approval changes the action state before application; rejection stops recovery and leaves the deployment failed. If cancellation and approval arrive together, cancellation is checked again immediately before the action touches the server and takes precedence.

Approvals expire and interrupted runs close

An approval wait lasts 30 minutes. If nobody decides within that period, the action is abandoned, the held plan attempt is released and the deployment fails with a timeout explanation. Cancelling while waiting abandons the action and releases the pause. A deployment runner is backed by an in-memory SSH session, so it does not resume through an API-server restart. Startup reconciliation marks running or awaiting-approval deployments as failed, marks unresolved actions abandoned and records that the server restarted. A stale approval button therefore cannot revive a runner that no longer exists.

Read approval as authorisation, not validation

Approving means the displayed proposal is authorised to run; it does not establish that the diagnosis is correct or that data is recoverable. Package installation, Nginx replacement and unfamiliar shell commands can have consequences beyond the application. Before approving, compare the diagnosis with the failing step and terminal output, inspect every shown command or replacement intent, and consider server-local state not visible to the model. Reject where the change is broader than the failure warrants. Rejection is a supported terminal decision and does not consume the held monthly fix attempt, though the deployment itself remains failed.

Every proposal keeps an outcome

The action record retains its deployment step, attempt number, diagnosis, action kind, summary, risk, provider and model. Its payload records relevant package names, environment keys with credential-like values hidden, command, engine, confidence and replacement-content length. Decisions and resulting states remain attached to the deployment. After execution, the action is marked applied or failed, and the retry outcome is recorded when available. This history supports review of what changed and why, but it does not capture an independent snapshot of the whole server. Host-level audit and configuration management remain separate controls.

FAQ

Common questions

Who can approve an agent proposal?

The implemented decision route requires an authenticated member of the team that owns the deployment. The current route does not add an administrator-role requirement.

How long does an approval request remain open?

The runner waits for 30 minutes. An unanswered action is then abandoned, its held fix attempt is released and the deployment fails.

Why does a harmless-looking command require approval?

Anything outside the fixed command and argument allowlist is classified conservatively. Approval is required when the system cannot prove that the complete operation remains within the deployment boundary.

Deploying something unusual?

If your stack does not fit what is documented here, describe it. The platform handles more than the defaults, and where it does not, we would like to know.