Change control
There is no button in Churchill that accepts new hashes. A protected application’s baseline cannot be edited where it stands, not by root on the host and not by an operator in the console. When the binary on disk stops matching the approved baseline outside this flow, that is an enforcement event, never a new normal.
Deliberate change walks one arc: stop the application, make your change while it is held, rescan, let the CAB approve the result, authorize the re-baseline, and watch the host adopt it. The controls live in two places: Stop… and Rescan… on the application’s detail page (see Protected applications), and the review and decision on the CAB page.
The change window schedule
Section titled “The change window schedule”Your organization can set a weekly change window (days and hours, in UTC) during which stopping a protected application is routine. Outside the window, a plain stop is refused. Stopping then requires an emergency declaration, which records your reason on the audit chain and flags the change request for immediate CAB review.
An unconfigured schedule reads as closed. Until a window is set, every stop is an emergency declaration. This is fail-closed by design: the absence of a policy never widens what is allowed. There is no console screen for editing the schedule yet.
Stopping an application
Section titled “Stopping an application”Open the application’s detail page and select Stop… in the Change control rail. It is available only while the lifecycle chip reads running or online.
The dialog states which situation you are in, with a CCB window · in window or CCB window · outside window line. Inside the window it reads: “Stopping holds the application under a change window. Hash-diff enforcement is suspended for this application only, until the change is approved or rejected.” Outside it: “The change window is closed. Stopping now declares an emergency change: the reason is recorded on the audit chain and the change request is flagged for immediate CAB review.” The button then reads Declare emergency & stop instead of Stop application, and an emergency risk badge appears in the dialog header.
Either way you must give a reason for the change (1 to 200 bytes, with no quote or backslash characters) and type the application’s name to confirm. Refusals surface verbatim in the dialog. “change already in progress for this app” means an earlier change window for this application is still open.
A stop applies to the application as a whole and is dispatched to its registered host. Stopping an application on a single host is not available.
The held state
Section titled “The held state”The host performs a controlled service stop, and the lifecycle chip walks running → stopping → change pending. The application is now held. Hash-diff enforcement is suspended for this application only, until the change is approved or rejected. Everything else on the host is still enforced.
While the application is held, its detail page shows a Change window card with your reason, the requester, and the deadline as a ticking countdown. This is when you make the change on the host: install the new binary, update the configuration, whatever the change is.
Rescan and the change request
Section titled “Rescan and the change request”When the change is in place, select Rescan…. It is enabled only while the application is held. The dialog explains itself: “Rescanning re-hashes the held binary and reports the result to the control plane. If it diverges from the approved baseline, a change request is opened for CAB review.” Type the application’s name to confirm.
Two outcomes:
- The binary still matches the baseline. No change request opens and the window stays open. You can keep working and rescan again.
- The binary diverges. A change request opens carrying two hashes: expected (the approved baseline) and proposed (what is on disk now). The lifecycle chip reads awaiting approval, and the Change window card gains the same hash pair.
What the CAB reviews
Section titled “What the CAB reviews”The change request appears on the CAB page like any other, and members cast receipts exactly as described in Approvals and quorum. Each receipt is a passkey assertion over a challenge built for this specific change, so it cannot be replayed onto another. What is specific to a binary change is the detail view:
| Card | What it shows |
|---|---|
| Summary | The requester, their reason, and the risk (an emergency badge or the word “routine”), plus whether the stop was in or out of the window. |
| Lifecycle | A rail tracing pending approval → quorum satisfied → published → deployed. A terminal rejected or expired state appears as a pill beside the rail. |
| Blast radius | The application, its host, systemd unit, and exec path, and the hosts affected. This is always one, since an application has a single registered host. |
| Manifest | The manifest digest and the canonical manifest text. |
| Binary divergence | The expected and proposed hash rows: the exact divergence being approved. |
| Approvals | Each member’s receipt with its verdict, and the quorum bar. |
Authorizing the re-baseline
Section titled “Authorizing the re-baseline”Once quorum is satisfied, the change-request detail gains an Authorize re-baseline card. Type the change id to confirm and select Authorize re-baseline.
Authorizing publishes the change, swaps the application’s approved baseline to the proposed hash, and pushes adoption to the host, which restarts the service on the new baseline. The lifecycle chip shows approved · adopting and flips to online only after the host verifiably reports it is running the new baseline. The console never shows online early. There is no Start button anywhere in this flow: restarts are always the host’s act, following an adopted baseline or an aborted window.
If the world moved underneath the approval, the authorize is refused and the reason surfaces verbatim: “quorum not satisfied”, “manifest diverged since approval”, or “baseline changed since report”.
Rejection and denial
Section titled “Rejection and denial”A single member veto terminates the change request. The stage flips to rejected, no matter how many approvals it had. The detail view then shows a Deny change card, which states plainly: “This change was vetoed. Denying dispatches the rejection; the host enters lockdown.”
Type the change id to confirm and select Deny change. The rejection is dispatched to the host, which enters lockdown with the changed binary in place. See Lockdowns.
The deadline
Section titled “The deadline”A change window lasts four hours from the stop. The deadline is not tunable per stop, and there is no control to extend it. The countdown runs on the Change window card the whole time.
If the deadline passes before the change is resolved, the outcome depends on what is on disk:
- The original binary is back. The window aborts and the host restarts the application on its old baseline. Nothing changed, nothing to approve.
- The binary is still changed. The host enters lockdown.
Tracking adoption
Section titled “Tracking adoption”“Published”, “adopted”, and “deployed” are different facts, and the console keeps them separate. Published means the control plane has issued the new baseline. Adopted means the host has acknowledged, verified, and staged it. Deployed means the host’s first authenticated heartbeat has proven the new baseline is live. The change-request detail’s Adoption card tracks all three.
The card’s corner pill names the directive state:
| Pill | Meaning |
|---|---|
| no directive | Nothing has been issued for this change. |
| awaiting host | Published, but the host has not picked the directive up yet. |
| staged · unconfirmed | The host staged the new baseline but has not heartbeated yet. The deployment is not confirmed live. |
| deployed | The host’s heartbeat carries the new manifest. The card reads “New baseline adopted · application restarted.” |
| stalled | The host acknowledged the bundle but never heartbeated. The control plane stopped re-serving the directive and parked it for an operator. This deployment is NOT live. |
The card’s rows show the published and adoption timestamps (host adoption reads “pending” until the host confirms), a deployment confirmed row that fills in with the first authenticated heartbeat carrying this manifest, and a serves count of how many times the control plane served the directive to the host’s deploy poll.
Two deep links round out the card: View audit chain opens the audit log filtered to this change, and View host evidence opens the host’s evidence stream. See Evidence.
The audit trail
Section titled “The audit trail”The whole arc lands on the audit chain: the stop with its reason and emergency flag, the rescan, every member receipt, and the final authorize or deny. To reconstruct a change afterwards (who asked, who signed, what the hashes were, when the host adopted), start from View audit chain on the change request, or search for the change id in the Audit log.