Files
felhom-controller/REPORT.md
T

6.2 KiB
Raw Blame History

REPORT — R-67: the NAS share appears in FileBrowser (controller v0.160.0, 2026-07-22)

Spec: the R-67 prompt (Phase-0 probe + implementation, controller-only, v0.159.0 → v0.160.0). Commit: 59cd260 on main · image felhom-controller:0.160.0 · deployed to demo-felhom 9201 and demo-hp 9201, both healthy. No agent changes; MinAgent unchanged.

1. Phase-0 probe — GO

On demo-hp, with the Felhom-Share automount confirmed IDLE (autofs trigger present in the guest's /proc/mounts, timeout=60, no cifs mount): docker run --rm -v /mnt/felhom-drives/Felhom-Share:/probe:rslave alpine ls -la /probe listed the REAL share content (demo-felhom's teszt/ + macOS dotfiles) and left cifs mounted in the guest. An in-container access through an rslave bind wakes the idle trigger — one namespace further than the spike's in-guest proof. The design shipped exactly as specified; the fallback fork was not needed.

2. What shipped

syncFileBrowserMounts' path loop extracted into the pure buildFileBrowserPaths (fbPathDeps: mount probe / FS classifier / skeleton fn / logger — every edge seamed), returning BOTH the mount lines and the config source set so a source can never render without its mount.

  • Network branch: bind = the share ROOT, …/<name>:/srv/<name>:rslave (:rslave load-bearing — automount wake / idle-unmount propagate into the RUNNING container). No EnsureUserdataSkeleton, no userdata scoping, nothing written toward the NAS. The drive-absent gate does NOT apply (idle is healthy — the old gate skipped an idle share forever); the gate is the stub classifier verdict via the existing Server.classifyFSPath seam: stub ⇒ excluded from mounts AND sources this pass + WARN (namespace sees a local stub, not the NAS). autofs / network / unknown / nil-classifier include (fail open). The stub rationale: an exposed local stub dir accepts uploads that the real mount later SHADOWS — the customer's files silently vanish from view; exclusion-until-recovery is the only safe rendering.
  • Drives: behavior byte-identical (userdata scoping, skeleton, drive-absent gate, always in the source list) — asserted by test, and observed live (§4).
  • Triggers: NAS add-success (runNetAdd done) + remove (handleNetStorageRemove) now call SyncFileBrowserMounts() (same debounced/H5-mutexed path as the drive flows). Removal drops source + mount next sync; F2 change detection forces the recreate.
  • Renderers unchanged: RenderFileBrowserCompose already takes fully-formed mount lines (propagation rides in the line), RenderFileBrowserConfig already names sources by Label.

3. Tests + red-proofs

filebrowser_network_test.go: A (drive line byte-identical with/without the share — the B invariant; share ROOT :rslave line exact; both sources in config; skeleton called for the drive ONLY), B (stub ⇒ absent from mounts + sources, drive intact, warn logged), C (autofs / network / unknown / nil classifier all include — idle is not a detached drive), D (removal leaves no trace; fbNeedsRecreate sees the change).

Red-proof A (network paths routed through the drive branch): FAIL — skeleton calls = [/mnt/felhom-drives/hdd_1 /mnt/felhom-drives/Felhom-Share] — the NAS path visibly receiving a skeleton — plus the share line degrading to a userdata subtree without :rslave. Restored, green. Red-proof B (stub gate dropped): FAIL — the stub share leaked into mounts AND the source list, and the warn disappeared. Restored, green.

Green gate (go build ./... && go vet ./... && go test ./...): clean. No template changes → no template gates in play.

4. Live leg (real surfaces; methods named)

demo-hp (the mounting side):

  • Startup sync recreated FileBrowser: compose carries /mnt/felhom-drives/Felhom-Share:/srv/Felhom-Share:rslave, config carries path: "/srv/Felhom-Share" named „Hálózati tárhely: Felhom-Share"; log: FileBrowser mounts synced (recreated) — 2 storage path(s); container healthy.
  • Content: docker exec filebrowser ls /srv/Felhom-Share → demo-felhom's real content (teszt/ + dotfiles), uid/gid 1000, group-writable.
  • Upload round-trip: wrote r67-test.txt as uid 1000 inside the filebrowser container (the exact mount namespace + process identity FileBrowser uses) → the file appeared on demo-felhom at /mnt/felhom-drives/hdd_1/shares/Share/r67-test.txt (19 B, uid 1000) → deleted from demo-hp → gone on demo-felhom. Residual: FileBrowser's HTTP/auth layer was NOT driven — its admin credential is customer/day-0-held (admin/admin and the operator demo password both 401); the browser click-through is the operator's residual, as is a look at the sidebar.
  • Dead-NAS: samba stack stopped on demo-felhom → demo-hp's in-container access returned a clean ls: /srv/Felhom-Share: Host is down in ~11 s wall (incl. ssh) — an error, not a hang (the soft/retry=0 recipe's promise held). docker compose start on samba → demo-hp listed the share again immediately, zero intervention (the :rslave + automount recovery working as designed).

demo-felhom (drives-only, the regression side): startup sync logged no config/compose change, ensured running without recreate (1 storage path(s)) — the render was byte-identical, FileBrowser untouched (Up 22 hours), zero :rslave lines in its compose. The B invariant held in production.

Screenshots by description: demo-hp's FileBrowser sidebar now has a second entry „Hálózati tárhely: Felhom-Share" beside the NVMe drive source; entering it shows the teszt folder from demo-felhom. During the dead-NAS minute the source errors instead of spinning.

Access notes: demo-hp via the hub-vaulted G1 break-glass again (file→file, shredded after, incl. the hub-DB copy). Probe + all execs left nothing behind (r67-test.txt deleted; alpine image remains in the guest's docker cache — inert).

5. Follow-ups

  • Operator: FileBrowser click-through on demo-hp (sidebar + upload via the UI) — CC lacks the FileBrowser admin credential by design.
  • ROADMAP: R-67 → SHIPPED, coupled to R-64 (browsing was its missing UX half); network-storage-nas.md gained the „Browsing (FileBrowser)" paragraph.