---
id: w6/m1/t004
title: "Core verb: DeleteWorkspace — guarded teardown of Apps, Databases, env-vars, FGA tuples"
worker: worker6
status: done
estimate: 35m
depends_on: [w6/m1/t001, w6/m1/t003]
---

## Objective

Admin-only DeleteWorkspace that tears down everything the workspace owns and leaves nothing stranded: the workspace's App CRs and Database CRs (operator reconciles the k8s resources away), its OpenBao `tenants/<id>` env-var secrets, its OpenFGA tuples, then the `tenant_members` and `tenants` rows. Guard semantics (confirmation contract, refusal conditions) follow what t001 captured from Render.

## Context

- Resource inventories already exist per workspace: App CRs (`kubectl get apps.app.bex.co` scoped by tenant), `Database` CRs (docs/ADR009-postgresql-management.md), OpenBao `tenants/*` mounts (docs/ADR013-secrets.md).
- Deleting the caller's **last** workspace: decide against t001's captured Render behavior (Render likely refuses or it's the account-deletion path) — encode whichever reality shows.
- Order matters: delete k8s CRs first (so the projector/operator can act while the tenant row still exists), then secrets, then FGA, then rows.
- This is destructive: the verb takes an explicit confirmation argument (e.g. the workspace name), checked server-side.

## Steps

1. Add store/core inventory helpers (list Apps/Databases by tenant) if missing.
2. Implement teardown in the order above; make it idempotent/resumable (re-running after a partial failure completes the remainder).
3. Enforce admin + confirmation-argument checks; typed errors for refusal cases from t001's artifact.

## Files

- `lego/backend/internal/core/`
- `lego/backend/internal/store/`
- `lego/backend/internal/secrets/` (OpenBao teardown)
- `lego/backend/internal/authz/` (tuple removal)

## Acceptance criteria

- [ ] Deleting a workspace with 1 App + 1 Database + env-vars removes the CRs, the OpenBao secrets, the FGA tuples, and the rows; subsequent get/list of the workspace 404/403s
- [ ] Wrong/missing confirmation argument refuses without side effects
- [ ] Non-admin delete refused; partial-failure re-run completes teardown

## Out of scope

- Grace period / soft-delete restore (flag as follow-up if t001 shows Render has one).
- Dashboard confirmation UI (w6/m3/t004).
