package store import "testing" // Scenario B (v0.60.1) — the customer Danger-zone Delete is the one true purge point: it removes // host_escrow AND host_escrow_superseded for ALL the customer's hosts, including hosts already deleted // (whose demoted blobs survive as superseded rows), so nothing is left orphaned. RED-PROOF: pre-fix // DeleteCustomerConfig deleted only customer_configs → the escrow blobs survived → the assertions FAIL. func TestDeleteCustomer_PurgesEscrowCustody(t *testing.T) { s := newTestStore(t) const cust = "cust-b" if err := s.UpsertHost(&Host{HostID: "b1", CustomerID: cust, APIKey: "k1"}); err != nil { t.Fatal(err) } if err := s.UpsertHost(&Host{HostID: "b2", CustomerID: cust, APIKey: "k2"}); err != nil { t.Fatal(err) } // b1: current SHA_A + superseded SHA_OLD; b2: current SHA_B. s.SaveHostEscrow("b1", []byte("old"), "fp", "zk", "t", "SHA_OLD") s.SaveHostEscrow("b1", []byte("A"), "fp", "zk", "t", "SHA_A") s.SaveHostEscrow("b2", []byte("B"), "fp", "zk", "t", "SHA_B") // ORDERING: delete b2 as a HOST first — SHA_B is demoted to a superseded row and the b2 host row is // gone (so it can only be found again via the F-14 host_deletions provenance). if err := s.DeleteHost("b2", true); err != nil { t.Fatal(err) } if n, _ := s.CountSupersededEscrow("b2"); n != 1 { t.Fatalf("precondition: b2 demoted blob = %d, want 1", n) } // The customer Danger-zone Delete purges EVERYTHING for the customer's hosts (current + orphaned). if err := s.DeleteCustomerConfig(cust); err != nil { t.Fatalf("DeleteCustomerConfig: %v", err) } for _, h := range []string{"b1", "b2"} { if cur, _ := s.GetHostEscrow(h); cur != nil { t.Fatalf("%s current escrow survived the customer delete", h) } if n, _ := s.CountSupersededEscrow(h); n != 0 { t.Fatalf("%s retained escrow survived the customer delete: %d (orphaned)", h, n) } } }