0d159d7e34
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
59 lines
3.2 KiB
Markdown
59 lines
3.2 KiB
Markdown
# REPORT — controller v0.72.0: FileBrowser converges on boot-recreate (2026-06-16)
|
||
|
||
**Deployed:** controller **v0.72.0** on guest 9201 / felhom-pve (bootstrap-managed; healthy).
|
||
**Commit (trunk):** `6ea2538` (Task B) + `c8d…`-era REPORT update.
|
||
**Live-accepted:** two REAL host reboots of felhom-pve — FileBrowser re-synced after the drive-backed
|
||
apps were recreated, both times; all drive-backed apps recovered with zero manual intervention.
|
||
|
||
## Task B — the gap
|
||
|
||
Follow-up to v0.71.0's guest-reboot recovery. A host-reboot test found `processGuestBootChange`
|
||
recreated the drive-backed app stacks (so their `${HDD_PATH}` binds re-resolved against the now-live
|
||
drives) but **never re-synced FileBrowser**. FileBrowser is base-infra: it binds each drive's
|
||
`userdata` directory but has no `HDD_PATH`, so it is **not** in the boot-recreate set — its mounts went
|
||
stale after a reboot (the early first-boot bring-up bound them before the drives were live).
|
||
|
||
## Fix
|
||
|
||
In `processGuestBootChange` (`internal/web/intermediary.go`), **after** `pollLiveBinds` confirms the
|
||
live binds and the drive-backed apps are recreated, the boot-recreate path now triggers
|
||
`go s.SyncFileBrowserMounts()` so FileBrowser converges against the now-live drives. The recreate loop
|
||
was refactored into a pure, seam-testable helper:
|
||
|
||
```go
|
||
func recreateDriveBackedApps(stacks []bootStack, presentStable map[string]bool,
|
||
recreate func(bootStack), syncFB func()) (recreated, skipped int)
|
||
```
|
||
|
||
`syncFB` is invoked exactly once, AFTER all recreates — the FileBrowser sync can never run before the
|
||
drive-backed apps are back.
|
||
|
||
## Tests (non-hollow, seam = the FB sync)
|
||
|
||
- `TestRecreateDriveBackedApps_SyncsFileBrowserAfterRecreate` — records the call sequence; asserts
|
||
`syncFB` runs exactly once and strictly AFTER every `recreate`. Red-proofed (stubbing out the
|
||
`syncFB()` call makes it fail).
|
||
- `TestRecreateDriveBackedApps_SyncsEvenWithNoRecreate` — FileBrowser still converges when nothing
|
||
needed recreating (e.g. binds already present).
|
||
|
||
`go build`, `go vet`, `go test ./...` all green on the build server (192.168.0.180).
|
||
|
||
## Live acceptance — real host reboot ×2 on felhom-pve
|
||
|
||
Both reboots: `processGuestBootChange` fired on the new boot-id, confirmed the live binds, recreated
|
||
every drive-backed app, **then** ran the FileBrowser sync. Captured controller logs:
|
||
|
||
```
|
||
[gate] boot 1781625729-1612: live bind confirmed — recreating drive-backed app … onto /mnt/felhom-drives/felhom-flash (×8 apps)
|
||
[gate] boot 1781625729-1612: re-syncing FileBrowser mounts against the live binds
|
||
[web] FileBrowser mounts synced — 3 storage path(s), config updated
|
||
```
|
||
|
||
(reboot #2 identical on boot-id `1781625955-1516`.) Post-reboot FileBrowser binds all three drives
|
||
non-stale — `felhom-usb`, `felhom-flash`, `felhom-data` → `/srv/felhom-*` — and the underlying agent
|
||
tolerated a `/dev/sdb`↔`/dev/sdc` reshuffle by mounting each drive by UUID (agent v0.37.0, Task A).
|
||
The earlier first-boot `Failed to recreate FileBrowser` line (drives not yet live) is the exact pre-fix
|
||
symptom; the boot-recreate path now recovers it.
|
||
|
||
Demo dashboard has no password set → controller API is open on the in-guest path; no secrets committed.
|