feat: ship enterprise control and desktop governance

This commit is contained in:
AI Bot
2026-05-11 14:59:26 +08:00
parent 0757d07521
commit a311280238
285 changed files with 48574 additions and 2428 deletions

View File

@@ -0,0 +1,181 @@
# Codex Desktop 同线程消息镜像设计
目标:当用户在 Boss App 里对一个已绑定 `codexThreadRef` 的单线程会话发消息时,这条用户消息不仅进入 Boss 自己的项目账本和 `conversation_reply` 执行队列,也要被镜像进本机 Codex Desktop 的同一个线程历史里。这样用户稍后回到 Codex Desktop看见的是同一个线程下连续的聊天记录而不是 Boss 与 Desktop 两套割裂历史。
## 背景与现状
当前 Boss 的普通线程单聊主链是:
- Web / Android 调 `POST /api/v1/projects/[projectId]/messages`
- 服务端写入 Boss 项目消息账本
- 服务端排一个 `conversation_reply` 任务
- 本机 `local-agent` 认领任务后调用 `codex exec resume <targetCodexThreadRef>`
- Codex 线程完成后,再把线程回复回写到 Boss 项目账本
这条链现在已经能做到“Desktop 回复被 Boss 看见”,因为 heartbeat 扫描 `~/.codex/sessions/.../rollout-*.jsonl` 时,会把最近桌面 assistant 回复镜像回 Boss。缺口在反方向
- Boss App 发起的用户消息只存在于 Boss 项目账本
- `codex exec resume` 虽然会把 prompt 交给目标线程继续执行,但 Boss 发起的这条消息并不会先出现在 Desktop 线程历史
- 结果就是用户在 APP 和 Desktop 里看到的“同一个线程”并不是同一份完整聊天记录
## 方案对比
### 方案 1直接操控 Codex Desktop GUI 输入并发送
优点:
- 理论上最贴近“像用户在桌面端亲自发了一条消息”
缺点:
- 依赖窗口前台、焦点、输入法、系统权限
- 极易被 Codex Desktop UI 更新打断
- 无法稳定支持后台运行和多线程并发
不推荐作为主方案。
### 方案 2直接把 Boss 用户消息写入对应 Codex rollout JSONL再继续现有 `codex exec resume`
优点:
- 与当前 Desktop/CLI 共用的真实线程存储一致
- 不需要操控 GUI
- 可以保持现有 `local-agent -> codex exec resume` 主链不变
- 能与现有 heartbeat 读取 rollout 的能力形成闭环
缺点:
- 需要谨慎贴合 Codex rollout 事件格式
- 需要处理重复写入和 Desktop 刷新感知
这是本次推荐方案。
### 方案 3单独给 Desktop 再建一条镜像线程
优点:
- 对现有线程文件侵入最小
缺点:
- 用户要的是“同一个线程”,不是“另一个镜像线程”
- 历史会继续分叉
不满足目标。
## 本次设计
### 1. 保持 Boss 账本为移动端/UI 主真相
Boss 的项目消息账本、会话排序、未读数、主 Agent 协同逻辑继续基于现有 `boss-state.json`。这次不把 Boss UI 改成直接读取 `~/.codex`
### 2. 对单线程 `conversation_reply` 任务增加“写入 Desktop 线程历史”的镜像步骤
当任务满足以下条件时,在 `local-agent` 侧做一次 rollout 镜像:
- `task.taskType === "conversation_reply"`
- 存在 `targetCodexThreadRef`
- 存在用户原始消息文本
- 不属于 `relayViaMasterAgent === true` 的接管中转任务
镜像行为:
- 优先通过 `state_5.sqlite``threads.rollout_path` 定位目标 rollout 文件
- 如果本机 Codex 因版本/迁移差异无法稳定解析 `state_5.sqlite`,则回退扫描 `~/.codex/sessions/**/rollout-*-<threadId>.jsonl`
- 向该 rollout 文件追加一组 Codex 用户消息记录:`response_item / message(role=user)``event_msg / user_message`
- 事件内容使用 Boss 原始用户消息文本,而不是执行 prompt
- 事件时间优先使用 Boss 消息的 `sentAt`
- 事件写入成功后,再继续现有 `codex exec resume`
### 3. 任务负载补齐“Boss 原始消息”字段
现在任务里只有:
- `requestMessageId`
- `requestText`
- `executionPrompt`
这还不够稳,因为后续去重和 Desktop 镜像需要区分:
- 哪条 Boss 用户消息已经镜像过
- 这次镜像的真实显示文本是什么
- 这条消息的原始时间戳是什么
因此为 `MasterAgentTask` 增加:
- `sourceMessageId?: string`
- `sourceMessageBody?: string`
- `sourceMessageSentAt?: string`
- `mirrorBossUserMessageToCodexDesktop?: boolean`
对普通线程单聊:
- `sourceMessageId = message.id`
- `sourceMessageBody = message.body`
- `sourceMessageSentAt = message.sentAt`
- `mirrorBossUserMessageToCodexDesktop = true`
对主 Agent 直聊、`@主Agent`、托管中转等不应写进子线程 Desktop 历史的场景,不开启这个标记。
### 4. 去重策略
同一条 Boss 消息可能因为:
- 任务重试
- local-agent 重启
- claim / complete 重放
而被多次处理。为避免在 Desktop 线程里重复写入同一条用户消息本次采用“rollout 末尾去重”:
- 生成稳定镜像 key`boss-user:<threadRef>:<sourceMessageId>`
- 写入的 `event_msg` 中带上 `payload.metadata.bossSourceMessageId`
- 写入前读取 rollout 尾部固定窗口,检查最近是否已经存在同一 `bossSourceMessageId`
- 若存在,则跳过写入,仅继续 `codex exec resume`
这样不需要引入新的状态库,也能与 Codex 原始线程文件保持局部自洽。
### 5. 刷新感知
第一版只写 rollout 还不够稳,因为 Desktop 的线程列表排序和“最近活跃”判断通常还依赖 `threads.updated_at / updated_at_ms / has_user_event`。因此本次实现改为:
- rollout append 成功后,若 `state_5.sqlite` 可写且能命中该 thread则同步刷新
- `updated_at`
- `updated_at_ms`
- `has_user_event = 1`
- 如果当前机器上的 Codex 状态库不可用、字段不兼容或压根没有这条 thread 记录,则只保留 rollout 写入,不把整条消息链路判成失败
这样做的取舍是:
- 先保证 Boss -> Codex Desktop 同线程历史不丢
- 再尽可能提升 Desktop 侧的列表刷新和最近活跃感知
- 不引入 GUI 自动化,不依赖桌面窗口前台
## 涉及文件
- 新增 `local-agent/codex-thread-rollout-writer.mjs`
- 修改 `local-agent/codex-task-runner.mjs`
- 修改 `local-agent/server.mjs`
- 修改 `src/lib/boss-data.ts`
- 修改 `src/app/api/v1/projects/[projectId]/messages/route.ts`
- 修改 `src/lib/boss-master-agent.ts`(如果当前普通线程任务创建逻辑在这里有共用 helper也一起补齐
- 新增测试 `tests/local-agent-codex-rollout-writer.test.mjs`
- 修改测试 `tests/local-agent-codex-task-runner.test.mjs`
- 修改测试 `tests/single-thread-message-execution.test.ts`
## 边界
- 本次只处理“Boss App -> 已绑定 Codex Desktop 同线程”的用户消息镜像
- 不处理群聊镜像到 Desktop
- 不处理主 Agent 自己的回复写入 Desktop 子线程
- 不做 Codex Desktop GUI 自动输入
- 不把 Boss 会话列表直接改成读取 Desktop 原始线程文件
## 验收标准
- 普通单线程会话发消息后,生成的 `conversation_reply` 任务带有完整 `sourceMessage*` 字段
- local-agent 在执行 `codex exec resume` 前,能把这条 Boss 用户消息写进目标 rollout
- 同一 `sourceMessageId` 重试时不会重复写入 rollout
- 若状态库可用,镜像后会同步刷新 thread 的活跃时间和 `has_user_event`
- 若状态库不可用或这台机器上的线程索引不完整,仍可通过 `sessions` 回退找到 rollout 并完成消息镜像
- 现有普通线程回复链不回归Boss 仍能收到 Codex 线程回复
- 若目标线程缺失、只读或 cwd 不合法,仍保持现有 fail-closed 行为

View File

@@ -0,0 +1,399 @@
# Boss 聊天统一电脑控制中枢设计
目标:让用户在 Boss App 里,无论是和 `主 Agent` 对话,还是和某个具体线程对话,都可以稳定驱动这台 Mac/Windows 设备完成三类事情:
- 项目开发与代码执行
- 浏览器/桌面 GUI 操作
- 普通产品讨论、调研和任务协同
并且这三类能力不再割裂成几条旁路,而是统一挂在 Boss 现有的聊天、执行底座和设备心跳体系下面。
## 背景与现状
当前 Boss 已经具备几条关键基础链路:
- `master-agent` 单聊可以通过 `local-agent -> codex exec` 真实产出回复
- 普通单线程聊天已经可以排 `conversation_reply` 任务,并恢复到真实 Codex 线程执行
- 群聊已有 `group_dispatch_plan -> dispatch_execution` 的编排链
- 设备模型已经支持同一台机器的 `GUI + CLI` 双能力声明与默认执行模式切换
- 本机 `local-agent` 已能做 Codex 线程发现、task claim、task complete、Desktop rollout 镜像
但目前缺的不是“再加一个按钮”,而是统一控制中枢:
- `conversation_reply` 只适合“把消息转给 Codex 线程继续聊”
- `dispatch_execution` 主要面向群聊下发和线程编排
- 还没有正式的“桌面控制 / 浏览器控制”任务类型
- 主 Agent 也没有显式的能力路由模型,无法稳定判断当前消息应该走:
- Codex 开发
- Browser automation
- Computer Use
- 单纯讨论/总结
这会导致现在的体验像“能做一些事”,但还不是“可以靠 Boss 聊天控制电脑做事”。
## 目标边界
### 本次要达到的能力
1. 主 Agent 能把用户消息识别成四类执行意图:
- `project_development`
- `thread_collaboration`
- `browser_control`
- `desktop_control`
2. Boss 执行底座能显式表达这四类请求,并把它们路由到正确 runtime。
3. `local-agent` 增加两条新 runtime
- `browser-automation-runtime`
- `computer-use-runtime`
4. Web / Android 前台至少能拿到任务执行方式和当前状态,知道这条消息是:
- 交给 Codex 线程
- 交给浏览器自动化
- 交给桌面控制
- 仅由主 Agent 直接回复
5. 对高风险桌面动作建立最小确认机制,避免“发一句话就直接在电脑上乱点/乱删”。
### 本次不做的事情
- 不做完整远控桌面产品
- 不做视频流式屏幕回传
- 不做跨设备键鼠镜像
- 不把 Codex Desktop 自己纳入 Computer Use 自动点击目标
- 不依赖 GUI 自动化去操控 Codex 自己的窗口
## 方案原则
### 原则 1复用 Boss 现有执行底座,不另起一套“远控系统”
如果我们再单独造一层 `remote-control service`,会把:
- 会话账本
- 任务队列
- 权限与确认
- 前台状态展示
- 设备能力发现
全部再复制一遍。成本高,而且会和当前 Boss 的“聊天即控制入口”相冲突。
所以本次明确采用:
- 用户入口仍然是 Boss 聊天
- 任务记录仍然是 `MasterAgentTask`
- 路由仍然收敛进 `src/lib/execution`
- 执行仍然由绑定设备上的 `local-agent` 落地
### 原则 2先把“控制判断”标准化再扩 runtime
现在最大的问题不是工具不够,而是没有统一的“这条消息该怎么执行”判断结果。
因此要先补一层执行意图:
- `discussion_only`
- `thread_reply`
- `browser_control`
- `desktop_control`
- `development_execution`
然后让不同后端只关心自己该执行哪一种。
### 原则 3危险动作永远要显式分级
Boss 最终要能“做任何事”,但不能把“任何事”理解成“任何时候都自动执行”。
所以本次引入最小风险分级:
- `low`
- 打开页面
- 搜索信息
- 读取项目文件
- 运行只读检查
- `medium`
- 登录态网页操作
- 浏览器表单提交
- 桌面应用点击导航
- 修改非代码业务内容
- `high`
- 删除/覆盖文件
- 系统设置改动
- 批量提交/发布
- 不可逆外部操作
策略:
- `low`:默认直接执行
- `medium`:默认轻确认,可在项目/会话级放行
- `high`:必须明确确认
## 控制中枢设计
## 1. 新的执行意图模型
在当前 `ExecutionRequestKind` 基础上新增:
- `browser_control`
- `desktop_control`
并补充一个统一意图字段,供主 Agent 和前台共用:
- `intentCategory`
- `discussion_only`
- `project_development`
- `thread_collaboration`
- `browser_control`
- `desktop_control`
其中:
- `project_development` 继续优先走现有 Codex 线程 / CLI 执行链
- `thread_collaboration` 继续走 `conversation_reply`
- `browser_control` 新增浏览器自动化 runtime
- `desktop_control` 新增 Computer Use runtime
## 2. 新的 runtime 层
### 2.1 browser-automation-runtime
用途:
- 打开网页
- 登录指定后台
- 提交表单
- 抓取页面信息
- 复现 Web bug
第一版实现直接复用现有 Playwright 能力,不重新造驱动协议。
建议协议:
- 输入:
- `taskId`
- `projectId`
- `requestText`
- `executionPrompt`
- `targetUrl?`
- `riskLevel`
- 输出:
- `status`
- `replyBody`
- `structuredResult?`
- `artifacts?`
落地约束:
- `local-agent/browser-control-task-runner.mjs` 先收口成外部 runtime 桥,不把 Playwright 逻辑硬编码进 `server.mjs`
- 通过 `browserControlEnabled / browserControlCommand / browserControlArgs / browserControlWorkdir / browserControlTimeoutMs` 配置启用
- runtime 进程只需要遵守单行 JSON stdout 协议,后续可以平滑替换成真实 Playwright/OpenClaw/browser adapter
### 2.2 computer-use-runtime
用途:
- 打开本机应用
- 在桌面 GUI 上点击、输入、切换
- 配合浏览器外的桌面软件完成操作
第一版实现直接对接 Codex App 现有的 Computer Use 能力约束:
- 只能操作普通桌面应用
- 需要系统 Screen Recording + Accessibility
- 不把终端/Codex 自己当作自动点击目标
这意味着:
- 项目开发仍然优先走 Codex CLI/线程
- Computer Use 负责 GUI 世界
- 两者由主 Agent 在同一条聊天链里自动选择
落地约束:
- `local-agent/computer-use-task-runner.mjs` 同样先做成外部 runtime 桥
- 通过 `computerUseEnabled / computerUseCommand / computerUseArgs / computerUseWorkdir / computerUseTimeoutMs` 配置启用
- 先统一 Boss 与 runtime 的协议,再按设备情况接 Codex App Computer Use、OpenClaw 或其他 GUI runtime
## 3. MasterAgentTask 扩展
当前 `MasterAgentTaskType` 只有:
- `conversation_reply`
- `attachment_analysis`
- `group_dispatch_plan`
- `dispatch_execution`
- `device_import_resolution`
本次新增:
- `browser_control`
- `desktop_control`
新增字段:
- `intentCategory?`
- `runtimeKind?`
- `riskLevel?`
- `confirmationPolicy?`
- `requiresUserConfirmation?`
- `confirmationScopeKey?`
目的:
- 前台能展示“当前这条消息要走哪条执行链”
- 服务端能统一处理确认/拦截
- `local-agent` 能按 runtimeKind 正确分流
## 4. 主 Agent 路由逻辑
主 Agent 不再简单分成“自己答”或“排 conversation_reply”而是多一步意图判断。
推荐判断顺序:
1. 如果是明显的项目讨论、总结、目标/版本记录、普通问答
- `discussion_only`
2. 如果是“继续开发 / 改代码 / 跑测试 / 看项目状态 / 接手某线程”
- `project_development``thread_collaboration`
3. 如果是“打开网站 / 点网页 / 查后台 / 提交表单 / 看页面”
- `browser_control`
4. 如果是“打开电脑软件 / 操作桌面 / 系统 GUI / 非浏览器界面”
- `desktop_control`
路由结果:
- `discussion_only`
- 主 Agent 直接回复
- `thread_collaboration`
- 继续 `conversation_reply`
- `project_development`
- 优先真实 Codex 线程 / CLI
- `browser_control`
-`browser_control` 任务
- `desktop_control`
-`desktop_control` 任务
## 5. 设备能力模型
当前设备只有:
- `gui`
- `cli`
这对“统一控制电脑”不够精确,所以建议在设备 heartbeat 能力里细化为:
- `cli`
- `gui`
- `browserAutomation`
- `computerUse`
其中:
- `browserAutomation` 可由本机 Playwright/runtime 探测
- `computerUse` 由本机配置和权限状态探测
这样前台与主 Agent 都能知道:
- 当前机器只能写代码
- 还是也能控浏览器
- 还是能做完整桌面 GUI 操作
## 6. 前台产品表现
### 会话页 / 聊天页
每条“触发执行”的用户消息,服务端返回时增加:
- `executionMode`
- `discussion`
- `thread`
- `development`
- `browser`
- `desktop`
- `riskLevel`
- `requiresConfirmation`
前台展示原则:
- 不做厚重控制台 UI
- 保持当前微信式聊天界面
- 只在消息下方补一条轻状态:
- `已交给主 Agent`
- `正在调用浏览器自动化`
- `正在调用桌面控制`
- `等待你确认后执行`
### 会话信息 / 设备详情
补一个轻量能力区:
- `默认开发模式CLI / GUI`
- `浏览器自动化:可用 / 不可用`
- `桌面控制:可用 / 不可用`
不把这些塞回聊天主界面。
## 7. 风险确认设计
### 会话级别
如果当前会话在某个项目下已经对中风险动作做过一次确认,则可以对这个项目保留:
- `禁止`
- `允许本次`
- `当前项目永久放行`
这和现有 GUI/CLI 并行冲突的项目级策略一致,避免用户多学一套规则。
### 任务级别
当主 Agent 判断为高风险时:
- 不直接执行
- 先在聊天里给出极简确认卡
- 用户点确认后再排任务
## 8. 本次实施顺序
### 第一批
- 写设计与计划文档
- 扩展任务类型、执行请求类型、设备能力类型
- 接入 `browser_control / desktop_control` 两类任务基础骨架
- `local-agent` 增加 runtime 分流占位
- 前台返回 `executionMode/riskLevel` 元数据
### 第二批
- 接入 browser automation 真执行
- 接入 computer use 真执行
- 完成确认链
### 第三批
- Android/Web 前台补状态展示
- 真机回归
- 文档回写
## 涉及文件
- 修改 `src/lib/execution/types.ts`
- 修改 `src/lib/execution/tool-registry.ts`
- 修改 `src/lib/execution/permission-policy.ts`
- 修改 `src/lib/boss-data.ts`
- 修改 `src/lib/boss-master-agent.ts`
- 修改 `src/app/api/v1/projects/[projectId]/messages/route.ts`
- 修改 `local-agent/codex-task-runner.mjs`
- 修改 `local-agent/server.mjs`
- 新增 `local-agent/browser-control-task-runner.mjs`
- 新增 `local-agent/computer-use-task-runner.mjs`
- 新增对应 tests
## 验收标准
- 主 Agent 能把聊天输入稳定区分成讨论、开发、浏览器控制、桌面控制四类
- `browser_control / desktop_control` 能以正式任务进入 Boss 队列
- `local-agent` 能识别并分流这两类任务
- 前台能看到当前消息是走哪条执行链
- 中高风险动作不会静默直接执行
- 现有 `conversation_reply / dispatch_execution` 主链不回归

View File

@@ -0,0 +1,151 @@
# Boss To B 总后台重构设计
日期2026-04-30
## 背景
当前 `/admin` 已经具备最高管理员访问控制、总览聚合、账号授权、风险处理和 Skill 生命周期治理能力,但页面仍像“几个数据表拼在一起”。对于 To B 交付场景,平台侧需要的是一套能服务客户成功、运维值守和权限开通的 PC 总后台,而不是一个调试看板。
本次重构不新增大业务边界,优先重组现有 `/api/v1/admin/overview``/api/v1/admin/access``/api/v1/admin/risks/actions``/api/v1/admin/skills/requests` 数据和动作,把后台做成可用、可读、可处置的运营控制台。
## 目标
1. 最高管理员进入后台后,能在 10 秒内看出哪些客户、设备、主 Agent 任务或线程风险需要处理。
2. 客户开通从“多个分散表单”收口成可理解的工作台公司、老板账号、子账号、设备、项目、Skill 授权有清晰入口和状态。
3. 风险处理从“表格按钮”升级为战情室按严重程度、客户影响、负责人、SLA 和下一步动作组织。
4. Skill 治理保留安全约束,但展示成可追踪的生命周期队列。
5. UI 风格从移动端微信效率风改为 PC To B 管理后台:高密度、强层级、清晰状态、少装饰。
## 非目标
- 不引入新的 Umi / Ant Design Pro 工程。
- 不切换 PostgreSQL 或重写状态存储。
- 不改 Android APP 端交互。
- 不绕过 local-agent 的 Skill allowlist、checksum、备份和回滚约束。
- 不把客户侧 Web 控制台和平台总后台混成一个产品。
## 信息架构
后台改为 4 个一级区:
1. `驾驶舱`:平台全局健康、关键风险、客户影响、在线设备、主 Agent 失败、待处理通知。
2. `客户与账号`:公司列表、客户详情、账号开通、角色状态、登录与安全概览。
3. `授权工作台`设备、项目、Skill 授权,权限模板,过期授权,离职回收和审计。
4. `风险与治理`风险战情室、SLA、负责人、修复工单、风险时间线、Skill 生命周期请求。
现有 `账号与授权``Skill 治理` 不是删除,而是拆到更合理的上下文里:账号归客户,授权归权限,风险和 Skill 请求归治理。
## 页面设计
### 驾驶舱
顶部保留平台身份和刷新动作但标题从“Boss 管理后台”升级为“平台运营驾驶舱”。主区域按优先级展示:
- `今日待处理`:关键风险数、超 SLA 通知、离线设备、主 Agent 失败。
- `客户健康排行`:按开放风险、在线设备比例、合同/套餐状态排序。
- `关键风险队列`只展示最值得处理的风险提供负责人、SLA、确认、关闭、工单动作。
- `设备与节点健康`GUI/CLI、Browser、Computer Use 能力状态集中展示。
- `最近事件`:风险时间线和权限审计摘要。
驾驶舱默认不展示大分页表,避免用户一打开就被表格淹没。
### 客户与账号
采用左侧客户列表 + 右侧详情的结构:
- 客户列表显示公司名、套餐、账号数、设备数、开放风险、客户成功负责人。
- 右侧详情显示老板账号、子账号、绑定设备、项目数量和最近风险。
- 新建客户流程拆成三步:创建公司、创建老板账号、绑定设备/项目。
- 子账号管理支持启用/停用、重置密码、MFA 状态和登录会话摘要。
这部分复用现有 `/api/v1/admin/access`,但前台从表单堆叠改成任务流。
### 授权工作台
授权页面按“给谁授权”而不是“授权类型”组织:
- 先选择账号或客户。
- 再选择设备、项目、Skill。
- 最后套用权限模板或手动勾选权限。
页面底部保留最近授权审计和过期授权提醒。高危动作继续二次确认。
### 风险与治理
风险页面采用“战情室”结构:
- 左侧风险队列:按 `critical / warning / info`、客户、负责人、SLA 筛选。
- 中间风险详情:影响对象、错误摘要、最近时间线、建议动作。
- 右侧处理面板:指派、设置 SLA、确认、关闭、创建工单。
Skill 生命周期治理放在同一区域的第二页签,展示为请求队列:
- 待认领、执行中、成功、失败分栏。
- 每条请求展示设备、Skill、动作、来源、checksum、结果摘要。
- 创建请求表单保留,但根据动作动态收敛字段。
## 组件边界
建议拆出以下组件,降低当前 `boss-admin-app.tsx` 的复杂度:
- `AdminShell`PC 后台壳、顶部栏、一级导航。
- `AdminDashboard`:驾驶舱。
- `AdminCustomerWorkspace`:客户与账号工作台。
- `AdminPermissionWorkspace`:授权工作台。
- `AdminRiskCommandCenter`:风险战情室。
- `AdminSkillGovernance`Skill 生命周期治理,可复用并改造当前组件。
- `AdminStatusBadge``AdminMetricCard``AdminActionRail`:统一状态、指标和动作区。
数据请求先继续使用现有 fetch不强制引入新的客户端状态库。
## 数据和接口
第一批不要求新增后端字段,但前台应完整使用现有字段:
- `summary`
- `companies`
- `accounts`
- `devices`
- `risks`
- `notifications`
- `riskTimeline`
- `grantsSummary`
如果发现页面需要客户健康分数,可先在前端由 `openRiskCount / onlineDeviceCount / deviceCount / status` 计算,不改状态 schema。
## 错误处理
- 后台总览读取失败时展示一张明确的恢复卡,提供重试按钮。
- 风险动作失败时保留原行状态,不做乐观关闭。
- 指派负责人和 SLA 不再使用 `window.prompt`,改成右侧处理面板或弹窗表单。
- 空状态要表达下一步,例如“暂无风险,可以查看设备在线情况”,不要只写“暂无数据”。
## 测试策略
- 保留并更新 `tests/admin-refine-page.test.ts`,验证新的一级区和关键文案。
- 增加组件 source 测试,确认不再使用 `window.prompt` 做风险指派和 SLA。
- 复跑 `tests/admin-overview-route.test.ts``tests/admin-risk-actions-route.test.ts``tests/admin-skill-lifecycle-panel-source.test.ts`
- 最后跑 `npm run lint` 和相关 Node 测试。
## 分批落地
第一批直接做到可用:
1. 重构 `BossAdminApp` 外壳和一级导航。
2. 做新版驾驶舱。
3. 做风险战情室,替换 `window.prompt`
4. 账号授权和 Skill 治理先迁入新结构,并压缩视觉层级。
第二批再增强:
1. 客户详情抽屉。
2. 新建客户三步流程。
3. 风险筛选和搜索。
4. 客户健康分数和趋势。
## 自检
- 无 TBD / TODO。
- 范围聚焦 `/admin` PC 总后台,不触碰 APP。
- 没有要求新增大后端能力,优先复用现有接口。
- 关键交互从数据表改成工作台与战情室,解决“后台管理不太好”的主要问题。

View File

@@ -0,0 +1,75 @@
# YuDao 风格企业后台独立化设计
日期2026-04-30
## 背景
Boss 需要从“客户也能用的 Web 页面”升级为平台侧 To B 总后台。这个后台用于平台运营人员管理公司、老板账号、子账号、电脑节点、Skill 授权、风险告警和审计记录。现有 `/admin` 已能展示核心数据,但仍运行在 Next 主站内,信息架构不够像成熟企业后台,后续不适合承载更复杂的租户、权限和治理能力。
调研 `YunaiV/yudao-cloud` 后,结论是:不直接引入它的 Spring Cloud 微服务后端;借鉴它的租户、用户、角色、菜单、日志、工作台和独立前端思路。前端形态参考 YuDao 的 Vben/Vue 管理后台,数据仍由 Boss 现有状态账本和 Admin BFF 提供。
## 目标
第一批目标是完成企业后台独立化的可运行骨架:
- 新增独立 PC 后台工程 `apps/boss-admin-web`,使用 Vue + Vite + Ant Design Vue。
- 新增 `/api/v1/admin/backoffice` 聚合接口,输出 YuDao 风格的菜单、工作台、租户、账号、角色权限、资源授权、风险和审计数据。
- 保留现有 `/admin`,作为 Boss 主站内 fallback不和独立后台互相替代。
- 后台权限继续只允许 `highest_admin` 访问不暴露密码哈希、MFA 密钥和会话令牌。
- 新后台先复用 Boss Cookie 登录态,后续再接独立域名 `admin.boss.hyzq.net`
## 非目标
- 不引入 YuDao Java 后端、MySQL 表结构或微服务网关。
- 不在第一批替换所有现有后台 mutation 页面。
- 不重新设计 Android APP。
- 不改变当前 Boss 文件存储运行时。
## 架构
```mermaid
flowchart LR
A["Boss Admin Web\nVue + Ant Design Vue"] --> B["/api/v1/admin/backoffice\nAdmin BFF"]
B --> C["boss-state.json\n当前状态账本"]
B --> D["buildAdminOverview\n现有后台聚合"]
B --> E["BOSS_PERMISSION_TEMPLATES\n权限模板"]
F["现有 /admin\nNext fallback"] --> G["/api/v1/admin/overview"]
```
`apps/boss-admin-web` 是独立前端工程。它只消费 BFF不直接读取本地文件也不复制业务规则。`/api/v1/admin/backoffice` 是企业后台的新契约层,负责把 Boss 当前状态翻译为更稳定的后台管理模型。
## 数据模型
第一批 BFF 返回:
- `menuTree`工作台、租户管理、账号管理、角色权限、资源授权、Skill 中心、风险告警、审计日志、系统设置。
- `workbench`:总览指标、客户健康、设备健康、风险摘要。
- `tenants`:公司列表、套餐、负责人、账号数、设备数、风险数。
- `users`:账号、昵称、角色、状态、公司、最近登录。
- `roles`:内置角色和权限模板。
- `resourceGroups`:设备、项目线程和 Skill 目录。
- `audit`:风险、风险时间线和权限审计。
- `yudaoMapping`Boss 账本字段到后台概念的映射,便于后续迁移数据库或接 YuDao 风格模块。
## UI 方向
第一批 UI 只做高保真骨架,不新增业务动作:
- 左侧固定菜单,右侧工作区。
- 顶部展示当前账号、后台说明和刷新入口。
- 工作台使用指标卡、风险横幅、客户健康和节点表。
- 租户、账号、角色、资源、风险、审计分别使用独立区块或表格。
- Skill 中心聚合展示 Skill 目录、来源、设备数和治理状态,后续再接完整安装向导。
## 权限与安全
- 未登录返回 `401`
-`highest_admin` 返回 `403`
- BFF 只返回安全账号字段,不返回 `passwordHash``mfaSecret``authSessions` 或任何 session token。
- 所有返回头使用 `private, no-store`,避免后台数据被缓存。
## 验证
- 新增 BFF 路由测试,验证鉴权、菜单结构、数据聚合和敏感字段过滤。
- 新增独立前端源代码测试验证工程骨架、API 契约、核心页面模块和根工程隔离。
-`npm run lint``npm run build`,确认不会破坏现有 Next 主站。