@@ -0,0 +1,417 @@
# Web UI + MCP 服务开发计划
> 状态:规划,尚未实施或验收。用户已确认目标为“浏览器 Web UI + MCP 服务”。
> 本次交付仅为开发计划,不启动服务、不执行微信写操作。
> 范围变化:原第一阶段排除正式 UI;本文规划其后的控制面阶段。用户已确认 HTTP/Web UI 与 MCP 支持外部访问且共用 Token,不要求 HTTPS,不实现服务端人工审批;不改变 Windows Service、协议及数据库安全边界。
## 1. 目标与基线
在已有 C# 微信业务能力上增加浏览器控制台和 MCP 调用入口,实现“查看状态 → 选择账号/会话 → 发起操作 → 查询进度 → 验证结果 → 获取诊断”的闭环。
依据:
- [C# 开发计划 ](WxAgent-CSharp-开发计划.md ):总体目标、项目边界、自动化规则。
- [PENDING ](PENDING.md ):最新功能边界、暂缓事项和未闭环问题;与早期计划冲突时以此为准。
- `src/WxAgent.Host/Program.cs` :现有 CLI 入口、参数校验、JSON 输出与 smoke。
- `src/WxAgent.Windows/WechatChatClient*.cs` : UI 操作及管理 API。
- `src/WxAgent.Core` :业务模型、错误码、监听及只读数据相关逻辑。
- `docs/validation/` :已记录的验收证据;实现存在不等于已通过真机验收。
### 1.1 当前事实
1. 当前主要交付是 Windows Host/CLI 和 C# 库,不把它们描述成已经可供浏览器调用的 HTTP/MCP 服务。
2. CLI 已包含诊断、会话、消息、监听、数据库只读查询等入口;部分管理功能仅通过库 API 提供。
3. 现有 UI 操作使用 `InterprocessCommandGate` 协调;服务化时复用并审查覆盖范围,不另建绕过它的点击通道。
4. 联系人、群和群成员列表使用数据库读取,不增加 UI 长列表枚举回退。
5. M6 未完成;500 条发送、多 DPI、长时监听及部分管理/朋友圈写路径仍属暂缓验收。
6. 不实现“下一个未读会话”。语音 Beta、长文本自动分段、多附件批量等不因增加 UI 而自动恢复开发。
### 1.2 首版范围
- 本机或外部浏览器、HTTP 客户端与 MCP 客户端访问同一 Host;外部访问必须认证,HTTP 与 MCP 共用 Token、身份及权限。默认仍仅监听回环地址,外部 HTTP 监听须显式启用;不要求 HTTPS。
- 一个交互式 Windows 用户会话、一个自动化控制目标;多数据库账号可显式选择,但不承诺多微信实例并行控制。
- 完成诊断、会话、基础消息、受控文件、只读联系人/群成员、监听及任务中心。
- 管理和朋友圈等风险功能按能力状态逐项接入,不默认开放未经真机验收的写操作。
- 支持经 Token 认证的外部 HTTP 入口;明文传输不具备保密性,不作为安全公网部署方案。暂不做多租户、Windows Service、自动升级、批量营销或绕过已有确认门禁的破坏性操作。
## 2. 最小架构与运行方式
以下为实施建议,不代表已安装相应依赖。U0 阶段确认具体 SDK 版本与目标客户端兼容性。
``` text
本机/外部浏览器 本机/外部 MCP 客户端
│ 同源 HTTP + SSE │ Streamable HTTP
└──────────────┬───────────────────┘
▼
WxAgent.Host(同一进程、默认回环,可显式外部监听)
静态页面 / REST API / MCP 适配
▼
共享操作处理、权限、任务与错误映射
├── 只读数据库查询(有界并发)
└── 统一 UI 调度 → 现有跨进程门禁
▼
FlaUI / Win32 / 微信
```
### 2.1 技术与文件组织
- 继续 .NET 8、System.Text.Json、Microsoft.Extensions.Logging。
- Host 增加 ASP.NET Core Minimal API 和静态文件托管;复用现有 CLI,不启动 CLI 子进程解析 stdout 作为正式服务接口。
- Web UI 首版采用原生 HTML/CSS/JavaScript 模块、浏览器表单和 `fetch` ,不先引入 SPA 框架。
- MCP 使用维护中的官方 C# SDK,验证其 .NET 8 支持后锁定版本;不自行实现协议解析器。
- 一个 Host 进程同时提供 REST 和 MCP。首版选 Streamable HTTP; stdio 只有明确客户端兼容需求时再补,不能额外启动独立 UI 写执行器。
- 消息事件对浏览器使用 SSE;MCP 用显式订阅和有界事件拉取工具,不假设客户端都支持服务端主动通知。
建议新增位置:
``` text
src/WxAgent.Host/Api/ REST 路由和鉴权
src/WxAgent.Host/Mcp/ MCP 工具薄适配
src/WxAgent.Host/wwwroot/ 本地 Web UI
src/WxAgent.Core/ 必要的跨平台契约、校验和任务状态逻辑
```
仅在实际代码需要时创建文件。Windows 类型留在 Windows/Host;不新建微服务、插件系统或通用仓储框架。
以上路由目录为暂定位置:当前 Host 为 `net8.0-windows` /`win-x64` 且引用 Windows 项目,不能仅凭替换业务处理器就宣称真实 HTTP/MCP 适配可在 Linux 测试。U0 必须先运行一个加载真实路由、鉴权中间件和 MCP schema 的 Linux 冒烟实验;据此选择最小跨平台适配程序集或经验证的多目标方案。跨平台适配不得引用 FlaUI/Windows 项目,Host 仅负责组合和注入 Windows 执行器;不得复制一套测试专用路由冒充集成测试。
### 2.2 生命周期与调度
- 新增计划命令 `WxAgent.Host serve` ,在已登录、未锁定的微信用户会话运行;不是 Windows Service。
- 同一桌面仅一个服务实例;端口/实例冲突明确失败,保留现有 CLI 跨进程互斥保护。
- 点击、输入、滚动、导航以及依赖页面状态的读取统一排队;数据库纯读取不占用 UI 写队列。
- 使用有界 `Channel<T>` 承接请求,UI 执行遵守 COM/UIA 线程约束;整个复合动作持有执行所有权,步骤之间不允许另一请求切换页面。
- 审查已有门禁获取位置,避免服务层和库层嵌套获取同一非重入门禁造成死锁。
- 监听器只在短快照采集时占用 UI 调度,不持锁等待整个监听生命周期;不同目标冲突时排队或明确拒绝,不偷偷切换。
- 关闭服务时停止接单、取消未执行任务、保存已有监听 checkpoint;重启不自动重放写任务。
## 3. 功能、页面与服务映射
以下 REST 和 MCP 名称为**拟新增契约**,不是现有接口。U0 输出最终逐项操作清单,包括真实方法签名、输入、输出、风险和证据。
| 页面/模块 | 现有依据 | 拟 REST / MCP | 首版操作及限制 |
| --- | --- | --- | --- |
| 总览/环境 | doctor、window-status、tray-status | `GET /api/v1/status` / `agent_status` | Host、微信版本、登录/锁屏、窗口、队列状态分开展示;服务在线不等于微信可用 |
| 诊断 | inspect-ui、diagnose、recover-ui | `POST /api/v1/operations` / `agent_diagnose` 、`agent_recover_ui` | 导出脱敏诊断;恢复是会改变 UI 的显式操作,不随刷新执行 |
| 账号与数据库 | db status、scan、query | `/api/v1/accounts` / `db_accounts` 、`db_scan` 、`db_metadata` | 显式选账号;密钥扫描为本机管理员操作,默认不向 MCP 开放;不暴露通用 SQL |
| 会话 | session list/search/current/open/scroll | `/api/v1/sessions` / `sessions_list` 、`sessions_search` 、`session_open` 、`sessions_scroll` | 显示可见列表边界;同名目标拒绝猜测;搜索/滚动按 UI 操作调度 |
| 消息阅读 | chat read/history/latest/locate | `/api/v1/messages` / `messages_read` 、`messages_history` 、`message_locate` | 标明 UI 可见快照、历史滚动范围与上限;旧指纹不当永久 ID |
| 消息发送 | chat send/reply-latest/mention、group at-all | `POST /api/v1/operations` / `message_send_text` 、`message_reply` 、`message_mention` | 固定目标、正文预览;引用绑定选定消息;@所有人显式确认 ;不自动重试 |
| 文件/图片/卡片 | send-file、send-image、send-url-card | `/api/v1/files` + operations / `message_send_file` 、`message_send_image` 、`message_send_url_card` | 上传后用 fileId 发送;单附件;URL 卡片不退化为文本;URL 卡片不强加原 API 没有的 CONFIRM |
| 监听 | chat monitor/listen | `/api/v1/subscriptions` 、`/api/v1/events` / `listener_start` 、`listener_stop` 、`listener_events` | 启停、目标、续接、丢失区间、最后事件时间;不宣称离线必达 |
| 联系人/群成员 | db contacts、db group-members、管理读取 API | `/api/v1/contacts` 、`/api/v1/groups` / `contacts_list` 、`contact_get` 、`groups_list` 、`group_members` | 只读分页;稳定 ID;字段未知显示未知;已知群不标为最近活跃群 |
| 数据库消息/合并记录 | db messages、db merged | `/api/v1/db/messages` 、`/api/v1/db/merged` / `db_messages` 、`db_merged` | 指定账号/会话;递归内容受深度/条数限制;不承诺附件原文件下载 |
| 子窗口/导航 | C# 子窗口、导航 API | operations / `windows_list` 、`window_open` 、`window_close` 、`navigation_switch` | 目标窗口须唯一;窗口关闭不是退出微信 |
| 消息动作/附件 | 管理及内容读取 API | operations / `message_forward` 、`message_download` 、`message_ocr` 、`message_to_text` 、`message_content` | 按实际能力逐项开放;独立 OCR 窗口无法归属时返回 ResultUnconfirmed |
| 联系人/群管理 | C# 管理 API | operations / 按编辑好友、建群、加成员、修改群信息分别建工具 | U6 条件交付;逐项补充专用对象真机验收,不开放任意菜单点击工具 |
| 朋友圈/低频动作 | C# Moments、拍一拍、语音 API | operations / 按读取、刷新、发布、点赞、评论分别建工具 | 读写分权;写操作 U6 条件交付;语音 Beta 默认禁用 |
| 任务/审计 | 新增服务能力 | `/api/v1/operations/{id}` / `operation_get` 、`operation_cancel` | 结果、阶段、错误、关联 ID、确认和脱敏诊断;取消不等于撤销 |
每个分页响应明确 `items/limit/offset/hasMore/nextOffset` 或实际可用游标。现有 offset 分页不是事务快照;数据变更时提示刷新,不声称全量一致。
## 4. 共享服务契约
### 4.1 能力清单
新增 `GET /api/v1/capabilities` 和 `agent_capabilities` ,对每项操作返回:
- 操作标识、输入输出版本、是否需 UI、是否有外部副作用。
- `implemented` 、`validated` 、`enabled` 分开表示,并附证据位置/适用微信版本。
- 是否需确认、所需权限、默认超时、限制、禁用原因。
- `Unavailable` /`Experimental` /`Ready` 是展示状态,不能用“有方法”自动推导 Ready。
UI 根据能力显示禁用原因;服务端仍独立校验。MCP 不注册未实现工具,实验功能仅显式启用后可调用。
### 4.2 请求与结果
- 查询使用受限的分页与筛选;任何会产生微信副作用的动作禁止使用 GET。
- 写操作请求包含 `operation` 、`accountId` 、明确 `target` 、类型化 `arguments` 、`timeoutSeconds` 和 `idempotencyKey` ;不提供 approvalId。有外部副作用的操作必须提供幂等键。客户端在首次提交前生成键,双击及网络重试复用同一键,明确发起另一操作才换键。
- 状态、联系人分页等短查询直接返回结果,不创建持久任务、不要求轮询;写操作及确实耗时的操作才返回任务 ID。直接返回不等于绕过调度,依赖 UI 页面状态的读取仍经过统一队列。
- 账号数据库指纹仅证明数据归属;不能据此推断当前微信 UI 活跃账号。当前 `GetMyInfoAsync` 返回显示名/微信号等,不构成到数据库根目录指纹的可靠绑定。U0 必须验证绑定证据及实现路径,禁止按昵称、缓存 PID 或仅 page 1 HMAC 猜测关联;未形成可靠关联前禁用写能力。
- 写前在取得 UI 执行所有权后验证账号绑定,复合动作在提交副作用前再次检查可观察身份。退出登录、账号切换、微信进程重启或身份不可判定时使绑定及待执行写任务失效,要求重新验证;无法可靠检测的场景保持禁用,不以人工选择数据库账号替代验证。
- 返回 `operationId/correlationId/status/result/error` ;错误包含稳定 `code` 、安全的 `message` 、`stage` 和明确的重试提示。
- 保留现有 WxAgent 错误码;新增鉴权、队列、幂等冲突和游标失效错误时先补测试,再固定对外契约。
- 接单返回 HTTP 202 不代表成功;MCP 同样返回任务 ID 和状态,不把“已入队”包装为“已发送”。
- HTTP 建议:参数 400、未认证 401、无权 403、冲突 409、队列饱和 429、微信不可用 503;运行后的业务结果以任务终态为准。
- MCP 协议参数错误与业务失败分开处理;已执行失败按 SDK 工具错误约定及结构化错误码返回,不伪装正常成功。
### 4.3 任务、超时与幂等
``` text
Queued → Running → Succeeded / Failed / Cancelled / Unconfirmed
```
| 当前状态/事件 | 转换及约束 |
| --- | --- |
| Queued:取消 | Cancelled,不执行微信动作 |
| Queued:预算耗尽 | Failed / Timeout,不进入执行器 |
| Queued:权限撤销/绑定失效 | Failed / AuthorizationRevoked 或 AccountBindingInvalid,不执行微信动作 |
| Running:取消/超时/权限撤销 | 未产生副作用且能证明已停止时按取消/失败收尾;已提交或无法证明未提交时为 Unconfirmed,绝不释放所有权后让后台残留动作继续运行 |
| Host 重启 | Queued 写任务变 Cancelled, Running 写任务变 Unconfirmed;不重放 |
- 无人工审批等待状态。默认预算建议查询 30 秒、写入 60 秒、扫描 120 秒,设置服务端上限;排队时间计入总预算。
- 监听为独立订阅生命周期,不使用无限长 HTTP 请求充当普通写任务。
- 尚未开始的任务可以确定取消;已点击发送/提交后取消或超时,若无法证明结果则为 `Unconfirmed` ,不能声称撤销成功。
- `ResultUnconfirmed` 映射为不确定终态,UI 提示人工核实且不显示默认重试按钮。
- 相同 principalId、幂等键与相同业务参数返回已有任务;同键不同参数报冲突。HTTP/MCP 使用相同去重命名空间;对规范化后的操作、账号、目标及完整业务参数计算摘要,不将传输关联 ID 纳入比较。幂等键不等于微信 exactly-once 保证。
- 原子创建任务和幂等记录并持久化成功后,才返回 HTTP 202/MCP 接单结果或将任务交给执行器;持久化失败不执行。Running 状态必须先持久化再开始副作用。记录不含消息正文/密钥;运行参数仅在受控内存中保留。
- principalId 独立于 Token 值;更换 Token 保留身份与去重记录,重新登录不重置去重窗口。显式创建新身份不共享幂等窗口,不得用新身份重试结果不确定的旧操作。
- 崩溃恢复按状态表处理;写任务不自动再发。队列无容量时拒绝接单,不返回虚假接单成功。
- 首版建议队列上限 100、终态保留 24 小时/最多 10000 条;提前清理意味着去重窗口缩短,必须公开窗口并拒绝将其宣传为永久幂等。
- 任务记录优先复用现有存储;无现成实现时使用小型 SQLite 任务表,不引入消息中间件。
## 5. 安全与隐私
### 5.1 本机与外部入口鉴权
1. 默认绑定 `127.0.0.1` /`::1` ;允许显式配置非回环 IP、`0.0.0.0` /`::` 、端口和允许的访问域名。外部 HTTP 监听必须先配置有效 Token,否则启动失败;不自动开放防火墙。不要求 HTTPS,不开发证书管理及反向代理适配。
2. HTTP API 与 MCP 共用高熵 Token、principalId、权限和撤销机制,同一 Token 可以调用两种协议。直接客户端使用 `Authorization: Bearer <TOKEN>` ,不得将 Token 放入 URL、查询参数、日志或 MCP session ID。Token 首次生成/配置及授权在 Windows 主机本地完成,文件由当前用户 ACL 保护;不通过匿名网络接口生成或提权。
3. 本机和外部 Web UI 统一输入 Token 登录,不实现配对码。只匿名提供无业务数据的登录页及静态资源;浏览器通过 POST 换取短期 `HttpOnly` 、`SameSite=Strict` 会话 Cookie,随后清空输入,不把 Token 写入 localStorage/sessionStorage 或持久缓存。明文 HTTP 下 Cookie 不设置 Secure,因此不具备传输保密性。会话继承 Token 身份和权限;SSE 使用该 Cookie,写请求另校验 CSRF。API/MCP 无 Token 或有效派生会话时拒绝,错误/状态接口不得匿名泄露环境信息。
4. Token 登录失败限流;校验配置的 Host 与精确 Origin 白名单,不设置通配 CORS。原生 MCP/HTTP 客户端可无 Origin,但仍须 Bearer 认证;有 Origin 则必须通过检查。本机专用入口仅接受直接回环连接,不信任客户端自报 Host、Origin 或 X-Forwarded-For 作为来源证明。
5. 首版权限区分只读、内容读取、普通写、管理写和本机诊断管理;凭据默认只读。共享 Token 即共享身份,不能隔离共享者;需要隔离时配置不同身份的 Token。密钥扫描、保存等本机专用动作不能因外部 Token 有管理权限而开放。
6. 更换或撤销 Token 立即使旧 Token、派生 Cookie 和 MCP 会话授权失效,关闭相关 SSE/事件流,不实现新旧 Token 重叠窗口;稳定身份和幂等记录保留。每次资源访问及每个事件输出批次检查授权;执行及实际提交副作用前重新检查。未执行任务失败且不执行;已提交任务保留真实/不确定结果,不承诺撤销微信动作。
**明文传输限制: ** Token、Cookie、聊天内容和附件可被网络监听或中间人窃取/篡改;Token 认证不等于加密。外部 HTTP 仅建议用于可信隔离网络,界面和部署说明必须提示此风险,不宣称可安全直接暴露公网。
### 5.1.1 对象级权限
- operation、subscription、事件游标、fileId、artifactId 均绑定 principalId 和适用账号范围;ID 不透明不等于授权。查询、列表、取消、续接、内容展开及下载都检查归属与当前权限,任务结果中的正文仍需内容读取权限。
- 普通任务、订阅和文件只允许所有者访问,不实现管理员跨身份读取/取消功能。
- 撤销、账号切换及退出时清理相关浏览器内容、关闭旧订阅;内容响应设 `Cache-Control: no-store` 。已交付客户端的数据无法追回,不宣称撤销能擦除第三方副本。
### 5.2 写入授权与现有确认门禁
- 不实现人工审批中心、审批记录、approvalId、AwaitingApproval 或等待另一人批准的流程。已启用操作在权限、参数、账号和目标校验通过后直接入队。
- 普通发送由 UI 明确点击发送;HTTP/MCP 要求普通写权限和显式目标。管理写权限不自动启用未验收功能,也不解除 PENDING 暂缓项。
- 已有要求 `CONFIRM` 的库操作仍需调用方在本次请求中明确提供对应确认参数,服务不得默认补入。该参数只表达本次动作确认,不是 Token、提权凭据或人工审批;参数纳入幂等摘要。UI 展示目标与影响后提交,不建立审批工作流。
- @所有人等既定显式确认要求保留 ;任何确认均不能代替目标唯一性、账号绑定及写后结果检查。
### 5.3 内容、文件与数据库
- 服务默认返回摘要;经授权并显式请求正文才返回内容。浏览器切换账号/退出时清理内容,不将聊天内容默认写入持久缓存。
- 消息、昵称、OCR 和 Markdown 都是非可信数据,用 textContent/安全渲染处理,禁止直接 innerHTML;不自动访问内容里的 URL。
- MCP 返回的消息内容只是数据,不能作为执行工具、授权或改变系统策略的指令。
- 上传建议首版单文件最多 50 MiB、临时区总量 500 MiB;以服务端最终配置为准并在 UI 展示。限制大小、类型、数量、保留时间,校验后以不透明 fileId 引用。
- 拒绝外部任意绝对路径、UNC、`..` 、符号链接/重解析点逃逸;发送前重新验证文件归属和摘要。浏览器下载只允许授权 artifactId,不提供任意本机文件读取。
- 文件上传/下载不自动执行;临时产物 24 小时清理,任务占用时不误删;下载诊断包也需权限。
- 数据库密钥仅服务端使用;扫描候选必须经 page 1 HMAC 校验后才允许使用/保存。仅本机显式管理动作可保存,MCP/UI 不返回完整密钥。
- 数据库只读、query_only、有界固定查询;不提供原始 SQL、进程内存读取或密钥导出工具。
- 日志只保留操作类型、脱敏目标摘要、耗时、错误码和 correlationId; Cookie、Token、消息正文、附件、完整 UI 树和密钥不得进入普通日志。
## 6. 开发阶段与验收门槛
阶段按 U0 → U1 → U2/U3 → U4 → U5 → U6 → U7 推进。U2/U3 可独立开发适配代码,但共用契约;不得并行操作同一微信桌面。
### U0:盘点和契约冻结(2–3 人日)
开发步骤:
1. 逐项核对 Program.cs、公开 C# API、PENDING 和验收记录,输出操作清单,不用旧里程碑状态替代现状。
2. 标记 Ready、待真机验证、暂缓、未实现;列清 UI 页面、REST、MCP、真实方法和风险对应关系。
3. 确认目标 MCP 客户端、协议/SDK 版本、首版浏览器;锁定本机与外部 HTTP 部署、共用 Token 和原生 Web UI 方案,验证目标 MCP 客户端支持非回环 HTTP 与 Bearer 配置;不支持时明确标记客户端不兼容,不绕过其安全限制。
4. 定义 DTO、错误、任务状态、权限、确认策略、上传限制和内容披露规则。
5. 验证数据库账号到当前 UI 账号的可靠绑定及失效检测;无可靠方案则写能力 No-Go,不阻塞只读基础版。
6. 验证 Linux 能加载真实 HTTP/MCP 适配层的最小测试,再冻结项目边界;不能仅以 Core 替身测试通过代替。
验收:
- 功能矩阵所有行均有真实入口或“未实现”说明;零虚构可用服务。
- 每项写动作有目标判定、确认规则、超时/取消语义和后置成功条件。
- SDK 可恢复/编译,目标 MCP 客户端可使用与 HTTP API 相同的 Token 经外部 HTTP 完成最小 initialize/list/call 实验。
- 账号绑定有可验证证据,覆盖切换账号、重启及身份未知时拒绝写入;缺失则明确阻塞 U4 写能力。
- Linux 真实适配冒烟覆盖至少一条路由、鉴权中间件和一个 MCP 工具 schema,不加载 Windows 实现。
- 交付 `docs/WebUI-MCP-功能矩阵.md` ,未经批准的暂缓项仍保持暂缓。
### U1:服务骨架与共享执行(4–6 人日)
开发步骤:
1. 增加 serve 分支和最小 HTTP Host, CLI 行为保持兼容。
2. 提取必要共享处理逻辑,使 REST、MCP 不复制参数校验和微信操作实现。
3. 接入有界队列、现有门禁、超时取消和任务记录,核查库 API 未受门禁保护的路径。
4. 实现默认回环及显式外部 HTTP 监听、HTTP/MCP 共用 Token、统一浏览器 Token 登录、权限、CSRF、Host/Origin 检查和脱敏日志。
5. 先接 status、capabilities、operations 查询和取消。
验收:
- 原 Core 测试与全量 Release 构建通过;CLI 原命令 smoke 不退化。
- 20 个并发模拟 UI 请求的最大执行并发数为 1;复合动作不交错;数据库读取不长期阻塞 UI。
- 队列超过上限明确拒绝,不无限增长;排队超时后不得执行微信动作。
- 未认证、错误 Origin/Host、无权限和跨站写请求均被拒绝;密钥与正文日志扫描为零泄漏。
- 重复任务返回同一 ID;冲突参数拒绝;强制终止后不重放写操作。
- 写请求缺幂等键被拒绝;同身份跨 HTTP/MCP 并发、接单响应丢失后重试、Token 轮换后重试均返回原任务;记录持久化失败无微信动作。
- 排队超时、取消、重启恢复及持久化失败有状态测试;短查询直接返回且不产生持久任务,UI 查询仍串行调度。
- 两个身份不能互读/取消任务、读取事件或下载产物,无管理员跨身份例外。更换或撤销 Token 后旧 Cookie/MCP/SSE 立即失效,未执行任务不再写入,已提交任务不虚报已撤销。
- 非回环监听缺 Token 时启动失败;配置 Token 后可使用 HTTP,无 TLS 前置要求。HTTP/MCP 同 Token 得到相同身份和权限,缺失/错误 Token 均被拒绝;伪造转发头不能使用本机专用入口。
### U2:只读服务与 MCP 基础(3–5 人日)
开发步骤:
1. 接账号状态、会话、可见消息、数据库联系人/群成员和消息读取。
2. 明确数据库账号与 UI 当前账号的不同含义;多账号未选择时报错。
3. REST 与 MCP 共用处理函数,增加只读/内容权限和结果大小限制。
4. 建立 MCP 初始化、工具列表、schema、调用、错误、取消的兼容测试。
验收:
- 同一固定快照从 REST/MCP 返回相同业务字段和错误码(忽略关联 ID/时间)。
- 联系人同名不同 ID 不合并;limit/offset 边界和末页正确;未知字段不虚构。
- 未选多账号不猜测;未授权 includeContent 不泄露正文。
- list/tools 不含未实现的可用工具;输入越界在触碰微信之前失败。
- 所有列表有数量上限;旧游标/数据变更的限制在响应或页面可见。
### U3: Web UI 只读闭环(4– 6 人日)
开发步骤:
1. 建总览、账号选择、会话/消息、联系人/群成员、诊断、任务中心页面。
2. 实现统一 loading/empty/error/offline/unsupported 状态、分页和刷新。
3. 加入正文显示开关、能力禁用说明、关联 ID 复制与脱敏诊断下载。
4. 实现键盘导航、可读焦点、表单标签和自适应布局。
验收:
- Edge/Chrome 目标版本在本机和外部均可完成“输入共用 Token → 状态 → 选账号 → 读取 → 分页 → 退出”。仅本机诊断管理动作在外部显示禁用。
- 登录失败、Token 失效/撤销有明确提示,外部 HTTP 页面提示明文风险;浏览器持久存储、URL、历史和普通日志不含 Token,注销关闭事件流。
- 刷新页面、服务离线、401、空列表、超时均有明确可恢复提示,不显示假数据或无限 loading。
- 昵称/消息含 HTML、脚本或 Markdown 链接时不执行代码,不自动请求外部资源。
- 1280× 720 和 1920× 1080 无关键控件遮挡;浏览器 100%/125%/150% 缩放可操作;这不替代微信 DPI 验收。
- 全程键盘可选择目标、打开详情、关闭弹窗,焦点不丢失。
### U4:基础写入、文件和确认门禁(工期 U0 重估)
开发步骤:
1. 接文本、引用、单图片、单文件、URL 卡片以及明确支持的提及操作。
2. 写前绑定账号/目标和消息引用,检测重名、旧快照与已有草稿,不能覆盖用户草稿。
3. 复用现有操作的显式确认参数与权限检查;HTTP/MCP 校验后直接入队,不实现人工审批中心。
4. 接上传、fileId、产物下载、限额及清理;实现写后确认与不确定状态展示。
验收:
- 仅对白名单测试对象执行,每种首版发送类型至少成功 1 次并读回对应类型/内容摘要;发送请求不因点击、HTTP/MCP 重试而重复执行。
- 前端快速双击、同幂等键并发、断连后重查均只产生一个逻辑任务。
- 已有要求确认参数的操作缺少确认时无副作用,适配器不自动补 `CONFIRM` ;确认不提升权限。相同幂等键下参数变更被拒绝;账号切换使待执行写任务失效,取得执行所有权后绑定不匹配则不发送。
- 点击提交后故意中断确认阶段,返回 Unconfirmed,不自动重发。
- 文件超限、扩展名伪装、路径穿越、非本用户 fileId 和过期产物被拒绝;合法文件发送并确认。
- URL 卡片验收必须确认原生卡片,不能以发送 URL 文本冒充。
### U5:实时监听与恢复(4–6 人日)
开发步骤:
1. 接现有 MessageEvent/checkpoint,建立服务订阅生命周期和所有权。
2. 浏览器 SSE 输出事件 ID、来源会话、恢复标记;MCP 分页拉取相同事件。
3. 有界环形缓存与慢消费者隔离;游标过期返回 gap/resyncRequired,不能静默跳过。
4. 浏览器断连重连只恢复读取;Host 重启的监听续接与写任务不重放分开处理。
验收:
- 60 分钟受控测试,记录至少 20 条独立标记消息;在声明的可见/监听覆盖范围内计数与来源正确、0 重复。
- 浏览器断连 30 秒且仍在缓存范围内,重连补齐事件;超过缓存范围明确报告缺口。
- 一个慢浏览器/MCP 客户端不能阻塞 UI 执行或其他订阅;缓存数量不超过上限。
- Token 撤销或权限收回后,现有 SSE/MCP 事件读取停止输出;另一身份不能凭窃取的订阅 ID/游标读取历史事件。
- UI 导航与监听冲突不会将消息归属到错误会话;无法确定时明确失败。
- 该短测不替代仍暂缓的 8/24/72 小时及多会话稳定性验收。
### U6:管理和高级功能(条件阶段,5–10 人日,不含暂缓等待)
开发步骤:
1. 按“只读详情 → 子窗口 → 消息动作 → 管理变更 → 朋友圈写入”逐项接入。
2. 对照真实方法签名建立专用 DTO 和 MCP 工具,不开放任意 UI 菜单、脚本或 shell。
3. 每项写能力先补专用测试对象的定位、确认及后置结果验证,再解除 capability 禁用。
4. 合并记录、OCR、转文字、语音 Beta 显示真实限制;保持 PENDING 决定。
验收:
- 每个解除禁用的动作分别具备成功、无权限、取消、歧义目标、结果不确定用例。
- 联系人/群管理、朋友圈写入必须另获恢复暂缓验收的明确授权;没有授权则维持禁用并标记条件未满足。
- 朋友圈刷新后旧指纹拒绝操作;管理弹窗不唯一时不点击;未知 OCR 结果不返回整窗拼接文本。
- 语音 Beta、长列表提及、嵌套合并附件等未验证项不得显示正式可用。
- U6 未完成不伪装全功能交付;可以发布明确标注功能范围的 U1–U5 基础版。
### U7:集成、部署与发布(3–5 人日)
开发步骤:
1. 完成 Core 契约测试、HTTP/MCP 一致性和浏览器端到端测试;UI 测试使用明确的 mock 数据,不计入真机通过数。
2. Linux restore/test/build/publish 后上传 Windows,同一已登录用户会话启动 serve。
3. 执行 doctor/inspect-ui/smoke 及本期实际接入功能回归,记录 Windows/微信/浏览器/MCP 客户端版本。
4. 验证关闭、崩溃重启、凭据撤销、端口冲突、锁屏、微信退出及版本不支持路径。
5. 从另一主机验证外部 HTTP Web UI、HTTP API 和 MCP:同一 Token 可访问,缺失/错误/撤销 Token 被拒绝,本机专用入口不可访问;验证 Host/Origin、限流和防火墙部署要求,不以 localhost 自测代替。
6. 输出使用说明、HTTP/MCP 共用 Token 配置样例(只用占位值)、显式监听配置、明文风险提示、凭据更换、回滚步骤及本轮验收报告。
验收:
- 发布包包含 Web 静态资源与 MCP 依赖;Windows 无全局 dotnet 也可运行。
- 未锁定会话正常工作;锁屏/未登录时明确拒绝写入,不进入 Session 0,不绕过登录。
- CLI、Web UI、MCP 并发提交时无 UI 步骤交错;原有 CLI 行为和安全门禁不退化。
- 所有首版必选测试通过;未完成项附禁用状态、影响及证据,零已知越权、重复写入和隐私泄漏缺陷。
- 回滚前停止新服务,保存必要任务记录;旧版本不得自动消费新版本未完成写任务。
## 7. 测试执行与证据模板
### 7.1 Linux 构建基线
``` bash
dotnet restore WxAgent.sln -p:EnableWindowsTargeting= true
dotnet test tests/WxAgent.Core.Tests -c Release
dotnet build WxAgent.sln -c Release -p:EnableWindowsTargeting= true
dotnet publish src/WxAgent.Host -c Release -r win-x64 --self-contained true \
-p:EnableWindowsTargeting= true -p:PublishSingleFile= true -p:PublishTrimmed= false
```
新增 HTTP/MCP 测试必须在 Linux 加载生产使用的真实路由、鉴权和协议适配,仅 Windows 业务执行器使用纯逻辑替身;不得通过重写测试路由规避 Host 的 Windows 目标限制。按 U0 验证后的最小跨平台项目边界实施,不在 Linux 执行 FlaUI;Windows 会话绑定、部署监听和桌面行为留在 Windows。实施时将新测试命令纳入发布清单。
### 7.2 Windows 真机
沿用 AGENTS.md:主机 `10.1.1.101` 、计算机 `DESKTOP-EGI7QCK` 、用户 `rogee` ,部署到 `C:\Users\Rogee\wx-agent` 。优先 Windows MCP,上传/日志可用 `ssh rogee@10.1.1.101` 。当前环境的 Windows MCP 是操作真机的工具,**不是本计划要开发的 WxAgent MCP 服务**。
每次发布至少执行:
``` powershell
WxAgent . Host doctor
WxAgent . Host inspect-ui - -output artifacts / ui-tree . json
WxAgent . Host smoke
# 本计划实施后的新增入口,当前不能作为已有命令执行:
WxAgent . Host serve
```
- smoke 有发送副作用,测试对象和次数必须写入报告。
- 消息测试仅使用“文件传输助手”“Hao 豪”“吉祥三宝”“消息测试专用群组”;@所有人仅在指定测试群 。
- 不为完成 UI/MCP 接入而操作真实联系人、真实群或朋友圈内容;已有暂缓写验收需另行授权。
- 新增验收记录建议保存到 `docs/validation/WebUI-MCP-<日期>.md` ,敏感原始产物不提交仓库。
### 7.3 单项验收记录
| 字段 | 必填内容 |
| --- | --- |
| 能力/用例 | 操作 ID、REST 路由、MCP 工具、UI 入口 |
| 环境 | 提交号、包版本、Windows/微信/浏览器/MCP 客户端版本、DPI、会话状态 |
| 前置条件 | 权限、账号绑定、目标别名、启用状态和既有确认参数要求 |
| 输入 | 脱敏参数、数量、边界及超时设置 |
| 预期 | HTTP/工具错误码、任务状态、可观察微信后置结果 |
| 实际 | correlationId、脱敏证据、耗时、重复/遗漏计数 |
| 结论 | 通过/失败/未执行/暂缓,不用“基本支持” |
| 限制 | 失败诊断、适用范围、是否阻塞对应 capability 启用 |
## 8. 排期、交付和完成定义
单工程师原本机范围估算:U0–U5 加 U7 为 **25– 39 人日 ** ; U6 另计 **5– 10 人日 ** 。当前范围增加外部 HTTP、共用 Token、对象级授权及撤销验证,补入账号绑定和 Linux 真实适配技术验证;同时取消 HTTPS 要求、配对码、人工审批、Token 重叠轮换及管理员跨身份管理。旧总工期和阶段人日仅为历史参考,U0 完成后重新估算;不含用户暂缓等待、微信版本适配及全面压力测试。
基础版交付:
- 可发布的 serve 入口、支持本机及外部 HTTP 的同源 Web UI、HTTP/MCP 共用 Token 与已验证连接配置。
- 共享契约与能力矩阵、鉴权、现有确认门禁、任务和事件通道。
- 首版功能的 Linux 自动测试和 Windows 真机证据。
- 用户操作手册、诊断导出、凭据撤销及回滚说明。
最终完成必须同时满足:
1. UI、REST、MCP 对同一业务操作使用同一校验、权限和调度路径。
2. 每个标记 Ready 的能力有输入/输出、超时取消、稳定错误、测试及当前微信版本验收记录。
3. 成功表示已满足明确后置条件;未确认结果不会误标成功,不盲目重试。
4. 应用日志及未授权响应无内容/密钥泄漏、无未认证写入、无任意文件或 SQL 入口;外部业务访问通过共用 Token 或其有效派生会话认证,对象级授权、撤销及本机专用边界有验收证据。明文 HTTP 不保证传输保密性,不能将通过应用鉴权验收描述为网络防窃听验收通过。
5. 未实现、暂缓与不支持项在文档、UI 和 MCP 能力信息中一致;不得将本次控制面交付描述为 M6 或全功能矩阵已完成。