---
id: w5/m14/t001
title: GraphQL document + useDeleteService hook (mutation, cache eviction, redirect)
worker: worker5
status: done
estimate: 30m
depends_on: []
---

## Objective

Add the `deleteService` GraphQL mutation document and an Apollo hook (`useDeleteService`) that, on success, evicts the deleted service from the `services` list cache and redirects the caller to the services list route.

## Context

- `dashboard/src/features/services/api/services.graphql` already has `suspendService`/`resumeService` as the pattern to follow.
- `dashboard/src/features/databases/hooks/use-delete-database.ts` is the sibling implementation for databases — reuse its cache-eviction + redirect shape.
- The backend `deleteService` GraphQL mutation already exists — w2/m4 shipped 2026-07-09 (`lego/backend/internal/apps/graphql.go:361`); no backend work needed, this task is pure dashboard.
- The dev stub `dashboard/scripts/local-bex.mjs` has `deleteWorkspace` and `deleteDatabase` resolvers but **no** `deleteService` — without it, t003's stub-fallback path would break the trustworthy-stub principle (w5/m10). Step 4 closes that.

## Steps

1. Add `mutation DeleteService($id: String!) { deleteService(id: $id) }` to `services.graphql`.
2. Run codegen to produce the typed hook/document.
3. Write `use-delete-service.ts`: wraps the generated mutation, evicts the service from the Apollo cache (`services` query + the individual `service(id)` entry), and exposes a `deleteService(id)` async function.
4. Add a `deleteService` resolver to the dev stub `dashboard/scripts/local-bex.mjs`, following its `deleteDatabase` resolver (~line 577): remove the service from the multi-service store and return `true`; unknown id → `null`/error — keeps the stub trustworthy for t003.

## Files

- `dashboard/src/features/services/api/services.graphql`
- `dashboard/src/features/services/hooks/use-delete-service.ts` (new)
- `dashboard/scripts/local-bex.mjs` (add `deleteService` resolver)

## Acceptance criteria

- [ ] Calling the hook against a real service removes it from a subsequent `services` query without a manual refetch.
- [ ] Hook surfaces loading/error state for the confirm dialog (t002) to consume.

## Out of scope

- The confirm-dialog UI itself (t002).
