agent v0.36.1: decommission keeps raw mounted (re-enrollable)

The decommission unmounted the raw /mnt/<name>, orphaning a non-removable drive
so re-enroll bound an empty dir. Now DetachDrive only (bind under parent); raw
stays mounted so re-enroll re-binds. Test: raw NOT unmounted + DetachDrive called.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-15 20:06:23 +02:00
parent 05be509e6e
commit 281c7b7e3f
4 changed files with 28 additions and 12 deletions
+14 -5
View File
@@ -92,15 +92,21 @@ func TestDecommission_RoleGated(t *testing.T) {
}
// TestDecommission_Effects: a user-data decommission sets IntentDecommissioned, removes the
// GuestBindStore entry, and unmounts — assert ALL THREE (not just no-error). NEVER formats.
// GuestBindStore entry, and DETACHES the bind under the parent — but (intermediary model) does NOT
// unmount the RAW host mount, so a one-click re-enroll (H3) can re-bind it. NEVER formats.
//
// COMPANION GUARD: the pre-fix decommission unmounted the raw drive (`d.unmountCalls`), which orphaned a
// non-removable drive so re-enroll bound an empty dir. The "raw NOT unmounted" + "DetachDrive called"
// assertions below fail that impl.
func TestDecommission_Effects(t *testing.T) {
d := &fakeDiskOps{}
intent := newFakeIntent()
intent.SetEnrolled("uuid:usb-1") // currently enrolled
gb := tempBindStore(t)
_ = gb.Record(8200, "uuid:usb-1")
ga := &fakeGuestAttacher{}
srv := decommServer(t, d, userDataAndProtected(), fakeGuestList{}, intent, gb, &fakeGuestAttacher{}, nil)
srv := decommServer(t, d, userDataAndProtected(), fakeGuestList{}, intent, gb, ga, nil)
w := do(t, srv.Handler(), "POST", "/disks/decommission", "A", `{"where":"/mnt/bulk"}`)
if w.Code != http.StatusOK {
t.Fatalf("decommission user-data: got %d want 200 (%s)", w.Code, w.Body.String())
@@ -113,11 +119,14 @@ func TestDecommission_Effects(t *testing.T) {
if ids := gb.Guests()[8200]; len(ids) != 0 {
t.Errorf("guest-bind not removed: %v", ids)
}
// 3) unmounted, never formatted
// 3) the bind under the parent is DETACHED, the RAW is NOT unmounted, and never formatted.
if len(ga.detachDrives) != 1 || ga.detachDrives[0] != "/mnt/bulk" {
t.Errorf("DetachDrive calls = %v, want [/mnt/bulk]", ga.detachDrives)
}
d.mu.Lock()
defer d.mu.Unlock()
if len(d.unmountCalls) != 1 || d.unmountCalls[0] != "/mnt/bulk" {
t.Errorf("Unmount calls = %v, want [/mnt/bulk]", d.unmountCalls)
if len(d.unmountCalls) != 0 {
t.Errorf("raw drive must NOT be unmounted on decommission (re-enrollable); got %v", d.unmountCalls)
}
if len(d.formatCalls) != 0 {
t.Errorf("decommission must NEVER format; formatCalls = %v", d.formatCalls)