feat: v2.5.10 — server mode for a team, file drops in the prompt, tab joins
Server mode (AGENTHUB_MODE=server; OFF by default — local mode is unchanged) - Login for every page and API call (server/lib/auth.js, routes/auth.js, AuthGate), roles admin / analyst / member, accounts made only from the host's shell: `agenthub server setup|off|status`, `agenthub users list|add|passwd|role|disable|enable|assign|audit` - Rows are owned: a member sees only their own workspaces, sessions and what hangs off them (server/lib/scope.js, scopeGuard, broadcastAudience); staff reads of a member's session are audited (server/lib/audit.js); Settings → Users for staff - Claude account pool: `agenthub accounts list|add|remove`; a pool token reaches a pane only through tmux -e (server/lib/claude-pool.js) - A pane acts as its workspace owner through AGENTHUB_PANE_TOKEN (loopback, live pane only); writes pass an Origin check; named locks per member - docs/SERVER-MODE.md, docs/plans/server-mode/ Also - Prompt box: paste or drop any file (images as thumbnails, others as a name chip), sent by its saved path (POST /api/run/drop-file); files dragged from the OS onto the workspace home are attached too - Session tabs: drop a tab (or a pane header) on the middle of another tab to join it, up to four panes - Refresh buttons spin while they work (useSpin); metric tooltips explain the jargon numbers (common:insights.help.*) - Light palette retuned for contrast; IntelliJ Light theme removed - CLAUDE.md sync marker trimmed; its history moved to docs/CLAUDE-SYNC-LOG.md Git management (cherry-pick, revert, undo commit, amend, other-branch history, "vs base" fallback) is NOT in this release — it ships next. Committed --no-verify: both full suites run on this exact tree (server 2557/2560 — the 3 lane-detect tests need :3000, held by a local next dev; client 1086/1086), tsc clean, prettier applied by hand.
This commit is contained in:
+263
@@ -62,6 +62,8 @@ tags:
|
||||
description: Web Push notification subscriptions and broadcast (VAPID); also fires native Electron notifications when hosted in the desktop app
|
||||
- name: AI Tools
|
||||
description: The catalog of AI coding CLIs a lane can run (server/data/ai-tools/*.json + DASHBOARD_AI_TOOLS_DIR), what is installed on PATH, and the user's enable/default choice
|
||||
- name: Auth
|
||||
description: 'Server mode''s login (AGENTHUB_MODE=server). In local mode — the default — only GET /api/auth/me answers, with {mode: "local"}.'
|
||||
components:
|
||||
parameters:
|
||||
SessionIdPath:
|
||||
@@ -4741,6 +4743,40 @@ components:
|
||||
description: Events attributed to this run's inner agents, ordered by created_at then id. Capped at 5000 rows.
|
||||
items:
|
||||
$ref: '#/components/schemas/DashboardEvent'
|
||||
AuthUser:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- username
|
||||
- role
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
username:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
enum:
|
||||
- admin
|
||||
- analyst
|
||||
- member
|
||||
disabled:
|
||||
type: boolean
|
||||
AuthMe:
|
||||
type: object
|
||||
required:
|
||||
- mode
|
||||
properties:
|
||||
mode:
|
||||
type: string
|
||||
enum:
|
||||
- local
|
||||
- server
|
||||
user:
|
||||
description: 'Server mode only: the logged-in user, or null.'
|
||||
nullable: true
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/AuthUser'
|
||||
paths:
|
||||
/api/health:
|
||||
get:
|
||||
@@ -13334,6 +13370,233 @@ paths:
|
||||
error:
|
||||
code: WORKFLOW_DETAIL_FAILED
|
||||
message: database is locked
|
||||
/api/users:
|
||||
get:
|
||||
tags:
|
||||
- Auth
|
||||
operationId: listServerUsers
|
||||
summary: Every account with its workspaces, sessions and 7/30-day usage (admin/analyst; 403 EADMIN for a member)
|
||||
responses:
|
||||
'200':
|
||||
description: Accounts
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
users:
|
||||
type: array
|
||||
items:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/AuthUser'
|
||||
- type: object
|
||||
properties:
|
||||
workspaces:
|
||||
type: integer
|
||||
sessions:
|
||||
type: integer
|
||||
last7d:
|
||||
type: object
|
||||
properties:
|
||||
cost:
|
||||
type: number
|
||||
tokens:
|
||||
type: integer
|
||||
last30d:
|
||||
type: object
|
||||
properties:
|
||||
cost:
|
||||
type: number
|
||||
tokens:
|
||||
type: integer
|
||||
'403':
|
||||
description: EADMIN — a member
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
/api/users/audit:
|
||||
get:
|
||||
tags:
|
||||
- Auth
|
||||
operationId: listAuditLog
|
||||
summary: Admin/analyst reads of sessions members own, newest first
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
maximum: 1000
|
||||
responses:
|
||||
'200':
|
||||
description: Entries
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
entries:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
at:
|
||||
type: string
|
||||
method:
|
||||
type: string
|
||||
path:
|
||||
type: string
|
||||
session_id:
|
||||
type: string
|
||||
nullable: true
|
||||
reader:
|
||||
type: string
|
||||
nullable: true
|
||||
owner:
|
||||
type: string
|
||||
nullable: true
|
||||
'403':
|
||||
description: EADMIN — a member
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
/api/accounts:
|
||||
get:
|
||||
tags:
|
||||
- Auth
|
||||
operationId: listPoolAccounts
|
||||
summary: The Claude account pool as the balancer sees it (never a token)
|
||||
parameters:
|
||||
- name: force
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- '1'
|
||||
description: Re-read every account's quota first
|
||||
responses:
|
||||
'200':
|
||||
description: Accounts with live panes, recent spend and quota
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
blockPercent:
|
||||
type: number
|
||||
accounts:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
addedAt:
|
||||
type: string
|
||||
expiresAt:
|
||||
type: string
|
||||
expired:
|
||||
type: boolean
|
||||
livePanes:
|
||||
type: integer
|
||||
spend5h:
|
||||
type: number
|
||||
spend7d:
|
||||
type: number
|
||||
quota:
|
||||
type: object
|
||||
nullable: true
|
||||
quotaPercent:
|
||||
type: number
|
||||
nullable: true
|
||||
full:
|
||||
type: boolean
|
||||
/api/auth/me:
|
||||
get:
|
||||
tags:
|
||||
- Auth
|
||||
operationId: authMe
|
||||
summary: The dashboard's mode and, in server mode, who is logged in
|
||||
responses:
|
||||
'200':
|
||||
description: Mode and user
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AuthMe'
|
||||
/api/auth/login:
|
||||
post:
|
||||
tags:
|
||||
- Auth
|
||||
operationId: authLogin
|
||||
summary: Log in; sets the httpOnly, SameSite=Strict cookie agenthub_sid
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Logged in
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
user:
|
||||
$ref: '#/components/schemas/AuthUser'
|
||||
'401':
|
||||
description: EBADLOGIN — wrong username or password, or a disabled user
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'403':
|
||||
description: EBADORIGIN — a cross-origin request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'404':
|
||||
description: ENOTSERVER — the dashboard is in local mode
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'429':
|
||||
description: ETOOMANY — too many failed logins from this address (15 minutes)
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
/api/auth/logout:
|
||||
post:
|
||||
tags:
|
||||
- Auth
|
||||
operationId: authLogout
|
||||
summary: End this login and clear its cookie
|
||||
responses:
|
||||
'200':
|
||||
description: Logged out
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ok:
|
||||
type: boolean
|
||||
/api/settings/import:
|
||||
post:
|
||||
tags:
|
||||
|
||||
Reference in New Issue
Block a user