docs: REPORT + CONTEXT + CLAUDE logging rule for v0.83.0 (deployed felhom-pve)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -104,6 +104,9 @@ All shippable work commits **directly to `main`**; `main` equals what is deploye
|
||||
guess** when you'd otherwise invent input/output.
|
||||
- Update `REUSE.md` if you added/changed/deprecated a shared helper or pattern (same commit).
|
||||
- Testing doctrine (non-hollow tests, red-proofs, seams): use the `felhom-testing` skill.
|
||||
- **Logging**: the slog logger fans out to journald (configured level) + the always-DEBUG `applog.Ring`
|
||||
(remote pulls) — English, keys-never-values, durations on outcomes; full rules in
|
||||
`felhom.eu/documentation/runbooks/logging-conventions.md`.
|
||||
|
||||
### Live validation
|
||||
|
||||
|
||||
+15
@@ -5,6 +5,21 @@
|
||||
|
||||
## Current
|
||||
|
||||
- **v0.83.0** (2026-07-11, LIVE on felhom-pve; NOT published — Peti stays 0.81.0) — **observability
|
||||
pass** (pairs with controller v0.116.1 + hub v0.46.0). `applog.New` → `(logger, *Ring)`: slog
|
||||
fan-out, journald at the configured level, ~1000-entry ring FIXED at DEBUG. `GET /debug/logs`
|
||||
(local API, token-authed; the controller Debug page's Ügynök tab) + request-level DEBUG
|
||||
middleware. Heartbeat log-pull: envelope `log_tail_requested` → next heartbeat ships `log_tail`
|
||||
(128 KB, consume-once; failed push re-armed by the next envelope; `operator log pull served` INFO
|
||||
on fulfillment). Gap-fill sweep: netverify phase/verdict lines (job start, trigger outcome,
|
||||
/proc/mounts verdict, journal bytes, classification code, rollback outcome, durations), netmount
|
||||
unit steps, signedjobs op-received (class/host/expiry — never signatures) + fetch duration,
|
||||
selfupdate invariants + download sha/duration, disks outcome INFOs, controller-swap pre-pull +
|
||||
health verdicts, desired/loop per-exchange DEBUG. Logging conventions:
|
||||
`felhom.eu/documentation/runbooks/logging-conventions.md`. OPEN: the hub-side live pull awaits
|
||||
the operator's button click (hub UI password-gated); pre-existing lanresolver
|
||||
permission-denied WARN on /var/lib/felhom-agent/guests noted in REPORT.
|
||||
|
||||
- **v0.77.0** (2026-07-09) — **fork-4: escrow the offsite restic repo password under R.** `IdentityBundle`
|
||||
gains `ResticRepoPassword` (rides the existing age-under-R `WrapIdentityBundle` path — validated by the
|
||||
custody spike `febdc56`). New `POST /escrow/stage-secret` (`withGuest`) transiently stages the
|
||||
|
||||
@@ -1,38 +1,53 @@
|
||||
# REPORT — agent v0.82.0: local-API version channel (X-Felhom-Agent-Version) — DEPLOYED
|
||||
# REPORT — agent v0.83.0: observability pass (capture ring + /debug/logs + heartbeat log-pull + sweep)
|
||||
|
||||
**Date:** 2026-07-11 · **Class:** implementation (agent slice of the NAS/coupling backlog-clear
|
||||
task, Part B). Baseline v0.81.0 (`1e60e88`) → **v0.82.0** (`fa9c7fe`), live on felhom-pve.
|
||||
Pairs with controller v0.115.0 (version-aware Supports) + hub v0.45.0.
|
||||
**Date:** 2026-07-11 · **Commit:** `cb692f8` · **Deployed:** felhom-pve (backup `.bak-0.82.0`) ·
|
||||
**NOT published** (Peti stays 0.81.0; reaches him with the next publish train)
|
||||
|
||||
## What shipped
|
||||
|
||||
- **`X-Felhom-Agent-Version` on EVERY local-API response** (`localapi/server.go`: the mux is wrapped
|
||||
so the header is set on all routes + all statuses, INCLUDING auth failures and 404s — the
|
||||
controller learns the agent version passively from ordinary traffic). Value = `main.version` via
|
||||
the new `localapi.Options.AgentVersion`. No new routes, no envelope changes, **no sudoers changes**.
|
||||
- The controller (v0.115.0) reads it and capability-gates by version comparison; header-less
|
||||
(≤0.81.0) agents keep working — the controller falls back to the v0.114.0 route probe unchanged.
|
||||
- **Capture layer** (`internal/log`): `applog.New` → `(logger, *Ring)`. slog fan-out: stderr/journald
|
||||
at the configured level (unchanged), a 1000-entry ring FIXED at LevelDebug. `Ring.Lines(maxBytes)`
|
||||
renders newest-kept plain text (the heartbeat tail source).
|
||||
- **`GET /debug/logs`** on the local API (token-authed, self-scoped like every sibling; `?raw=1`
|
||||
plain text; 503 unwired) + request-level DEBUG middleware (method/path/status/duration, never bodies).
|
||||
- **Heartbeat log-pull**: `ControlEnvelope.log_tail_requested` (additive) → the NEXT heartbeat
|
||||
carries `log_tail {collected_at, lines[]}` (128 KB cap, newest kept). Consume-once mirrored from
|
||||
report logtail.go: local pending drains onto the carrying push; a failed push is re-armed by the
|
||||
next envelope (retry proven in tests). Serving a pull logs `operator log pull served` (INFO).
|
||||
- **Gap-fill sweep**: netverify (job start / trigger outcome / **/proc/mounts verdict** / journal
|
||||
byte-count / classification code / rollback outcome / durations), netstorage add (pre-probe PASS
|
||||
verdict, creds staged/removed — path only), netmount (unit install/enable/remove-step results),
|
||||
signedjobs (jobs fetched ids+duration; op received class/host/expiry — never signatures),
|
||||
selfupdate (invariants passed, download sha-match+duration), disks (assign/eject/decommission
|
||||
outcome INFO), ReassertGuestBinds pass summary, controller-swap (pre-pull verify, negative health
|
||||
verdict), desired syncer + hub loop per-exchange DEBUG.
|
||||
|
||||
## Tests + red-proof
|
||||
## Red-proofs (all demonstrated, then restored)
|
||||
|
||||
`TestVersionHeader_OnEveryResponse` (authed / unauthed / 404 all carry the header) +
|
||||
`TestVersionHeader_OmittedWhenUnset`. Red-proof: dropping the Handler() wrap (return the bare mux) →
|
||||
every row fails with an empty header (observed: `X-Felhom-Agent-Version = "", want "9.9.9-test"`),
|
||||
reverted → green. Full `go build && go vet && go test ./...` PASS (the known
|
||||
TestGenerateRecoveryCode wordlist flake did not recur this run).
|
||||
| Scenario | Reverted shape | Failure seen |
|
||||
|---|---|---|
|
||||
| S1 capture-at-info | ring handler gated at the emit level | `ring holds 1 entries, want 2` |
|
||||
| S2 consume-once | `logTailPending = false` drain removed | `report 3 carries a tail again — consume-once broken` |
|
||||
| S7 log sequence | /proc/mounts verdict Debug dropped | `phase line "netverify: /proc/mounts verdict" missing` |
|
||||
|
||||
## Deployed + verified
|
||||
## Live validation (felhom-pve, 2026-07-11 ~17:00 CEST)
|
||||
|
||||
felhom-pve: `.bak-0.81.0` kept → `install -m0755` → restart; `felhom-agent --version` → 0.82.0;
|
||||
clean start journal (enrolled drive re-bound, local-api listening). Wire proof: an authed
|
||||
`GET /storage` to the live agent returns `x-felhom-agent-version: 0.82.0`. **NOT published** —
|
||||
demo-deploy only; Peti stays 0.81.0 (the live probe-fallback path). Hub now shows demo agent 0.82.0,
|
||||
Peti 0.81.0.
|
||||
- `felhom-agent 0.83.0` live; journal clean (ReassertGuestBinds bound felhom-usb, local-api
|
||||
listening, no capability degradation).
|
||||
- A real NAS add from controller 0.116.1 at `logging.level=info`: the agent ring (via the
|
||||
controller's Ügynök tab) shows the request middleware lines including
|
||||
`POST /netstorage/add status=502 duration_ms=2001` — the refusal flow is reconstructable remotely.
|
||||
- Heartbeat log-pull live round-trip: **pending the operator's hub button click** (hub UI is
|
||||
password-gated; CC cannot log in). The channel is fully proven by hub API tests incl. the S6
|
||||
stays-pending case.
|
||||
|
||||
## Observations (documented, NOT acted on)
|
||||
## Green gate
|
||||
|
||||
- **Q1c FAIL surfaced during this task's Part E** (supervised, agent 0.82.0 live): a NAS automount
|
||||
trigger does NOT survive a guest reboot — the guest sees an empty dir; the agent has no
|
||||
network-mount reassert on guest reboot (unlike drive `ReassertGuestBinds`). Follow-up spec'd:
|
||||
`felhom.eu/documentation/backlog/FOLLOWUP-nas-automount-guest-reboot-reassert.md`. NOT this
|
||||
release — a distinct agent task.
|
||||
`go build ./... && go vet ./... && go test ./...` — all green (no flakes this run).
|
||||
|
||||
## Observations
|
||||
|
||||
- Pre-existing (not from this change): `lanresolver: cannot list provisioned guests — permission
|
||||
denied on /var/lib/felhom-agent/guests` WARN at startup — worth a follow-up look.
|
||||
- The 20 s reconcile tick adds one DEBUG ring line per pass (`guest-bind re-assert pass`) — accepted
|
||||
ring churn (~180/h; the ring holds ~1000).
|
||||
|
||||
Reference in New Issue
Block a user