Adds operator-friendly admin controls to /sovereign/deployments:
* Sortable column headers — click any of FQDN / Status / Started /
Finished / Region to sort the table; second click toggles ASC↔DESC.
Default is Started DESC (newest first). Sort is client-side; the
list is small enough that round-tripping via ?sort= would only add
latency without operator benefit.
* Per-row Delete button → opens DeleteDeploymentModal with TWO modes
via a radio group:
1. "Delete record only (mother)" — DELETE /api/v1/deployments/{id}.
Removes the catalyst-api row (in-memory map + on-disk store +
kubeconfig file) but LEAVES THE HETZNER SOVEREIGN RUNNING.
2. "Delete record AND wipe Sovereign (kill the kid)" — POSTs to
the existing /wipe endpoint (tofu destroy + Hetzner orphan
purge + PDM release + record cleanup in one pass).
Both modes require typing the deployment FQDN to confirm (same
safety pattern WipeDeploymentModal uses, per Fix#46 / #914).
Deep-delete additionally requires the Hetzner token, which flows
straight through to the wipe handler (S3 + Hetzner creds never
logged, per principle #10).
Backend:
* New DeleteDeployment handler (record-only). Refuses adopted (422)
+ in-flight (409) + unknown (404, matching the issue #689
anti-enumeration posture). Idempotent: a second DELETE on a
vanished row returns 404 cleanly.
* Route wired in cmd/api/main.go alongside the existing /wipe and
/release-subdomain endpoints, inside the session-required group.
* 5 unit tests covering happy path / adopted / in-flight / unknown /
terminal-wiped paths.
Frontend:
* DeploymentsList now mounts the new modal and invalidates the
React Query cache (`catalyst, deployments, list`) on success so
the table refreshes without a hard reload.
* 8 unit tests covering default sort order, header-click sort
switching, ASC↔DESC toggle, status sort, delete button rendering
(enabled for terminal rows, disabled for in-flight), modal open
with both radios, conditional Hetzner-token field per mode.
Files:
* products/catalyst/bootstrap/api/internal/handler/deployments_delete.go
* products/catalyst/bootstrap/api/internal/handler/deployments_delete_test.go
* products/catalyst/bootstrap/api/cmd/api/main.go (route)
* products/catalyst/bootstrap/ui/src/components/CrudModals/DeleteDeploymentModal.tsx
* products/catalyst/bootstrap/ui/src/components/CrudModals/index.ts (export)
* products/catalyst/bootstrap/ui/src/pages/sovereign/DeploymentsList.tsx
* products/catalyst/bootstrap/ui/src/pages/sovereign/DeploymentsList.test.tsx
Co-authored-by: e3mrah <1234567+e3mrah@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>