Rebuild a Bot's computer when it holds a token the deployment no longer uses - #502
Merged
Conversation
…er uses A computer checks callers against the COMPUTER_TOKEN it was created with and keeps that one for the life of the container. The shell mints the generated secrets once per deployment and does not rotate them, because a computer outliving a restart is exactly what rotating would strand, so normally there is nothing to reconcile. Setting a machine up from nothing is where the token does change. The credential store is emptied, a new one is minted, compose rebuilds what it owns, and the computers are the one thing compose does not own: they survive holding the old token and refuse everything. What that looks like is the reason this is a defect rather than an inconvenience. The gateway allows the action, the trail records it as carried out, the computer answers 401, and the screen says Not authorised while naming no token and no container. Measured on a first run of v0.0.9 against a computer made by the install before it, five days earlier. Replaced the way a stale image already is, keeping the profile and workspace volumes, so the Bot comes back with its logins and its files. A deployment that sets no token is left alone: a computer with no door on it is a choice the environment made. Two cases in the Docker lifecycle fixture, against a real daemon. Checked by disabling the comparison: the replacement case then reuses the old container and fails.
davidmckayv
requested review from
MikeRyanDev,
guidovizoso,
mxmzb and
tylerslaton
as code owners
September 12, 2026 17:44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found by doing the thing nobody had done: a from-zero install of the desktop app on a Mac,
against the published v0.0.9, with the credential store emptied first.
Every page the Bot tried to open failed, and so did the live screen. What the trail said:
{ "bot": "picked-harness", "page": "https://news.ycombinator.com/", "action": "computer_navigate", "failure": "Not authorised.", "decision": { "mode": "enforce", "rule": "true", "source": "allow", "allowed": true, "carriedOut": true } }The gateway allowed it. The computer refused it. Nothing on screen named a cause.
Why. A computer checks callers against the
COMPUTER_TOKENit was created with and holds thatone for the life of the container. The shell mints the generated secrets once per deployment and
deliberately does not rotate them, because a computer outliving a restart is what rotating would
strand. But a machine set up again from nothing does mint a new token: compose rebuilds everything
it owns with it, and the computers are the one thing compose does not own, because the supervisor
makes them. On this machine the surviving containers were from installs five days and one hour
earlier, still holding their own tokens:
The fix.
ensurealready replaces a computer built from an older image, for the same class ofreason: the supervisor makes these, so nothing else reaches them. It now also replaces one whose
token is not the one being handed out. The profile and workspace volumes are kept, so the Bot comes
back with its logins and its files, exactly as on the image path. A deployment that sets no token is
left alone, because a computer with no door on it is a choice the environment made rather than a
mismatch to act on.
Tests. Two cases in the Docker lifecycle fixture, against a real daemon: replaced when the token
has changed, left alone when it has not, including when the new environment names no token at all.
The fixture's case count and the assertion guarding it go from five to seven. Checked by disabling
the comparison, at which point the replacement case reuses the old container and fails.