dashboard: per-container journald viewer

new GET /api/journal/{name}?unit=&lines= shells out journalctl -M
<container> -b --no-pager --output=short-iso --lines=<N> (cap 5000).
optional unit filter, restricted to hive-ag3nt.service /
hive-m1nd.service so the shell-out can't be coerced into reading
unrelated units. validates the container name against the live list
before invoking journalctl.

frontend renders a collapsed '↳ logs · <container>' details block
on each container row. expanding triggers a lazy fetch; refresh
button re-fetches; unit dropdown switches between the harness
service (default) and the full machine journal. output sits in a
24em-tall monospace pre, auto-scrolled to the bottom on fresh
fetch.

hive-c0re's systemd unit already runs as root, so journalctl has
the access it needs.
This commit is contained in:
müde 2026-05-15 20:42:56 +02:00
parent 79a46f359a
commit 0385d96bf3
4 changed files with 173 additions and 11 deletions

11
TODO.md
View file

@ -107,17 +107,6 @@ Pick anything from here when relevant. Cross-cutting design notes live in
## Lifecycle / reliability
- **journald viewer per container in the dashboard.** Surface the
equivalent of `journalctl -M h-coder -b` in the dashboard so the
operator can see container logs without ssh-ing in. Optional
filter by hive-specific systemd unit (`hive-ag3nt.service`,
`hive-m1nd.service`). Implementation: backend shells out to
`journalctl -M <container> -b --output=short-iso --no-pager`
(optionally `-u <unit>`), streams or paginates the result over a
new dashboard endpoint. Could be a `<details>` per container row
or a dedicated page. Honest journalctl, not the in-container
events stream — those are different surfaces (events = claude turn
loop; journalctl = systemd-wide logs incl. boot, network, etc.).
- **Container crash events.** Watch `container@*.service` via D-Bus, push
`HelperEvent::ContainerCrash` to the manager's inbox so the manager can
react (restart, escalate, etc.).