Skip to content

admin: block org deletion while the warehouse exists; confirm modals#892

Merged
benben merged 1 commit into
mainfrom
ben/org-delete-guard
Jul 3, 2026
Merged

admin: block org deletion while the warehouse exists; confirm modals#892
benben merged 1 commit into
mainfrom
ben/org-delete-guard

Conversation

@benben

@benben benben commented Jul 3, 2026

Copy link
Copy Markdown
Member

Deleting an org in the admin UI removed only the config rows, silently orphaning the org's Duckling CR and its infrastructure (S3 bucket, metadata database, IAM role). The drift banner caught exactly this in dev after an org delete. This enforces the correct order: deprovision the warehouse (the provisioner tears down the CR + infra and removes the row) → then delete the org.

Backend

  • DeleteOrg checks for a managed-warehouse row inside the delete transaction and refuses with a sentinel error; the handler maps it to 409 ("warehouse still exists — deprovision it and wait for teardown to complete before deleting the org"). 404/500 behavior unchanged; apiStore interface untouched.
  • Handler tests: delete with a warehouse present → 409 (org + warehouse survive); after teardown → 200.

Admin UI

  • Deprovision warehouse action (new "Danger zone" in the warehouse panel, admin-only, hidden while state is deleting/deleted) wired to the existing POST /orgs/:id/deprovision. Confirmation modal spells out what gets destroyed (Duckling CR, S3 data bucket, metadata DB, IAM role; asynchronous) and requires typing the org id to arm the button.
  • Org deletion is type-to-confirm too. While a warehouse exists, the header Delete button is disabled with an immediate tooltip ("Deprovision the warehouse first…") and the dialog hard-disables confirm — the server 409 is the backstop.

Verification

  • go build -tags kubernetes ./..., go vet, gofmt — clean; new handler tests pass (remaining local skips are the pre-existing Postgres-container tests, run in CI).
  • npm run build — clean. Reviewed live against mw-dev via the dev proxy.

🤖 Generated with Claude Code

Deleting an org in the admin UI removed only the config rows, silently
orphaning the org's Duckling CR and its infrastructure (S3 bucket,
metadata database, IAM role) — the drift banner caught exactly this in
dev. Enforce the correct order: deprovision the warehouse (provisioner
tears down the CR and removes the row), then delete the org.

- DeleteOrg checks for a managed-warehouse row inside the delete
  transaction and refuses with a sentinel; the handler maps it to 409
  ("deprovision it and wait for teardown to complete"). Handler tests
  for both the rejection and the post-teardown success path.
- Admin UI gains a Deprovision warehouse action (danger zone in the
  warehouse panel) with a type-the-org-id confirmation modal spelling
  out what gets destroyed, wired to POST /orgs/:id/deprovision.
- Org deletion is type-to-confirm too; while a warehouse exists the
  header Delete button is disabled with an immediate tooltip and the
  dialog hard-disables confirm (server 409 as backstop).
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Test Impact Plan

Deterministic summary of how this PR changes tests, CI runners, and coverage-risk signals.

Summary

Area Added Changed Deleted
Test files 0 1 0
E2E/journey files 0 0 0
Workflow files 0 0 0

Signals

  • Test cases: +2 / -0
  • Assertions: +6 / -0
  • Skips or known failures added: 0
  • Workflow continue-on-error added: 0
  • Workflow path filters added: 0
  • Test commands removed from justfile: 0
  • E2E/journey retry lines added: 0

Coverage risk: neutral or increased

No coverage-reduction warnings detected.

@benben benben merged commit 722ee18 into main Jul 3, 2026
27 checks passed
@benben benben deleted the ben/org-delete-guard branch July 3, 2026 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant