---
id: w4/m12/t004
title: Dashboard — Settings → Team page (list, invite, role dropdown, remove)
worker: worker4
status: done
estimate: 40m
depends_on: [w4/m12/t003]
---

## Objective

The human surface: a Team section in dashboard Settings showing members (name/email, role, pending badge), an invite dialog (email + role picker), a role dropdown per member, and remove-with-confirmation — wired to the t003 GraphQL operations, visible/enabled only for admins.

## Context

- Read `dashboard/CLAUDE.md` first; follow the settings-page composition w4/m8 establishes (API Keys section) and the i18n conventions (w5/m3).
- Role labels/descriptions come from Render's role matrix wording (docs/ADR012-auth.md) so the UI teaches the same model the API enforces.
- Non-admin members see the list read-only (or per the matrix — mirror what `can_manage` gates server-side; never render controls that will 403).
- Screenshots via Playwright MCP with bare filenames (land in `.playwright-mcp/`).

## Steps

1. Team section: members query, list rendering with pending state.
2. Invite dialog + role dropdown + remove confirmation, each calling its mutation with optimistic/refresh handling per existing Apollo patterns.
3. Last-admin and self-removal edge states surfaced as disabled controls with tooltips (matching the server's typed errors).

## Files

- `dashboard/src/` (settings Team section, GraphQL documents)

## Acceptance criteria

- [ ] Admin invites/changes/removes from the browser; a viewer sees no mutation controls.
- [ ] Server-side refusals (last admin) render as understandable UI states, not raw errors.

## Out of scope

- Workspace switching UI (single-workspace dashboard until w2/002-era work); billing role behavior beyond the label.
