跳转至

ADR-005: hermesx-webui Admin Bootstrap 端点设计

决策信息

字段
编号 ADR-005
标题 POST /admin/v1/bootstrap — 首次部署超管引导端点
状态 Accepted
日期 2026-05-08
Owner architect + backend-engineer
关联需求 docs/artifacts/2026-05-08-hermesx-webui/prd.md (US-Bootstrap)

背景与约束

  • PRD 决策 #3:首次部署时若无 admin key,展示 Bootstrap 引导页,通过 HERMES_ACP_TOKEN 完成首个 admin key 创建。
  • 挑战会发现:ACP(Agent Communication Protocol)是编辑器集成协议包,不是 admin 引导 token 机制。
  • internal/acp/ 包实现了 editor ↔ agent 的 JSON-RPC 协议
  • HERMES_ACP_TOKEN 是静态 bearer,由 StaticTokenExtractor 在 auth chain 中处理,赋予 system:acp-admin identity
  • 因此,Bootstrap 流程可以复用 HERMES_ACP_TOKEN 作为一次性授权凭证,但需要独立的 Bootstrap 端点
  • 当前无 GET /admin/v1/tenants/{id}/api-keys 接口(已在 intake 识别为 backend gap)。

设计决策

Bootstrap 端点规格

GET /admin/v1/bootstrap/status

  • 无需认证(公开端点)
  • 响应:{"bootstrap_required": true} — 当 DB 中 admin role 的 API key 数量为 0 时返回 true
  • 前端用途:页面加载时检查,决定展示"登录"还是"Bootstrap 引导"

POST /admin/v1/bootstrap

  • 认证:Authorization: Bearer <HERMES_ACP_TOKEN>(静态 token,仅在初始化阶段已知)
  • 请求体:{"name": "initial-admin-key", "expires_at": "2027-01-01T00:00:00Z"}
  • 逻辑:
  • 验证 ACP token(通过现有 StaticTokenExtractor chain)
  • 原子检查:若 admin API key 数量 > 0,返回 403 Forbidden {"error": "bootstrap already completed"}
  • 创建 API key,roles: ["admin"],scopes: ["admin", "chat", "read"]
  • 返回明文 key(唯一一次返回明文):{"api_key": "hx-...", "key_id": "...", "name": "..."}
  • 安全门:端点在 bootstrap_required=false 时返回 403,防止重复调用

GET /admin/v1/tenants/{id}/api-keys

新增接口,列出租户下所有 API keys(掩码展示): - 认证:admin API key(RequireScope("admin")) - 响应:{"api_keys": [{"id": "...", "name": "...", "prefix": "hx-...", "roles": [...], "scopes": [...], "expires_at": "...", "revoked_at": null, "created_at": "..."}]} - 实现:查询 api_keys 表,按 tenant_id 过滤,不返回 key_hash

前端 Bootstrap 流程

GET /admin/v1/bootstrap/status
  → {bootstrap_required: true}  → BootstrapPage.vue
  → {bootstrap_required: false} → AdminLoginPage.vue

BootstrapPage.vue:
  1. 用户输入 HERMES_ACP_TOKEN(运维人员提供)
  2. 输入新 admin key 名称和过期时间
  3. POST /admin/v1/bootstrap → 显示一次性明文 key(复制后确认关闭)
  4. 跳转 AdminLoginPage,用新 key 登录

安全说明

  • HERMES_ACP_TOKEN 不存储在前端,仅用于一次性 POST 请求,不放 sessionStorage
  • Bootstrap 端点在正式运行后永久返回 403(因为 admin key 已存在)
  • 明文 key 只在 POST /admin/v1/bootstrap 响应中出现一次,后端只存 SHA-256 hash

后续动作

动作 Owner 完成条件
实现 GET /admin/v1/bootstrap/status backend-engineer Phase 0
实现 POST /admin/v1/bootstrap backend-engineer Phase 0
实现 GET /admin/v1/tenants/{id}/api-keys backend-engineer Phase 0
前端 BootstrapPage.vue frontend-engineer Phase 1
前端 Bootstrap 状态检查集成到 AdminApp 启动 frontend-engineer Phase 1