703db166e7
gates / gates (push) Successful in 8s
After a rebuild the customer's own drives could not be re-attached: candidates returned initialize:[] attach:[] while both drives sat there, and the deploy refused with 'choose an attached drive from the list' — a list that was empty. Measured live three times. Mechanism: enrolment mounts a drive TWICE, at /mnt/felhom-drives/<name> and at the raw /mnt/<name> it creates on the host. The host survives a guest rebuild; the controller's registry does not. So classifyClaim saw a mount outside the managed prefix and concluded 'claimed by something else' — about our own mount. The fix is CORROBORATED, not a widened prefix: a non-managed mountpoint is forgiven only when the SAME device is also mounted under the managed path, a pairing only our enrolment produces. A disk another system uses — /srv/data, /media/x, even /mnt/someone-elses-disk — has no counterpart and is STILL refused, with its own test and a red-proof showing an over-wide fix offering it for formatting. Read from /proc/mounts deliberately: the lsblk invocation is pinned verbatim in configs/felhom-agent.sudoers, so using the plural MOUNTPOINTS would have coupled this to a sudoers rollout. /proc/mounts is world-readable — no sudo, no new allowlisted command, no config change. Fail-safe: an unreadable mount table corroborates NOTHING, so the device classifies exactly as before. 'Could not corroborate' must never read as 'ours'. 29 packages ok, vet clean, agent gates OK.
42 lines
2.1 KiB
Markdown
42 lines
2.1 KiB
Markdown
# REPORT — felhom-agent v0.127.0: a mount Felhom made is not foreign (R-220)
|
|
|
|
**Scope: the host half of R-220.** The customer-facing refusal message is the controller's half and
|
|
ships as felhom-controller v0.203.0.
|
|
|
|
## What changed
|
|
|
|
| File | Change |
|
|
|---|---|
|
|
| `internal/storage/claim.go` | `claimFacts.felhomOwnedMounts`; `classifyClaim` forgives a non-managed mountpoint **only when corroborated**; `felhomOwnedMounts()` + `procMounts()` |
|
|
| `internal/storage/hostops.go` | `mountTable` seam (nil ⇒ real `/proc/mounts`) |
|
|
| `internal/storage/claim_r220_test.go` | new — the own-drive case, the fence, and the corroboration's four edges |
|
|
|
|
## The shape chosen, and why (§7.3)
|
|
|
|
**Candidate (b): the claimed check distinguishes a mount Felhom made from a foreign one** — the task
|
|
called it "nearer the truth" and it is, because the host and its knowledge survive the rebuild while
|
|
the guest's registry does not. Candidate (a) — having the rebuild path clear the raw mounts — would
|
|
have made correctness depend on a cleanup step running, and a cleanup that does not run leaves exactly
|
|
today's defect.
|
|
|
|
**The discriminator is corroboration, not a path prefix**: the same device must ALSO be mounted under
|
|
`/mnt/felhom-drives`. Only enrolment produces that pairing.
|
|
|
|
**`/proc/mounts` rather than `lsblk MOUNTPOINTS`**, because the lsblk invocation is pinned verbatim in
|
|
the sudoers file; changing it would have coupled this fix to a config rollout. `/proc/mounts` is
|
|
world-readable and needs neither.
|
|
|
|
## Green gate
|
|
|
|
`go build` · `go vet` clean · `go test ./...` → **29 packages ok** · `agent_gates.py --fast` → all OK.
|
|
|
|
| Red-proof | Result |
|
|
|---|---|
|
|
| remove the `felhomOwnedMounts` exemption | **FAILS** — "device is mounted at /mnt/adatok (sdb)", the pre-fix refusal |
|
|
| over-widen the exemption to any `/mnt/*` | **FAILS** — "/mnt/someone-elses-disk was offered for formatting" |
|
|
|
|
## Not changed
|
|
|
|
No sudoers, no allowlisted command, no PVE surface, no format path. Every other claim signal
|
|
(system disk, read-only, LVM PV, ZFS member, member FSTYPEs, empty-topology backstop) is untouched.
|