# 051 — Allow deleting a declared metric ## Summary There is currently no way to delete a metric once declared. `src/api.rs` only routes `GET`/`POST /api/metrics` and `GET`/`PUT /api/metrics/{name}` (`src/api.rs:132-135`) — there is no `DELETE`. The engine already has the machinery for it internally: `EngineMessage::RemoveMetricDeclaration` (`src/engine.rs:103`) removes a metric's declaration from the index, but it is only ever sent as part of `delete_profile`'s cleanup (`src/api.rs:689`) when an entire profile is deleted, not as a user-facing action on a single metric. Persistence has the same gap: `Settings`/profile storage (`src/profile.rs`, post ticket 049 now inline in `settings.json`) has `record_metric_declaration`/ `record_metric_declaration_update` but no corresponding removal method, so even if a metric were removed from the live engine index there'd be nothing to stop it reappearing on next load. The webapp UI (`webapp/src/components/Metrics.tsx`) has no delete affordance either — compare to param declarations, which have the same underlying gap (no `RemoveParamDeclaration`-triggering UI or persisted-removal path either), though this ticket is scoped to metrics only. ## Scope - Add `DELETE /api/metrics/{name}` in `src/api.rs`, sending `EngineMessage::RemoveMetricDeclaration` to the engine (same message the profile-delete cleanup path already uses) and returning 404 if the metric doesn't exist. - Add a persisted-removal method (e.g. `Settings::remove_metric_declaration` or equivalent, alongside `record_metric_declaration`/ `record_metric_declaration_update` in `src/profile.rs`/`src/settings.rs`) so a deleted metric doesn't reappear when declarations replay from `settings.json` on the next restart, and call it from the new route the same way `persist_metric_declaration` is called from `declare_metric`. - Add a delete affordance in `webapp/src/components/Metrics.tsx` (icon button or similar, following whatever confirm-before-destructive-action pattern already exists elsewhere in the settings/profile UI — check `NavMenu.tsx`'s profile deletion for the existing convention) that calls the new endpoint and removes the metric from the list on success. - Decide and document what happens to bucket-value history already recorded under the deleted metric's name (e.g. `MetricPrimitive` samples indexed by metric name in the engine) — either leave it orphaned (queryable by name won't work without a declaration, but doesn't need active cleanup) or purge it; state the choice in the PR. - Decide and document what happens to dashboard panels or alert rules whose PromQL query text/filter references the deleted metric by name — at minimum they should fail gracefully (a clear "unknown metric" error rather than a panic or silent empty result) rather than needing to be actively kept in sync; a full dependent-reference check/warning before delete is out of scope unless trivial. ## Acceptance criteria - A metric can be deleted via the API and the UI; it disappears from `GET /api/metrics` immediately and does not reappear after a restart. - Deleting an unknown metric name returns a clear 404, not a 500 or panic. - A dashboard panel or alert rule referencing the deleted metric by name fails with a readable error rather than crashing the engine or API, verified with a seeded fixture. ## Depends on None (touches the same engine/persistence seam as ticket 049, but that ticket is already merged).