---
id: w2/m10/t004
title: Surfaces — REST cancel + rollback (Render shapes) · GraphQL · MCP extensions
worker: worker2
status: todo
estimate: 30m
depends_on: [w2/m10/t002, w2/m10/t003]
---

## Objective

Expose both verbs on all three adapters: REST `POST /v1/services/{id}/deploys/{deployId}/cancel` and `POST /v1/services/{id}/rollback` (paths/bodies/status codes verified against Render's OpenAPI; `/v1/apps` alias too); GraphQL `cancelDeploy`/`rollbackService` mutations in the existing style; MCP `cancel_deploy` + `rollback_deploy` — bex extensions named after the REST verbs (the official server ships neither; note that in the tool descriptions, per the m5 precedent).

## Context

- Fragments: `lego/backend/internal/deploys/{rest,graphql,mcp}.go` — m5's package, same composition root.
- Error mapping: the t002/t003 typed errors → the spec's 4xx codes; unknown service/deploy → 404; unauthorized → 403 (swept by `TestAuthzGuardsEveryVerb`).

## Steps

1. REST routes + error mapping; docs/ADR006-bex-api.md table rows.
2. GraphQL mutations; MCP tools returning the (new) deploy object.
3. docs/ADR018-render-parity.md left to t006 (don't double-edit).

## Files

- `lego/backend/internal/deploys/{rest,graphql,mcp}.go`
- `docs/ADR006-bex-api.md`

## Acceptance criteria

- [ ] All three surfaces cancel and roll back through the identical verbs; REST shapes match the spec for every field bex serves.

## Out of scope

- Dashboard buttons (`w5/007`); parity-matrix refresh (t006).
