Admin API 完整参考

July 7, 2026 · View on GitHub

HotPlex Admin API 提供网关运维管理能力:会话管理、健康检查、监控指标、配置审计、日志查询和定时任务控制。默认监听 localhost:9999,独立于网关主端口(8888)。

交互式 API 控制台:可直接在浏览器中浏览和测试所有端点 → 打开 API 控制台 (基于 OpenAPI 规范自动生成,与代码保持同步)

认证

所有 Admin 端点(/admin/health/admin/health/ready 除外)均需 Bearer Token 认证。Token 通过以下两种方式传递:

# 方式一:Authorization header(推荐)
curl -H "Authorization: Bearer <token>" http://localhost:9999/admin/stats

# 方式二:Query string(适用于浏览器场景)
curl http://localhost:9999/admin/stats?access_token=<token>

Token 使用 crypto/subtle.ConstantTimeCompare 进行常量时间比较,防止时序攻击。

Cookie 认证兜底(WebChat 多租户部署):当请求未携带 Bearer Token 时,若已启用 WebChat 多租户(CookieAuth 与本地账号身份提供者就绪),中间件会转而解析 chat session cookie,校验为 active 且角色为 admin 的用户后放行,并授予完整 scope 集合——嵌入式 WebChat 中已登录的管理员可直接访问 Dashboard/Bots/Cron,无需另发 admin token。Bearer 仍优先;standalone/CLI 部署(未启用多租户)保持仅 Bearer 行为。该 cookie 通道的写方法同样适用下文的「CSRF 同源校验」;跨源 cookie 调用还需在 CORS allowedOrigins 显式列出 WebChat origin(* 通配会抑制 Allow-Credentials,浏览器将拒绝发送 session cookie)。

Token 配置

admin:
  enabled: true
  addr: "localhost:9999"
  tokens:                          # 简单 token,使用 default_scopes
    - "my-admin-token"
  token_scopes:                    # 细粒度 scope token
    "ops-token": ["session:read", "stats:read", "health:read"]
    "admin-token": ["session:read", "session:write", "session:delete", "stats:read", "health:read", "admin:write"]
  default_scopes: ["session:read", "session:write", "session:delete", "stats:read", "health:read", "admin:write"]

Scope 权限矩阵

不同的 Scope 控制着对 Admin API 不同模块的访问级别。

Scope TokenHealthSessionsStatsConfigDebugCron覆盖的核心端点 (Endpoints)
health:read🟢 Read-----/admin/health/workers
session:read-🟢 Read----GET /admin/sessions
GET /admin/sessions/{id}/stats
session:write-🟠 Write----POST /admin/sessions/{id}/terminate
session:delete-🔴 Delete----DELETE /admin/sessions/{id}
stats:read--🟢 Read---GET /admin/stats
GET /admin/metrics
config:read---🟢 Read--POST /admin/config/validate
config:write---🟠 Write--POST /admin/config/rollback
admin:read----🟢 Read🟢 ReadGET /admin/logs
GET /admin/debug/...
GET /admin/bots
GET /admin/cron/jobs
admin:write-----🟠 WritePOST/PATCH/DELETE /admin/cron/jobs
POST /admin/cron/jobs/{id}/run

💡 图例:🟢 Read (只读查询) | 🟠 Write (状态变更/操作) | 🔴 Delete (物理删除)

安全中间件

按以下顺序执行:

  1. CORSAccess-Control-Allow-Origin: *,允许 GET/POST/DELETE/OPTIONS
  2. Panic Recoverydefer recover() 捕获 handler panic,返回 500 Internal Server Error
  3. Rate Limiting — 令牌桶算法(默认 10 req/s,burst 20),超限返回 429 Too Many Requests
  4. IP Whitelist — CIDR 匹配(默认 127.0.0.0/8, 10.0.0.0/8),使用 r.RemoteAddr 防止 X-Forwarded-For 伪造
  5. Token Auth — Bearer Token 提取 + scope 校验

Rate Limit 和 IP Whitelist 支持配置热重载,无需重启生效。

操作审计

所有 admin 写操作(POST/PUT/PATCH/DELETE)均进入 user_activity 防篡改审计表(issue #833),并在兼容期继续输出结构化 slog 事件(admin_audit,issue #788 A5)。user_activity 是权威审计载体;admin_audit 仅保留给既有日志看板迁移使用。

覆盖范围

  • /admin/*(端口 9999,Bearer Token):在 AdminAPI.Middleware 的审计 defer 中统一记录——无论请求最终成功或失败,写方法都会产生一条审计记录;(method, path) 映射为稳定 action 枚举,未映射路由回退 "<method> <path>",确保无写操作静默丢失。
  • /api/admin/*/api/workspaces/*(端口 8888,Cookie):在各 handler 的成功/失败路径显式记录;CSRF 同源校验拦截的跨站写请求同样记审计(action auth.denied,详见下文「CSRF 同源校验」)。

审计字段

字段说明
actor_user_id操作者标识:Cookie 通道为用户 uid;Bearer 通道为 admin-token;认证未解析或失败时为 anonymous
action稳定动作枚举(见下表),日志看板按此过滤,不可重命名
target请求路径(含资源 id)
resultok(成功)/ failed(操作失败)/ denied(认证或授权拒绝)

action 枚举

资源域action
网关gateway.restart
Botbot.create / bot.update / bot.delete
API Keyapikey.create / apikey.update / apikey.delete
Croncron.create / cron.update / cron.delete / cron.trigger
Sessionsession.delete / session.terminate / session.patch / session.put
Auditaudit.identity_link.create / audit.identity_link.delete
Configconfig.rollback / config.validate
多租户成员/邀请member.status.update / invitation.create / invitation.delete
认证拒绝auth.denied

端点总览

健康检查

方法路径Scope说明
GET/admin/health无需认证综合健康状态(gateway + DB + workers)
GET/admin/health/workershealth:readWorker 粒度健康状态
GET/admin/health/ready无需认证就绪探针(k8s readiness)

GET /admin/health — 无需认证,适合负载均衡器探活。返回 status(healthy/degraded)、checks(gateway + database + workers)和 version。数据库不可用时降级为 degradeddatabase.error 附带错误信息。

GET /admin/health/workers — Worker 粒度健康状态,含 workers[](healthy/type/pid)和 checked_at。任一 Worker 不健康时返回 503

会话管理

方法路径Scope说明
GET/admin/sessionssession:read列出会话(分页)
GET/admin/sessions/{id}session:read获取单个会话
DELETE/admin/sessions/{id}session:delete物理删除会话
POST/admin/sessions/{id}/terminatesession:write终止会话(状态迁移)
GET/admin/sessions/{id}/statssession:read会话 Turn 统计

GET /admin/sessions — 支持 query 参数过滤:

curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:9999/admin/sessions?limit=50&offset=0&platform=slack&user_id=U12345"
参数类型默认值说明
limitint100每页数量(上限 1000)
offsetint0偏移量
platformstring""按平台过滤
user_idstring""按用户过滤

POST /admin/sessions/{id}/terminate — 将会话状态迁移至 terminated(软终止,保留记录)。DELETE 则为物理删除。

注意:会话创建不通过 Admin API,而是通过 Gateway API(POST /api/sessions)或 WebSocket init 握手完成。Admin API 仅提供只读查询和终止/删除操作。

监控指标

方法路径Scope说明
GET/admin/statsstats:read网关聚合统计
GET/admin/metricsstats:readPrometheus 格式指标

GET /admin/stats — 返回 gateway(uptime/websocket_connections/sessions_active/sessions_total)、workers(按 worker_type 分组统计)和 database(sessions_count)。

配置管理

方法路径Scope说明
POST/admin/config/validateconfig:read校验配置片段
POST/admin/config/rollbackconfig:write回滚到历史版本

POST /admin/config/validate — 校验配置合法性(不应用),请求体最大 1MB:

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"gateway":{"addr":":8888"},"pool":{"max_size":50}}' \
  http://localhost:9999/admin/config/validate

支持校验:gateway(buffer sizes >= 0)、db(path 长度 <= 4096)、worker(timeouts)、pool(max_size 1-10000)。返回 { "valid", "errors[]", "warnings[]" }

POST /admin/config/rollback — 回滚到指定版本,请求体 {"version": 3},返回 { "ok", "rolled_back", "history_index" }。无 configWatcher 时返回 503

日志与调试

方法路径Scope说明
GET/admin/logsadmin:read最近日志(环形缓冲区)
GET/admin/debug/sessions/{id}admin:read会话调试快照

GET /admin/logs — 从 100 条环形缓冲区读取,?limit=N(最大 1000)。返回 { "logs[]", "total", "limit" }

GET /admin/debug/sessions/{id} — 会话详情 + 调试快照(debug.availablehas_workerturn_countlast_seq_sentworker_health)。

Cron 定时任务

方法路径Scope说明
GET/admin/cron/jobsadmin:read列出所有任务
GET/admin/cron/jobs/{id}admin:read获取单个任务
POST/admin/cron/jobsadmin:write创建任务
PATCH/admin/cron/jobs/{id}admin:write更新任务
DELETE/admin/cron/jobs/{id}admin:write删除任务
POST/admin/cron/jobs/{id}/runadmin:write手动触发执行
GET/admin/cron/jobs/{id}/runsadmin:read执行历史

请求体约定

  • POST /admin/cron/jobs — JSON body 含 nameschedule(cron:/every:/at: 前缀)、messagebot_idowner_idenabled。返回 201 Created
  • PATCH /admin/cron/jobs/{id} — 部分更新,JSON body。返回 204 No Content
  • POST /admin/cron/jobs/{id}/run — 手动触发(异步),返回 202 Accepted
  • GET /admin/cron/jobs/{id}/runs — 查询执行历史。

Cron 未启用时返回 503 Service Unavailable

Bot 管理

Bot 状态查询、配置管理和 Agent 配置文件操作端点。

方法路径Scope说明
GET/admin/botsadmin:read列出所有活跃 bot
GET/admin/bots/{name}admin:read单个 bot 详情
POST/admin/botsadmin:write注册新 bot
PATCH/admin/bots/{name}admin:write更新 bot 配置(部分更新)
DELETE/admin/bots/{name}admin:write删除 bot 注册
GET/admin/bots/configadmin:read列出所有 bot 配置
GET/admin/bots/{name}/configadmin:read单个 bot 完整配置
GET/admin/bots/{name}/config/{file}admin:read读取 Agent 配置文件(如 SOUL.md、AGENTS.md)
PUT/admin/bots/{name}/config/{file}admin:write写入 Agent 配置文件
GET/admin/bots/platform/{platform}/config/{file}admin:read读取平台级 channel 默认配置文件(webchat 等,绕过 registry 寻址 dir/{platform}/ 层)
PUT/admin/bots/platform/{platform}/config/{file}admin:write写入平台级 channel 默认配置文件
GET/admin/bots/{name}/previewadmin:read预览组装后的系统提示(B+C 通道完整输出)

GET /admin/bots — 返回所有活跃 bot 列表,含 name、platform、worker_type、状态等信息。

POST /admin/bots — 注册新 bot,JSON body 含平台凭证和配置。返回 201 Created

PATCH /admin/bots/{name} — 部分更新 bot 配置(凭证、worker_type 等)。返回 204 No Content

GET /admin/bots/{name}/preview — 返回该 bot 组装后的完整系统提示,包含 B 通道(directives)和 C 通道(context)内容,便于调试 Agent 人格配置。

**PUT /admin/bots/{name}/config/{file}** — 写入指定 Agent 配置文件(如 SOUL.mdAGENTS.mdUSER.md)。请求体为文件内容,Content-Type 为 text/plain`。

GET/PUT /admin/bots/platform/{platform}/config/{file} — 读写平台级 channel 默认 Agent 配置文件。{platform} 为平台标识(如 webchat),绕过 messaging registry 直接寻址 dir/{platform}/ 层,让无 bot 实例的平台(webchat team-default)获得与消息平台 bot 对等的配置编辑能力。文件白名单与 bot 级端点一致(SOUL.md/AGENTS.md/SKILLS.md/USER.md/MEMORY.md),复用 /admin/* 中间件鉴权(admin:read/admin:write)与审计。

网关重启

方法路径Scope说明
POST/admin/restartadmin:write触发网关重启

POST /admin/restart — 异步触发网关重启。Gateway 在 500ms 延迟后执行重启,立即返回 { "status": "restarting" }。使用 restart helper(独立 PGID)确保安全隔离。未配置 restart handler 时返回 503

用户行为审计

/admin/activity 系列端点查询 issue #833 的 user_activity 表。所有读端点需要 admin:read;导出默认脱敏,include_pii=true 需要 admin:write。每次导出都会写入 system.audit_export meta-audit。

方法路径Scope说明
GET/admin/activityadmin:read查询全局活动时间线
GET/admin/activity/exportadmin:read导出全局活动时间线(`format=json
GET/admin/users/{id}/activityadmin:read查询单个原生 user_id 的活动
GET/admin/users/{id}/activity/exportadmin:read导出单个原生 user_id 的活动
GET/admin/audit/identity-linksadmin:read列出跨通道身份链接
POST/admin/audit/identity-linksadmin:write创建或更新身份链接
DELETE/admin/audit/identity-links/{id}admin:write删除身份链接

查询参数:

参数说明
user_id按审计行原始 user_id 查询
principal_user_id按本地 canonical 用户查询;会展开 audit_identity_links 中的所有平台原生 subject
action精确匹配 action,如 tool.call / admin.bot.create
outcomesuccess / failure / denied
from / toRFC3339 时间范围
limit / offset分页
format导出格式:jsoncsv

POST /admin/audit/identity-links — JSON body:

{
  "principal_user_id": "local-user-uuid",
  "provider": "feishu",
  "subject": "ou_xxx",
  "subject_type": "platform",
  "display_name": "Alice",
  "email": "alice@example.com"
}

principal_user_idprovidersubject 必填;subject_type 默认为 platform,允许 registered / platform / system / anonymousUNIQUE(provider, subject) 保证一个平台原生 ID 只归属一个 principal。写操作通过 middleware 审计为 admin.audit.identity_link.create / admin.audit.identity_link.delete

API Key 用户管理

管理 API Key 到用户身份的映射,用于企业级多用户 Session 隔离。每个 user_id 与 API Key 为 1:1 映射(一个 user_id 仅能关联一个 API Key),创建或更新时若 user_id 已被其他映射占用则返回 409 Conflict。需要数据库支持(SQLite 或 PostgreSQL),未配置 DB resolver 时返回 501 Not Implemented

方法路径Scope说明
GET/admin/api-keysadmin:read列出所有 API Key 映射
POST/admin/api-keysadmin:write创建 API Key 映射
GET/admin/api-keys/{id}admin:read获取单个映射详情
PATCH/admin/api-keys/{id}admin:write更新映射
DELETE/admin/api-keys/{id}admin:write删除映射

POST /admin/api-keys — 创建 API Key → UserID 映射。JSON body 含 user_id(必填,最长 128 字符)和 description(可选,最长 512 字符)。API Key 由系统自动生成(24 字节随机 hex)。返回 201 Created;若 user_id 已存在则返回 409 Conflict

GET /admin/api-keys — 返回所有映射列表,api_key 字段自动脱敏(仅显示前 8 + 后 4 位)。

PATCH /admin/api-keys/{id} — 更新指定映射的 user_iddescription。若新 user_id 与其他映射冲突则返回 409 Conflict

DELETE /admin/api-keys/{id} — 物理删除映射,同时清除缓存的 resolver 条目。

Workspace 管理(admin 控制台)

🆕 issue #807 — admin 控制台的 workspace 全局视图。区别于用户自助的 /api/workspaces/*(见下文 Gateway API 段):这两个端点走 admin 双通道鉴权(Bearer + Cookie fallback,强制 role==admin && status==active),列出全平台 workspace 并支持 inline 修改 permission_mode

方法路径Scope说明
GET/admin/workspacesadmin:read列出所有 workspace(带 owner 可读标识)
PATCH/admin/workspaces/{id}admin:write修改单个 workspace 的 permission_mode

GET /admin/workspaces — 返回所有 active workspace,LEFT JOIN users 带上 owner 可读标识(owner_display_name + owner_username),admin 无需面对裸 UUID。owner 行缺失时(并发删除窗口)owner 字段回落为空串、workspace 仍返回。响应:{"workspaces":[{id, owner_user_id, owner_display_name, owner_username, name, work_dir, permission_mode, status, created_at, updated_at, agent_config_overrides, worker_preference}]}。读操作不审计。

PATCH /admin/workspaces/{id}接受 permission_mode 字段(admin 控制台范围最小化:不暴露 work_dir/name 修改,避免 admin 误改用户工作目录;这些仍走用户自助 /api/workspaces/{id})。JSON body:{"permission_mode":"<tier>"}permission_mode 必须显式提供(缺失返回 400 BAD_REQUEST);值为 4 档之一(bypass/auto-edit/workspace/read-only)或空串(清除覆盖,回落 config.worker.default_permission_mode,缺省 workspace)。返回更新后的 workspace 裸行。

⏱️ 生效语义:写库后运行中 session 不受影响(worker 进程已注入权限参数);新 session(新对话 / /reset)初始化时 resolveWorkspacePermissionMode 读到新值。UI 标注「对新会话生效」。

🛡️ 审计:PATCH 写操作由 middleware 级 admin_audit 统一记录,action = workspace.permission_mode.update,actor = uid(Cookie 通道)或 admin-token(Bearer),target = /admin/workspaces/{id}

PATCH 错误码:400 INVALID_PERMISSION_MODE(档位非法)/ 400 BAD_REQUEST(body 缺 permission_mode)/ 404 WORKSPACE_NOT_FOUND(id 不存在)/ 409 WORKSPACE_VERSION_MISMATCHupdated_at CAS 冲突;或并发更新下 workspace 恰有活跃会话时的 CAS heuristic 误判——本端点只改 permission_mode、不动 work_dir,活跃会话不真正阻塞,故两种成因都应重新 GET 最新 updated_at 后重试,新值仅对新会话生效)。

Gateway API 端点

Gateway API(/api/sessions)监听在网关主端口(8888),面向客户端 SDK 和 WebSocket 连接,使用 API Key 认证(非 Bearer Token)。

方法路径认证说明
GET/api/sessionsAPI Key列出当前用户的会话
POST/api/sessionsAPI Key创建会话
GET/api/sessions/{id}API Key获取单个会话
DELETE/api/sessions/{id}API Key删除会话
POST/api/sessions/{id}/cdAPI Key切换工作目录
GET/api/sessions/{id}/historyAPI Key获取会话历史
GET/api/sessions/{id}/eventsAPI Key获取会话事件流
GET/api/workersAPI Key列出 Worker 类型及二进制安装状态

所有 Gateway API 端点启用 CORS(Access-Control-Allow-Origin: *),支持 GETPOSTDELETEOPTIONS 方法。

GET /api/workers — 返回所有已注册 Worker 类型(claude_code / opencode_server / codex_cli / acp)的二进制安装状态,供客户端(如 WebChat「新建会话」弹窗)动态过滤可选引擎,避免误选未安装的 Worker。命令名取自配置(worker.<type>.command),缺失时回落到各类型的默认二进制(claude / opencode / codex / hermes),再经 exec.LookPath 探测。响应体为 JSON 数组:[{"type":"<worker_type>","installed":<bool>,"path":"<abs_path, omitempty>"}]

WebChat 多租户端点(spec ① / ④ / ⑥)

WebChat 多租户登录与工作区管理端点,同样监听在网关主端口 8888,默认使用 Cookie 认证(登录后签发的 HMAC Cookie);其中 workspace CRUD 还接受 API Key(跨通道租户接入,详见下方「Workspace 管理」)。仅在启用 WebChat 多租户(CookieAuth + WorkspaceStore 就绪)时注册,普通 SDK/WebSocket 集成不涉及。

账号登录(spec ①)

方法路径认证说明
POST/api/auth/login内建账号登录(username/password),成功签发 Cookie
POST/api/auth/logoutCookie登出并清除 Cookie
GET/api/auth/meCookie当前登录用户信息
POST/api/auth/accept-invite无(邀请码)凭邀请码(body code)注册本地账号并自动登录(签发 cookie,返回 first_login:true),加入 workspace
GET/api/auth/bootstrap-status首次部署引导状态(是否已存在管理员),登录页据此决定是否引导建号

企业 SSO(spec ④,OIDC + PKCE)

方法路径认证说明
GET/api/auth/oauth/providers列出已配置的 SSO provider(登录页据此渲染按钮)
GET/api/auth/oauth/{provider}/login发起 OIDC 登录,重定向到 IdP(name 须匹配 [a-z0-9-]+
GET/api/auth/oauth/{provider}/callbackstate cookieOIDC 回调,完成 token exchange + ID Token 验证后签发 Cookie

GET /api/auth/oauth/providers 始终返回稳定 envelope:

{
  "providers": [
    { "name": "keycloak", "display_name": "企业 SSO" }
  ]
}

Workspace 管理(spec ⑥ A1 / ⑦ 跨通道租户)

Workspace CRUD 是跨通道租户锚:同一个 users.id 无论经 API Key(header X-API-Key 或 query api_key,面向第三方集成)还是 Cookie(WebChat UI)进入,都能拥有并管理自己的 workspace。鉴权链为 API Key 优先、Cookie 兜底(AuthenticateRequest),与 session REST、WS upgrade 对齐。work_dir workspace 级可改:PATCH 携带 work_dir 时校验 owner 沙箱(403 WORK_DIR_OUTSIDE_SANDBOX)且 workspace 必须无活跃会话(409 WORKSPACE_NOT_EMPTY,因 work_dir 进 session key 派生)。session 级 switch-workdir 对 workspace-bound session 返回 400 WORK_DIR_IMMUTABLE(worker 须跟随 workspace)。详见 WebChat-Workspace-Create-WorkDir-Prefix-Spec §5.1.4。

方法路径认证说明
POST/api/workspacesAPI Key / Cookie创建 workspace
GET/api/workspacesAPI Key / Cookie列出当前用户可访问的 workspace
GET/api/workspaces/{id}API Key / Cookieworkspace 详情(含归属校验)
PATCH/api/workspaces/{id}API Key / Cookie更新 workspace(乐观并发,见下)
DELETE/api/workspaces/{id}API Key / Cookie删除 workspace

🔒 permission_mode 为 admin-only 字段(r3 #804):POST /api/workspaces 与 PATCH /api/workspaces/{id} 仅 admin 可设置/修改 permission_mode。非 admin 请求体携带该字段(含空串清空)一律返回 403 PERMISSION_DENIEDmessage: permission_mode can only be configured by admins);非 admin 仍可改 name / work_dir / agent_config_overrides / worker_preference。未显式配置的 workspace 由 bridge 注入 config.worker.default_permission_mode(缺省 workspace)。

PATCH 乐观并发(CAS):更新基于 updated_at 做乐观锁——服务端 UPDATE ... WHERE id = ? AND updated_at = ?,调用方缓存的 updated_at 不再匹配(被并发修改)时影响 0 行,返回 409 WORKSPACE_VERSION_MISMATCH("workspace concurrently modified, please re-fetch and retry")。客户端无需在 body 显式传版本字段(先 GET 取最新值再 PATCH),收到 409 后应重新 GET 再重试,避免静默 lost update。

PATCH body 字段语义nameagent_config_overrides 传空字符串表示不更新(无法通过 PATCH 清空这两项);worker_preference 为指针类型以区分三态——省略(字段未传)不更新、空字符串 "" 显式清除回默认 worker、非空设为指定类型(校验失败返回 400 INVALID_WORKER_TYPE);work_dir 为 workspace 级可变字段——省略/空字符串不更新,非空时校验 owner 沙箱(403 WORK_DIR_OUTSIDE_SANDBOX)、值变更须 workspace 无活跃会话(409 WORKSPACE_NOT_EMPTY,因 work_dir 进 session key 派生)、且未被该 owner 其他 workspace 占用(409 WORK_DIR_TAKEN)后更新(见上)。

Workspace 用户与邀请管理(spec ⑥,admin 维度)

方法路径认证说明
GET/api/admin/usersCookie列出 workspace 用户
PATCH/api/admin/users/{id}Cookie启用/禁用用户(disable 后 per-request 即时拦截)
POST/api/admin/invitationsCookie创建邀请码
GET/api/admin/invitationsCookie列出邀请
DELETE/api/admin/invitations/{id}Cookie删除邀请

GET /api/admin/invitations — 每条邀请额外返回服务器计算的 is_expiredtrue 表示邀请码未被使用且已过期),客户端无需自行比对 expires_at 与本地时钟,规避时钟漂移。

⚠️ 注意区分:此处的 /api/admin/*(端口 8888,Cookie 认证,WebChat workspace 维度)与本页上方「认证」章节描述的 Admin API(端口 9999,Bearer Token,网关运维维度)是两套独立端点,认证模型和作用域完全不同,不要混淆。

🔒 CSRF 同源校验(写方法)/api/admin/*/api/workspaces/* 的状态变更方法(POST/PATCH/DELETE)挂载同源验证中间件,防御针对 SameSite=None session cookie 的跨站写请求;GET 一律放行。写方法需提供「同源证明」之一——浏览器 Sec-Fetch-Site 取值为 same-origin/same-site,或 Origin 精确命中 CORS allowedOrigins* 通配满足:SameSite=None cookie 恰在 allowlist 宽松时跨站送达)。未通过返回 403 FORBIDDENmessage: cross-origin write blocked)并记入 admin 审计日志。嵌入式 WebChat SPA 与网关同源,天然通过;跨域前端需将自身 origin 列入 allowedOrigins

错误响应格式

所有错误统一返回 JSON envelope(Content-Type: application/json),形状为:

{"error":{"code":"NOT_FOUND","message":"resource not found"}}

code 为机器可读的大写下划线标识符,message 为人类可读的英文描述。客户端应依据 code 做分支,而非解析 message。此信封由 web.WriteAppError 统一生成,Admin API(Bearer)与 /api/admin/*(Cookie)共用同一形状。

错误码表

HTTPcode典型场景
400BAD_REQUESTJSON 解析失败、参数校验错误、非法枚举值
400INVALID_CONFIG_JSONworkspace agent_config_overrides 不是合法 JSON 对象
400UNKNOWN_CONFIG_FILEworkspace overrides 含未知配置文件键
400CONFIG_TOO_LARGEworkspace overrides 超过单文件大小上限
400INVALID_CONFIG_VALUEworkspace overrides 值类型/内容非法
400INVALID_WORK_DIRworkspace work_dir 路径无法展开或不存在
400INVALID_WORKER_TYPEworkspace worker_preference 非已注册 worker 类型
401UNAUTHORIZEDToken 缺失或无效
401INVALID_CREDENTIALSCookie 会话失效或未登录
403INSUFFICIENT_SCOPEBearer Token scope 不满足(Admin API)
403FORBIDDEN非管理员访问管理端点,或请求 IP 不在白名单(见「安全中间件」IP Whitelist,两类 403 共用同一 code)
403USER_DISABLED用户已被禁用
403WORKSPACE_FORBIDDEN非所有者访问他人 workspace(且非 admin)
403WORK_DIR_FORBIDDENworkspace work_dir 命中安全黑名单(系统目录等)
403WORK_DIR_OUTSIDE_SANDBOXworkspace work_dir 不在 owner 沙箱前缀下
403PERMISSION_DENIED非 admin 试图在 workspace Create/Update 设置或修改 permission_mode(admin-only 字段,r3 #804)
404NOT_FOUNDSession/Cron Job/Invitation 未找到
404WORKSPACE_NOT_FOUNDworkspace id 不存在
409CONFLICT资源状态冲突
409WORKSPACE_VERSION_MISMATCHPATCH workspace 乐观并发冲突(updated_at CAS 失败,re-fetch 后重试)
409WORKSPACE_NOT_EMPTYworkspace 存在活跃会话,拒绝改 work_dir / 删除
409WORK_DIR_TAKENworkspace work_dir 已被该 owner 的其他 workspace 占用
429RATE_LIMITED触发 Rate Limit
500INTERNALHandler panic、未分类内部错误
501NOT_IMPLEMENTED该接口尚未实现
503SERVICE_UNAVAILABLE数据库故障、Cron 未启用
503NO_IDP未配置身份提供者

常用操作示例

# 快速健康检查(无需 Token)
curl http://localhost:9999/admin/health

# 查看活跃会话
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:9999/admin/sessions?limit=10

# 查看 Prometheus 指标
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:9999/admin/metrics

# 终止异常会话
curl -X POST -H "Authorization: Bearer $TOKEN" \
  http://localhost:9999/admin/sessions/abc-123/terminate

# 查看最近日志
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:9999/admin/logs?limit=20"

# 调试特定会话
curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:9999/admin/debug/sessions/abc-123

# 触发 Cron 任务
curl -X POST -H "Authorization: Bearer $TOKEN" \
  http://localhost:9999/admin/cron/jobs/daily-health/run