# 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 -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.