Systematic pass over every docker-mutating operation (#2, thanks @famewolf for the nudge):
- Cleanup can no longer delete an image an update just pulled.
docker image prune -afilters on image creation time — an image built upstream days ago but pulled seconds ago was prunable during the update's pull→recreate window. All four cleanup triggers (Telegram/cleanup, Web UI, disk-warning auto-cleanup, post-auto-update cleanup) now take the shared update mutex; manual triggers report the skip, automatic ones retry on their own cadence. - Stop/start/restart are refused while an update runs. A
/stoplanding during the post-update health wait read as "unhealthy" and rolled back a perfectly good update. All lifecycle entry points now refuse with an honest message while the mutex is held; the update machinery's own steps are never blocked. - A self-update queued during cleanup runs right after it.
New i18n keys cleanup_busy / lifecycle_busy.