Bug Fixes
-
A wedged USB hub no longer takes every later USB command down with it. A
hub operation that hung — native hub-driver code blocking forever against a
hub whose USB link is wedged, typically after a re-enumeration — held the
box’s USB lock for the life of the process. Every subsequent
lager usbcommand and every state poll queued behind it with no timeout of its own, and the box’s self-restart recovery could not help, because it only ran when an operation raised. A call that never returns raises nothing. Three bounds close that. A hub command that cannot get the lock within 10 seconds now answershub-busyinstead of queueing; a hub that cannot be claimed reports as unavailable rather than waiting forever; and each hub operation runs under a 30-second deadline. On expiry the caller getshub-op-timeoutand the box schedules the same supervised restart it already used for unreachable devices, which is the only thing that clears an orphaned USB context. Hubs are bounded independently, so a wedged hub no longer affects the others on the bench. -
The same treatment for hardware-service device calls. Per-device locks are
acquired with an 8-second timeout and answer
device-busyinstead of queueing forever behind a wedged instrument open or a hung driver call. The driver call itself runs under a 30-second deadline; expiry answersinvoke-timeoutand schedules the restart. A device whose operation hung keeps its lock on purpose — the stuck operation still owns the instrument, so later requests get a fast, honest “busy” rather than wedging in turn. -
lager usbnow waits long enough to hear the box’s answer. Its timeout was 30 seconds, but the box’s own limits are additive, so a wedged hub answered at around 40 seconds and the command had already given up. That surfaced as “cannot reach box”, which reads as a network fault and hides both the real diagnosis and the fact that the box had already started recovering. -
Errors no longer tell you to update the box when a device is unplugged.
lager usb,lager supplyandlager batteryappended “This box image does not expose<endpoint>; update the box.” to every not-found response — including the ones meaning “this net or its instrument was not found”. An unplugged USB hub reported both at once, sending the diagnosis somewhere the fault never was. -
Secret files are now owned by the container user, not just locked down.
/etc/lager/org_secrets.jsonand/etc/lager/secret_keywere tightened to mode 0600, but 0600 grants the owner alone — and everything that reads these files runs as the container user. A secrets file copied onto a box by hand belonged to the host login user, so tightening it locked the runtime out of its own secrets. Nothing failed loudly: secret injection simply returned empty, and scripts broke far from the cause.lager updatenow repairs ownership of both files automatically, including on boxes that are already up to date. The box also repairs what it can at boot and prints an unmissable warning, with the exact commands to run, when it finds a secrets file the runtime cannot read.

