---
id: w4/m12/t003
title: REST + GraphQL surface for members (Render dashboard shapes where captured)
worker: worker4
status: done
estimate: 25m
depends_on: [w4/m12/t001]
---

## Objective

Thin adapters over the t001 verbs: GraphQL for the dashboard (member list with role/status, invite/setRole/remove mutations) and a REST projection — following Render's dashboard operation names where captures exist in `docs/render-artifacts/`, else bex's own names, documented as such (the env-var-mutations precedent). Render's public REST has no team CRUD, so REST here is bex's own under Render vocabulary.

## Context

- Feature-fragment pattern: `rest.go` / `graphql.go` beside the service, composed in `internal/api/server.go`.
- Pending invites appear in the member list with a `pending` status (the Render dashboard pattern).
- MCP deliberately omitted — Render's official MCP server has no team tools (w2/002 tracks workspace tools separately).

## Steps

1. GraphQL: `members(workspaceId)` query + `inviteMember`/`setMemberRole`/`removeMember` mutations.
2. REST: `GET/POST /v1/members`, `PATCH/DELETE /v1/members/{id}` (bex's own, documented).
3. `docs/ADR006-bex-api.md` + `docs/ADR012-auth.md` updates.

## Files

- `lego/backend/internal/` members feature `rest.go`, `graphql.go`
- `docs/ADR006-bex-api.md`, `docs/ADR012-auth.md`

## Acceptance criteria

- [ ] Both surfaces delegate to the same verbs; non-admin 403s; shapes documented with their Render-vs-bex provenance.

## Out of scope

- MCP tools; dashboard UI (t004).
