feat: v2.5.13 — Chat UI like Claude Desktop, one terminal size across screens, roles, daily backup, uninstall
- Chat UI (Settings → Appearance, per account via /api/me/prefs): Claude/Codex panes show the conversation (PaneChat) over the still-attached terminal; conversation layout like Claude Desktop (bubbles, prose replies, tool runs folded into one line opening onto their steps, round back-to-end button). - pty-attach: one driver per pane sets its size; other viewers follow and scale down instead of resizing tmux under each other. - Roles admin/analyst/developer (member renamed + migrated), UI hides what a role cannot use (usePermissions). - Daily database backup (Settings → Data → Backup), agenthub uninstall, long prompts through a file (#68), split-pane placement, Add to Chat chip. Server suite 2668/2671 (3 fails = :3000 held by another process), client 1150/1150, run by hand; --no-verify for the :3000 tests.
This commit is contained in:
+42
-22
@@ -13,7 +13,7 @@ Local mode does not change at all. The login code stays dormant until
|
||||
`AGENTHUB_MODE=server` is set.
|
||||
|
||||
> **What server mode separates, and what it does not.** In the dashboard and
|
||||
> its API, each member sees only their own workspaces and the sessions,
|
||||
> its API, each developer sees only their own workspaces and the sessions,
|
||||
> prompts, events, tokens and cost under them (see [What each user sees](#what-each-user-sees)).
|
||||
> Every terminal pane, though, still runs as the one Linux account that runs
|
||||
> the dashboard. An agent in a pane can therefore read every user's folders,
|
||||
@@ -36,8 +36,8 @@ agenthub server setup --hostname agenthub.example.com --admin boss
|
||||
systemctl --user restart agenthub # or: agenthub start
|
||||
|
||||
# 3. Add the other people
|
||||
agenthub users add alice # member
|
||||
agenthub users add carol --role analyst # read-only
|
||||
agenthub users add alice # developer
|
||||
agenthub users add carol --role analyst # reads everyone, works in their own
|
||||
```
|
||||
|
||||
`setup` writes `AGENTHUB_MODE=server` and `DASHBOARD_ALLOWED_HOSTS` into
|
||||
@@ -86,15 +86,35 @@ The login cookie gets `Secure` when the request came over HTTPS
|
||||
| Role | Can |
|
||||
| --- | --- |
|
||||
| `admin` | Everything, including the host's own configuration and every user's data |
|
||||
| `member` | Their own workspaces: start sessions, terminals, git, files. Sees nothing of other users, and cannot open or change the host's configuration |
|
||||
| `analyst` | Reads everything (usage, prompts, every user's sessions); no terminal, no write |
|
||||
| `analyst` | Reads everything (usage, prompts, every user's sessions), and works in their OWN workspaces like a developer. Never changes another user's rows or the host's configuration |
|
||||
| `developer` | Their own workspaces: start sessions, terminals, git, files. Sees nothing of other users, and cannot open or change the host's configuration |
|
||||
|
||||
`developer` was called `member` before; a database with members is migrated on
|
||||
start (`server/db.js`), and `member` is no longer accepted.
|
||||
|
||||
"The host's configuration" means a write (anything but GET/HEAD) under
|
||||
`/api/settings`, `/updates`, `/cc-config`, `/codex-config`, `/ai-proxies`,
|
||||
`/ai-routers`, `/git-credentials`, `/ai-tools`, `/import`, `/pricing`,
|
||||
`/budgets`, `/webhooks`, `/remote-sources` and `/reports`
|
||||
(`ADMIN_WRITE_PREFIXES` in `server/lib/auth.js`). A member who tries one gets
|
||||
`403 EADMIN`. An analyst who tries any write gets `403 EREADONLY`.
|
||||
`/budgets`, `/webhooks`, `/remote-sources`, `/reports`, `/pets`, `/users` and
|
||||
`/alerts/rules` (`ADMIN_WRITE_PREFIXES` in `server/lib/auth.js`). A developer
|
||||
or analyst who tries one gets `403 EADMIN`, shown in the UI as "Only an admin
|
||||
can do this". An analyst's other writes are scoped like a developer's: one
|
||||
naming another user's row gets `404 ENOTFOUND` (`memberId` in
|
||||
`server/lib/scope.js` limits every non-GET request of an analyst to their own
|
||||
rows).
|
||||
|
||||
The UI hides what a role cannot use (`usePermissions` in
|
||||
`client/src/components/AuthGate.tsx`): for anyone but an admin, Settings shows
|
||||
no Data, Pricing, AI proxy or per-tool pages, no scheduled reports or git
|
||||
credentials, no start-at-login/icon/Quit/Uninstall on System, no alert
|
||||
rules or channels, no install/update/enable on AI tools, no pet upload or
|
||||
delete, and no update check. An analyst's Workspace page and sidebar list only
|
||||
their own workspaces (`useWorkLanes`); other users' work is read on Sessions,
|
||||
Analytics and Users, where Resume, Fork, Snapshot and "Open in workspace" are
|
||||
hidden for a session that is not theirs. An analyst's alert feed
|
||||
(`GET /api/alerts`) carries `can_ack` on each alert — true only for their own
|
||||
sessions' — and the feed offers Acknowledge only there; Ack all acknowledges
|
||||
only theirs.
|
||||
|
||||
## What each user sees
|
||||
|
||||
@@ -104,34 +124,34 @@ Workspaces made before server mode, or by the host account, have none.
|
||||
- A session belongs to the workspace that owns it: `sessions.lane_id`, or the
|
||||
workspace whose pane holds it. Its agents, events, tokens, cost, alerts,
|
||||
snapshots and workflow runs belong to that session.
|
||||
- A **member** sees only rows of their own workspaces, everywhere: lists,
|
||||
- A **developer** sees only rows of their own workspaces, everywhere: lists,
|
||||
counts, charts, cost, the Sessions/Events/Agents tables, exports, live
|
||||
WebSocket updates and terminals. A request naming someone else's row (in the
|
||||
path, the query or the body) gets `404 ENOTFOUND`, the same answer as a row
|
||||
that does not exist (`scopeGuard`, `server/lib/scope.js`). Sessions with no
|
||||
workspace, such as ones started in a terminal outside AgentHub, are not shown
|
||||
to members.
|
||||
to developers.
|
||||
- An **admin** or **analyst** sees everything. Each time one of them opens a
|
||||
session a member owns (its page, transcript, events or cost), the read is
|
||||
session a developer owns (its page, transcript, events or cost), the read is
|
||||
written to the audit log: `agenthub users audit`, or `GET /api/users/audit`.
|
||||
- `GET /api/users` (admin/analyst) lists every account with its workspaces,
|
||||
sessions, and the tokens and $ it used in the last 7 and 30 days — the
|
||||
Users page in the sidebar shows it, with the audit log under it.
|
||||
|
||||
A member also cannot open the host's own configuration, or any view across all
|
||||
A developer also cannot open the host's own configuration, or any view across all
|
||||
users: Claude Code / Codex config (except the command and skill lists the
|
||||
prompt box uses), git credentials, remote sources, webhooks, reports, metrics,
|
||||
imports, data export, alert rules and `/api/users`. Those return
|
||||
`403 EADMIN`, and Settings hides them for members.
|
||||
`403 EADMIN`, and Settings hides them.
|
||||
|
||||
### Keep members' folders apart
|
||||
### Keep developers' folders apart
|
||||
|
||||
```bash
|
||||
# in ~/.config/agenthub/settings.env
|
||||
AGENTHUB_USERS_ROOT=/srv/agenthub/users
|
||||
```
|
||||
|
||||
With this set, a member can create a workspace only inside
|
||||
With this set, a developer or analyst can create a workspace only inside
|
||||
`/srv/agenthub/users/<username>`; any other folder gets `403 EFOLDER`. A folder
|
||||
that already belongs to another user's workspace gets `409 EOWNED`. Admins are
|
||||
not limited. Create each user's folder yourself. Until S3 this keeps workspaces
|
||||
@@ -151,10 +171,10 @@ apart, not agents.
|
||||
`403 EBADORIGIN`. This is on top of the `SameSite=Strict` cookie, which a
|
||||
sibling subdomain would still satisfy.
|
||||
- WebSockets need a login, and an `Origin` that is the request's own allowed
|
||||
Host. A terminal (`/ws-pty/*`) is refused to an analyst and to anyone but the
|
||||
owner of the pane's workspace. Open sockets are re-checked: `/ws` every 30 s,
|
||||
Host. A terminal (`/ws-pty/*`) is refused to anyone but an admin and the
|
||||
owner of the pane's workspace (an analyst included). Open sockets are re-checked: `/ws` every 30 s,
|
||||
terminals every 10 s (`AGENTHUB_PTY_RECHECK_MS`). A logout, a disable, a
|
||||
password change, or a demotion to analyst closes them.
|
||||
password change, or losing the pane's workspace closes them.
|
||||
- A login lasts 30 days in the httpOnly, `SameSite=Strict` cookie
|
||||
`agenthub_sid`. Only the token's SHA-256 is stored. Logging out, a password
|
||||
change and disabling the user each end it.
|
||||
@@ -170,12 +190,12 @@ apart, not agents.
|
||||
machine and only while that pane is alive, as header `x-agenthub-pane-token`.
|
||||
A workspace with no owner has no such user. Give old workspaces an owner with
|
||||
`agenthub users assign <workspace id> <user>`.
|
||||
- Named locks (`agenthub lock …`) are per user: a member's lock names live in
|
||||
- Named locks (`agenthub lock …`) are per user: a developer's lock names live in
|
||||
their own namespace, so one user's agents never see or take another's.
|
||||
- Browser push subscriptions belong to the user who made them. A
|
||||
notification goes only to that user's own browsers, never to the host's
|
||||
desktop.
|
||||
- A member cannot create a session by hand (`POST /api/sessions` → `403`), and
|
||||
- A developer or analyst cannot create a session by hand (`POST /api/sessions` → `403`), and
|
||||
cannot change a workspace's pane or session columns: `PATCH` accepts only
|
||||
`title`, `pipeline`, `notes`, `links` and `branch` (`403 EFIELD`).
|
||||
Pet uploads are admin-only.
|
||||
@@ -196,13 +216,13 @@ The same from the host's shell:
|
||||
|
||||
```bash
|
||||
agenthub users list
|
||||
agenthub users add <name> [--role admin|analyst|member]
|
||||
agenthub users add <name> [--role admin|analyst|developer]
|
||||
agenthub users passwd <name> # ends that user's logins
|
||||
agenthub users role <name> <role>
|
||||
agenthub users disable <name> # ends that user's logins; users are never deleted
|
||||
agenthub users enable <name>
|
||||
agenthub users assign <workspace id> <name> # give a pre-server-mode workspace an owner
|
||||
agenthub users audit [--limit N] # who read which member's session
|
||||
agenthub users audit [--limit N] # who read which developer's session
|
||||
agenthub server status
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user