Closes#113, #102.
#113 — RouterBOOT as a follow-on rollout step
Firmware rollouts upgraded RouterOS and stopped, leaving the bootloader to be
done by hand on every device — the exact task staged rollouts exist to remove.
The data was already collected and the collector already had the two methods; the
orchestrator simply never called them.
An optional "Then RouterBOOT" step now runs per device after the RouterOS upgrade
has been verified, rides out the second reboot, and confirms the firmware version
actually moved.
Ordering is deliberate: the bootloader ships inside the RouterOS package, so
upgrading it first would apply the old one. It runs only once the OS half is
confirmed good, and off by default, because it is a second flash and a second
reboot per device.
A device with nothing pending is a success rather than a failure — most of a fleet
is already current, and treating "nothing to do" as an error would halt rollouts
for no reason. When RouterBOOT does fail after a successful RouterOS upgrade the
error says so explicitly, rather than reporting the device as simply failed and
sending someone to re-run an upgrade it already has.
#102 — snooze an item in "Things to handle"
Insights are recomputed from live state on every request and have no id, so a
dismissal is keyed on a fingerprint of category, target and title. That survives a
reworded title without swallowing a different device's version of the same issue.
Dismissals expire, defaulting to 24 hours. "Handled" and "not now" look identical
to the code, and an item that is genuinely resolved stops being generated anyway —
so a permanent dismissal could only ever hide something still true. Expired rows
are cleared on read, so a lapse needs no scheduled job, and the panel reports how
many items are currently hidden rather than quietly shrinking.
Verified against the fleet: snoozing took the list from 8 items to 7 with
dismissedCount 1, and removing the dismissal restored it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>