1e60e88eb2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
59 lines
4.1 KiB
Markdown
59 lines
4.1 KiB
Markdown
# REPORT — agent v0.81.0: NAS verify-before-commit (retry=0 + classifier + detached verify job) — DEPLOYED
|
||
|
||
**Date:** 2026-07-11 · **Class:** implementation (agent half of the cross-repo "NAS
|
||
verify-before-commit + page redesign" task). Baseline v0.80.0 (`300f06722b`) → **v0.81.0**
|
||
(`added9d`), live on felhom-pve. Pairs with controller v0.113.0 + host-install v1.13.0.
|
||
**Full task-wide record (red-proof outcomes, live A–E transcripts, teardown):**
|
||
`felhom-controller/REPORT.md`. Evidence base: SPIKE-nas-verify-2026-07-11 (b57f6c1).
|
||
|
||
## What shipped (agent)
|
||
|
||
- **`retry=0` in the production NFS option string** (`netmount.go mountOptions`, Q4-vi): a dead-NAS
|
||
on-demand access fails clean in ~3.8 s (ENODEV) instead of a 91 s wedge; verify failures classify
|
||
as `No route to host` instead of a diagnostic-free systemd timeout. SMB unchanged (mount.cifs
|
||
rejects `retry=`). Installed units are NOT rewritten (none existed on the demo anyway).
|
||
- **`internal/storage/netverify.go`** — `ClassifyNetVerifyFailure(journalTail, tcpReachable)`:
|
||
pure, first-match table on the Q4 VERBATIM substrings → `unreachable | nfs_export | smb_auth |
|
||
smb_share | timeout | mount_failed`; `nfs_export` deliberately merges not-found/not-permitted
|
||
(NFSv4 identical strings). String-based BY DESIGN — every mount failure exits rc=32.
|
||
- **Detached verify job** (`localapi/netverifyjob.go`, formatjob shape but IN-MEMORY single slot —
|
||
a restart empties the slot; `GET /netstorage/verify-status` phase `none` is the CONTROLLER's
|
||
rollback signal, Scenario F): add = decode → role-gate → **sync fast-fail** (full spec validation
|
||
+ 2 s TCP pre-probe; unreachable = HTTP 502 `{code:unreachable}`, NOTHING installed) → SMB creds
|
||
(0600) → EnsureNetworkMount → detached verify: trigger read through the automount, success judged
|
||
from **/proc/mounts ONLY** (§8: EACCES on a 0700 export is a GOOD mount), failure = journal
|
||
classification + **auto-rollback** (RemoveNetworkMount + creds). Single-flight: second add = 409.
|
||
- **Unprivileged journal read** (`journalctl -u <unit> -n 20 -o cat`, NO sudo, NO new sudoers
|
||
grant): needs the `systemd-journal` group (host-install v1.13.0; existing hosts:
|
||
`usermod -aG systemd-journal felhom-agent`). Unavailable ⇒ degrade to `mount_failed` + hint,
|
||
still rolled back.
|
||
- New exports: `storage.NetworkMountedAt`, `storage.NetworkEndpointReachable`. REUSE.md updated
|
||
(helpers + the in-memory-vs-persisted job pattern row + the four Server net-verify seams).
|
||
|
||
## Tests + red-proofs (agent side; outcomes verbatim in felhom-controller/REPORT.md)
|
||
|
||
A1 retry=0 (revert → fail) · A2 classifier table incl. merged nfs_export + empty-journal
|
||
degradation (exit-code mutant → every non-generic row fails) · A3 rollback effects via fakes
|
||
(drop rollback → `removed=[]` + creds linger) · A4 §8 truth table (readability mutant → both rows
|
||
fail) · A5 pre-probe zero-install (skip probe → 200-with-install) · A6 single-flight + no-job shape
|
||
(drop check → 409 lost). Green gate `go build && go vet && go test ./...` PASS (known
|
||
TestGenerateRecoveryCode wordlist flake hit once, clean on re-run).
|
||
|
||
## Deployed + verified (felhom-pve)
|
||
|
||
`.bak-0.80.0` kept → `install -m0755` → `usermod -aG systemd-journal felhom-agent` →
|
||
`systemctl restart felhom-agent`. Verified: `felhom-agent 0.81.0`; `id felhom-agent` →
|
||
`…,999(systemd-journal)`; clean start journal (enrolled drive re-bound, local-api listening,
|
||
desired-state gen 10). Live proof the journal path works: Scenario A's failure detail carried the
|
||
REAL `mount.nfs4 … reason given by server: No such file or directory` lines read unprivileged.
|
||
|
||
**NOT published:** 0.81.0 is deployed on the demo only — no Gitea publish, Day-0 manifest untouched
|
||
(the publish train is the operator's separate decision); Peti's box untouched.
|
||
|
||
## Observations
|
||
|
||
- Pre-existing (2026-07-08, unrelated): `lanresolver: cannot list provisioned guests: permission
|
||
denied` — `/var/lib/felhom-agent/guests` is root-0700 under the non-root agent.
|
||
- `RemoveNetworkMount` leaves the empty mountpoint dir + a `not-found failed` residual unit listing
|
||
(until `reset-failed`/reboot) — cosmetic, documented in the task report.
|