---
id: w6/m1/t006
title: "GraphQL surface: workspaces query + create/rename/delete mutations (dashboard-shaped)"
worker: worker6
status: done
estimate: 25m
depends_on: [w6/m1/t004, w6/m1/t005]
---

## Objective

Expose the lifecycle over the dashboard's GraphQL adapter: a `workspaces` query (the caller's workspaces: id, name, plan, role — what the m3 switcher needs) and `createWorkspace(name, plan)` / `renameWorkspace` / `deleteWorkspace(confirmation)` mutations. Deliberately GraphQL-only: Render has no REST workspace mutations (RESEARCH-workspaces.md finding 9), so REST `/v1/owners` stays read-only (m2's scope).

## Context

- GraphQL adapter lives in `lego/backend/internal/api/` (thin over core, per docs/ADR006-bex-api.md).
- Session auth: dashboard calls arrive with Kratos session cookies (docs/ADR012-auth.md); the caller identity drives `workspaces`.
- Error mapping: typed limit/refusal errors from t003–t005 → GraphQL errors the dashboard can render (same shapes as existing mutations).

## Steps

1. Schema: `Workspace` type (id, name, plan, viewer role), `workspaces` query, three mutations.
2. Resolvers delegating to the core verbs; no business logic in resolvers.
3. Regenerate/wire whatever codegen the adapter uses; update the GraphQL schema artifact the dashboard codegen consumes.

## Files

- `lego/backend/internal/api/` (schema + resolvers)

## Acceptance criteria

- [ ] `workspaces` returns exactly the caller's workspaces with plan and role
- [ ] All three mutations round-trip against a live core (create → appears in query; delete → gone)
- [ ] Limit errors (6th Hobby workspace) surface as structured GraphQL errors, not 500s

## Out of scope

- REST owners endpoints and MCP tools (w6/m2).
- Dashboard components (w6/m3).
