# WP-36 — Admin cases page + admin delete Status: done Phase: 7 — refinements ## Why Admins can maintain stamdata and org-templates but have no view of the cases (aanvragen) in the register, and no way to remove an erroneous one. This WP adds an admin-only overview of **all** cases across owners and an admin **delete** that can remove any case — the back-office counterpart of the user's own dashboard. ## Decisions (made while building — no spec existed; flagged for review) - **Single capability `cases:manage`** covers both the list and the delete (one back-office concern), following the `orgtemplate:edit` / `stamdata:edit` precedent exactly (Authz role→cap + a `CanManageCases` gate + a `CasesAdmin(ctx,…)` helper; FE `Capability` union + `me.adapter` `KNOWN` + `capabilityGuard` + nav item + `role.interceptor` prefix). - **Page lives in `registratie` (not `beheer`).** `registratie` owns the `Aanvraag` aggregate, so the admin view reuses its `aanvraag-view` labels + `parseApplications` trust boundary instead of duplicating them — and it respects the layer boundary (`beheer` may not import `registratie`). This matches the existing pattern (stamdata-admin lives in `beheer` because `beheer` owns stamdata; org-template-admin in `brief`). Routed at `/beheer/zaken` for a legible admin URL. - **Admin delete removes ANY case** — any owner, submitted or not — unlike the user-facing `DELETE /applications/{id}` (owner-scoped, 409 on a submitted case). That is the admin power. - **Native `confirm()` guards the delete.** No confirm-dialog component exists (the only precedent is a native `confirm()` in behandel-scherm); the delete is irreversible, so it gets a prompt rather than the dashboard's no-confirm optimistic cancel. - **Single owner in practice.** Only `DemoOwner` exists, so the list shows that owner's cases with an Owner column; no fake multi-user seed was added (the endpoint is cross-owner-capable — `ListAll()` — so real multi-owner data would just appear). ## Files - Backend: `ApplicationStore.ListAll()` + `DeleteAny(id)`; `ApplicationSummaryDto.Owner` + `ToAdminSummaryDto`; `Authz` cap + `CanManageCases`; `Program.cs` `CasesAdmin` gate + `GET /admin/cases` + `DELETE /admin/cases/{id}`; `AdminCasesTests` (+ update the org-template `/me` cap-list assertion). SQLite can't `ORDER BY DateTimeOffset` → `ListAll` sorts client-side. - FE: `capability.ts` + `me.adapter` `KNOWN` + `role.interceptor` (`/api/v1/admin/cases`); `aanvraag.ts` `owner?`; `applications.adapter` `listAll`/`deleteAny` + parse owner; `registratie/application/admin-cases.store.ts` (+spec); `registratie/ui/admin-cases.page.ts`; route in `app.routes.ts`; nav item in `site-header`; new `$localize` ids + English targets. ## Acceptance criteria - [x] Admin-only page at `/beheer/zaken` lists all cases (owner + type + status), gated by `cases:manage` (denial alert for non-admins; server re-enforces via `CasesAdmin`). - [x] Admin delete removes any case (incl. submitted); confirmed, optimistic with rollback. - [x] `npm run ci` green (336 FE tests, backend 129, localized build, drift clean after commit).