Commit Graph
4 Commits
Author SHA1 Message Date
Mitchell-JohnsonandClaude Fable 5.1 285278abdb A sweep of the whole console: status codes, a data race, atomic writes, dead code
From the race detector, staticcheck, a garbage-in battery over every safe route and a
headless pass through every tab on two machines. Fixed:
- docker inspect/health of a container that isn't there answered 500; now 404, and a
  daemon that is down 503 (dockerErr, with a test).
- /api/virt/instances/{name} on a machine without Incus answered 502 "incus not found";
  it now says Incus isn't ready, like its siblings.
- Deleting a ZFS snapshot with a bad name answered 500; a bad name is 400, a snapshot
  that doesn't exist 404.
- The task list read a task's Running flag without the task's lock while the waiter
  goroutine cleared it: a data race, now read under the lock.
- The Virtualization export config and run record were written in place; a crash
  mid-write would have left a half file. Atomic now, like the config and state files.
- An unused function in kvm.go, one in incus/subnet.go, an unused field in files/move.go
  and a capitalised error string, from staticcheck.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-13 17:52:18 -07:00
Mitchell-JohnsonandClaude Fable 5.1 f3ca3d8f73 Idle sessions sign themselves out; a KVM's login is remembered; the compose editor knows YAML
A session unused for seven days is dropped, the Sessions list marks a day's idleness and
can sign all of those out at once. The hub keeps a KVM's own cookies from any browser that
has them and lends them to one that hasn't, on the wire and back to the page. The stack
editor and the new-stack dialog use CodeEditor: line numbers, YAML and .env colour under a
real textarea, Tab/Shift+Tab/Enter indentation, and a key bar on touch screens.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 01:20:27 -07:00
Mitchell-JohnsonandClaude Opus 5 f3441ae718 The KVM tab is per machine, and follows the machine switcher
It was a hub-side list you pointed at machines, which had it backwards. A machine has one
KVM; switch to grid and you get grid's. The address is still kept on the hub rather than on
the machine, because a KVM earns its keep exactly when that machine is down and cannot
answer for itself — so the tab reaches the device either way. Adding a second KVM for a
machine replaces the first rather than sitting beside it.

The tab is no longer hub-only and now sits beside Machines in the rail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-24 16:58:08 -07:00
Mitchell-JohnsonandClaude Opus 5 fd88c4ff78 A KVM tab: paste an address, get the device's own page
Ham Lab proxies each KVM from its own origin, which is what makes the simple version
possible. A KVM that speaks only plain HTTP would otherwise be blocked outright as mixed
content in a TLS console; served from here it loads, it is behind this login rather than a
second one, and the iframe is same-origin.

Nothing in it knows anything about any particular device. The prefix /kvm/<id>/ is only the
entry point — a device UI asks for its assets by absolute path, which no prefix can rewrite
away, so any request Ham Lab does not serve itself is routed back to whichever KVM the
asking page belongs to, worked out from the Referer and from a cookie when there is no
Referer, as on a WebSocket upgrade. Ham Lab's own routes always match first, so a device can
never shadow the console, and the fallback is gated on a live session.

The list is hub-side on purpose: a KVM earns its keep when the machine is down, which is
when that machine's own Ham Lab cannot answer.

On the keyboard, a page cannot forward keys into an iframe and does not need to — one with
focus receives them directly. Fullscreen plus navigator.keyboard.lock() is what takes
Escape, Tab and Ctrl-W back from the browser; that is Chromium-only and the tab says so
rather than pretending otherwise.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-24 16:39:27 -07:00