Admin User Management
Platform admins manage accounts from Admin → Users (/admin/users).
Capabilities
| Action | API | UI |
|---|---|---|
| List / search / filter | GET /admin/users | Table with role, status, pagination |
| View detail | GET /admin/users/:userId | Detail sheet — memberships, audit snippet |
| Create user | POST /admin/users | Create form — optional invite email |
| Edit user | PATCH /admin/users/:userId | Edit form — name, email, role, status |
| Suspend | POST /admin/users/:userId/suspend | Row action + confirmation |
| Activate | POST /admin/users/:userId/activate | Row action |
| Delete | DELETE /admin/users/:userId | Safe delete with activity checks |
| Resend invite | POST /admin/users/:userId/resend-invite | Row action |
| Reset password | POST /admin/users/:userId/reset-password | Sends reset email (mock/real per email provider) |
Safety rules
- Last active admin — cannot suspend/delete/demote the only remaining
ADMIN/OWNERwithout another admin - Self-lockout — admins cannot remove their own last admin capability unsafely
- Delete — blocked when user owns workspaces or has meaningful activity; friendly message suggests suspend instead
- Secrets — API never returns password hashes or tokens
Suspended users
When User.status = SUSPENDED:
- Login returns 403 with friendly message (not raw error codes in UI)
- Refresh token rotation blocked
- JWT validation rejects non-active users
Login page shows: "Your account is suspended. Please contact your workspace administrator or support team." with Contact Support mailto link.
See Authentication.
Demo admin (read-only)
When DEMO_READONLY_ADMIN_EMAILS includes the logged-in admin:
- Create/edit/suspend/delete/invite/reset blocked
- Response: "Demo admin is read-only."
- View/list endpoints still work
See Demo Mode.
Audit
User mutations write audit events: admin.user_created, admin.user_updated, admin.user_suspended, admin.user_activated, admin.user_deleted, etc. Metadata excludes secrets.
See Audit Logs.