Launch finishes as soon as any peer comes online; offline dials notify the tray and keep retrying in the background. Fleet cards that hit max reconnect tries show a clear Reconnect button that resets the retry budget.
Dark remains default; users can pick light or match system under Settings → Appearance. Drop the full-height connection-lost banner that stretched across the window.
Fleet builds a roster from configured peers so hosts stay visible when
they drop (online / reconnecting / failed / offline). Settings → Behavior
adds max reconnect tries (1–8 or unlimited, default 8) wired into
ConnectionManager, with Retry connect to redial after the budget is spent.
Dead links now force disconnect after failed pings, failed dials keep
retrying every 5s, and the UI rebinds peers after a successful redial
instead of leaving the workspace stuck offline.
Grey out the Swarm sidebar item with a help popover explaining how to
enable swarm mode. Recheck the peer on each hover and re-enable the
nav when LocalNodeState becomes active.
Reusable column visibility control after Clear on containers and on
other resource tables, with preferences persisted. Suppress horizontal
scrollbars so columns ellipsize instead of overflowing.
Validate port mappings for empty host ports, in-form duplicates,
privileged low ports, and peer-side host port conflicts. Runs on
template deploy, deploy view, and add-container before create RPC.
Replace em-dash and ad-hoc loaders with the shared job-tray spinner
for deploy templates, host/swarm/tunnels/events, health latency,
container stats/logs/processes, and registry/volume browsers.
Gatekeeper reported the Bare server binary as damaged because it only
had a linker ad-hoc stamp after embed. Seal darwin server binaries with
the same sign-macos path used for Electron apps (codesign / rcodesign).
Peers live under Settings; Images is local-only. Registry is a top-level view with vault credentials, Hub search, and Registry API V2 catalog/tags/manifest/delete over the wire.
HTTPSAgent extends the patched Agent; mistaking path for socketPath made every registry digest check fail with ENOENT and broke image update indicators.
Registry HTTP now sets host/hostname, disables keep-alive, and times out cleanly; resolve container image tags/digests more reliably and surface check errors in the UI.
Compare local RepoDigests to remote registry manifest digests, show status in the containers table Updates column, and support force recheck with vault credentials for private registries.
Adds a dedicated blank create form (name, image, always pull, ports,
auto-remove, advanced settings) separate from template Deploy, reuses
deployContainer with pull-if-missing and publish-all-ports support.
Lifecycle RPCs now use a 120s operation timeout, remove cleans up
stats/terminal/log streams then SIGKILLs before force-remove, and the
UI awaits the request instead of a fragile 30s wait race.
Installer and operator docs now tell users to read SERVER_PUBLIC_KEY and
SERVER_SEED from /opt/peardock/.env, and how to connect as viewer, admin, or
via a pd1. invite without sharing the seed.
Force fresh capability auth after pairing, heal active grants stuck on the spent list, and fail closed when a grant is spent instead of falling back to bare viewer.
Stop silently dropping failed capabilities (which forced viewer), log handshake role/auth, and show each AutoPass invite with its linked capability on one Access card.
Force-wipe AutoPass invite packages on create/delete so spent capabilities cannot poison new invites, clear stale grants on the client, and let admins unrevoke or clear revoked peers from Access.
Default peers are read-only; admin requires seed proof and operators redeem AutoPass packages with signed grants. ACL UI and docs match the new trust model.
PM2 and similar tools emit VT100 color codes that browsers hide only
partially, leaving artifacts like [32m between table columns. Strip CSI/OSC
escapes when formatting log lines, and harden Docker multiplex demux on the
server so frames are not mis-parsed as text.
Show start, stop, kill, restart, pause, resume, recreate, duplicate/edit,
and remove in the container details header, enabled by runtime state, using
typed RPC for lifecycle operations.
Always show a containers action bar (start/stop/restart/pause/resume/kill/
recreate/remove/prune) driven by row selection via typed bulk RPC. Rebuild
the container Networking tab into a join/leave network manager with aliases
and optional static IPs, plus a clearer ports table.
Replace the broken fire-and-forget submit path with deployDockerContainer
(including replace prompts), suggest a free name-copy by default, correctly
map custom networks/mounts/ports from inspect, and load config via typed RPC.
When deploying a container whose name already exists, prompt to Replace
(stop and remove the old container) or Cancel. Server accepts replace:true
to perform the swap; clients pre-check names and retry on conflict races.
Expand server history samples with network/block rates and longer
retention, and rebuild the details Stats tab with live KPIs, 1m–30m
windows, auto-scale, pause, CSV export, and CPU/memory/net/disk charts.
Split overview into a stretching Identity/Runtime/Network band and a
content-height Ports/Mounts/Timeline strip with timeline, mount rows,
and clearer empty states so vertical space is used without sparse panels.
Make the overview tab body, card, and section grid grow with the details
shell so Identity/Runtime/Network and related panels use empty vertical
space instead of sitting in a short content-sized block.
Tighten container detail tabs into a fit-to-viewport layout with a richer
overview, debounced process filters, and a readable process table. Make
dashboard KPI cards navigate to resource views (with status filters that
reset on leave), and raise per-peer RPC limits so normal UI polling no
longer trips rate limiting.
Cause
navigateToView was running document.querySelectorAll('.nav-link') and clearing active on every nav link — including container detail tabs (Logs, Terminal, etc.).
That left the previous pane with .show.active while its tab button no longer had .active. Bootstrap’s Tab.show() then couldn’t find/hide the previous pane, so opening Overview (or another tab) stacked both.
Fix
1. Sidebar-only nav updates — only #sidebar .nav-link[data-view] get active-state changes; detail/swarm/settings tabs are left alone.
2. Explicit tab reset — activateContainerDetailsTab() forces a single visible pane when opening a container (defaults to Overview).
3. Safer click wiring — sidebar navigation listeners are scoped the same way so they don’t attach to tab buttons.
Result
• Overview → Logs → other container → Overview shows only Overview
• Same for any other tab when switching containers
• Manual tab clicks continue to show only that tab’s content
The Basics/Network/Volumes/Security/Review steps never advanced and only cluttered Container Configuration. Drop the strip, related CSS, and the structure test id.
Probe bash/sh/ash and related shells until a container terminal works, enable Swarm APIs by default, add keyboard go-chords and appearance prefs, and point install docs at https://install.peardock.boats.
Parse Docker stats streams as NDJSON so samples actually land, ship
memory limit for accurate bars, keep CPU/Memory columns visible with a
compact stacked meter, and match stats updates to table rows reliably.
Use fixed table layout, cell ellipsis, and progressive column hiding
on narrower widths so containers/images/networks tables stay within
the content pane instead of growing a horizontal scrollbar.
Replace exponential backoff and the 12-attempt cap with a fixed 5s
retry loop that keeps dialing after unexpected disconnects. Throttle
toasts so the UI is not spammed while the offline banner stays up.
dockerode/modem (and Bare HTTP shims) can still emit a non-empty start
body, which Engine API ≥1.24 rejects. Start/pause/unpause now write a
minimal HTTP request on the docker.sock with Content-Length: 0.
Keep the containers table scoped to the active peer with a merge store,
restore the last active server on boot with a restoring screen, start
containers without a Docker API body (v1.24+), and stop ⋮ menus from
sticking to the viewport bottom after refreshes.
Ignore transient empty list payloads so rows never vanish, and reconcile
in place with insertBefore instead of replaceChildren (which flashed a
blank tbody). Stats and existing rows stay put until data actually changes.
Skip skeleton wipes when data already exists, fingerprint list content so
auto-refresh does not rebuild unchanged DOM, and short-circuit container
structure updates when only live stats change.