Add fleet registry removal with confirm modal and agent_removed WS.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled

Operators can remove machines from Crucible and dashboard rosters with honest messaging that deletion is registry-only; bulk select, oath ledger entries, and Go/Vitest coverage included.
This commit is contained in:
AetherForge
2026-06-07 18:23:41 -07:00
parent e1b1a2aa65
commit 07fdb39b63
21 changed files with 533 additions and 53 deletions

View File

@@ -663,6 +663,7 @@ func EstimateXMRPerDay(hashrate float64) map[string]interface{} {
// DeleteAgent removes an agent record from the database.
// If the agent is currently online it is also disconnected (kicked).
// This is fleet-registry removal only — it does not uninstall the agent binary on the host.
func (f *FleetHandler) DeleteAgent(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
if id == "" {
@@ -674,20 +675,29 @@ func (f *FleetHandler) DeleteAgent(w http.ResponseWriter, r *http.Request) {
_ = f.ws.SendToAgent(id, Message{Type: "disconnect", Payload: mustMarshalFleet(map[string]string{"reason": "deleted from roster"})})
f.ws.RemoveAgent(id)
}
if err := f.db.DeleteAgent(id); err != nil {
if removed, err := f.db.DeleteAgent(id); err != nil {
http.Error(w, "delete failed: "+err.Error(), http.StatusInternalServerError)
return
} else if !removed {
http.Error(w, "agent not found", http.StatusNotFound)
return
}
// Clear stale in-memory alerts so the machine stops showing up in the
// dashboard alert banner after deletion.
if f.alerts != nil {
f.alerts.ClearAgent(id)
}
_ = (&OathLedgerBridge{DB: f.db, Hub: f.ws}).Record(
AuthUsername(r), db.OathAgentRemoved, id, "", db.OathOutcomeSuccess,
map[string]string{"scope": "fleet_registry"},
map[string]string{"agent_id": id},
)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]bool{"success": true})
}
// BulkDeleteAgents deletes multiple agents from the database in one call.
// Fleet-registry removal only — does not uninstall agent binaries on hosts.
func (f *FleetHandler) BulkDeleteAgents(w http.ResponseWriter, r *http.Request) {
var req struct {
IDs []string `json:"ids"`
@@ -702,11 +712,16 @@ func (f *FleetHandler) BulkDeleteAgents(w http.ResponseWriter, r *http.Request)
_ = f.ws.SendToAgent(id, Message{Type: "disconnect", Payload: mustMarshalFleet(map[string]string{"reason": "deleted from roster"})})
f.ws.RemoveAgent(id)
}
if err := f.db.DeleteAgent(id); err == nil {
if removed, err := f.db.DeleteAgent(id); err == nil && removed {
deleted++
if f.alerts != nil {
f.alerts.ClearAgent(id)
}
_ = (&OathLedgerBridge{DB: f.db, Hub: f.ws}).Record(
AuthUsername(r), db.OathAgentRemoved, id, "", db.OathOutcomeSuccess,
map[string]string{"scope": "fleet_registry", "bulk": "true"},
map[string]string{"agent_id": id},
)
}
}
w.Header().Set("Content-Type", "application/json")