diff --git a/docs/design/heicode-hm-team-control-design.md b/docs/design/heicode-hm-team-control-design.md new file mode 100644 index 0000000..150013c --- /dev/null +++ b/docs/design/heicode-hm-team-control-design.md @@ -0,0 +1,219 @@ +# HM 团队管控设计(参考 Claude Code 企业范式) + +> 起草:2026-06-05 · 状态:设计草案(供讨论,不含实现) +> +> 类比锚点:**我们的桌面客户端 ≈ Claude Code** · **HM(Heicode Manager)≈ Claude.ai 企业/管理控制台** · **AM(agent_management)≈ 云端 agent 运行时**。 +> +> 本文把 Claude 的企业管控范式(来自官方文档 admin-setup / authentication / server-managed-settings / settings / managed-mcp / auto-mode-config)提炼为「团队如何通过 HM 控制与分配」的设计,并**逐条对齐 HM 现状**(new-api fork 本身已有的能力 + 我们已加的 V2 设备鉴权 / 资源绑定 / agent 模板 / 模型网关)。 + +--- + +## 0. 一句话目标 + +让一个**团队/组织**的管理员,能在 HM 控制台里:**拉人 → 分角色 → 配可用模型与额度 → 授权可用资源/agent/工具 → 把策略强制下发到每个客户端 → 看用量与审计**。客户端(我们的桌面端)只能在 HM 划定的边界内工作;真正的硬边界由 HM **网关侧**强制,而非依赖客户端自觉。 + +--- + +## 1. Claude 范式精炼:三层控制 + +Claude 的企业管控可归纳为三层,HM 应整体借鉴这套分层: + +| 层 | Claude 机制 | 作用 | +|---|---|---| +| **身份与准入** | 提供商选择 + 座位(seat) + 邀请/角色 + SSO/SCIM/域名捕获 | 决定「谁能用、用哪个组织身份」 | +| **策略下发(受管设置)** | server-managed-settings:管理员在 Web 控制台下发 JSON,客户端登录时拉取、每小时刷新、**最高优先级不可本地覆盖**、数组规则只增不删 | 决定「客户端能做什么、不能做什么」 | +| **能力供给(受管工具/agent)** | managed-mcp + agent/插件下发:组织级统一发一批可用 MCP/工具,可「软允许」或「独占控制」,deny 永远优先 | 决定「客户端有哪些工具/agent 可用」 | + +外加两条贯穿性能力:**分配与计费**(模型白名单、支出/速率上限、用量归属)与**审计**(compliance API、审计日志、ZDR)。 + +**Claude 自己承认的最大短板**,正是 HM 的机会: +- server-managed 是**纯客户端控制(client-side control)**——有 sudo 的用户能改二进制/绕过;HM 是网关,可把强制放在**服务端**,更硬。 +- server-managed **暂不支持分组**(全组织统一);HM 用 V2 设备鉴权天然能按设备/用户/组织下发。 +- 配置第三方 provider(Bedrock/自定义 BASE_URL)会**完全绕过** server-managed;HM 须在网关侧封死这条旁路。 + +--- + +## 2. HM 现状盘点(已有 vs 缺口) + +> 重要:HM 是 new-api fork,**很多分配原语已经现成**,团队管控不是从零造,而是「加一个组织层 + 一套策略下发通道」。 + +### 2.1 已有(可直接复用的原语) +- **用户与角色**:new-api 有 `role`(普通=1 / 管理员=10 / 超级管理员=100)。 +- **分组(group)**:`User.Group` + 分组级模型倍率/可用性。 +- **令牌(sk-)**:`model.Token` 支持 **per-token 模型限制 `model_limits`**、配额 `RemainingQuota`/`UnlimitedQuota`、**过期 `ExpiredTime`**、速率、`HideFromUserUI` 等——这就是「按 key 限模型 + 限额」的现成能力。 +- **配额/计费**:用户 `Quota`/`UsedQuota`、计费表达式系统(`pkg/billingexpr`)、日志归属。 +- **模型网关**:`/v1/*` 统一鉴权 + 计费 + 路由(团队可用模型的强制点天然在这)。 +- **V2 设备鉴权**(我们加的):Ed25519 验签 + X25519/ChaCha20 加密,`/api/agnet/user/*` 用户身份唯一来源——**这是策略安全下发的现成通道**。 +- **资源绑定**(我们加的):KV + secret_ref,按用户隔离。 +- **agent 模板库**(我们加的):admin CRUD + 下发客户端列表 + 部署到 AM——**这已经是一个「受管 agent registry」雏形**。 + +### 2.2 缺口(需新建) +1. **组织/团队对象层**:当前是「用户」单层,没有 org→team→member 的多租户层与座位概念。 +2. **角色细化**:只有 1/10/100 三档全局角色,缺「组织内 owner/admin/member/auditor」与「能配 AM / 能配模型 / 只能用客户端」的能力维度。 +3. **受管设置下发通道**:没有「服务端下发、客户端强制、不可覆盖」的策略机制(对标 server-managed-settings)。 +4. **受管工具/agent 的 allow/deny 策略语义**:agent 模板目前是「全部可见」,缺组织级白/黑名单与「软下发 vs 独占」两档。 +5. **SSO/SCIM/域名捕获**:缺企业身份联邦与自动归属。 +6. **组织级用量看板与审计日志**:缺按组织/成员的用量归属与策略变更审计。 + +--- + +## 3. HM 团队管控设计 + +### 3.1 对象模型:组织 → 团队 → 成员 → 座位 + +``` +Organization (租户,计费主体) + ├─ Team (可选二级,部门/项目组) + │ └─ Membership (User × role × seat) + ├─ Plan / Seats (席位订阅:座位是否含「客户端访问」「AM 调用额度」) + ├─ Policy (受管设置,§3.4) + ├─ ToolCatalog (受管 agent/MCP/资源目录,§3.5) + └─ Quota / SpendLimit (组织级额度池,§3.3) +``` + +- **座位(seat)= 客户端访问的硬开关**(对标 Claude「座位不含 Claude Code 访问会被拒登」)。HM 落点:**V2 设备登录后,先校验该用户在某组织有有效座位,才签发客户端身份**;无座位 → 拒绝拿到 agent 列表/资源/模型 key。 +- 复用 new-api:`Organization` 可由现有 `group` 升级承载,或新建 `organizations`/`memberships` 表(GORM AutoMigrate 加表,跨 SQLite/MySQL/PG)。 + +### 3.2 角色与权限 + +借鉴 Claude「角色 = 能创建/使用哪类凭证 + 能调哪些能力」的朴素范式,定义组织内角色: + +| 角色 | 能力 | +|---|---| +| **Owner** | 全权:计费、座位、下发受管策略、增删 admin | +| **Admin** | 管成员、配模型白名单/额度、配 agent 目录、下发策略(不含计费/删 owner) | +| **Member** | 用客户端 + 已授权的 agent/资源/模型 | +| **Auditor**(只读) | 看用量、审计日志,不能改 | + +并用**正交的能力位**细分(参考 Claude 把「能创建哪类 key」做成角色):`can_manage_models` / `can_manage_agents` / `can_manage_resources` / `can_push_policy` / `can_view_audit`。落点:成员表加 `role` + `capabilities` 位图。 + +### 3.3 分配(模型 / 配额 / 资源 / agent)—— 大量复用 new-api 现成能力 + +这是 HM 相对 Claude 的**强项**(Claude 这部分靠外部 gateway,HM 自己就是 gateway): + +| 分配维度 | 机制 | 复用 HM 现状 | +|---|---|---| +| **可用模型白名单** | 组织/团队/成员级允许模型集 | 复用 `Token.model_limits` + 分组模型可用性;网关 `/v1/*` 已是强制点 | +| **支出上限(spend limit)** | 组织额度池 + 成员子额度 | 复用 `User.Quota`/`UnlimitedQuota` + 计费表达式 | +| **速率限制(rate limit)** | 按组织/成员/key | 复用 new-api 既有 rate limit | +| **凭据有效期** | CI/服务用短期/长期 token(对标 `claude setup-token` 一年期、仅推理、不可建远控会话) | 复用 `Token.ExpiredTime` + 范围位 | +| **可用资源** | 授权某成员/团队可绑定哪些资源类型 | 复用资源绑定 + KV secret_ref | +| **可用 agent 模板** | 组织级 agent 目录(§3.5) | 复用 agent 模板库 + 下发列表 | + +**关键设计**:把「分配」做成**组织池 → 成员子额度**的两级(组织买总量,admin 切给成员),对应 Claude 的座位/支出归属。 + +### 3.4 受管设置下发(核心,对标 server-managed-settings) + +这是最值得照搬的范式。HM 设计: + +**a) 下发通道 = 复用 V2 设备鉴权** +- 策略以 JSON 形式,挂在**设备鉴权返回**里下发(`/api/agnet/user/*` 已是身份唯一来源)。 +- Ed25519 验签保证策略**不被中间篡改**——比 Claude 纯客户端控制更强。 +- 天然支持**按组织/团队/设备分组下发**,补上 Claude「暂不支持分组」的缺口。 + +**b) 优先级与合并(照搬 Claude 语义)** +- 受管层 = **最高优先级,客户端 user/project/CLI 本地配置不可覆盖**。 +- 区分两类:**强制项(enforced,不可改)** vs **默认值(default,客户端可改)**。 +- 数组类规则(如允许模型、允许域)**只增不删**:客户端只能在受管基础上扩展,不能删受管项;但允许「自我收紧」(客户端可为自己再 deny)。 + +**c) 拉取 / 缓存 / 故障策略(照搬)** +- 客户端**启动拉取 + 周期刷新**(Claude 每小时);本地缓存,断网仍按上次策略执行。 +- **fail-closed 开关**(对标 `forceRemoteSettingsRefresh`):高敏组织拉取失败即拒绝启动客户端,杜绝「未强制窗口」。 +- **豁免重认证**:fail-closed 不能把「登录/续签」也锁死(Claude 的教训——凭证过期时要留重认证口子)。 +- **`/status` 式自检**:客户端能显示「当前生效策略来源 + 是否受管」。 + +**d) 优先做的强制项(对标 Claude managed-only 键,挑贴合 HM 的)** +| HM 强制项 | 对标 Claude 键 | 为什么 | +|---|---|---| +| 可用模型白名单 | `availableModels` | HM 是 `/v1/*` 网关,计费/合规边界 | +| 网络/域名准入 | `sandbox.network.allowedDomains` + `allowManagedDomainsOnly` | 锁客户端只能连 HM 及受信域 | +| 危险操作禁止 | `permissions.deny` + `allowManagedPermissionRulesOnly` | 禁读 secrets、禁危险命令,且禁客户端放宽 | +| 登录组织绑定 | `forceLoginOrgUUID` / `forceLoginMethod` | 强制客户端只认 HM 签发身份,堵旁路 | +| 高危能力开关 | `disableBypassPermissionsMode` / `disableRemoteControl` 等 | 按组织策略关高危能力 | +| 审计 hook | managed `hooks` + `PostToolUse` | 客户端编辑后强制跑审计 | + +> ⚠️ MEMORY 已记的隐患:**策略状态不要只放单实例内存 map**,要持久化 + 多实例一致(HM 单实例内存 map 隐患)。 + +### 3.5 受管工具 / agent(对标 managed-mcp) + +HM 已有 agent 模板下发,等于自带 registry(Claude 反而没有内置 registry)。把它升级为带策略的「组织级能力供给」: + +**a) 两档下发语义(必须显式,不要隐式)** +- **软下发(additive)**:HM 发一批可用 agent/工具,客户端仍可叠加自配 → 对标 Claude「软允许列表」。 +- **独占控制(exclusive)**:客户端**只能**用 HM 下发的,本地自建被**服务端**拒绝 → 对标 `managed-mcp.json` 独占控制。 + +**b) allow/deny 三步评估(照搬)** +1. 各源 allow/deny 合并;开启「仅受管」开关时本地 allow 失效、只认 HM allow; +2. **deny 永远优先、不可被任何层覆盖**,且 deny 从所有源合并(用户能为自己再禁,不能放宽); +3. allow 命中才放行。 + +**c) 匹配落到不可伪造标识** +- Claude 警告「只按 server 名字匹配不安全」。HM 校验客户端可用 agent/工具时,**不要只信客户端上报的名字**,要绑定**模板 ID + 签名 + 设备身份**(V2 鉴权链已具备)。 +- 直接受益:解决我们 AM 契约 §3.1 那条「按用户隔离」——agent 准入也走同一套不可伪造标识。 + +**d) 凭据 per-user,不入下发物** +- Claude 禁止把 key 写进下发的 `env`。HM **下发「连接定义」但凭据按用户动态注入/OAuth**(契合已有 Managed Identity / Key Vault)——下发物里**绝不出现共享密钥**。 + +**e) 变更可观测** +- Claude 痛点是「server 被新策略静默消失、用户不知原因」。HM 作为网关,下发变更时**给客户端可见原因**,并在服务端记录「客户端实际调了哪些工具/agent」。 + +### 3.6 认证与准入(对标 authentication + SSO) + +- **多种登录分层**:个人订阅式 OAuth、Console 式 key、CI 长期 token(范围限定:仅推理、不可建远控会话)、网关 bearer token(`ANTHROPIC_AUTH_TOKEN` 路线天然契合 HM 作网关)。 +- **确定性凭据优先级**:客户端需一套固定选择顺序(网关 token > 设备 OAuth > …),并处理「key 属过期组织→认证失败」的冲突态,给 `/status` 诊断。 +- **企业强制**:组织可强制 **SSO/SAML + SCIM 自动配置 + 域名捕获**,把同域用户自动归属到组织身份——决定「客户端用哪个组织身份接入」。 +- **封旁路**:Claude 承认配第三方 provider 会绕过 server-managed。HM 必须在**网关侧**强制:客户端的模型请求只能经 HM,绕过即无额度/无身份。 + +### 3.7 auto-mode 类客户端行为(软策略 + 网关硬边界) + +- auto-mode 的教训:分类器合并是**累加、可被用户 allow 覆盖,不是硬边界**;真正不可绕过的放 `permissions.deny`(分类器之前)。 +- 映射 HM: + - HM 可下发一套「受信环境/允许/拒绝」**语义偏好**(组织级),统一风险口径、减少误拦; + - 但**「绝不允许」的能力边界,HM 在网关侧(请求进模型/工具前)硬拦**,等同 `permissions.deny` 角色,**不依赖客户端分类器**。 +- **隔离不可信来源**:客户端/项目侧上报的规则**只能收紧、不能放宽** HM 下发的策略(对标「分类器不读 check-in 的共享项目设置」)。 + +### 3.8 审计与用量 + +- **用量归属看板**:对标 Claude Analytics(每用户指标、贡献、排行榜)——按组织/团队/成员的 token 用量、模型分布、agent 调用,复用 new-api 日志 + 计费。 +- **审计日志**:对标 compliance API——策略下发、成员变更、agent 部署/删除全程留痕(操作者、设备、新旧值)。HM 作网关是放**请求级审计**的天然位置。 +- **数据留存**:可选 ZDR / 零留存档位。 + +--- + +## 4. 关键设计原则(HM 要比 Claude 更硬的三点) + +1. **硬强制在服务端,不在客户端**。Claude 的 server-managed 是客户端控制、可被 sudo 绕过。HM 把模型/工具/agent 的真正准入放在**网关 + V2 鉴权**侧——客户端策略只是第一道 UX,越权请求在 HM 被拒。 +2. **下发通道带验签**。复用 V2(Ed25519+ChaCha20)下发策略,防篡改、可按组织/设备分组——一举补上 Claude「分组缺失 + 纯客户端控制」两个短板。 +3. **不对称权限**:受管策略「能自我收紧、不能自我放宽」;deny 永远优先且不可覆盖;凭据 per-user 永不入下发物。 + +--- + +## 5. 落地优先级(建议分阶段) + +**P0(地基)** +- 组织/团队/成员/座位对象模型(新表,AutoMigrate);座位作为 V2 登录签发客户端身份的前置门。 +- 组织内角色 + 能力位。 + +**P1(分配,复用现成原语,见效快)** +- 组织池 → 成员子额度(模型白名单 / 支出上限 / 速率 / 凭据有效期),全部映射到 `Token.model_limits` + 配额 + `ExpiredTime`。 +- 组织级 agent 目录:给现有 agent 模板加「组织可见性 + allow/deny + 软/独占」字段。 + +**P2(受管设置下发,核心差异化)** +- 受管策略表 + V2 通道下发 + 优先级合并 + 拉取/缓存/fail-closed + `/status` 自检。 +- 先落 6 个强制项中的:可用模型白名单、网络域白名单、`permissions.deny`、登录组织绑定。 + +**P3(企业身份与审计)** +- SSO/SAML + SCIM + 域名捕获;组织用量看板 + 审计日志。 + +--- + +## 附:来源与对照 + +| 本文章节 | Claude 文档来源 | +|---|---| +| §1、§3.1 座位/准入、§3.6 认证 | admin-setup、authentication | +| §3.4 受管设置下发 | server-managed-settings、settings | +| §3.5 受管 agent/工具 | managed-mcp | +| §3.7 auto-mode | auto-mode-config | + +> 待补(Claude 文档外链未展开,设计 SSO/SCIM 细节前再抓):SAML 字段、SCIM 属性映射、域名捕获流程、Enterprise 完整角色清单(在《Claude Enterprise Administrator Guide》)。