Wheelhouse docs

The Commit Bar#

The Commit Bar sits along the bottom of every page. It shows how many operations are in the working set, renders them as a diff on demand, and offers three actions: Commit, Commit-confirm, and Discard. It is the only component in the product that calls POST /api/commit. Every editor stages and stops; the Commit Bar is where a change stops being a proposal.

What it shows without being asked#

  • A dot, and a count: No staged changes, or 3 staged.
  • The most recently staged command, with (+2 more) after it when there are others.
  • Any error from the last staging or commit attempt, as a button that dismisses it.

Pressing Diff opens the working diff: every staged operation on its own line, + for a set and for a delete, each with an × that un-stages that one operation, followed by a block headed Copy into a configure session holding the whole set as text. That block is the same rendering the agent produces for GET /api/staged — see Every click shows its commands.

How it decides a change is dangerous#

"Dangerous" here means one thing: committing this could take away your own access to the router. The test is a list of path patterns in ui/src/lib/format.ts (isDangerousPath), applied to each staged path after joining it with spaces.

PatternWhy it is on the list
firewall …A rule that drops your session drops your session.
nat …Address translation decides whether the reply reaches you.
service ssh, service https, service http-apiThe management services themselves, including the one the agent talks to.
interfaces <kind> eth1 …The interface treated as the uplink.
protocols static route 0.0.0.0/0 …The default route.
protocols failover …, load-balancing …, policy route …, protocols static table …Every multi-WAN mechanism decides which way packets leave, including yours.
high-availability …Virtual addresses move.
pki …The certificate the management interface serves can vanish.
system login …An account change can lock you out.
anything containing addressAn address change, anywhere in the tree.
anything containing dhcp-options or default-route-distanceBoth can change the default route from underneath you.

When the set is flagged, three things change: the dot turns amber, the diff header says touches firewall / NAT / addressing — commit-confirm recommended, each matching line is coloured, and the plain Commit button is styled as a destructive action rather than a primary one (ui/src/components/CommitBar.tsx). Nothing is disabled or hidden. The bar makes the safe path the obvious one and leaves the decision with you.

What the two commit buttons do#

Commit-confirm (2m) posts {"confirm_minutes": 2}. The number comes from agent settings (commit_confirm_minutes, default 2 — agent/store.go, defaultSettings). Only an admin can read that setting, so a viewer's or operator's bar shows the default rather than being blocked by a 403 (ui/src/lib/staging.tsx). What happens next is on Commit-confirm.

Commit posts no window. The change is permanent as soon as the router accepts it.

Both take the same road through the agent (agent/main.go, handleCommit):

  1. Refuse with 400 if the working set is empty — including the case where it was emptied by another session a moment ago.
  2. Send the whole set to the router as one array, through /configure, with confirm_time when a window was asked for.
  3. On failure, record an audit entry with success: false and the router's own message, answer 502, and leave the working set intact so you can fix the operation and try again.
  4. On success, record the audit entry, clear the working set, and answer with the number of operations actually sent.

That last number is counted from the payload that went to the router, not from a second read of the queue — a concurrent stage between the two used to make it lie.

What it will not do#

  • It will not commit for you. No page, no editor, no background task in the UI calls commit. The reconcile loop can, but only when it has been deliberately started in commit mode — see Desired state.
  • It will not partially commit. The set goes to the router as one array, so either every operation applies or none does.
  • It will not hide a rejection. A commit the router refuses comes back as the router's own words, prefixed only to say whose words they are (agent/vyos.go, routerError).
  • It will not offer its buttons to a viewer. A principal without the operator role sees Your role cannot commit changes in their place, and the agent refuses the route regardless — see Read plane, write plane, admin plane.

See also#

Checked against#

ui/src/components/CommitBar.tsx · ui/src/lib/format.ts · ui/src/lib/staging.tsx · agent/main.go · agent/store.go · agent/vyos.go · docs/ui.md

Updated 2026-09-02 concepts commit safety