Wheelhouse docs

Pending changes#

No editor in Wheelhouse changes the router. An editor's Save, Add or Delete button adds the change to the pending changes, a list held by the agent, and the editor is finished: nothing has reached the router. The list is applied as one unit from the Commit Bar, which appears at the bottom of the page while anything is pending. Until then it can be reviewed, trimmed one change at a time, or discarded.

Where the pending changes are kept#

The router's own API applies whatever it is sent at once; it has no list of changes that wait. The pending changes are Wheelhouse's. The agent holds the list and, when somebody presses Apply changes, sends the whole of it to the router in one request, which the router applies as one change.

One applied change is what can be reviewed as a whole, refused as a unit, applied with auto-revert, and undone by restoring one revision.

Shared by every session#

There is one list of pending changes per agent, and everything that adds to it adds to the same list:

  • every browser session signed in to that router;
  • the reconcile loop, which adds its changes here unless it was started to apply them itself;
  • wheelhouse-agent apply --agent-url … from a script or a scheduled job.

The browser takes up whatever the agent already holds when a page loads, and reads it again whenever the tab comes back into view. Two people preparing changes on one router see each other's changes in the bar.

The list is kept in memory, not on disk, so restarting the agent empties it. Nothing on the router is lost by that, because nothing had been applied, but the prepared work is gone. For that reason Restart agent on Admin → Agent settings is refused while there are pending changes: Apply or discard the pending changes first.

How the list reads#

Review changes on the Commit Bar lists the pending changes as sentences, grouped by area, one line for each thing changed:

  • Add VLAN 20 on eth1 — Address 10.20.0.1/24, description “IoT”
  • Change the host name to edge-1
  • Remove certificate “old-web”

Each line has a Remove button that takes everything that line covers back out of the list. The sentences never contain a password, a key or an SNMP community, whatever the reader's role. With Advanced mode on, the same list shows the configuration operations themselves; see Advanced mode and the router's commands.

What the agent accepts#

Every pending change is made of two kinds of operation: one that adds or changes a setting, and one that removes a setting. Anything else is refused rather than carried, because the Commit Bar could not show it truthfully:

  • An operation of another kind, one with no setting named, or one naming an empty element is refused with the position of the offending operation.
  • An operation already in the list is not added a second time, so pressing Save twice, or the reconcile loop passing while somebody clicks, does not queue the same change twice.
  • The list holds at most 10,000 operations. A request that would take it past that is refused whole, rather than half added.

Editors check what they know before they add anything: a field that needs an address says Enter an IPv4 address, such as 192.0.2.10. under it, and the Save button waits until the form is complete. The router has the final word when the changes are applied.

Adding to the pending changes needs the operator role and a usable licence. An approver can apply changes others prepared, but cannot add, remove or discard them.

What pending changes do not do#

  • They are not checked against the router until they are applied. The router decides then, and a refusal leaves the list as it was so the change can be corrected.
  • They are not reordered. Operations are applied in the order they were added.
  • They do not lock the configuration. Somebody applying a change from an SSH session while your changes wait alters the configuration your changes will land on.

For automation#

An API client uses the same list:

bash
R=https://<router>:8443
T=wh_...                                  # an API token with the operator role

curl -sk -X POST "$R/api/stage" -H "Authorization: Bearer $T" \
  -d '[{"op":"set","path":["interfaces","ethernet","eth1","description","primary uplink"]},
       {"op":"set","path":["interfaces","ethernet","eth1","address","203.0.113.2/24"]}]'
json
{"staged": 2,
 "ops": [{"op":"set","path":["interfaces","ethernet","eth1","description","primary uplink"]},
         {"op":"set","path":["interfaces","ethernet","eth1","address","203.0.113.2/24"]}],
 "commands": ["set interfaces ethernet eth1 description 'primary uplink'",
              "set interfaces ethernet eth1 address 203.0.113.2/24"]}

Read it back at any time, from any session, remove the second operation, and apply the rest with auto-revert:

bash
curl -sk -H "Authorization: Bearer $T" "$R/api/staged"
curl -sk -X POST "$R/api/stage/remove" -H "Authorization: Bearer $T" -d '{"index":1}'
curl -sk -X POST "$R/api/commit" -H "Authorization: Bearer $T" -d '{"confirm_minutes":2}'

Every answer carries the structured ops beside the rendered commands, so a client never has to parse a command back into a path. That cannot be done safely: a value containing a space does not survive a join-then-split round trip.

See also#

Updated 2026-09-18 concepts staging commit