v0.54.0: format-safety foundation — unclaimed-disk guard + guarded-mkfs wrapper
Impl-1. Format now runs a mandatory unclaimed-disk guard (internal/storage/claim.go: SystemDisks + lsblk member-FSTYPE + foreign-mount + RO + pvs/zpool; fail-safe → CLAIMED) before any mkfs — refuses the OS disk / LVM PV / ZFS-mdraid member / foreign-mounted device even when non-data-bearing (guard sits in Format, not the handler). Below the agent, mkfs goes ONLY through configs/felhom-mkfs-guarded.sh (sudoers no longer allowlists raw mkfs.*), which re-checks the catastrophic cases as root. Read-only pvs/zpool added to FELHOM_DISK. Tests + red-proof; capability manifest updated. go build/vet/test clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -156,26 +156,46 @@ func TestInspect_RejectsBadDevice(t *testing.T) {
|
||||
|
||||
// ---- Format (mkfs) ----------------------------------------------------------------------
|
||||
|
||||
// Format now (Impl-1) runs the unclaimed guard then execs the guarded wrapper (<device> <fstype>),
|
||||
// not raw mkfs. These use the stubbed guard (unclaimed /dev/sdb; system disk = /dev/sda).
|
||||
func TestFormat_Ext4(t *testing.T) {
|
||||
r := &scriptedRunner{}
|
||||
if err := newSudo(r).Format(context.Background(), "/dev/sdb", "ext4"); err != nil {
|
||||
defer stubRO(false)()
|
||||
sr := &scriptRunner{out: map[string][]byte{
|
||||
"/usr/bin/lsblk": []byte(`{"blockdevices":[{"name":"sdb"}]}`),
|
||||
}}
|
||||
ops := newGuardOps(sr, []Mount{{Device: "/dev/sda2", MountPoint: "/"}})
|
||||
if err := ops.Format(context.Background(), "/dev/sdb", "ext4"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !r.ran("mkfs.ext4 -F /dev/sdb") {
|
||||
t.Fatalf("mkfs.ext4 not invoked correctly: %v", r.calls)
|
||||
if !srRan(sr, "/usr/local/sbin/felhom-mkfs-guarded /dev/sdb ext4") {
|
||||
t.Fatalf("guarded wrapper not invoked correctly: %v", sr.calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormat_Xfs(t *testing.T) {
|
||||
r := &scriptedRunner{}
|
||||
if err := newSudo(r).Format(context.Background(), "/dev/nvme0n1p1", "xfs"); err != nil {
|
||||
defer stubRO(false)()
|
||||
sr := &scriptRunner{out: map[string][]byte{
|
||||
"/usr/bin/lsblk": []byte(`{"blockdevices":[{"name":"nvme0n1","children":[{"name":"nvme0n1p1"}]}]}`),
|
||||
}}
|
||||
ops := newGuardOps(sr, []Mount{{Device: "/dev/sda2", MountPoint: "/"}})
|
||||
if err := ops.Format(context.Background(), "/dev/nvme0n1p1", "xfs"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !r.ran("mkfs.xfs -f /dev/nvme0n1p1") {
|
||||
t.Fatalf("mkfs.xfs not invoked correctly: %v", r.calls)
|
||||
if !srRan(sr, "/usr/local/sbin/felhom-mkfs-guarded /dev/nvme0n1p1 xfs") {
|
||||
t.Fatalf("guarded wrapper not invoked correctly: %v", sr.calls)
|
||||
}
|
||||
}
|
||||
|
||||
// srRan reports whether the scriptRunner recorded a call whose joined form contains substr.
|
||||
func srRan(sr *scriptRunner, substr string) bool {
|
||||
for _, c := range sr.calls {
|
||||
if strings.Contains(strings.Join(c, " "), substr) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestFormat_RejectsBadArgs(t *testing.T) {
|
||||
r := &scriptedRunner{}
|
||||
if err := newSudo(r).Format(context.Background(), "/dev/disk/by-uuid/x", "ext4"); err == nil {
|
||||
|
||||
Reference in New Issue
Block a user