Status endpoint and dashboards¶
helper status is the one-screen answer to "is anything wrong, and is
anything waiting on me?" — open findings by severity, action proposals awaiting
approval, when discovery last ran, the trust cells, the last day's receipts.
The same rollup is served over HTTP for a dashboard tile, so the harness shows
up next to everything else on the wall instead of only in a terminal.
It is a read. The endpoint has two GET routes and nothing that acknowledges a
finding, approves a proposal or touches the trust gradient; a test holds it to
that. Approving still happens on the phone (helper approvals) or at the CLI.
In the terminal¶
helper status show # traffic light, headline, one table
helper status show --json # the object the endpoint serves
health is one of three words:
health |
When |
|---|---|
critical |
a critical or high finding is open, or an execution failed in the last 24 h |
attention |
a medium finding is open, a proposal awaits approval, or discovery has not run in 12 h |
ok |
otherwise (low and info findings do not raise it) |
Serving it¶
helper status serve --host 0.0.0.0 --port 8710
curl -s http://host:8710/status | jq .health
curl -s http://host:8710/healthz # {"ok": true}, never needs a token
The process reads the same database and .env as every other verb, so run it
where the daemon runs. A systemd user unit is enough:
# ~/.config/systemd/user/homelab-status.service
[Unit]
Description=homelab-helper status endpoint
[Service]
WorkingDirectory=%h/repos/homelab-helper
ExecStart=%h/.local/bin/helper status serve --host 0.0.0.0 --port 8710
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user daemon-reload && systemctl --user enable --now homelab-status
loginctl enable-linger # keep user units running when you are logged out
Set HOMELAB_HELPER_STATUS_TOKEN (a literal or a file:/keyring:/env:
reference, like every secret-valued setting) and /status requires
Authorization: Bearer <token> or X-API-Token: <token>. Leave it unset on a
LAN that is already the boundary; the body holds counts and finding titles,
never a credential.
The object¶
Keys are only ever added. The ones a widget usually wants:
| Key | Meaning |
|---|---|
health, headline |
the traffic light and a one-line summary |
findings.open, findings.highest, findings.critical_or_high |
open + acknowledged findings |
findings.by_severity.<sev>, findings.by_kind.<kind> |
counts |
proposals.pending, proposals.titles, proposals.oldest_at |
action proposals awaiting an operator |
discovery.last_run_at, discovery.age_seconds, discovery.failed_24h |
the newest DiscoveryRun and the last day |
discovery.probes.<name> |
newest run per probe |
assertions.last_run_at |
newest AssertionRun |
trust.cells_by_level.<level>, trust.open_windows |
the gradient at a glance |
receipts_24h.succeeded, receipts_24h.failed |
what actually ran |
inventory.hosts … |
row counts |
Homepage¶
A customapi service
widget; dot paths reach nested keys.
- Homelab Helper:
href: https://moellere.github.io/homelab-helper/
description: inventory, audit, approvals
icon: mdi-clipboard-check-outline
widget:
type: customapi
url: http://ubuntu-dev.lan:8710/status
refreshInterval: 60000
# headers: { X-API-Token: "{{HOMEPAGE_VAR_HOMELAB_HELPER_TOKEN}}" }
mappings:
- field: health
label: Health
format: text
- field: findings.open
label: Open findings
format: number
- field: proposals.pending
label: Awaiting approval
format: number
- field: discovery.last_run_at
label: Last discovery
format: relativeDate
Home Assistant¶
A REST sensor turns
health into an entity automations can watch — a light that goes amber when a
proposal is waiting, say:
sensor:
- platform: rest
name: homelab_helper
resource: http://ubuntu-dev.lan:8710/status
scan_interval: 120
value_template: "{{ value_json.health }}"
json_attributes_path: "$"
json_attributes: [headline, findings, proposals, discovery, trust]