Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,61 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- **Demo site favicon now matches the refreshed branding.** The v1.5.1 brand refresh (#439) moved the website to the cropped whale "headshot" icon and the app UI followed, but demo.getdrydock.com kept showing the old full-body whale: its stale `favicon.svg` β€” which modern browsers preferred over the PNGs β€” was never replaced. The demo now ships the same headshot icon set as the website and app UI, the `favicon.svg` is removed, and the icon links carry a `?v=2` cache-buster so browsers re-fetch instead of serving the aggressively cached old icon. (#689)

## [1.6.0] β€” 2026-08-11

Consolidates the `1.6.0-rc.1` … `1.6.0-rc.13` prereleases. Users upgrading from
`1.5.2` get everything below; users already on `1.6.0-rc.13` receive no additional
runtime changes.

### Added

- **Portwing edge and agent integration matures into a first-class transport.** Portwing 0.9.0+ agents work over either inbound Standard HTTP or dial-out Edge WebSocket transport, and drydock 1.6.0-rc.11+ recognizes Portwing's own Docker watcher marker to run native registry checks plus single/batch Docker updates controller-side ([#632](https://github.com/CodesWhat/drydock/issues/632), [#637](https://github.com/CodesWhat/drydock/issues/637), [Portwing #76](https://github.com/CodesWhat/portwing/issues/76)). Standard-mode agents can sign every request with Ed25519 (`DD_AGENT_{name}_AUTHMODE=ed25519`, upgraded mid-series to signature version 2) instead of sending a shared secret. Edge agents stream live container logs and process deletes over the existing WS tunnel with correlated per-request IDs, pick their own display name (bound to their signing key so it can't be squatted), and are proactively disconnected when they stop answering pings. The `portwing/1.0` edge endpoint is enabled by default (`DD_EXPERIMENTAL_PORTWING=false` remains an emergency disable), backed by a real fleet-soak workflow that runs signed Portwing processes against production infrastructure on every PR and on a weekly schedule.
- **Declarative, three-tier update policy with a maturity stabilization gate** ([Discussion #307](https://github.com/CodesWhat/drydock/discussions/307), [Discussion #406](https://github.com/CodesWhat/drydock/discussions/406), [#320](https://github.com/CodesWhat/drydock/issues/320)). Containers can declare `dd.updatePolicy.*` labels (maturity mode/min-age, skip tags, skip digests) with watcher-level defaults and UI/API overrides, resolving through label β†’ watcher default β†’ persistent override precedence and surviving agent refresh, container recreation, and error-state rebuilds. A candidate held back by `maturityMode: mature` is visible immediately with a live minute-by-minute countdown to its unlock time, and a new `maturity-cleared` notification (backed by a 5-minute background sweep) announces the moment it clears instead of waiting for the next scan. **Update Now** remains available as an explicit soft-policy override.
- **Per-rule notification templates, bell preferences, and a new health-status event** ([Discussion #205](https://github.com/CodesWhat/drydock/discussions/205), [Discussion #198](https://github.com/CodesWhat/drydock/discussions/198), [Discussion #210](https://github.com/CodesWhat/drydock/discussions/210)). The Notifications view can override title/body/batch-title text per rule and provider with a live preview, and independently control which event categories reach the in-app bell β€” including a new `container-unhealthy` rule (disabled by default) that fires off Docker health-check transitions. Bidirectional MQTT lets Home Assistant's Install button trigger a real drydock update through the normal eligibility/dispatch path, rate-limited per container and audited. `dd.action.*`/`dd.notification.*` labels are now strictly scoped to their own trigger category instead of one silently gating the other ([#494](https://github.com/CodesWhat/drydock/issues/494)).
- **Global update mode and an actionable Update Status panel** ([Discussion #325](https://github.com/CodesWhat/drydock/discussions/325)). **Settings β†’ General** now selects one server-wide mode β€” `notify`, `manual`, or `auto` β€” and the container side panel and detail view replace the old eligibility-badge stack with plain-language status plus a structured, deep-linking condition list covering all 16 eligibility reasons. Existing installs migrate to `auto` on upgrade so configured automatic updates keep working; fresh installs default to `manual` (see Upgrade Notes).
- **Cross-device preference sync and a zero-dependency dashboard grid** ([Discussion #220](https://github.com/CodesWhat/drydock/discussions/220), [#281](https://github.com/CodesWhat/drydock/issues/281)). An opt-in **Sync across devices** toggle stores the full UI preference set server-side per user and propagates changes to a user's other signed-in sessions in real time over SSE. The dashboard grid drops its `grid-layout-plus` dependency for a deterministic CSS Grid implementation with edit-mode drag/reorder, bounded resizing, touch support, and per-breakpoint layout persistence. Audit, Security, Servers, and Watchers gain the same per-view column show/hide picker Containers and Agents already had.
- **More signal, less noise in update visibility.** A pinned tag now surfaces the best newer same-family tag as a purely informational badge without making it an actionable update candidate ([#498](https://github.com/CodesWhat/drydock/issues/498)); a new **Version Update** filter isolates real semver bumps from digest-only churn on fleets that rebuild images daily ([#538](https://github.com/CodesWhat/drydock/issues/538)); and a startup warning flags minute-precise maintenance-window crons that only open their window for one minute per matching hour instead of the intended full range ([Discussion #639](https://github.com/CodesWhat/drydock/discussions/639)).
- **Opt-in wud-card/Homepage compatibility endpoints.** With the unversioned `/api/*` alias removed (see Removed, below), `DD_COMPAT_WUDCARD=true` (default `false`) mounts a narrow compatibility layer covering exactly the four endpoints the Home Assistant [wud-card](https://github.com/angryvoegi/wud-card) integration and Homepage's `whatsupdocker` widget call, reshaped into the bare-array response those integrations expect. ([Discussion #469](https://github.com/CodesWhat/drydock/discussions/469))

### Changed

- **Every major list view is responsive and consistent.** Containers, Agents, Notifications, Security, Triggers, Watchers, Servers, Registries, Audit, and Auth now share one `DataTable` with a persisted per-view table⇄card toggle that auto-reflows to cards below ~640px; card views gained a sort control; and Source/Release-notes/Registry resource shortcuts render through one consistent 44px toolbar everywhere they appear ([#498](https://github.com/CodesWhat/drydock/issues/498), [Discussion #295](https://github.com/CodesWhat/drydock/discussions/295)). The Dashboard and Containers views no longer overflow horizontally on narrow phone screens. Update-status vocabulary was overhauled ("Digest update", "Security hold", neutral Major/Minor/Patch badges for informational-only updates), pinned reverted to being a tag property rather than an update status, and the maturity panel now shows exactly one countdown clock instead of two that could disagree with the gate ([#556](https://github.com/CodesWhat/drydock/issues/556)). Table polish across the series fixed pinned-column overlay clipping, a registry error overwriting the visible tag, sticky-column/auto-hide width miscalculation, and a clipped icon column.
- **Trigger taxonomy migration reaches its final warning stage.** Every `DD_TRIGGER_*` variable and the deprecated `dd.trigger.include`/`dd.trigger.exclude` labels still work in v1.6 but now log at `error` level ahead of removal in v1.7; use `DD_ACTION_*`/`DD_NOTIFICATION_*` and category-scoped labels, or run `config migrate --source trigger`.
- **Less duplicate work on the hot paths.** Registry tag-list requests are shared across containers within a poll instead of being repeated per container; scheduled security scans and the shared log viewer avoid redundant store writes and re-renders; and transient registry network errors (timeouts, connection resets, DNS blips) now retry with backoff before a watch error is recorded.
- **Base image bumped from Alpine 3.21 to 3.24**, later rebased onto `node:24-alpine` at Node 24.19.0 with a matching Trivy build-stage bump to 0.73.0, closing several HIGH/MEDIUM CVEs in the underlying image ([#682](https://github.com/CodesWhat/drydock/pull/682)).

### Deprecated

- **`GET /api/auth/methods`** and the legacy `GET /auth/strategies` response shape are deprecated in v1.6.0 (removal in v1.7.0 and v1.8.0 respectively). Both now log on every request and return `Deprecation`/`Sunset` headers pointing callers at canonical `GET /api/v1/auth/status`. See [DEPRECATIONS.md](./DEPRECATIONS.md).

### Removed

- **Unversioned `/api/*` and `WS /api/log/stream` aliases are gone**, returning `410 Gone` (or a rejected upgrade) instead of serving the request. This is a breaking change for integrations that hardcode the unversioned base path, notably the Home Assistant [wud-card](https://github.com/angryvoegi/wud-card) integration and Homepage's `whatsupdocker` widget β€” use the `DD_COMPAT_WUDCARD` shim above, or migrate to `/api/v1/*` directly.
- **Legacy v1.4-era authentication compatibility.** Basic auth now accepts only argon2id hashes (`{SHA}`, APR1/MD5, crypt, and plain-text hashes fail validation), and OIDC discovery now requires `https://` with no insecure HTTP workaround.
- **Legacy WUD configuration aliases, obsolete watcher switches, and legacy trigger-template variables.** `WUD_*` environment variables and `wud.*` labels are ignored (the migration CLI still recognizes them so existing files can be rewritten); `DD_WATCHER_<name>_WATCHDIGEST`/`WATCHATSTART` are no longer configuration keys (use `dd.watch.digest=true`; startup watches always run); and `$id`/`$name`/`$watcher`/`$kind`/`$semver`/`$local`/`$remote`/`$link`/`$count` no longer populate in trigger templates.
- **Kafka `clientId` and token-only public-registry compatibility handling.** Kafka validation accepts only lowercase `clientid`, and malformed public-registry configurations (a bare `PUBLIC_TOKEN` with no `PUBLIC_LOGIN`) now fail closed instead of silently falling back to anonymous pulls.

### Fixed

- **The maturity soak clock, update-policy overrides, and digest identity now survive the paths that used to reset them.** Container recreation, agent report ingestion, watch errors, concurrent security scans, and manual rechecks each previously had at least one path that could silently restart a maturity countdown, drop a stored policy override, or roll back freshly detected update state β€” every one of those is closed, including the store's digest anchor now self-healing from a stale, multi-entry `RepoDigests` ordering instead of trusting whichever entry happened to land first ([#669](https://github.com/CodesWhat/drydock/issues/669)). Notification dedup no longer fires a duplicate one-shot notification when a manual recheck returns drifted metadata for the same candidate, and containers with no available update are no longer ranked or filtered as though they had one.
- **Agent- and edge-specific reliability fixes.** The container list no longer flashes a false "Agent Mismatch" during an agent's brief re-registration window; start/stop/restart/rollback return an explicit `501` instead of an ambiguous `404` when an agent lacks lifecycle transport ([#637](https://github.com/CodesWhat/drydock/issues/637)); WebSocket log streams accept anonymous-auth sessions; and edge `memoryGb` now reports binary GiB instead of decimal GB.
- **Operational fixes.** The Star History chart is now self-hosted after the third-party chart services' outage ([#671](https://github.com/CodesWhat/drydock/issues/671)); the icon bundle no longer silently drops icons that became iconify aliases mid-series; `GET /api/v1/containers/backups` is reachable again (it was shadowed by the container router's own root handler); infrastructure-mode self-updates no longer fail to spawn their helper container on Docker Hub installs ([#644](https://github.com/CodesWhat/drydock/issues/644)); unchanged pending updates stop bloating the audit log on a timer; and the app and demo favicons match the v1.5.1 brand refresh (#439).

### Security

- **Anonymous access fails closed on upgrade, not just on fresh installs.** An unconfigured or unconfirmed-anonymous instance now rejects protected API requests with `401` instead of showing an open dashboard; set `DD_ANONYMOUS_AUTH_CONFIRM=true` to keep an intentionally open instance working.
- **Transport and session hardening.** HTTP notification triggers are hardened against SSRF (blocked cloud-metadata/link-local targets, contained redirects); WebSocket upgrades validate the complete origin instead of a host substring; the session cookie is renamed to `drydock.sid`, signing every existing user out once; `/store` and its contents are created owner-only (`0700`/`0600`); and icon CDN sources are pinned to exact upstream revisions instead of floating tags.
- **Ongoing dependency and base-image CVE sweeps ran throughout the series** β€” notably Next.js 16.2.11 and React 19.2.8 on the documentation site, `fast-uri`/`ip-address`/`brace-expansion` override advances, and the Node 24.19.0 + Trivy 0.73.0 bump in the final release candidate. See the individual `rc.*` entries below for full CVE detail.

### Upgrade Notes

- **Existing installs keep automatic updates; fresh installs start in manual mode.** The new global `updateMode` setting defaults to `manual` only when drydock creates a settings record for the first time; an existing record with no `updateMode` migrates to `auto`, preserving pre-v1.6 behavior. Review **Settings β†’ General β†’ Update mode** after upgrading if you prefer notifier-only or manual-only operation.
- **A lone `dd.action.include`/`dd.action.exclude` (or `dd.notification.include`/`dd.notification.exclude`) label stops filtering the other trigger category.** If you relied on the pre-v1.6 cross-category leak (#494), previously-suppressed notification (or action) triggers may fire once on the first scan after upgrading. drydock logs a one-time warning per affected container naming the missing label; set the matching label to the same value to restore the previous filtering.

### Documentation

- **Podman/Docker socket security docs refreshed**, and a full configuration/env-var and API/OpenAPI parity audit brought the docs and generated spec in line with the shipped `/api/v1` surface, including the authentication component, registry webhook signature auth, notification outbox actions, bulk container updates, backup listing, and container summary/update-response details.

## [1.6.0-rc.13] β€” 2026-08-08

### Security
Expand Down Expand Up @@ -2345,7 +2400,8 @@ Remaining upstream-only changes (not ported β€” not applicable to drydock):
| Fix codeberg tests | Covered by drydock's own tests |
| Update changelog | Upstream-specific |

[Unreleased]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.13...HEAD
[Unreleased]: https://github.com/CodesWhat/drydock/compare/v1.6.0...HEAD
[1.6.0]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.13...v1.6.0
[1.6.0-rc.13]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.12...v1.6.0-rc.13
[1.6.0-rc.12]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.11...v1.6.0-rc.12
[1.6.0-rc.11]: https://github.com/CodesWhat/drydock/compare/v1.6.0-rc.10...v1.6.0-rc.11
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</div>

<p align="center">
<a href="https://github.com/CodesWhat/drydock/releases"><img src="https://img.shields.io/badge/version-1.6.0--rc.13-blue" alt="Version"></a>
<a href="https://github.com/CodesWhat/drydock/releases"><img src="https://img.shields.io/badge/version-1.6.0-blue" alt="Version"></a>
<a href="https://github.com/orgs/CodesWhat/packages/container/package/drydock"><img src="https://img.shields.io/badge/platforms-amd64%20%7C%20arm64-informational?logo=linux&logoColor=white" alt="Multi-arch"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-AGPL--3.0-C9A227" alt="License AGPL-3.0"></a>
<br>
Expand Down Expand Up @@ -178,6 +178,20 @@ See the [Quick Start guide](https://getdrydock.com/docs/quickstart) for Docker C
<h2 align="center" id="recent-updates">πŸ†• Recent Updates</h2>

<details open>
<summary><strong>v1.6.0 highlights</strong></summary>

- **Portwing edge/agent transport matures** β€” controller-owned native Docker checks/updates for Portwing 0.9.0+, continuous edge log streaming, Ed25519 request signing (v2), and agent-owned display names bound to their signing key. ([#632](https://github.com/CodesWhat/drydock/issues/632), [#637](https://github.com/CodesWhat/drydock/issues/637))
- **Declarative update policy with a maturity stabilization gate** β€” three-tier `dd.updatePolicy.*` precedence, a live countdown to a held-back candidate's unlock time, and a dedicated `maturity-cleared` notification. ([Discussion #307](https://github.com/CodesWhat/drydock/discussions/307), [Discussion #406](https://github.com/CodesWhat/drydock/discussions/406))
- **Per-rule notification templates, bell preferences, and a new `container-unhealthy` event**, plus bidirectional Home Assistant MQTT (Install button triggers a real update). ([Discussion #205](https://github.com/CodesWhat/drydock/discussions/205), [Discussion #198](https://github.com/CodesWhat/drydock/discussions/198))
- **Every major list view is responsive** β€” one shared `DataTable` with a persisted table⇄card toggle across all ten list views, reflowing to cards below ~640px. ([#498](https://github.com/CodesWhat/drydock/issues/498))
- **`/api/v1` parity completes** β€” the unversioned `/api/*` alias and `WS /api/log/stream` are removed (`410 Gone`); an opt-in `DD_COMPAT_WUDCARD` shim covers wud-card/Homepage. ([Discussion #469](https://github.com/CodesWhat/drydock/discussions/469))
- **Security hardening** β€” anonymous access fails closed on upgrade (not just fresh installs), HTTP triggers are SSRF-hardened, WebSocket origin checks are full-origin, and the session cookie is renamed to `drydock.sid`.

Full release notes in [CHANGELOG.md](./CHANGELOG.md#160--2026-08-11).

</details>

<details>
<summary><strong>v1.6.0-rc.13 highlights</strong></summary>

- **Digest comparison anchors on repo-matched candidates** β€” `getOrderedRepoDigests` filters a container's `RepoDigests` to entries whose repo component matches its own image reference before comparing, instead of trusting an arbitrary index-0 entry; a store already poisoned with a stale anchor self-heals. ([#670](https://github.com/CodesWhat/drydock/pull/670))
Expand Down
2 changes: 1 addition & 1 deletion apps/demo/src/mocks/data/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const agents = [
host: '192.168.1.50',
port: 3001,
connected: true,
version: '1.6.0-rc.13',
version: '1.6.0',
os: 'linux',
arch: 'amd64',
cpus: 4,
Expand Down
4 changes: 2 additions & 2 deletions apps/demo/src/mocks/data/audit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const auditEntries = [
id: 'aud-001',
timestamp: '2026-03-10T08:00:00.000Z',
action: 'system:start',
details: 'Drydock v1.6.0-rc.13 started',
details: 'Drydock v1.6.0 started',
},
{
id: 'aud-002',
Expand Down Expand Up @@ -207,6 +207,6 @@ export const auditEntries = [
timestamp: '2026-03-03T18:00:00.000Z',
action: 'container:watch',
container: 'drydock',
details: 'Started watching ghcr.io/codeswhat/drydock:1.6.0-rc.13',
details: 'Started watching ghcr.io/codeswhat/drydock:1.6.0',
},
];
2 changes: 1 addition & 1 deletion apps/demo/src/mocks/data/containers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export const containers = [
displayName: 'Drydock',
displayIcon: 'sh-drydock',
image: 'codeswhat/drydock',
tag: '1.6.0-rc.13',
tag: '1.6.0',
registryType: 'ghcr',
registryUrl: 'https://ghcr.io',
scanStatus: 'scanned',
Expand Down
2 changes: 1 addition & 1 deletion apps/demo/src/mocks/data/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const serverInfo = {
version: '1.6.0-rc.13',
version: '1.6.0',
uptime: 864000,
hostname: 'drydock-demo',
platform: 'linux',
Expand Down
Loading
Loading