v1.5.0-rc.13
[1.5.0-rc.13] — 2026-04-24
Added
- Update-eligibility blockers on container rows — Backend surfaces 12 structured blocker reasons (
maturity-not-reached,container-paused,no-update-detected, etc.) per container, and the Containers list renders them inline so users see why a row isn't updating without opening the detail drawer. Amber formaturity-not-reached(informational — will self-clear at the maturity threshold), red for terminal blockers. GET /update-operations/:idendpoint — Returns the current state of a specific update operation. The UI falls back to this endpoint when the terminal SSE is missed (reverse-proxy reconnect-without-replay), so update toasts and hold release still fire even when the browser never saw the final server-sent event.
Fixed
- #308 (partial) — Two of the three reporter symptoms are resolved:
- Row status during scan. Triggering a scan from the row's
...menu no longer shows "Updating" on the row.actionInProgressnow tracks the kind of action per container (update/scan/lifecycle/delete) instead of a bare id set, and the status label and row-lock predicates read from the per-kind map so a scan in progress shows "Scanning" and doesn't dim other row actions. - Batch-mode triggers on single-container scans. Providers that only listen to
emitContainerReports(batch-mode, e.g. Pushover) were silently skipped on single-container scan paths, which only emitted theemitContainerReportsingleton. Threaded{ emitBatchEvent: true }through thewatchContainercall from the single-scan handler so batch-mode triggers fire too. - Still open: the empty
updateKind.{kind,localValue,remoteValue}fields in simple-template notification email bodies reported by begunfx. The dispatch snapshot shouldn't normally loseupdateKind— needs a repro to chase the root cause.
- Row status during scan. Triggering a scan from the row's
- #317 — Two fixes around reconnect-without-replay SSE:
- Rollback actions no longer broadcast spurious container-lifecycle events (
dd:sse-container-added/-removedin quick succession) while the store is mid-recreate. - When the terminal update-operation SSE is missed, the Containers view's reconciliation pass now releases the display hold and fires the update toast from the reconciled state, matching what would've happened on a live SSE.
- Rollback actions no longer broadcast spurious container-lifecycle events (
- #318 — Kind and status columns in the Containers list now stay visible at narrow viewports. The container-query thresholds that gated column visibility were tripping too early; adjusted so the columns survive down to the minimum useful table width.
- #291 (rc.12 follow-up) — Dashboard update flow now shares the same
useOperationDisplayHoldcomposable that the Containers view uses, fixing the last two reporter symptoms that survived rc.12 on the dashboard path. (1) The updating row no longer drops to the bottom of the Recent Updates widget mid-update: the backend transiently clearsupdateDetectedAtwhile the container recreates, which was sorting the ghost row last — the shared hold now overlays the snapshottedupdateDetectedAtso sort position is stable through the whole update window. (2) A dropped terminal SSE (Synology DSM reverse-proxy style reconnect-without-replay) no longer leaves the dashboard silent: the view now reconciles holds against refreshed container data and falls through toGET /update-operations/:idthe same way the Containers view did. Both views are now driven by one hold map, one sort-snapshot overlay, and one reconciliation fallback.
Performance
- #301 (rc.11 follow-up) — Dashboard and Containers view now do dramatically less work on every SSE reconnect. Addresses the residual slow-load reports on those two pages after the rc.10/rc.11 backend fixes.
- Dashboard reconnect refresh is live-only. On
dd:sse-connectedthe dashboard now refetches only the endpoints that can go stale between frames (/containers,/containers/stats,/containers/recent-status) and TTL-guards the static ones (/server,/agents,/watchers,/registries) for 30s.dd:sse-resync-required(server-signaled state loss) still forces a full 7-endpoint fan-out — the TTL skip only applies to reconnect blips. On a flaky Synology LAN this turns a reconnect storm into a handful of requests instead of 7× that. - Dashboard stats read no longer warms Docker stats streams per container.
GET /api/v1/containers/statsaccepts a new?touch=falsequery param; the dashboard uses it so a summary read returns already-cached snapshots without spinning up a per-container Docker stats stream. The Containers view / detail panel still pass the default (touch=true) so streaming stats stay warm where they actually render. - Containers list dedup fingerprint is ~30× cheaper.
loadContainers()was recursively fingerprinting every field (includingdetails.ports/volumes/env/labelsarrays) on both the incoming and current lists to skip redundant reactive reassignment. Replaced with a flat hash of the ~13 scalar fields that actually affect row rendering. Identity-and-tag changes still trigger reassignment; deep-field-only changes that never reach the list render no longer do. - SSE lookup-map churn halved.
updateLookupMapsForContainerwas doing 4 full-map spreads ({ ...map, ...key }) per container SSE event; collapsed to 2.removeLookupMapsForContainercollapsed the same way and skips reassignment entirely when neither the id nor the alias is present.
- Dashboard reconnect refresh is live-only. On
Docs
- v1.5.0 deprecation sweep. Migrated every documentation example and test fixture off the v1.5.0-deprecated
DD_TRIGGER_*/dd.trigger.*prefixes onto canonicalDD_NOTIFICATION_*+dd.notification.*(messaging providers) andDD_ACTION_*+dd.action.*(update executors). Touched 29 files incontent/docs/current/**, the in-repo README roadmap and Recent Updates sections, CONTRIBUTING, all QA/CI/demo compose fixtures (exceptmigration-test-compose.yml, which intentionally exercises the legacy prefix), and the apps/web landing-page roadmap. The legacy prefixes still work as aliases through v1.7.0 — this sweep makes every example in the project canonical so new users stop copy-pasting deprecated forms. SeeDEPRECATIONS.md. - Registry credentials:
*_TOKEN→*_PASSWORD. The Docker Hub and DHI provider docs no longer instruct users to setDD_REGISTRY_HUB_PUBLIC_TOKEN(deprecated) — examples now useDD_REGISTRY_HUB_PUBLIC_PASSWORD, matching the canonical form every other registry provider already documents.
Tests / CI
- Dashboard helper + computed coverage — Added targeted tests for
createRealtimeRefreshScheduler'sfull-live→refreshFullfallback branch (when no full-live handler is configured) and for the WeakMap cache-hit branch ofuseDashboardComputed's name-counts memoization. Closes the last two UI coverage gaps left after rc.12.