# Roles: admin / analyst / developer — checklist Decisions (user, 2026-10-08): - `member` is renamed `developer` everywhere, stored value included (migration). - developer: full control of OWN workspaces/sessions/git; nothing host-wide. - analyst: sees every user's rows (as today) AND works on OWN rows like a developer (was: read-only); nothing host-wide, never another user's rows. - UI hides every control the role cannot use; refusals show a clear toast. ## Server - [x] db.js: rebuild `users` with CHECK(admin, analyst, developer), member→developer - [x] auth.js: ROLES, default role, STAFF_ONLY gate, analyst no longer EREADONLY - [x] auth.js: `/alerts/rules` joins ADMIN_WRITE_PREFIXES (host-wide rules) - [x] scope.js: `memberId` = developer always, analyst on writes only - [x] websocket.js: analyst terminal only on own runs; broadcast member→developer - [x] audit.js, users.js, workflow-stats.js, openapi-extra/auth.js, CLI users - [x] tests: update member→developer, add analyst write-scope tests ## Client - [x] one role helper (isAdmin / canSeeAll) from useAuth - [x] hide admin-only controls (inventory from Explore) - [x] analyst: hide write controls on other users' rows - [x] errors: EADMIN / EREADONLY / ENOTFOUND toasts translated (en + vi) - [x] role label "Developer" en/vi, Users page role select ## Finish - [x] npm run test:server, npm run test:client - [x] docs: SERVER-MODE.md, CLAUDE.md lines naming `member` - [x] headers check ## Follow-ups (2026-10-08) - [x] analyst alert feed: `can_ack` per alert, Ack hidden on others' (server test + client test) - [x] Settings search: admin-only entries (autostart, quit, tray, reports, webhooks, git creds) hidden - [x] SessionDetail: an unstamped session's owner resolved by folder (`owningLane`) - [ ] prod/dev share one DB: restart prod on the new build together with the first run (migration) - [ ] `agenthub stop` in server mode answers EAUTH (fix was blocked; user to decide)