diff --git a/docs/better-douyin-整合计划.md b/docs/better-douyin-整合计划.md new file mode 100644 index 0000000..2e428c9 --- /dev/null +++ b/docs/better-douyin-整合计划.md @@ -0,0 +1,268 @@ +# better-douyin 整合计划 + +> 状态:待排期,仅作为 CreatorHub 的独立实现计划,不代表相关功能已经完成。 +> +> 参考项目: +> +> 审阅快照:commit `f534c66d61f541a526fa3f5251d32494aad758a8`(2026-08-28) +> +> 需求基线:[`docs/plan01.md`](./plan01.md) + +## 1. 目标 + +从 `better-douyin` 中吸收经过验证的产品组织方式和状态处理思路,补强 CreatorHub 的抖音完整流程: + +- 真实事件监听、断线恢复和事件去重; +- 竞品创作者监控、作品发现和素材处理; +- 统一的自动响应与人工发送工作台; +- 评论线索、通知和私信的可追溯处理; +- AI 建议、动作策略和任务结果证据。 + +本计划只吸收**功能思想和交互原则**,不复制源代码、界面资源、提示词、品牌内容或私有协议实现。 + +## 2. 审阅结论与边界 + +### 2.1 参考项目的公开边界 + +公开仓库主要包含: + +- React 前端界面; +- Tauri mock bridge; +- Node mock backend; +- 前端契约和模拟数据。 + +公开内容不包含真实抖音接口、登录会话、Cookie、签名、下载解析、发布密钥或真实平台验收证据。因此,项目中的功能只能作为产品和代码组织参考,不能作为 CreatorHub 的真实平台能力证明。 + +### 2.2 许可证限制 + +仓库使用 `Better Douyin Non-Commercial License`。CreatorHub 面向商业使用,不能直接复制或改造其代码、资源和衍生实现;如需复用原代码,必须先取得明确的书面许可。本计划默认全部功能由 CreatorHub 独立实现。 + +### 2.3 必须保持的 CreatorHub 原则 + +1. 自动动作与人工动作分离:自动动作按策略和 UID 冷却执行,人工发送逐次确认。 +2. 自有账号的点赞、评论、关注、转发和私信优先使用真实事件监听,不以轮询或 Mock 冒充实际能力。 +3. 写操作必须核对账号身份,并记录成功、失败或结果不明;不能把异常静默转换为成功。 +4. 不增加本地 Web UI 或本地 MCP。统一管理继续放在远程 Web 和控制面。 +5. 抖音真实流程完成并验收前,不提前扩展小红书实现。 + +## 3. 可吸收功能清单 + +| 优先级 | 参考亮点 | CreatorHub 整合方式 | 参考位置 | +| --- | --- | --- | --- | +| P0 | 私信实时事件、历史补偿、断线恢复、账号切换保护、静默基线 | 独立重写到真实事件链路,增加我们的结果证据和 `uncertain` 状态 | `frontend/src/components/friends/`、`frontend/src/hooks/use-global-friends-im.ts` | +| P0 | 统一自动化工作台 | 集中展示来源、策略、动作、运行状态、日志和失败原因 | `frontend/src/components/automation/automation-view.tsx` | +| P0 | 关键词、阈值、延迟、单次动作上限、去重 | 映射到账号策略、UID 冷却、人工确认和自动策略 | `automation-settings-dialog.tsx`、`lib/ai-automation.ts` | +| P1 | 创作者监控、基线、新作品发现、周期扫描、批量下载 | 用于竞品创作者采集;按 CreatorHub 的真实分页、采集和限时要求实现 | `lib/contracts.ts`、`automation-view.tsx` | +| P1 | 下载任务状态和历史 | 用于素材下载、提音轨、转写;增加结果不明和证据查看 | `components/downloads/`、`hooks/use-downloads.ts` | +| P1 | 通知分类、作品跳转、直接回复 | 作为评论线索和私信入口;主触发仍来自真实事件 | `components/notices/notices-view.tsx`、`use-global-notice-monitor.ts` | +| P1 | 搜索和链接解析 | 作为竞品 UID、作品和创作者监控的导入入口 | `components/search/`、`components/link/link-view.tsx` | +| P2 | AI 供应商、模型、建议回复配置 | 先用于建议和人工确认,再按策略开放自动动作 | `components/settings/settings-ai.tsx` | +| 不整合 | 本地 MCP 服务 | 与 CreatorHub 的远程 Web/控制面架构冲突;只保留写授权、确认和审计原则 | `components/settings/settings-mcp.tsx` | + +## 4. 实施阶段 + +### 阶段 0:冻结边界和验收口径 + +**目标**:避免把 mock 功能误当成真实能力,也避免直接引入不适合 CreatorHub 的架构。 + +**工作内容**: + +- 建立独立的事件、动作、监控任务和素材任务契约; +- 统一动作结果为 `success`、`failed`、`uncertain`; +- 为每次真实写操作定义最小证据:账号、目标 UID/作品、动作、时间、平台返回或页面证据; +- 将自动策略和人工确认建模为两条不同流程; +- 标注所有“仅离线可验证”的功能,禁止进入真实能力清单。 + +**完成标准**: + +- 计划、契约和测试都明确区分真实、模拟、失败和结果不明; +- 不存在静默回退、隐式重试或将 Mock 结果标记为成功的路径。 + +### 阶段 1:真实事件基础和私信恢复 + +**目标**:完成 CreatorHub 待办中的真实平台事件监听、去重和断连恢复。 + +**工作内容**: + +- 接收实时事件并核对平台、账号和当前会话代际; +- 使用账号和会话维度的事件身份,避免重复处理; +- 对历史同步建立静默基线,不把旧消息当成新消息; +- 断线后按游标、同步提示或有限历史窗口补偿; +- 对未确认身份、过期时间戳、旧账号事件和重复事件拒绝自动写操作; +- 保留有限长度的待处理队列,并记录溢出和停止原因; +- 将自动化副作用放在事件确认之后。 + +**必须覆盖的检查**: + +- 实时新消息; +- 重复事件; +- 断线重连; +- 账号切换期间的旧事件; +- 历史消息基线; +- 事件身份不可信; +- 超时、取消和结果不明。 + +**完成标准**: + +- 在真实测试账号上完成事件接收、恢复和去重证据; +- 满足 `plan01` 规定的 5 秒/30 秒时限; +- 所有自动动作都能追溯到唯一事件和账号。 + +### 阶段 2:统一自动化工作台和动作策略 + +**目标**:将推荐流、评论、通知、好友和创作者监控的响应集中到一个工作台。 + +**工作内容**: + +- 按事件来源、账号、策略、动作状态筛选; +- 展示候选动作、执行中的动作、成功、失败和结果不明; +- 展示动作前的目标、内容、策略命中原因和冷却信息; +- 人工发送必须先预览,再逐次确认; +- 自动动作必须经过启用状态、关键词/阈值、UID 冷却、单次上限和账号身份校验; +- 记录每个动作的尝试次数、实际结果、错误原因和证据链接。 + +**完成标准**: + +- 自动和人工动作在界面和服务层均不可混淆; +- 同一 UID 在冷却期间不会重复自动触发; +- 失败和结果不明不会被列表隐藏,也不会无条件重试。 + +### 阶段 3:创作者监控与竞品采集 + +**目标**:把创作者监控变成可审计的竞品采集流程。 + +**工作内容**: + +- 支持通过创作者 UID、主页链接或作品链接创建监控目标; +- 首次运行建立基线,历史作品不触发新作品动作; +- 后续运行只处理新增作品,并保存游标、最后成功时间和错误原因; +- 支持按账号、创作者、作品和采集状态查看结果; +- 新作品进入下载任务,不在采集阶段假设下载成功; +- 采集失败、分页异常、账号失效和权限变化都保留证据。 + +**完成标准**: + +- 真实创作者目标能够完成基线和新增作品识别; +- 重复运行不会重复创建同一作品任务; +- 采集证据与后续素材任务可以关联。 + +### 阶段 4:素材下载、提音轨和转写 + +**目标**:完成 CreatorHub 当前待办中的真实素材处理链路。 + +**任务状态**: + +`pending → running → succeeded / failed / uncertain`,并支持明确的 `cancelled`;只有有证据的失败才允许重试。 + +**工作内容**: + +- 下载任务支持进度、暂停、恢复、取消、重试和历史查看; +- 每一步保存输入作品、输出文件、尝试次数和实际错误; +- 下载完成后再进入提音轨和转写,不用空文件或 Mock 数据继续下游; +- 供应商响应超时或写入结果无法确认时标记 `uncertain`,交由人工处理; +- 成功证据至少包含输出文件存在性和可读取性,必要时保存校验值。 + +**完成标准**: + +- 真实素材可以从作品进入下载、提音轨和转写; +- 失败重试不会重复污染结果; +- 结果不明不会被显示为成功。 + +### 阶段 5:通知、评论线索和私信动作 + +**目标**:将通知和评论转化为可确认、可追踪的业务线索。 + +**工作内容**: + +- 将点赞、评论、关注、@和私信统一成事件列表; +- 每条事件显示账号、来源、目标作品、对方 UID、发生时间和处理状态; +- 支持从事件直接打开作品、查看评论上下文或进入私信; +- 评论回复和私信发送沿用人工确认流程; +- 自动回复只处理经过策略授权的真实新事件,不能处理历史基线事件; +- 发送成功、失败和结果不明均保存平台证据。 + +**完成标准**: + +- 从真实通知或私信事件到人工确认发送可以完整追踪; +- 事件去重、UID 冷却和账号切换保护有效; +- 不因通知轮询或页面刷新产生重复动作。 + +### 阶段 6:AI 建议和生产配置 + +**目标**:在真实事件和人工确认稳定后,再引入 AI 辅助。 + +**工作内容**: + +- 支持供应商、模型、提示词和超时配置; +- AI 默认生成建议,不默认代表已发送; +- 对建议保存输入事件、上下文、模型配置和最终人工修改; +- 供应商失败时直接暴露错误,不静默切换或伪造回复; +- 不采用“伪装成人工、否认 AI 身份”等提示词; +- 生产配置由控制面管理,凭据不进入前端日志、事件证据或普通租户数据。 + +**完成标准**: + +- AI 建议和平台写操作可以分别验收; +- AI 失败不会阻断人工处理,也不会被包装成成功; +- 配置、权限和审计边界符合 CreatorHub 的控制面设计。 + +### 阶段 7:小红书扩展 + +抖音真实流程、证据和失败处理完成后,再复用已经验证的事件、动作和任务模型实现小红书。不得因为 `better-douyin` 同时覆盖多个页面,就提前复制未经验证的平台适配层。 + +## 5. CreatorHub 与参考项目的差异化要求 + +| 参考项目做法 | CreatorHub 要求 | +| --- | --- | +| 公开 shell 使用 mock bridge | 真实平台能力必须有独立验收证据 | +| 通知可通过轮询触发自动化 | 真实事件监听为主,轮询只能用于恢复或健康检查 | +| 自动评论、私信、关注统一配置 | 自动策略与人工确认严格分离 | +| 下载任务有基础状态 | 增加结果不明、证据、真实输出和下游处理状态 | +| 本地 MCP 配置 | 使用远程 Web/控制面,不新增本地 MCP | +| AI 可配置自动动作 | 默认先生成建议,写操作需按策略或人工确认 | +| 项目许可证允许非商业使用 | CreatorHub 独立实现,不直接复制代码和资源 | + +## 6. 验收与回归要求 + +### 6.1 自动检查 + +按照受影响服务执行现有仓库门槛: + +- Go 控制面:`go test ./...`、`go vet ./...`、构建目标程序; +- 有并发、生命周期或共享状态变化时:`go test -race ./...`; +- Python gateway:非交互式单元测试、覆盖率检查、Compose 健康检查; +- 前端:使用 lockfile 安装,执行仓库测试和 `npm --prefix web run build`; +- 单元测试覆盖率保持 65% 以上。 + +### 6.2 真实平台验收 + +每个真实写操作至少记录: + +- 测试时间、平台、账号和目标 UID/作品; +- 触发事件及其唯一身份; +- 发送或操作内容; +- 平台页面、响应、状态或其他可复核证据; +- 最终分类:成功、失败或结果不明; +- 是否发生重试、断线恢复或账号切换。 + +离线测试、Mock bridge、截图占位和本地假数据只能证明界面或流程,不得作为真实平台成功证据。 + +## 7. 风险与处理 + +- **平台协议变化**:适配层失败必须显式暴露,并保留足够日志;不使用静默降级。 +- **事件重复或延迟**:依靠账号范围、事件身份、时间窗口和基线处理;不靠扩大重试次数掩盖问题。 +- **写操作结果不确定**:进入人工复核队列,不自动重拨或重复发送。 +- **账号身份错误**:写操作前再次核对当前账号、窗口和会话代际。 +- **许可证风险**:只参考公开行为和组织方式,所有实现、文案和资源独立完成。 +- **公开项目可信度不足**:其 mock 实现和缺失的检查脚本不纳入 CreatorHub 的质量证明。 + +## 8. 参考文件 + +- [better-douyin README](https://github.com/anYuJia/better-douyin/blob/f534c66d61f541a526fa3f5251d32494aad758a8/README.md) +- [better-douyin LICENSE](https://github.com/anYuJia/better-douyin/blob/f534c66d61f541a526fa3f5251d32494aad758a8/LICENSE) +- [开放边界说明](https://github.com/anYuJia/better-douyin/blob/f534c66d61f541a526fa3f5251d32494aad758a8/OPEN_SOURCE.md) +- [适配器边界说明](https://github.com/anYuJia/better-douyin/blob/f534c66d61f541a526fa3f5251d32494aad758a8/docs/adapter-boundary.md) +- [共享契约](https://github.com/anYuJia/better-douyin/blob/f534c66d61f541a526fa3f5251d32494aad758a8/frontend/src/lib/contracts.ts) +- [自动化工作台](https://github.com/anYuJia/better-douyin/blob/f534c66d61f541a526fa3f5251d32494aad758a8/frontend/src/components/automation/automation-view.tsx) +- [私信事件处理](https://github.com/anYuJia/better-douyin/tree/f534c66d61f541a526fa3f5251d32494aad758a8/frontend/src/components/friends) +- [下载任务](https://github.com/anYuJia/better-douyin/tree/f534c66d61f541a526fa3f5251d32494aad758a8/frontend/src/components/downloads) diff --git a/docs/e2e-evidence-20260914.md b/docs/e2e-evidence-20260914.md new file mode 100644 index 0000000..81f6bf5 --- /dev/null +++ b/docs/e2e-evidence-20260914.md @@ -0,0 +1,61 @@ +# CreatorHub E2E 执行证据(2026-09-14) + +本文件只保存脱敏摘要;Cookie、密码、token、主密钥和原始平台响应未写入仓库。 + +## 基线与回归 + +- Git:`main` 与远程同步;测试前后未发现源码或 staged 修改,任务提供的 `docs/e2e-test-plan.md` 为唯一既有未跟踪文件。 +- 回归门禁:`go test ./...`、`go vet ./...`、`go test -race ./...`、control-plane build、Python gateway 56 tests、Web 81 tests/build、`bash docs/deployment_stop_test.sh` 通过。 +- PostgreSQL Go 集成测试因 `CREATORHUB_POSTGRES_TEST_URL` 未设置而跳过;隔离 Compose 数据库故障测试见下文。 +- 历史脱敏控制面报告:`/home/rogee/.pi/agent/sessions/--home-rogee-Workspace-creator-hub--/subagent-artifacts/outputs/2cbcddb6-c347-41d0-a6f7-356dccd81a3e/api-e2e.txt`。 +- 历史回归报告:`/home/rogee/.pi/agent/sessions/--home-rogee-Workspace-creator-hub--/subagent-artifacts/outputs/2cbcddb6-c347-41d0-a6f7-356dccd81a3e/regression.txt`。 + +## 本轮补充控制面结果 + +- 作品:RUN 记录创建/重复写入/详情和来源筛选完成;重复返回同 ID。当前部署对不存在的 `owned` source 返回 201,故 API-01 判 FAIL;负计数返回 400。 +- 指标:verified 发布时间作品首次快照 200,重复 200,过期 409,负数/溢出/非法时间/未来时间均 400。完整设置 PUT 将 `metric_age_seconds` 改为 60 后仍保留未来 `next_metric_at` 且无停止原因,API-02 判 FAIL;设置已恢复为 2592000。 +- 评论:创建 201、重复 200、详情/作品过滤 200;空 author UID 保留正文;非法类型 400,缺失作品 404。API-03 PASS。 +- 事件:按当前 `InteractionEvent` 合同重新提交 comment baseline:新事件 201、重复 200、display 204、baseline process 200;空 interactor UID 的事件 201 且为 blocked,重复处理 200。此前报告中的 400 是错误/过载 payload,不代表当前合法合同结果。API-04 PASS。 +- 消息:创建 201、重复 200、会话/消息读取 200;同 peer 不同账号隔离;非法 direction/state/peer/platform 均 400。API-05 PASS。 +- JSON 边界:未知字段、尾随 JSON、错误类型、空 body 为 400;大于 1 MiB 为 413;不存在资源 404;不支持方法 405。`GET /api/creator/workz` 和 `GET /api/creator/profiles` 返回 200 HTML 而不是 JSON/404,API-06 判 FAIL。 +- 素材:选择 200;`material/process` 当前部署返回 405;仿写确认/更新在未处理状态返回 409。MAT-01 PASS,MAT-05/MAT-06 FAIL。 +- 规则:创建、列表、详情、更新、启停均成功;分析返回 503 `AI 分析不可用`;规则 DELETE 返回 405,测试规则已禁用。LEAD-01/02 PASS,LEAD-03 受工作台空白影响,LEAD-05 为 BLOCKED,LEAD-07 PASS。 +- 操作:缺 target 返回 400;重发 action 创建可成功,但执行结果保持不确定/失败,不自动重试;当前运行时对 confirmed like/repost 返回 `TARGET_MISMATCH`,未产生平台写副作用。OP-07 判 FAIL(未得到明确 `REPOST_TEXT_UNSUPPORTED`)。 + +## 隔离 Compose 故障证据 + +隔离项目 `creatorhub-e2e-isolated` 使用动态本地端口,未停止共享 Compose 服务;结束时已 `down -v --remove-orphans`,项目容器、卷、控制网络均为 0。 + +```text +isolated_base=http://127.0.0.1:42681 +health HTTP=204 +account_create HTTP=201 +account_get HTTP=200 +after_cp_restart HTTP=200 +db_fault_read HTTP=500 error=phase A operation failed +after_db_restore HTTP=200 +gateway_fault_list HTTP=200 empty list +gateway_fault_browser HTTP=200 empty list +after_gateway_restore HTTP=200 empty list +after_gateway_restore_browsers HTTP=200 empty list +cleanup: containers=0 volumes=0 network=0 +``` + +数据库失联响应可观察且未伪装为空成功,但该次未完成带 RUN 规则保存和结构化关联日志核验,因此 SYS-05 不判 PASS。隔离账号因无登录会话无法入队,未伪造 Phase A 任务结果。 + +另用无 Docker socket 的 gateway 一次性进程验证:进程非零退出,输出包含 socket/Docker 依赖错误且不包含 token;未创建任何业务资源。 + +## 浏览器与 REAL 边界 + +- 浏览器录制:`/home/rogee/.config/browser-harness/agent-workspace/recordings/creatorhub-e2e-final/`,覆盖列表、创建、详情、任务、草稿、审计、设置、网关、镜像、网络出口和运行环境路由;事件索引为同目录 `events.jsonl`。 +- 当前 managed browser 的 gateway identity 曾返回 HTTP 200,UID `99491952055`,昵称 `抖盲求真`;这是真实浏览器身份读取证据,不是平台写入证据。 +- Douyin 受限读取返回 HTML web shell 或空 detail,而非稳定作品 JSON;confirmed like/repost 返回 `TARGET_MISMATCH`。没有真实评论、私信、点赞、关注、转发写入被计为成功。 +- 竞品 `美食作家王刚` 登记后同步 503,原因 `resolve account credential`;竞品已暂停。控制面账号状态虽为 authorized/active,仍无可用于 connector 的 credential。 +- gateway 事件读取曾出现 `CDP message failed during Runtime.evaluate`;无事件、去重、重连、5 秒/30 秒平台证据。 +- 当前无健康代理/出口,无生产 AI/转写配置;规则分析 503。 +- browser-harness 对控制面 HTTP Basic challenge 的未登录 fetch 长时间处于“登录中”,错误凭据 UI 未显示明确 401 文案;因此 UI-02 判 FAIL,UI-01 的正向表单登录不判 PASS。 + +## 清理 + +- 未引用的临时镜像已删除,保留的验收镜像仍为 enabled;测试竞品已 pause,测试规则已 disable,临时账号已 revoke;隔离 Compose 项目已销毁。 +- API 作品、评论、指标、消息、事件没有公开删除 API;按约束未用 SQL 删除,RUN 数据作为残余记录并在报告中列出。END-02 因不能完全清理判 FAIL。 diff --git a/docs/e2e-test-plan.md b/docs/e2e-test-plan.md new file mode 100644 index 0000000..e58bf91 --- /dev/null +++ b/docs/e2e-test-plan.md @@ -0,0 +1,1665 @@ +# 当前系统全量功能测试计划(不含小红书) + +## 1. 基线、目标与执行边界 + +- 源码基线:`main`,HEAD `4d1dd37438b7c7001f572695feb5e1b56b9fc78d`。编写前父会话已同步远程且工作树干净。本文件是测试计划,**所有用例初始状态均为“未执行”**,不是测试报告。 +- 目标:验证当前页面、公开 API、Docker/浏览器 gateway、持久数据及实际抖音链路;以当前源码为准,不将 `docs/plan01.md` 的未实现目标列为既有功能。 +- 本次只编写并静态核验文档;不运行测试、不启动或停止服务、不改配置、不访问外部平台、不提交或推送。下文命令和故障操作均供**后续获准执行**,本次未执行。 +- 排除:小红书全部业务测试;未实现的自动密码登录、真实文章/视频发布、自动聊天、附件发送、运营工作台新建私信会话、永久删除账号/环境/出口、RBAC/多租户及性能压测。公众号/快手仅覆盖现有通用账号建档,不测试其采集或平台动作。 +- 不排除:已有代码但尚无真实验收证据的抖音读取、通知监听、点赞、回复、关注、私信、素材处理。外部条件不具备时标“阻塞”,不得改为“不适用”以提高通过率。 + +### 1.1 测试层级 + +| 标记 | 含义 | 可证明 / 不可证明 | +| --- | --- | --- | +| UI | 真实页面→控制面→数据库/实际运行资源 | 页面与服务闭环;单独不证明平台写入成功 | +| API | 用真实 HTTP 访问没有页面的接口或补充校验 | API 契约与持久化;人工导入数据不是采集/监听 E2E | +| REAL | 测试平台账号→真实浏览器/gateway→控制面→页面,再对照平台 | 真实平台端到端;必须有账号、目标和逐项写授权 | +| MOCK | 现有 Phase A Mock 执行接口 | 仅证明离线草稿/任务/审计链,不证明实际发布 | +| FAULT | 在隔离测试系统真实断网、停服务、撤销资源或浏览器请求阻断 | 故障处理;使用浏览器响应替换时只能证明 UI 防御,单独标为“UI 注入” | + +每条用例的“预期”是通过标准,不是已通过声明。已有缺陷也保留检查项;证实缺陷应记失败,不能因“代码就是这样”记通过。明确不支持的动作以拒绝和不产生副作用作为当前边界验收,不宣称其正向业务可用。 + +### 1.2 核对来源与纠偏 + +主要来源:`web/src/main.jsx`、`web/src/dataProvider.js`、`web/src/*Page.jsx`、`web/src/Layout.jsx`、`web/src/lib/ui.jsx`;`cmd/control-plane/{main,hub,phasea,creator,creator_events,creator_material}.go`;`internal/creator/{models,accounts,actions,collection,content,metrics,rules,settings,bailian}.go`;`internal/hub/{environment,fingerprint}.go`;`internal/douyin/creator_collector.go`;`cmd/docker_gateway/{gateway,douyin,proxy,docker_client}.py`;`compose.yaml`、`compose.dev.yaml`、`Dockerfile`、`docker/browser-wrapper/`。 + +其他运行文档只作操作参考:其中“代理仅凭据引用”“仿写自动生成”“抖音仅首批读取”等旧表述不能覆盖当前路由和源码。当前出口表单/API 接收用户名与密码,列表/详情会明文展示;证据必须脱敏。仿写确认只保存要求与确认时间,**没有 AI 生成调用或按钮**。`decodeCreator` 直接读 JSON body,不依据 Content-Type 选择解码,故保存仿写缺 header 不等于已经证实失败。 + +## 2. 前置条件与数据账本 + +### 2.1 环境 + +1. 使用专用、可销毁的 Linux Docker 测试主机;禁止与现有业务共用固定 `creatorhub_control` 网络、浏览器 alias 或数据卷。只修改 Compose project 名不足以隔离固定网络名。 +2. 由执行负责人按 `docs/deployment.md` 准备一次完整 Compose 部署,记录控制面/gateway 构建提交、镜像 digest、Docker/Compose/浏览器版本、操作系统、数据库版本、时区、测试起止 UTC;另用独立时段验证 `compose.dev.yaml` 的开发入口。不得一边测试一边自动升级源码。 +3. 准备 `curl`、`jq`、Docker CLI、浏览器 DevTools;媒体核验使用当前镜像内的 `ffprobe`/`ffmpeg`。真实浏览器镜像使用 `docker/browser-wrapper/README.md` 中已登记来源与 digest 的包装镜像,准备两个可用版本和一个不存在引用。 +4. 配置必须来自测试凭据保管渠道:`CONTROL_PLANE_USERNAME`、`CONTROL_PLANE_PASSWORD`、32 字节 Base64 `CREATORHUB_CREDENTIAL_MASTER_KEY`、`DOCKER_GID`、`GATEWAY_TOKEN`。不得将实际密码、Cookie、token、证件号贴入文档/缺陷/日志截图。 +5. 记录控制面 `LISTEN_ADDR`、`WEB_DIR`、`DATABASE_URL`、`CREATORHUB_CREDENTIAL_STORE_DIR`、`LOG_LEVEL`;gateway 的 `LISTEN_ADDR`、`DOCKER_SOCKET`、`BROWSER_NETWORK`。媒体目录 `CREATOR_MEDIA_DIR` 可写;如测转写,`CREATOR_TRANSCRIPTION_BIN` 必须是已安装的真实供应商适配程序,接受音轨路径参数、stdout 输出正文;不能用 `echo` 冒充真实转写。 +6. 如测 AI:准备已审批的 Bailian 账号、配额、`BAILIAN_API_KEY`,可选 `BAILIAN_BASE_URL`;页面 provider 填 `bailian`,model 填实际批准模型。勾选“已完成审批”并不验证密钥。转写页面元数据也不替代可执行程序配置。 +7. 对所有代理协议 http/https/socks4/socks5 分别准备真实可控测试端点;至少一个无认证端点、一个带认证端点、两个不同公网 IP、一个不可达端点,保存实际地区与供应商定义。没有某协议服务时该行阻塞,不能用另一协议代替。 +8. 记录观察窗口:普通 API 30 秒;创建/升级含拉镜像最多按控制面 11 分钟预算;运行租约调和每 20 秒、采集调度每 30 秒、监听绑定调和每 10 秒;事件长等待至多 25 秒,重连退避 1–30 秒。超时记录请求/日志,不自动重复写。 + +### 2.2 账号、目标与数据 + +| 代号 | 前置数据与用途 | +| --- | --- | +| RUN | 每轮唯一标记,如 `e2e-20260913-01`;名称、草稿和测试消息带此标记 | +| A / B | 两个抖音测试大号;平台 UID 是真实数字 UID,另记录 sec_user_id,不混用内部账号 ID | +| S1 / S2 | 两个同平台小号;测试前仅绑定一个大号,业务正常、已授权;真实动作需有效浏览器登录 | +| U1 / U2 | 两个已同意的互动方/收件方测试账号;用于事件、冷却与收件箱核对 | +| C | 已同意的竞品测试账号,必须与采集执行账号不同;有可人工核对的近期/历史作品、分页及一级评论 | +| W / K | 从真实采集得到的内部作品 ID / 评论 ID;另存平台 work_key/comment_key、作者 UID、原页面链接和时间证据 | +| M1 / M2 / M3 | 有明确授权的带语音视频、无音轨视频、音轨无语音视频;保存原片时长与参考文稿,不把网页 HTML 当媒体 | +| G / V1 / V2 | 测试网关名、两个镜像版本;升级使用第二个已启用版本 | +| E0 / E1 / P1 / P2 | 直连环境、代理环境、两个已健康出口;每个环境固定不同账号 | +| T / D / Q / AT | 本轮生成的任务、草稿、确认、Attempt ID;不得拿旧轮次同名结果充数 | + +**真实登录前置的特别限制**:`POST /api/creator/accounts/:id/login-result` 明确拒绝 `logged_in`;新建资料默认 `unknown`,采集/监听/人工写前置又依赖 `logged_in`。先执行 AC-06 核验当前可达的真实身份闭环;若人工登录浏览器后控制面仍不能形成已验证状态,记录首次登录链路阻塞。可以在有来源证明的既有真实已验证账号上继续独立用例,但必须保留新账号失败,不能 SQL 改 login_status、导入假登录结果或调用内部 Go 函数补齐。 + +### 2.3 写授权单 + +执行 REAL 写操作之前,审批单逐项记录:RUN、发送账号、收件 UID、作品/评论标识、动作、完整文案或已批准候选/AI 要求、允许次数、可执行时段、平台清理方式和批准人。自动策略授权与人工逐次确认分开;六种动作各自授权,不因批准“测试”就无限发送。平台验证码/设备验证由账号所有者人工完成,不自动破解。 + +发生 `uncertain`、连接中断、超时或“已发出但响应未知”:立刻停止该操作,保存原 idempotency_key,先只读查询操作记录及平台目标,不换 key、不换小号补发。只有确认未执行且得到再次授权才可另行人工处理。明确失败也不允许后台自动重试;已完成点赞/关注不要通过“再点一次”变成取消。 + +## 3. 执行入口、请求约定与故障方法 + +### 3.1 入口约定 + +- UI 地址使用 HashRouter:`BASE/#/accounts`,关联审计例 `BASE/#/audit?task_id=T`。生产同源静态页面也受 HTTP Basic 保护,浏览器可能先弹原生认证框;开发 Vite 入口 `/login` 的表单另经 API 验证。不要把两层认证混为一体。 +- 下文 API 路径均含 `/api`,除 `/healthz`。`GET` 无 body;POST/PUT 示例一律 JSON;省略 body 的显式动作不要求人为增加 JSON。 +- `{A}` 等路径占位换成本轮账本的 URL 编码真实 ID;JSON 内 `"A"` 等也是占位,须替换。`API_*` 文件只存测试数据;敏感 body 文件放仓库外权限 0600,证据另存脱敏版本。 +- 公共调用样例(仅后续执行;不加 `--retry`): + +```bash +# BASE、API_AUTH_FILE 由测试负责人设置;API_AUTH_FILE 是仓库外 0600 curl 配置,含测试 Basic user。 +curl --silent --show-error --config "$API_AUTH_FILE" \ + --dump-header "$EVIDENCE/headers.txt" --output "$EVIDENCE/body.json" \ + --write-out '%{http_code}\n' "$BASE/api/creator/works?platform=douyin" +curl --silent --show-error --config "$API_AUTH_FILE" \ + -X POST -H 'Content-Type: application/json' --data-binary @"$BODY_FILE" \ + --dump-header "$EVIDENCE/headers.txt" --output "$EVIDENCE/body.json" \ + --write-out '%{http_code}\n' "$BASE/api/creator/operations" +``` + +每次调用使用独立证据目录;不要将一次响应覆盖上一条。响应、截图和日志都需移除认证头与代理凭据。gateway Bearer 另用 0600 curl 配置;Compose 基础部署不发布 8081,可由执行人员通过已批准的容器内 HTTP 客户端调用,或使用独立的开发部署映射端口,不能假定外网可访问。 + +### 3.2 可复用故障操作(每次只注入一种;恢复后再继续) + +| 编号 | 注入方法 | 观察与恢复 | +| --- | --- | --- | +| F1 浏览器请求失败 | DevTools → Network request blocking 添加准确 URL(如 `*/api/creator/rules*`),启用后刷新对应页;网络断开用 Network Offline | 记录报错、写请求数;取消规则/恢复 Online,只刷新读取;不能把页面断网当后端平台失败 | +| F2 慢响应/页面竞争 | DevTools Network 选 Slow 3G、勾 Preserve log,快速切账号/素材/会话并观察完成顺序 | 恢复 No throttling;若没有形成倒序响应,记该竞争子项未触发,不宣称已验证 | +| F3 gateway 故障 | 专用主机执行 `docker compose stop docker-gateway`;持久化错误场景可在生命周期操作已发出时停止,记时刻 | 读取控制面错误/审计/cleanup 状态;`docker compose start docker-gateway`,先查询环境与 Docker 实物,再按提示显式恢复。不得重发真实平台动作 | +| F4 控制面中断 | 在目标 operation 为 processing 时执行 `docker compose stop creator-hub`;崩溃专项才使用 `docker compose kill -s SIGKILL creator-hub` | `docker compose start creator-hub`,记录自动重启竞争;只读核对旧操作、租约及平台结果;不重复 execute。优雅与强杀分别记录 | +| F5 PostgreSQL 故障 | `docker compose stop postgres`,发一次指定读取/保存;记录是否已发出保存请求 | `docker compose start postgres`,待 `pg_isready` 后重读;不盲目补写。数据库不可用使多个后台报错是预期故障影响 | +| F6 实际代理断连 | 对专用测试代理容器 `docker stop "$TEST_PROXY_CONTAINER"`(先核验其归属);或使用供应商已批准的暂停端点动作 | 显式检测出口/访问测试目标,确认未回退直连;`docker start "$TEST_PROXY_CONTAINER"` 或恢复供应商端点后重新检测健康 | +| F7 实际浏览器丢失/断线 | 先核验 `docker inspect creatorhub-browser-$ALIAS` 的 RUN 对应别名/managed 标签,再 `docker stop`;仅丢失容器专项用 `docker rm -f`,不带 `-v` | 观察后台调和及动作审计;控制面重新启动环境,不直接复用旧 generation;确认 Profile 仍在 | +| F8 媒体本地故障 | 专用测试部署中,读取已选素材 `video_reference` 并核验属于 RUN;在 control-plane 停止后由卷维护人员将该文件重命名为 `.e2e-backup`,再启动并 process;或对下一条全新素材临时撤掉真实转写程序配置 | 记录原文件/配置;停止控制面,按原路径恢复备份/原 `CREATOR_TRANSCRIPTION_BIN` 并重建该服务;清除临时文件。禁止修改 step 状态冒充成功;不存在可安全操作的独立卷则阻塞 | +| F9 服务启动配置 | 不动运行中服务,用 `docker compose run --rm --no-deps -e NAME=VALUE creator-hub` 启动一次性命令;仅对预校验会失败的变量使用。gateway 以 `docker-gateway` 服务同法 | 校验失败应无新监听、无新文件/数据库/Docker 副作用;一次性容器退出即恢复。不将有效未知配置指向真实环境 | +| F10 UI 异常响应 | 浏览器 Local Overrides 对指定 GET 保存脱敏副本,仅改待测字段,例如任务 `hold_reason` 与 `allowed_action`;记录原响应与改动 | 仅作 UI 注入,不算服务端 E2E;禁止用该响应点击实际执行/恢复写按钮,观察禁用状态即可;关闭 Overrides 并重新读取 | + +F8 的可执行操作补充(只供后续获准的专用部署;`SOURCE_PATH`必须由本轮material.video_reference定位到媒体目录下的普通文件,人工核对不是目录/其他账号文件;操作时无其他素材处理): + +```bash +# 移走本轮source以验证“已记录下载成功但实际文件缺失”的恢复。 +docker compose stop creator-hub +docker compose run --rm --no-deps --entrypoint /bin/sh creator-hub \ + -c 'test -f "$1" && test ! -e "$1.e2e-backup" && mv "$1" "$1.e2e-backup"' sh "$SOURCE_PATH" +docker compose start creator-hub +# 此时按MAT-04只发一次process并留证。恢复原文件: +docker compose stop creator-hub +docker compose run --rm --no-deps --entrypoint /bin/sh creator-hub \ + -c 'test -f "$1.e2e-backup" && mv "$1.e2e-backup" "$1"' sh "$SOURCE_PATH" +docker compose start creator-hub +``` + +撤掉转写程序配置的独立分支:先在执行终端私密保存已验证的原值 `ORIGINAL_TRANSCRIPTION_BIN`;执行 `CREATOR_TRANSCRIPTION_BIN= docker compose up -d --no-deps --force-recreate creator-hub`,对一条全新带音轨素材执行MAT-04;留证后执行 `CREATOR_TRANSCRIPTION_BIN="$ORIGINAL_TRANSCRIPTION_BIN" docker compose up -d --no-deps --force-recreate creator-hub` 恢复,并核对健康与设置。只改页面转写provider/model不会让服务进程中的二进制消失,不能用来替代此故障分支。 + +OP-08的UI注入在浏览器Console执行 `Object.defineProperty(crypto, 'randomUUID', {value: undefined, configurable: true}); Object.defineProperty(crypto, 'getRandomValues', {value: undefined, configurable: true});`,整页刷新恢复;如果浏览器禁止覆写则记录未触发,不安装不受控扩展。 + +外部媒体下载 403/超时、平台限流/验证码、供应商失败必须由真实返回或有权限的测试端点触发,保存操作路径及恢复凭据;不主动滥用平台制造封禁。无法稳定触发的分支标阻塞,不伪造结果。只读 DB 查询可辅助定位,但不得 SQL UPDATE/INSERT 构造业务成功或强行推进生命周期。 + +## 4. 功能覆盖矩阵与执行顺序 + +共 **122 个独立编号用例,17 个覆盖模块(19 组编号)**;参数化子项另逐项记录。下表编号用于查找模块,不代表无条件逐项执行;实际按下方依赖顺序执行。破坏性/不可逆项在正常路径留证之后执行。API 补充用例与对应 REAL 结果分开统计。 + +| 顺序 / 模块 | 当前页面、领域入口 | 用例 | +| --- | --- | --- | +| 1 基础部署与配置 | `/healthz`,Compose、Cobra、配置、持久化、日志、静态资源 | SYS-01~SYS-06 | +| 2 登录/导航/公共组件 | `/#/login`、`/#/`、Layout、全部页面共用控件 | UI-01~UI-07 | +| 3 网关与镜像 | `/#/gateways`、`/#/browser-images` | GW-01~GW-05、IMG-01~IMG-04 | +| 4 出口 | `/#/network-exits`、`/#/network-exits/:id` | NET-01~NET-06 | +| 5 账号/环境 | `/#/accounts`、`/#/accounts/:id`、`/#/browsers`、`/#/browsers/new`、`/#/browsers/:id` | AC-01~AC-07、ENV-01~ENV-10 | +| 6 gateway 领域能力 | `/v1/browsers`、代际/代理/CDP/抖音受限路由 | API 附录 G、GATE-01~GATE-06 | +| 7 Phase A | `/#/drafts/:id`、`/#/tasks`、`/#/tasks/:id`、`/#/attempts/:id` | PH-01~PH-10 | +| 8 审计 | `/#/audit`、环境动作对/任务/Attempt | AUD-01~AUD-04 | +| 9 采集与 AI 设置 | `/#/creator/settings` | SET-01~SET-04 | +| 10 账号策略 | `/#/creator/accounts`,profile/关系/策略 | STR-01~STR-07 | +| 11 竞品/作品/评论采集 | `/#/creator/competitors`,works/metrics API,后台调度 | COL-01~COL-09 | +| 12 素材/仿写 | 竞品页素材区,material API | MAT-01~MAT-06 | +| 13 评论/线索/规则 | `/#/creator/workbench` 三个页签,rule-results API | LEAD-01~LEAD-07 | +| 14 人工写/私信/操作记录 | 工作台另两个页签,operations/messages API | OP-01~OP-08 | +| 15 真实事件/自动响应 | 浏览器通知→gateway events→creator events→策略执行 | EVT-01~EVT-08 | +| 16 API 契约补充 | 无 UI 的导入、详情、显示时间及错误边界 | API-01~API-06 | +| 17 清理与最终核对 | 账号、策略、平台内容、环境/卷及证据 | END-01~END-02 | + +依赖执行顺序(从干净环境开始): + +1. 完成 SYS-01~03、SYS-06 及 UI 登录/导航,创建 GW-01 网关、IMG-01 镜像、NET-01 出口、AC-01 账号与 ENV 创建/启动所需记录;公共组件的有数据/错误状态随对应模块补测。 +2. 取得环境引用后执行 GW-02 的引用冲突分支及其他资源关联检查;删除/停用/令牌失效等分支使用独立资源,或延后至这些资源的所有依赖用例完成。不得提前删掉后续真实测试使用的网关、镜像或出口。 +3. 完成 AC-06 登录检查及非破坏性环境/gateway 检查;创建 Phase A 草稿并完成任务流程;配置采集设置与账号资料/关系。策略可保存,但自动写入保持关闭。 +4. 完成竞品采集,再以真实作品/评论执行素材、规则/线索和人工操作。完成前述数据创建后,才执行 SYS-04 持久化检查:账号、环境、草稿、规则、素材均实际存在;保存各项证据后重启。不能为满足前置而改库造数据。 +5. 人工动作留证后执行 EVT 自动响应,再立即停用策略;审计用例在所需动作/任务记录产生后执行。API-only 导入可在合法账号/来源就绪后独立执行,但修改全局指标设置的 API-02 应在 REAL 指标观察完成后执行并恢复设置。 +6. 完成上述正常路径后执行依赖中断与其他破坏性分支(含 SYS-05、AC-07、NET-06、ENV-09),逐项恢复,再做 END 最终核对及清理。涉及重启/断网的其他用例也遵循“先留证、独立资源或延后、再恢复”。 + +执行依赖:AC-06 失败会阻塞 COL/EVT 及依赖 logged_in 的 OP 正向流程,但不阻止网关受限读取的独立核验和通用模块。REAL 采集产生 W/K 后再做素材和线索;若用 API 样例数据做界面补充必须标 API,不替代这条依赖。先测试人工动作,再开启自动策略;结束自动测试后立即停用策略。AC-07 撤销、NET-06 停用、ENV-09 故障与 END 清理放在相应数据不再被后续用例需要时执行。 + +## 5. 详细用例 + +下列每例均必须单独填写结果。前置里的其他编号意为其输出已真实取得,不允许只因计划写了该编号就视为满足。参数化子项逐行记录;一项失败即该用例未全部通过。 + +### 5.1 基础部署与配置 + +#### SYS-01 部署、健康和静态入口 [UI/API] + +- 前置:专用干净主机,2.1 配置齐备;允许后续部署。 +- 操作: + 1. 按部署说明启动本轮三个服务并记录 ps、镜像 digest + 2. GET 控制面和 gateway 的 /healthz;GET 带认证的 /api/gateways + 3. 打开 BASE/,再打开实际 JS/CSS 资源;刷新 /#/accounts 及 /#/browsers/new +- 预期:两个健康接口 204;数据库健康、服务持续运行;API 返回 JSON,页面/资源可加载。healthz 不等于数据库、平台或全部依赖已通过。 + +#### SYS-02 控制面配置与命令校验 [API/FAULT] + +- 前置:SYS-01 镜像;采用 F9,禁止改运行配置。 +- 操作: + 1. 分别单项设置 LISTEN_ADDR=:0、LOG_LEVEL=bogus、WEB_DIR仅三个空格、DATABASE_URL=`http://example.invalid/db` + 2. 分别设置用户名仅三个空格或含冒号、密码不足6字节、主密钥非Base64或解码长度不为32、凭据目录为相对路径、BAILIAN_BASE_URL 含 userinfo + 3. 一次性容器运行 control-plane 的 --help;另传不支持的位置参数 +- 预期:非法输入非零退出、日志清楚指出字段且不泄露值;配置校验先于数据库/凭据/Docker副作用。只有当前最小根命令,无编造子命令。help 不启动服务;未支持参数拒绝。Viper可能将空环境变量视为未设置并采用默认值,因此空白字符串校验与“未设置/空变量默认值”另行记录,不能混为必然启动失败。 + +#### SYS-03 gateway 配置与依赖错误 [API/FAULT] + +- 前置:SYS-01 镜像;F9 独立命令。 +- 操作: + 1. 单项试 LISTEN_ADDR=:0、GATEWAY_TOKEN=short、DOCKER_SOCKET=空、BROWSER_NETWORK=creatorhub_control 或非法名称 + 2. 恢复有效配置;在专用测试实例令 DOCKER_SOCKET 指向不存在路径,GET /v1/browsers + 3. 结束一次性实例并回读原服务列表 +- 预期:非法配置明确失败;缺 Docker socket 的真实领域请求报错、不返回假空成功;原环境不受影响。健康接口能返回不证明 Docker socket 可用。 + +#### SYS-04 持久化与重启 [UI/FAULT] + +- 前置:已有账号/资料密码、环境、草稿、规则、素材至少各一条;主密钥备份。 +- 操作: + 1. 记录各 ID、版本、非秘密字段和 Profile 内自建 RUN 书签 + 2. 正常重启 creator-hub、docker-gateway,保留 PostgreSQL/凭据/素材/Profile卷 + 3. 重新登录并逐页读取;浏览器启动后核对书签;用原真实会话执行一次已授权只读身份检查 +- 预期:记录、版本链及文件不丢;原主密钥可解密既有凭据。启动不得无限复制记录;事件恢复另按 EVT-03。无主密钥不做破坏性换密钥实验。 + +#### SYS-05 数据库失联与日志 [UI/FAULT] + +- 前置:没有正在进行的 REAL 写动作;已保存一条规则。 +- 操作: + 1. 用 F5 停 postgres,读取账号并尝试保存一条带 RUN 的规则 + 2. 查看页面、响应与 creator-hub 结构化日志 + 3. 恢复 postgres,只读查询规则列表判断前次是否入库,再手动决定是否补写 +- 预期:报错可观察,不把失败当空列表或成功;日志含 service/关联上下文但无凭据。未知提交结果先核验,不自动重复建档。 + +#### SYS-06 部署模式、关停和资源归属 [API/FAULT] + +- 前置:可切换独立测试时段;本轮资源已登记。 +- 操作: + 1. 正常停止 gateway,记录耗时/退出码/日志并检查无 SIGKILL,随后恢复 + 2. 核对只有 gateway 挂载 Docker socket,浏览器由其创建且命名与标签可追踪 + 3. 完整部署结束后按 compose.dev.yaml 单独启动依赖与开发进程;打开5173入口并观察 /api 到8082、网关8081映射 +- 预期:正常关停在45秒宽限内完成或明确失败;代理/事件订阅不悬挂。生产8080与开发5173/8082入口均可用,错误网关地址不能假成功;两种模式不共用活动测试实例。 + +### 5.2 登录、导航与公共组件 + +#### UI-01 登录正常与持久凭据 [UI] + +- 前置:正确测试 Basic 凭据;清除本浏览器 creatorhub.auth,不删除业务数据。 +- 操作: + 1. 打开 /#/login,输入空白用户名/空密码检查禁用与密码遮挡 + 2. 输入有效凭据登录,检查 GET /api/gateways 和跳转 + 3. 刷新页面;访问 /#/login;再直接访问 /#/accounts/{A} +- 预期:合法登录进账号列表且可刷新;已有本地凭据不重复显示登录表单。页面不承诺退出按钮或登录后恢复原深链。生产若先出现 HTTP 原生认证框应如实记录。 + +#### UI-02 错误凭据、过期和网络失败 [UI/FAULT] + +- 前置:UI-01;可以清除自己的本地键。 +- 操作: + 1. 错误密码提交一次,记录401文案与输入保留 + 2. F1 Offline 再提交一次,恢复后再登录 + 3. 仅把本地 creatorhub.auth 改为错误测试凭据,访问账号列表触发真实401 +- 预期:错误密码提示不正确;网络失败不等于401;业务401清键并转登录;再次登录回账号列表。不得将“键存在”当凭据已验证。 + +#### UI-03 导航、深链与窄屏 [UI] + +- 前置:正常登录,各模块至少有一条记录。 +- 操作: + 1. 逐一打开覆盖矩阵所有 Hash 路由和详情链接,检查当前导航高亮、返回、浏览器前进后退 + 2. 桌面从顶部和侧栏各折叠/展开一次;360px宽打开导航,点遮罩与项目关闭 + 3. 打开不存在资源ID和未知 hash 路径,记录页面状态 +- 预期:已定义路由可达、核心操作不被遮挡;详情归属高亮。不存在资源不能显示另一条记录;无通配404是边界观察,不编造已有404页面。移动环境卡片缺详情入口单列缺口。 + +#### UI-04 下拉、标签与基础表单 [UI] + +- 前置:账号创建及环境创建表单可打开,不提交真实写。 +- 操作: + 1. 下拉用上下/Home/End移动,Enter/空格选择,Escape及点外部关闭 + 2. 标签输入带空格和重复项,分别用 Enter、英文逗号、失焦提交;空输入 Backspace 和移除按钮删项 + 3. 切换复选框/开关,检查禁用项;尝试只填星号字段但值空白 +- 预期:标签trim去重、不出现空项;下拉选择/焦点反馈明确,禁用项不能提交;星号不代替真实校验,若无效值发出,继续核验后端拒绝,不记前端已阻止。 + +#### UI-05 弹窗取消、忙碌和重复点击 [UI/FAULT] + +- 前置:镜像或账号普通创建弹窗、出口停用确认框;F2。 +- 操作: + 1. 普通创建输入后分别用取消、关闭图标、Escape、遮罩退出再打开 + 2. 确认框先取消一次,检查无写请求 + 3. 限速后只确认一次并迅速二次点击,尝试关闭;恢复网络读取最终结果 +- 预期:取消不写、重开按页面规则重置;busy按钮不重复写。确认框忙碌不可关闭;普通创建弹窗若仍可Escape/遮罩关闭记录真实行为并核对迟到结果,不能统一宣称所有弹窗锁定。 + +#### UI-06 加载、失败、空态与错误恢复 [UI/FAULT] + +- 前置:干净数据时留存各页空态;F1可用。 +- 操作: + 1. 分别阻断 accounts、browsers、gateways、browser-images、network-exits、creator各列表、drafts、audit、attempt详情 GET + 2. 逐页检查加载结束后错误区、操作禁用及是否显示假空态 + 3. 取消阻断,只有存在重试按钮的页面点击重试,其余重新进入页面 +- 预期:失败与空数据可区分,不能隐藏依赖错误;没有重试按钮不写“重试成功”。特别记录账号草稿、环境创建依赖、规则列表异常呈现;不得自动重做先前写请求。 + +#### UI-07 长内容、可访问性与复制 [UI] + +- 前置:准备长中文/英文ID、URL、标题及换行文本;仅测试数据。 +- 操作: + 1. 在窄屏和键盘模式遍历页面操作,检查横滚、换行、焦点、标签、role=status/alert + 2. 打开弹窗,Tab/Shift+Tab及关闭检查焦点;核对帮助/错误与输入关联 + 3. 复制可显示的CDP和网关token到本地私密临时区,随后撤销剪贴板权限再试 +- 预期:核心内容可读、禁用可辨;复制内容与来源一致但不要求当前不存在的成功提示。焦点圈定/自动聚焦、aria-describedby缺口如实报,不把缺失能力当支持;截图无秘密。 + +### 5.3 网关和镜像 + +#### GW-01 注册、令牌与列表 [UI] + +- 前置:测试 gateway 已运行,知道其真实 token。 +- 操作: + 1. 注册名称G、实际Endpoint、显式token;读取列表并尝试相同名称再次注册 + 2. 另建未被环境引用的登记项,token留空,记录自动生成提示、显示/隐藏/复制 + 3. 关闭再进页面检查值持久化,不进行未授权健康探测 +- 预期:真实项能用于ENV创建;重复注册冲突;生成token只代表登记成功,未与gateway配置一致不能调通。列表不显示不存在的实时健康状态。 + +#### GW-02 编辑、改名和令牌替换 [UI] + +- 前置:G已有一个测试环境,备份原名称/Endpoint/token。 +- 操作: + 1. 编辑时确认token不预填;只改名并保持空token保存 + 2. 重读环境与网关,核对引用同步;再改回原名 + 3. 将token改为另一个格式合法但不匹配的测试值,显式启动测试环境一次;恢复原token并只读核对 +- 预期:改名关联一致,空token保持旧值;错误token造成可见gateway失败而非成功;恢复不自动重发未知生命周期操作。 + +#### GW-03 注册字段与失败保留 [UI/API] + +- 前置:未引用的测试名称。 +- 操作: + 1. 分别输入空白/非法首字/超64名称、非法scheme或含空格Endpoint、短于16或超128token + 2. 通过附录A请求绕过前端提交一项非法值 + 3. 用F1阻断保存,请求失败后检查表单内容,恢复后手工保存 +- 预期:前后端按各自校验拒绝非法输入,失败保留内容,不自动新增。格式合法但连接失败与字段非法分开记录。 + +#### GW-04 页面删除接线检查 [UI] + +- 前置:新建未引用网关登记项,保存其名字。 +- 操作: + 1. 点击删除先取消,确认列表仍在且无DELETE + 2. 再打开确认删除并确认一次,观察Network、Console与页面 + 3. 刷新列表读取实际记录 +- 预期:预期删除应发送领域DELETE并移除记录;当前 provider.deleteOne 仅支持browser-images,预计阻断/报错,证实则记失败。不得使用后端删除成功掩盖UI失败;后续清理另用GW-05。 + +#### GW-05 网关删除 API 与引用冲突 [API] + +- 前置:GW-04未引用登记项和被环境引用G;附录A。 +- 操作: + 1. DELETE /api/gateways/{未引用项},GET列表 + 2. 重复DELETE原名称,记录不存在结果 + 3. DELETE仍被环境引用的G,回读G和环境 +- 预期:未引用项成功删除;不存在返回明确结果、不影响其他项;引用中的网关409拒绝且环境引用不丢。此用例独立于UI删除缺陷。 + +#### IMG-01 创建镜像版本与字段边界 [UI/API] + +- 前置:两个可拉取的已登记镜像摘要。 +- 操作: + 1. 创建启用V1,检查版本/引用/备注;再创建V2 + 2. 重复V1;试非法版本首字符、65字符版本、空引用、非法引用字符、超长备注 + 3. F1阻断一次创建,恢复后只读查重 +- 预期:成功持久化,重复/非法值不覆盖已有版本;失败不清表单或误报成功。仅登记版本不证明镜像可运行。 + +#### IMG-02 编辑、禁用和跨页候选 [UI] + +- 前置:V1/V2已登记,V1被E1引用。 +- 操作: + 1. 编辑V2引用/备注并保存,版本字段不可修改 + 2. 关闭V2启用开关,到环境创建/升级重新打开选项 + 3. 再启用V2;编辑时清空引用点击保存 +- 预期:停用版本不出现在新建/升级候选,已有环境不静默换版;空引用应阻止请求或被后端拒绝;错误在编辑框可见。 + +#### IMG-03 删除引用与取消 [UI] + +- 前置:V1被引用,另有未引用临时版本。 +- 操作: + 1. 删除临时版本先取消,再确认;刷新列表 + 2. 尝试删除V1并检查确认框内错误 + 3. 恢复临时登记项以供下一用例或登记已删除 +- 预期:未引用删除成功;取消无DELETE;引用中拒绝且保留信息,不移除V1或破坏E1。 + +#### IMG-04 镜像不可拉取与动作忙碌 [UI/FAULT] + +- 前置:临时版本指向不存在的仓库引用,独立暂停账号。 +- 操作: + 1. 新建环境选该版本并提交,记录拉取过程、按钮禁用和超时 + 2. 查看环境列表、审计和Docker实际容器,不假定登记已回滚 + 3. 修改该临时版本为正确测试digest,核验残留后显式恢复环境一次 +- 预期:失败可见,有requested/finished证据;没有假running;已保存环境/binding按实物核验恢复,不能重复生成绑定。 + +### 5.4 网络出口 + +#### NET-01 创建与认证字段 [UI/API] + +- 前置:四类真实代理端点;认证凭据仅在私密表单输入。 +- 操作: + 1. 逐协议创建出口,填写host/port及已知预期IP/地区,初次读取列表/详情 + 2. 带认证端点填用户名密码;核对当前明文展示并遮盖证据 + 3. 先不检测,打开环境创建候选 +- 预期:初态unchecked,未检测不能成为健康候选;协议/地址可回读。当前UI/API明文不是遮挡断言,凭据不得进入对外证据。 + +#### NET-02 字段与无效出口 [UI/API] + +- 前置:附录B出口样例。 +- 操作: + 1. 依次试空host、非法host、端口0/65536/小数、只有密码无用户名、超长值 + 2. 分别经UI和一次API提交越界值 + 3. 对不存在ID GET/check/disable +- 预期:非法输入明确拒绝、不保存半条记录;不存在资源明确失败、不误操作其他出口。 + +#### NET-03 真实检测、健康与身份不符 [UI] + +- 前置:真实端点P1;另建预期IP故意不等于实际IP的测试出口。 +- 操作: + 1. 在列表点击P1检测并查看观测IP、检测时间、状态和reason_code + 2. 进入详情回读;再显式检测一次 + 3. 检测IP不匹配项及不存在服务的端点 +- 预期:健康以实际观测匹配为准,不以“检测完成”toast为准;不匹配/连接失败为unhealthy并有原因,最近检测更新;无自动列表检测。 + +#### NET-04 代理故障与禁止直连回退 [UI/FAULT] + +- 前置:P1绑定运行环境,测试目标可读取实际公网IP;无平台写。 +- 操作: + 1. 浏览器访问批准的IP回显目标并存证 + 2. F6停止代理,点击检测并在浏览器重试只读目标 + 3. 恢复代理并重新检测,再核对环境、账号和任务状态 +- 预期:失败期间不能从宿主直连出口成功访问;出口不健康和相关阻断可见;恢复健康不自动恢复旧hold任务。 + +#### NET-05 绑定关系、详情和请求失败 [UI/FAULT] + +- 前置:P1至少绑定一个账号,另有直连环境。 +- 操作: + 1. 查看列表绑定账号、详情、出口条件审计链接 + 2. F1阻断 /api/browsers,重新进入出口页 + 3. 解除阻断,点击实际提供的环境重试;进入不存在出口详情 +- 预期:读取失败显示未知而非未绑定;恢复后绑定一致;直连不误关联P1。详情无编辑/删除/重新启用按钮。 + +#### NET-06 停用与重复操作 [UI/API] + +- 前置:专用P2绑定账号且有排队Mock任务;不再供后续正常流程。 +- 操作: + 1. 点击停用先取消,再确认,连续点击检查busy + 2. 回读出口、账号、任务、浏览器实例 + 3. 附录B重复disable并调用check +- 预期:停用导致账号暂停/排队任务hold,运行清理结果明确;disabled不能通过check重新健康;UI检测/停用均禁用,服务端重复动作不产生新活动实例或恢复任务。 + +### 5.5 社媒账号 + +#### AC-01 账号创建、标签和平台范围 [UI/API] + +- 前置:RUN;真实A UID与可选Cookie,另有仅用于建档的公众号/快手测试标识。 +- 操作: + 1. 创建抖音账号名称两端空白、UID、去重TAGS,Cookie留空;读取列表与详情 + 2. 再建一条含合法Cookie的测试账号,检查响应与日志不回显Cookie + 3. 分别创建wechat-official、kuaishou建档项,仅核对通用字段,不打开其平台业务 +- 预期:服务端生成ID、authorized/paused、版本1;名称/UIDtrim,标签持久化;空Cookie允许,不证明真实登录。非抖音仅建档范围。 + +#### AC-02 账号非法、重复和创建未知 [UI/API/FAULT] + +- 前置:AC-01;附录C。 +- 操作: + 1. 试空白名称/ID、128上限及超长、非法platform、非法Cookie格式 + 2. 重复同平台同UID,核对409和输入保留 + 3. 在发送合法新建后用F1断开浏览器连接;恢复只读查平台UID是否已创建 +- 预期:非法/重复明确失败;技术ID/授权/状态不由客户端创建字段控制;连接失败保留输入但不得立即盲重发,503 account_creation_result_unknown 时按返回account_id核验。 + +#### AC-03 详情与资源就绪 [UI/FAULT] + +- 前置:未绑定账号、E0直连账号、E1代理账号。 +- 操作: + 1. 逐个进入详情核对账号版本、授权、运行状态、环境/出口/绑定版本和原因 + 2. F1阻断环境GET,检查状态未知与重试按钮 + 3. 恢复读取,分别观察未绑定、cleanup_pending(ENV-09生成)、出口不健康(NET-04)时恢复/草稿禁用 +- 预期:依赖读取失败不当ready;直连允许无出口;调度原因与后端一致。没有活动实例不等于账号已恢复,后续显式恢复/启动分开。 + +#### AC-04 暂停、恢复与版本关联 [UI] + +- 前置:账号已有运行环境与queued Mock任务。 +- 操作: + 1. 暂停先取消确认,再确认;查看版本、实例及任务 + 2. 资源就绪且无活动实例后点击恢复账号 + 3. 回读账号和旧任务,再到环境页显式启动 +- 预期:暂停递增版本并hold相关任务、停止结果可追踪;恢复无第二确认框,只恢复账号,不自动恢复旧hold或平台发送;资源不满足时拒绝。 + +#### AC-05 文本草稿创建及失败保留 [UI/MOCK] + +- 前置:账号资源ready;草稿只测Phase A。 +- 操作: + 1. 输入空白检查禁用;输入含首尾空格/换行的RUN文本创建 + 2. 核对草稿版本和原文本,创建第二版 + 3. F1阻断创建再提交一次,检查输入保留;单独阻断草稿GET并查看错误呈现 +- 预期:创建成功刷新并清输入,保存原文本;新版本可追踪。草稿列表失败不得默认为无草稿;若界面隐藏错误记失败。绝不当真实发布。 + +#### AC-06 真实登录身份与首次可达性 [REAL/API] + +- 前置:新建抖音A、实际UID;已启动专用浏览器,所有者可人工登录。 +- 操作: + 1. 在真实浏览器手工登录A,使用附录G identity(expected_account_key)核对UID,保存脱敏响应 + 2. 回读 /api/creator/accounts/{A}/profile,观察控制面是否出现logged_in及时间 + 3. 调用login-result提交logged_in确认不能人工冒充;若仍unknown,检查当前公开操作是否存在可达真实核验入口,不改库;同时用已真实验证的既有账号作对照 +- 预期:gateway能核实真实UID;公开写logged_in返回409。若真实登录无法反映到控制面,首次登录E2E记阻塞/缺陷并阻断依赖用例;不能用内部方法/伪造数据强行通过。密码配置不自动登录。 + +#### AC-07 撤销授权 API [API] + +- 前置:一次性账号已绑定环境、有queued任务;本轮不再使用,附录C。 +- 操作: + 1. POST /api/phase-a/accounts/{A}/revoke,无body + 2. 读取账号、环境、任务与审计;尝试resume、创建草稿、确认入队 + 3. 重复revoke,记录版本和事件变化 +- 预期:撤销不再允许调度,queued转hold,运行清理结果明确;不存在重新授权页面/接口不能假设可恢复。重复动作不产生平台写或恢复授权,具体版本变化留证。 + +### 5.6 运行环境 + +#### ENV-01 最小直连环境与显式启动 [UI] + +- 前置:已授权暂停账号、G、启用V1。 +- 操作: + 1. 打开创建环境填写名称、alias、seed1000、账号/G/V1,出口选直连,提交 + 2. 读取列表/详情及Docker实例状态 + 3. 去账号详情恢复账号,回环境列表显式启动,复制CDP并按已批准连接方式打开浏览器 +- 预期:创建先停止态,固定绑定正确;恢复账号和启动分离;运行有实际容器/租约,直连无出口也可用。CDP展示/复制不代表公网端口已发布。 + +#### ENV-02 代理环境和高级指纹 [UI/REAL] + +- 前置:另一暂停账号、healthy P1、G/V1。 +- 操作: + 1. 创建E1选择P1;高级字段依次填windows/linux/macos中的一个、Chrome/Edge/Opera/Vivaldi中的一个、版本、CPU、语言、时区与伪装禁用项 + 2. 恢复账号并启动,Docker inspect核对argv、Profile卷和无凭据代理地址 + 3. 浏览器查看navigator语言/CPU等及真实公网IP;停启后重新核对 +- 预期:选择参数保留且argv独立传递;实际IP匹配P1,凭据不出现在命令/标签。OS/brand其余合法选项分轮独立记录,不要求同一环境改指纹入口。 + +#### ENV-03 创建边界、默认项与依赖错误 [UI/API] + +- 前置:空依赖与齐备依赖分时段;附录D。 +- 操作: + 1. 缺网关/镜像/可绑账号/健康出口时打开表单查看准备提示;F1阻断依赖GET后再开 + 2. 分别试alias非法/超32、seed0/2147483648/小数、CPU负数/129、非法语言/时区、指纹内proxy_server + 3. 修正后创建;并用API重复同alias不同账号或已绑定账号的新alias +- 预期:默认只选合法依赖;错误读取不伪装业务缺项;字段越界后端拒绝。相同资源配置重复按幂等核验,冲突配置409;一账号不出现两个活动绑定。 + +#### ENV-04 列表详情与不主动探测 [UI/API] + +- 前置:E0/E1存在;能读取gateway日志。 +- 操作: + 1. 刷新列表及详情多次,观察浏览器Network和gateway请求时间 + 2. 从桌面环境名进详情、跳账号/出口并返回;360px宽重复观察 + 3. 读取长alias、已停止环境、不存在alias详情 +- 预期:列表/详情只取持久状态,不因刷新触发显式检测或生命周期;独立20秒后台调和日志不得误判为页面轮询。详情无生命周期按钮,移动详情入口缺失按实际记录。 + +#### ENV-05 启停、重复和取消回收 [UI/API] + +- 前置:运行E1,Profile建RUN书签。 +- 操作: + 1. 停止一次并核对容器/列表,再用API重复stop;启动一次后用API重复start + 2. 点击回收取消,确认容器仍在;再确认回收 + 3. 只读核对容器消失、环境/binding/Profile仍在;从控制面启动重建 +- 预期:running时UI启动禁用、停止只对running开放;重复动作不多建runtime;回收不是永久删除,书签/seed保持。真实结果不明先查实物,不自动重发。 + +#### ENV-06 升级、版本与Profile [UI] + +- 前置:E1使用P1且V2启用,已保存书签。 +- 操作: + 1. 打开升级不选目标及选当前版本检查禁用 + 2. 选择V2确认,忙碌时尝试关闭 + 3. 完成后核对旧容器消失、新digest、指纹/书签/绑定版本;再选择不可用目标验证错误 +- 预期:升级重建容器但保留Profile/指纹;错误可见且不声称自动回滚。当前失败可能关闭弹窗,应在列表仍可见错误与实际版本。 + +#### ENV-07 直连升级与出口重绑边界 [API/UI] + +- 前置:E0直连、E1已暂停并无活动runtime、healthy P2;附录D。 +- 操作: + 1. 对E0在UI尝试升级一次,记录真实返回和残留,不据直连create推断升级支持 + 2. POST E1/rebind {network_exit_id:P2},读取新绑定版本/旧任务快照 + 3. 分别试运行中rebind、unhealthy出口、空字符串切回直连 +- 预期:合法重绑只在暂停无执行/活动runtime条件满足后成功,旧快照不得沿用;空出口重绑当前400拒绝。直连升级若因出口校验失败记当前限制,不假称支持。 + +#### ENV-08 并发互斥和失败后的恢复 [API/FAULT] + +- 前置:仅E1测试账号;两个API客户端,不发平台业务动作。 +- 操作: + 1. 两端同时POST start,保存每个响应与operation_id + 2. 在一次启动/升级进行时另端pause账号或disable目标镜像 + 3. 读取账号、镜像、environment及Docker实物,按最终有效配置恢复 +- 预期:不会双runtime或使用已失效配置绕过锁;完成审计与实际generation匹配;冲突/失败明确,未批准状态不能偷偷启动。取消禁用镜像或恢复账号只在核验后显式执行。 + +#### ENV-09 gateway失联、清理待定与租约 [UI/FAULT] + +- 前置:E1有runtime/queued任务;F3/F7可用。 +- 操作: + 1. F3停gateway后停止或回收环境一次,记录cleanup_pending/unknown/错误 + 2. 恢复gateway,只读观察至少两个20秒调和周期及审计 + 3. 另轮F7移除容器,不删除Profile,观察missing/runtime释放,再显式启动 +- 预期:失败不能假已停止/无绑定;后台恢复有requested/finished证据,租约不长期显示可调度假running;新旧generation不混用,Profile不丢。 + +#### ENV-10 非法动作与资源失效 [API] + +- 前置:附录D;测试alias及不存在alias。 +- 操作: + 1. POST现有alias/unknown-action;给upgrade增加未知字段或非法version + 2. 给create未知字段、已停用镜像或未授权账号;GET不存在alias + 3. 回读原环境和动作审计 +- 预期:非法操作400/冲突404等明确,不修改旧环境;升级/重绑拒绝输入的审计不泄露输入秘密;没有通用PUT更新或任意Docker操作入口。 + +### 5.7 gateway 领域 API + +#### GATE-01 路由、认证与请求格式 [API] + +- 前置:附录G;测试gateway可达。 +- 操作: + 1. 分别无token/错误token GET /v1/browsers,再用正确Bearer读取 + 2. POST create提交未知字段、非对象JSON、缺body及超过1MiB body + 3. 访问非领域路径与不存在alias,最后回读正常列表 +- 预期:除healthz外领域请求校验token;非法body400,未知路径404,不提供通用Docker或任意CDP代理;列表未夹带其他非managed容器。 + +#### GATE-02 创建/启停/删除与代际 [API] + +- 前置:单独的gateway实验alias,不对应活动控制面环境;附录G创建样例及已批准V1镜像。 +- 操作: + 1. POST /v1/browsers 创建停止态实验容器,GET列表提取实际runtime/network/binding + 2. 按附录G正确generation进行stop/remove;重复remove核对幂等或明确冲突 + 3. 另轮G-create改stopped=false创建运行态实验容器,GET取得真实network与runtime后用正确generation依次stop/start,核对实际状态;再用旧runtime_id或错误binding执行start/stop/remove并读取Docker实物 +- 预期:合法操作可观察,创建返回201;过期代际409且不操作新容器;不匹配managed标签的对象不可删除。实验资源按END单独回收,不交给控制面冒充业务环境。 + +#### GATE-03 代理恢复与隧道生命周期 [API/REAL/FAULT] + +- 前置:代理E1;附录G proxy payload必须从本轮真实generation组成;只读测试目标。 +- 操作: + 1. 打开经代理的HTTP请求与HTTPS CONNECT长连接并记录实际出口 + 2. F3重启gateway,通过正常租约恢复或独立实验alias的POST proxy恢复;观察恢复前后连接 + 3. 替换代际/回收实验alias,验证旧连接关闭;错误network_id恢复再观察新旧连接 +- 预期:恢复只允许当前generation;旧隧道关闭不继续借用已失效代理;不从代理失败回退直连;错误代际拒绝且不损害新runtime。 + +#### GATE-04 Cookie注入、身份与受限读取 [API/REAL] + +- 前置:测试账号所有者提供有效Cookie或已手动登录;附录G。 +- 操作: + 1. POST cookies仅注入允许域的测试Cookie,不保存原值证据;POST identity使用真实expected_account_key + 2. POST get读取self、作品分页、一级评论分页;与平台页面对照 + 3. 分别改为非法域Cookie、错误身份、非抖音URL、额外query或非法cursor +- 预期:合法身份和读取可核验;错误目标/不允许的URL拒绝,不执行任意JS/CDP;Cookie不回显。验证码/设备挑战保留为真实失败,人工处理后重新只读核对。 + +#### GATE-05 六类动作预览与拒绝边界 [API/REAL] + +- 前置:已登录测试环境,只有预览授权;附录G action;不提交confirm=true。 +- 操作: + 1. 逐个action填批准目标,confirm=false请求预览;关注预览只读检查关注状态 + 2. 分别填错误expected_uid、自己为目标、缺comment/work/UID、文本空或超1000 + 3. 查看平台目标确认没有发生新评论/私信/点赞/关注 +- 预期:预览无写,身份核对失败不发送;目标字段和文本校验可见。对仅confirm阶段才校验的目标保留区分,不能以preview响应证明实际发送成功。 + +#### GATE-06 订阅/取件/确认与停止 API [API/REAL] + +- 前置:单独事件实验alias已真实登录;暂不由控制面监听同alias;附录G events。 +- 操作: + 1. POST启动订阅;GET带generation body及limit=100&wait=25等待真实基线/通知 + 2. 保存delivery_id,未ack再GET检查重投;GET带ack确认后再次读取 + 3. 分别GET limit=0、limit=101、wait=-1、wait=31核验非法参数400;再用合法参数读取确认订阅未被破坏 + 4. DELETE停止,再重复停止;用旧generation请求不得影响新订阅 +- 预期:真实通知字段/边界可观察;确认后不重复交付已确认项,断连有状态而不是假连续;GET队列不是轮询平台源,端到端处理仍由EVT验证。 + +### 5.8 Phase A 草稿、确认、任务与 Attempt + +#### PH-01 草稿版本与确认 [UI/MOCK] + +- 前置:AC-05有两版草稿,资源ready。 +- 操作: + 1. 打开第一版草稿核对“非最新”及最新版本链接 + 2. 到最新版本,不勾已核对检查确认禁用;勾选后打开确认框,取消一次 + 3. 再次核对账号/草稿版本与环境/出口并保存,GET确认列表/详情 +- 预期:旧版本不能当最新确认;快照包含正确关联,确认请求busy防重复;成功显示确认记录,取消无写。 + +#### PH-02 入队、幂等与直连 [UI/API/MOCK] + +- 前置:PH-01确认Q;分别代理与直连各一条。 +- 操作: + 1. 点击加入队列,记录T及状态 + 2. 用同Q再次入队,包括API重复POST /api/phase-a/tasks + 3. 查看关联任务、任务列表与确认详情 +- 预期:首次201/后续复用同任务,不多创建T;直连可入队;已有有效确认时入队不额外要求重新勾已核对。关联任务ID无UI链接时经任务列表/API进入。 + +#### PH-03 版本失效与重新确认 [UI/API/MOCK] + +- 前置:已确认未执行的Q/T。 +- 操作: + 1. 新建更新草稿或暂停再恢复账号使版本变化 + 2. 旧页面继续确认/入队并读取409/任务readiness_reason + 3. 从最新草稿重新核对确认、重新入队 +- 预期:旧版本拒绝且不会执行旧内容;前端刷新快照;只通过新确认推进,不通过resume绕过版本变化。 + +#### PH-04 四类 Mock 结果 [API/UI/MOCK] + +- 前置:仅本轮测试队列,按子项各建一个独立Q/T;附录C mock。 +- 操作: + 1. 逐项POST mock/execute,outcome分别为succeeded、failed、uncertain、policy_hold,每次记录返回task_id/attempt_id + 2. 打开对应任务和Attempt详情,检查原确认/账号/环境关联 + 3. 重复读取各状态;空队列再execute一次,另发非法outcome +- 预期:四项分别为succeeded、failed、needs_confirmation、policy_hold;Attempt evidence明确mock_outcome,不声称真实发送。无任务不假领任务;非法outcome400。该接口不接收指定task_id,必须先核对隔离队列。 + +#### PH-05 任务筛选、空态与详情链接 [UI] + +- 前置:PH-04产生多状态任务。 +- 操作: + 1. 在任务页按账号和各状态筛选、再清空,记录每次请求 + 2. 分别进入详情访问账号/草稿/环境/出口/审计链接 + 3. GET不存在T/AT,并在UI进入对应深链 +- 预期:筛选立即生效,清空恢复列表,无匹配与无任务区分;链接身份一致,不存在记录不能显示上一次详情。 + +#### PH-06 不确定结果人工核验与恢复 [UI/API/MOCK] + +- 前置:PH-04 uncertain任务,原绑定/版本仍有效;仅Mock。 +- 操作: + 1. 在详情选择not_executed记录核验,确认仍未排队 + 2. 若allowed_action=resume且ready,单独点击恢复;再调用Mock执行 + 3. 同一动作busy时重复点击,并在终态试API resume +- 预期:核验与恢复分离;恢复前校验原资源/版本;无额外不明尝试,终态拒绝不安全恢复。 + +#### PH-07 核验成功/失败并结束 [UI/API/MOCK] + +- 前置:两条新的uncertain Mock任务,分别作succeeded/failed核验。 +- 操作: + 1. 在任务详情记录核验succeeded或failed,不点击恢复 + 2. 单独点击结束,再读详情/审计 + 3. 结束后重复finish,或以非法result调用verify +- 预期:结论与任务终态对应;核验本身不直接结束、不自动重发;非法/不允许状态明确拒绝。核验仅Mock证据,不能给真实操作编造结论。 + +#### PH-08 资源hold和未知原因 [UI/API/FAULT/MOCK] + +- 前置:queued任务;NET-04或AC-04可造成资源hold。 +- 操作: + 1. 暂停账号或使代理不健康,读任务hold/readiness/allowed_action + 2. 在未恢复资源时API resume检查409/503及reason_code,再按流程恢复原资源 + 3. F10仅替换任务GET为未知hold+allowed_action=resume,观察按钮与警告,勿点击写;关闭替换 +- 预期:旧hold不自动解除;已知原因给安全动作;未知原因不应露出可误用恢复入口,当前矛盾返回的UI缺口记失败。响应替换仅UI覆盖,不证明后端能产生该状态。 + +#### PH-09 取消 API [API/MOCK] + +- 前置:一条queued及一条policy_hold任务;附录C。 +- 操作: + 1. POST T/cancel并回读,重复cancel + 2. 对已succeeded任务调用cancel观察拒绝 + 3. 如能在真实在途Mock请求中捕捉executing则取消并核验needs_confirmation,否则执行中子项阻塞 +- 预期:未执行任务取消后不被Mock领取;执行中不能假称未执行,需核验;无页面取消按钮。为造executing不得改数据库,竞态未命中如实记录。 + +#### PH-10 领取并发、崩溃及租约 [API/FAULT/MOCK] + +- 前置:只有一条本轮queued任务;两个Mock客户端。 +- 操作: + 1. 同时调用两个worker_id的mock/execute,记录was_claimed/attempt_id + 2. 新建任务再次执行,能捕捉executing时用F4强杀;恢复后等待超过1分钟再触发一次Mock领取 + 3. 查询旧任务/Attempt/审计,记录是否进入需要核验而非重复执行 +- 预期:同任务至多一个领取;过期执行租约隔离为needs_confirmation,不自动当未执行重试。Mock处理很快,若无法命中执行窗口则该子项阻塞,不能SQL塞租约通过。 + +### 5.9 审计 + +#### AUD-01 动作链和安全证据 [UI/API] + +- 前置:ENV生命周期及PH流程已有成功/失败/unknown记录。 +- 操作: + 1. 按环境或任务进入审计,逐条对照requested/finished的同operation_id + 2. 访问账号/任务/Attempt/环境/出口链接,核对版本及实例 + 3. 检查公开details、Attempt evidence及结构化提醒日志 +- 预期:每次领域动作结果可追踪,关联实际runtime;失败/不明不混成功;公开证据不含Cookie/代理密码/token。仅task需关注状态应有结构化提醒,不编造短信/邮件通知。 + +#### AUD-02 过滤、深链与日期 [UI/API] + +- 前置:已知两个账号/任务及跨日期事件。 +- 操作: + 1. 逐个输入账号、任务、Attempt、alias、出口、事件类型和起止日期,记录API query及结果 + 2. 用hash内前五个条件深链打开;更改过滤后确认页码回1 + 3. 清除过滤;提交反向日期和API非法RFC3339 +- 预期:命中集合和时区转换正确,反向/非法时间不能悄悄返回无关记录;深链事件/日期不初始化是当前边界,不误写已支持。 + +#### AUD-03 分页和当前页CSV [UI] + +- 前置:通过实际生命周期/Mock动作产生超过25条审计,不改库。 +- 操作: + 1. 逐页前进后退,检查total、每页25与首尾禁用 + 2. 按条件过滤并导出当前页CSV,用文本编辑器查看行数/引号/11列 + 3. 换到另一页再导出;空集合检查导出禁用 +- 预期:CSV仅当前页,文件名creatorhub-audit.csv,11个白名单列与当前页一致,双引号转义,无details或凭据;不宣称全量导出。 + +#### AUD-04 只读、异常和恢复 [UI/API/FAULT] + +- 前置:已留存审计证据。 +- 操作: + 1. 确认页面无编辑删除按钮;F1阻断audit GET再进入 + 2. 取消阻断重新进入,确认先前审计仍在 + 3. API请求page=0、page_size非法值及不存在关联过滤 +- 预期:请求失败区别于空记录,已有记录不丢;非法分页明确拒绝或按已记录契约规范化,不返回误导页码;不写不存在的重试按钮。 + +### 5.10 采集与 AI 设置 + +#### SET-01 读取、修改与默认值 [UI/API] + +- 前置:保存原settings白名单快照;附录E。 +- 操作: + 1. 打开采集设置核对30/1800/3600/2/86400/2592000默认值(新库) + 2. 修改回溯、作品/一级评论间隔及指标初始/倍数/上限/最长时长,保存再刷新 + 3. 检查PUT仅12白名单字段,响应updated_at不回写 +- 预期:设置持久化,成功回显;作品和一级评论共用当前新作品间隔,没有独立评论秒数字段;不编造密钥或连接测试控件。 + +#### SET-02 数值、审批与未知字段 [UI/API] + +- 前置:原配置快照;无自动写运行。 +- 操作: + 1. 依次试0/负数/小数秒、倍数1、最大间隔小于初始,查看前端及API结果 + 2. 勾AI或转写已审批但provider/model空保存 + 3. 在附录E payload加unknown字段及重复JSON对象提交 +- 预期:非法值400且原设置不变;审批不完整拒绝;严格JSON不接受未知字段/尾随对象,失败保留输入。 + +#### SET-03 AI真实接入与不可用 [UI/REAL/FAULT] + +- 前置:批准的Bailian与样本评论;LEAD规则已准备,自动写关闭。 +- 操作: + 1. 填bailian/model/审批后执行一次真实评论主题与线索判断,记录模型、响应和业务结果 + 2. 取消AI审批后对另一评论分析;再改provider为不支持值并分析 + 3. 恢复原批准配置,重新人工发起只读AI分析 +- 预期:真实供应商成功才判可用;禁用/不支持/无密钥明确失败且无假线索;保存设置成功不等于供应商成功,不用Mock AI替代。 + +#### SET-04 保存异常与指标重排 [UI/FAULT] + +- 前置:COL中已有新作品和超龄作品;原配置可恢复。 +- 操作: + 1. F1阻断settings PUT保存,查看busy/错误和输入保留,解除后只读校对是否生效 + 2. 显式修改指标计划参数,GET作品列表和metrics比较next_metric_at/stop_reason + 3. 恢复原12字段设置,再读取作品计划 +- 预期:失败不误报;更新按新参数重新计算未来计划,超龄/发布时间未知不伪造未来采集;恢复可核验,无页面附加字段污染请求。 + +### 5.11 账号资料、关系与策略 + +#### STR-01 资料保存与敏感字段 [UI/API] + +- 前置:A/S1账号;附录E profile。 +- 操作: + 1. 切换A,填写登录名、更新密码、实名状态/测试姓名/虚构证件号、业务状态、备注、冷却、统一AI要求并保存 + 2. 刷新资料,检查密码输入清空、仅password_configured;空密码再保存 + 3. 更新另一个测试密码,检查返回/日志/数据库公开读取均无明文 +- 预期:资料正确持久化;空密码保持原凭据,密码变更不自动登录。人工实名/业务状态不代表平台验证或登录结论。 + +#### STR-02 切换账号与保存竞争 [UI/FAULT] + +- 前置:A/B资料不同;F2。 +- 操作: + 1. 编辑A未保存切B,取消确认保留A;再次切换确认丢弃 + 2. 限速时加载A后快速切B,再在A保存发出后切B + 3. 恢复网络并回读A/B,比较选中账号、表单、密码标志和实际持久字段 +- 预期:迟到A响应不得覆盖B;保存归属准确,不丢未授权丢弃的编辑;失败保留本账号输入。 + +#### STR-03 大号开关与单归属关系 [UI/API] + +- 前置:A/B同平台,S1/S2;另用已建档kuaishou测试跨平台拒绝。 +- 操作: + 1. 开启A大号,附录E POST relation将S1绑定A,再重复同请求 + 2. 尝试S1同时绑定B、自己绑定自己、跨平台绑定 + 3. 关闭A大号,回读关系/策略,再恢复大号 +- 预期:合法关系唯一且可回读;冲突不悄悄转移小号;关闭大号/关系影响策略与执行前置,重新开启不自动恢复已禁用策略。 + +#### STR-04 六动作策略创建与候选 [UI/API] + +- 前置:A大号、S1关系;含文本动作有批准候选。 +- 操作: + 1. 分别为reply_comment/dm/like_comment/like_work/follow/repost填顺序、目标小号、触发事件并创建后停用,逐项保存响应 + 2. 测试未选小号、零触发事件、position0、空候选且无AI要求 + 3. 输入英文逗号候选并回读规范化target_type/候选列表 +- 预期:策略可创建/读取且按顺序显示;非法配置明确失败;无候选文本时必须具备统一AI要求和配置,不把创建策略当动作执行成功。repost实际写边界见OP-07。 + +#### STR-05 编辑排序、启停、删除、解除 [UI/API] + +- 前置:至少两条停用策略,S1与S2可用;无事件自动写授权则保持停用。 +- 操作: + 1. 编辑顺序/执行账号/动作,保存检查排序;取消编辑观察回填保留 + 2. 启用再停用、删除一条,反复GET验证;删除不存在ID + 3. 解除S1关系,读策略状态;重建关系后确认不会自动恢复旧策略 +- 预期:显式动作直接生效无虚构确认框;解除关系使相关策略不可继续执行;启停/删除busy防重复,失败不误删行。 + +#### STR-06 两段保存失败与切换竞争 [UI/FAULT] + +- 前置:A/B及未绑定S2,F1/F2。 +- 操作: + 1. 仅阻断 /api/creator/accounts/{A}/strategies 的POST,UI保存先绑定关系再建策略 + 2. 解除阻断,GET relations及strategies核对部分成功,不马上重建 + 3. 限速再次编辑策略并切换B,回读两账号关系列表和策略 +- 预期:关系成功/策略失败不报全部成功;页面最终与后端一致,迟到响应不串号。关系不自动刷新或切换竞争缺口证实则记失败。 + +#### STR-07 资料枚举、业务限制及登录结果 API [API/UI] + +- 前置:一次性S2;附录E;实际原资料已保存。 +- 操作: + 1. PUT profile试非法实名/业务枚举、cooldown0及超边界,回读原值 + 2. POST login-result分别needs_login/failed/manual_required并填写测试原因;再次试logged_in + 3. 在各登录/业务状态尝试创建manual operation(不execute),恢复原人工业务状态;登录依真实核验恢复 +- 预期:非法字段拒绝;人工登录结果不伪造成功;正常/禁言/封禁/注销的动作限制按当前CanWrite执行,禁言文本写阻止,封禁/注销全阻止;不可通过错误登录推断封禁。 + +### 5.12 竞品、作品、评论与指标采集 + +#### COL-01 竞品登记与本地链接预览 [UI/API] + +- 前置:获准C主页、真实稳定标识;附录F。 +- 操作: + 1. 抖音主页填入后点解析链接预览,对照人工确认标识;填写昵称加入监测 + 2. 试错误host、无路径、非法标识和非法URL;重复登记同平台标识 + 3. 读取列表/详情,确认同步状态与启用标志 +- 预期:预览仅本地候选,不冒充身份认证;重复/非法明确失败;成功清表单但保留平台,未同步不显示伪作品。 + +#### COL-02 暂停恢复与同步前置 [UI/API] + +- 前置:C已登记;分别准备无合格账号和有真实已验证采集账号。 +- 操作: + 1. 无合格账号时点击同步,观察提示和无请求 + 2. 暂停C并尝试API sync;恢复后选定可用账号发一次sync + 3. 记录202响应、报告和最终sync_status/last_sync_at/next_sync_at +- 预期:无权限/未登录/无运行环境不可采;暂停不继续调度;202仅接收结果,必须核对实际采集记录,不直接判完成。 + +#### COL-03 真实竞品目标与分页 [REAL] + +- 前置:AC-06真实已验证执行账号与C不同;C有超过20作品/评论且在回溯窗内。 +- 操作: + 1. 先从平台人工记录C的作者UID、若干第一页/第二页作品key;同时记录执行账号不同的作品key + 2. 点击同步并保存gateway受限读取目标、cursor与控制面报告 + 3. GET source_type=competitor&source_id=C的作品和每作品评论,对照平台作者/发布时间/页数 +- 预期:必须采到C而非执行账号作品,正确分页无漏重;只采一级评论并保留真实来源。目标canonical转换疑点只是待验证风险,观察到错误归属才记缺陷,不能接受错作品为成功。 + +#### COL-04 自有账号后台采集 [REAL] + +- 前置:A真实已验证、有已授权近期作品;记录settings间隔。 +- 操作: + 1. 不点竞品同步,等待后台到期调度一个完整窗口加30秒 + 2. GET works?source_type=owned&source_id=A与comments,对照A真实平台内容 + 3. 下一个窗口后重复查询,同一作品若也关联竞品来源检查sources +- 预期:自有采集无需虚构UI按钮;按当前调度实际产生作品/一级评论;同一平台作品不重复建实体,多来源保留,不互相覆盖。 + +#### COL-05 回溯、固定周期与断点恢复 [REAL/FAULT] + +- 前置:C具有回溯窗边界内外历史作品;采集量足以分页,F3可用。 +- 操作: + 1. 保存原settings,在UI设置获批较短间隔/回溯窗;记录首轮开始时间 + 2. 采集正在分页时F3停gateway,留存成功页/失败cursor与状态;恢复后按调度或显式sync一次 + 3. 核对续采、去重、窗口边界,延迟跨过一周期后检查下次时间,再恢复settings +- 预期:失败不会清掉已采作品或错认全量完成;按真实断点恢复,无并发双claim;迟到跳过过期计划点而非补发一串平台请求。未命中分页中断要记未触发。 + +#### COL-06 身份失败、挑战与被阻止 [REAL/FAULT] + +- 前置:独立采集账号可由所有者登出;没有平台写在途。 +- 操作: + 1. 登出平台或换成不同测试UID,点击sync一次 + 2. 若自然出现验证码/设备验证/限流,记录原响应分类,不绕过 + 3. 所有者恢复正确登录,通过真实身份核对再显式sync,观察blocked/failed及恢复 +- 预期:错身份不采集冒名数据;挑战/认证与普通网络失败分开可追踪;同步前置失败也留下blocked原因,不永久卡syncing。 + +#### COL-07 作品过滤、详情和缺字段 [UI/API] + +- 前置:真实采集有不同计数的作品;缺字段样本来自真实响应或另标API补充。 +- 操作: + 1. UI修改最低点赞/评论/转发立即筛选,分别试0、正数、非法负数 + 2. 附录F按source、发布时间上下界组合GET,并逐条GET作品详情/metrics + 3. 核对未知发布时间、null指标、真实0、无下次采集原因;F2快速改变筛选 +- 预期:满足全部条件才列出,null不是0,待核验不编造发布时间;迟到请求不能覆盖当前筛选。页面没有作品详情/快照曲线按钮,详情用API。 + +#### COL-08 真实指标更新和停止条件 [REAL] + +- 前置:C与A各一条可监测作品,已记录初始metrics;获批低频计划。 +- 操作: + 1. 等待next_metric_at后一个调度周期,读取metrics及作品最新指标 + 2. 与平台同时间人工读数对照;记录下一间隔递增、最大间隔封顶 + 3. 用settings缩短最长时长使已存在测试旧作品自然超龄,回读停止原因,再恢复原设置 +- 预期:快照时间递增且真实计数一致,计划严格在未来;超龄/未知发布时间停止有原因。竞品指标必须更新目标作品,不因只查执行账号作品而漏采;不足等待时间标阻塞。 + +#### COL-09 并发同步、重复来源与读取失败 [UI/API/FAULT] + +- 前置:有真实采集C,两个API客户端。 +- 操作: + 1. 同时POST同C/sync相同account_id,读取响应与sync_status + 2. 完成后再次sync并对比work_key/comment_key数量与sources + 3. F1分别阻断competitors、works和账号依赖GET,观察错误/空态再解除 +- 预期:同C同期只一个有效同步,重复不造重复实体;失败不丢来源关系或隐藏为无作品;lease过期/重启后恢复不得由旧请求覆盖新结果,若无法形成迟到竞争则子项阻塞。 + +### 5.13 素材处理与仿写 + +#### MAT-01 选择素材与未保存切换 [UI/API] + +- 前置:COL-03真实取得两条作品;附录F。 +- 操作: + 1. 点选择素材,GET material记录selected及各step;重复选择同作品 + 2. 修改未保存文稿/要求后点另一素材,先取消再确认丢弃 + 3. F2限速快速选择两作品后回读当前素材 +- 预期:同作品选择复用任务,不自动开始处理;取消保留编辑;迟到响应不得把另一作品结果放当前区。没有真实采集时只能标API界面补充。 + +#### MAT-02 真实下载、提音轨、转写 [REAL] + +- 前置:选中真实带语音视频M1;媒体授权、磁盘及真实转写程序齐全。 +- 操作: + 1. 点开始处理,观察download/audio/transcription各状态及按钮busy + 2. GET material,对video_reference/audio_reference定位本轮文件;执行只读ffprobe查看格式/时长/采样率/声道,人工播放核对 + 3. 打开真实transcript文件与参考文稿核对,检查API及页面是否正确呈现正文 +- 预期:必须获得有效媒体而非HTML;音轨为有效单声道16kHz音频且可解码;转写正文与内容一致且能被用户读到。OriginalURL、.tmp输出格式、transcript字段可能仅路径/未展示均为源码待验证风险,未运行不定性;不能把succeeded字符串作为通过证据。 + +#### MAT-03 无音轨、无语音与重复处理 [REAL] + +- 前置:独立M2无音轨/M3有音轨无语音;已选中。 +- 操作: + 1. 分别开始处理并GET状态、实际文件,人工核对媒体确实无音轨或无语音 + 2. 完成后再次显式process,比较引用/文件时间/状态 + 3. 检查无音轨/无语音情况下确认要求是否可用 +- 预期:无音轨为no_audio并no_speech;空转写为no_speech,不伪造文稿;已完成步骤可复用,不重复下载/转写成功步骤;不把正常无音轨等同失败。 + +#### MAT-04 失败步骤、磁盘/供应商及恢复 [REAL/FAULT] + +- 前置:全新已选素材;F8及真实失效媒体链接样本,配置已备份。 +- 操作: + 1. 使用真实失效下载样本,或F8撤转写程序后处理新素材;另轮对本轮已下载source重命名后process + 2. 记录HTTP与job.failed_step/failure_reason、残留.tmp以及文件内容 + 3. 恢复原程序/文件/权限,仅对明确失败的素材显式process一次,核对已完成步骤复用 +- 预期:下载/提音轨/转写错误定位到实际步骤,不用“供应商未配置”掩盖所有原因;失败不生成假成功或残缺成品。恢复只处理明确失败、非平台写操作,临时文件清理可验证。 + +#### MAT-05 仿写要求确认与保存 [UI/API] + +- 前置:MAT-02或MAT-03真实完成处理;附录F。 +- 操作: + 1. 未确认前试API保存,检查冲突;在UI输入要求并确认 + 2. 确认后观察要求锁定,人工填写标题/口播保存,刷新或切回核对 + 3. 检查实际PUT body及响应;重复保存相同内容并回读 +- 预期:确认只记录要求/时间,不期待自动生成文稿;未确认保存409;人工文稿正确持久化且归属当前作品。缺Content-Type只观察,按真实结果判定;不得新增或声称存在AI生成按钮。 + +#### MAT-06 处理/仿写边界与失败保留 [UI/API/FAULT] + +- 前置:未选作品及已选未处理作品各一条;已确认素材一条。 +- 操作: + 1. 未选时API process、未处理时confirm,试要求超4000字符 + 2. 已确认素材保存空标题/口播、标题超1000或口播超100000;F1阻断保存一次 + 3. 解除阻断回读,检查旧稿和当前编辑不被丢弃/串作品 +- 预期:未满足前置冲突、超长/空稿400;星号不能代替后端校验。失败保留输入且不覆盖已存稿;未授权并发process不宣称队列化,若双请求可触发要记录真实结果。 + +### 5.14 规则、评论分析与线索 + +#### LEAD-01 规则创建与关键词 [UI/API] + +- 前置:有真实自有/竞品评论;附录F。 +- 操作: + 1. 规则页填名称、来源all、主题、包含/排除关键词、AI要求创建 + 2. 输入带内部空格/大小写关键词,查看英文逗号trim结果 + 3. 试连续逗号/结尾逗号/纯空白、必填空值及未知source_type +- 预期:有效规则持久化,关键词不随意改内部内容;空项/非法值拒绝,失败保留表单。规则不是自动发送授权。 + +#### LEAD-02 编辑启停与异常呈现 [UI/FAULT] + +- 前置:至少两条规则。 +- 操作: + 1. 编辑并保存,取消编辑检查当前表单;停用规则再编辑保存并检查enabled值 + 2. F1阻断规则GET,切规则页;解除阻断重进 + 3. 启用/停用busy时重复点击,查看无删除按钮 +- 预期:编辑停用规则是否重新启用要显式记录,不能悄悄改变用户意图;列表失败应可识别。当前规则分支缺统一错误/空态时记缺陷,不编造重试/删除功能。 + +#### LEAD-03 一级评论展示和规则选择 [UI] + +- 前置:COL真实一级评论,含已知UID和缺UID样本(缺样本则该子项阻塞)。 +- 操作: + 1. 评论页逐项核对作者/UID/正文/来源/时间 + 2. 选择一条规则触发analyze,记录返回status/reason;重复选择首条规则观察是否实际发请求 + 3. 切换到线索、私信再回来,F1阻断评论读取后恢复 +- 预期:缺UID/时间明确标不可用,不能凭昵称发送;规则选择触发分析而无“分析”按钮;分析中禁止冲突选择,页签数据不串结构。 + +#### LEAD-04 完整线索判定与来源范围 [REAL/API] + +- 前置:真实Bailian已配置;参考样本分别命中主题/包含/排除/AI意向。 +- 操作: + 1. 为all/owned/competitor各建规则,对同一来源已知的评论逐项analyze + 2. 用不匹配主题、包含关键词缺失、含排除关键词、AI否定样本分别分析 + 3. GET rule-results?comment_id=K&rule_id=R 与leads,检查规则快照和理由 +- 预期:来源、主题、包含/排除、AI各条件形成可解释结果;同评论多个规则聚合rule_ids而非造重复线索;主题/AI结论必须源自真实供应商响应。 + +#### LEAD-05 重复分析、禁用规则与AI失败 [UI/API/FAULT] + +- 前置:已分析K/R;原AI配置备份。 +- 操作: + 1. 重复分析同K/R,比较rule-results数量/快照;编辑R后再分析比较新快照 + 2. 停用R后调用analyze;取消AI审批后分析另一评论 + 3. 恢复设置,仅显式重分析,观察线索是否曾被伪造 +- 预期:重复不重复造结果实体;禁用/AI失败理由可见,无假命中。失败返回即使为503也应显示业务原因,恢复不自动执行回复。 + +#### LEAD-06 线索列表与人工联系入口 [UI] + +- 前置:至少一条真实线索,含UID。 +- 操作: + 1. 打开线索页核对原评论、作者、UID、命中规则 + 2. 点击人工联系,观察是否显示回复编辑区/切评论页 + 3. F1阻断leads GET后恢复,检查空态与失败 +- 预期:可追溯线索;人工联系应提供可继续的人工编辑与确认,当前仅requestReply但线索页不渲染编辑区,证实则记失败;不能通过切评论页绕过后宣称本按钮通过。 + +#### LEAD-07 评论/规则详情与只读结果 API [API] + +- 前置:附录F;真实K/W/R。 +- 操作: + 1. GET单评论、单规则及enabled_only=true列表;按platform/work_id筛评论 + 2. GET rule-results分别只按comment/只按rule/组合筛选,并查不存在ID + 3. 确认分析前后无新增operation、无平台回复 +- 预期:过滤返回对应记录且详情完整;不存在资源404;分析只产生分析结果,不隐式平台写。未提供评论删除/规则删除的路径不编造。 + +### 5.15 人工写操作、私信与操作记录 + +#### OP-01 评论人工回复与逐次确认 [UI/REAL] + +- 前置:AC-06、COL真实K,发送账号、目标U1及唯一文案已批准。 +- 操作: + 1. 在评论点人工回复,选择同平台发送账号并输入完整RUN文案;分别试缺UID/账号/空白文案 + 2. 有效输入进入确认框,核对账号、目标UID、完整文本,取消一次确认无operation + 3. 再次确认只发送一次,保存create和execute响应;在真实平台目标评论核对作者/正文/新评论ID +- 预期:无效输入不发送;取消无写;成功须operation=succeeded且平台证据匹配,不能只看toast。failed/blocked/processing/uncertain分别可见且不自动重试。 + +#### OP-02 私信接收、会话及消息展示 [UI/REAL] + +- 前置:真实已登录接收账号,EVT真实通知可用;U1经授权发送一条RUN文本。 +- 操作: + 1. U1在平台发送后,读creator/events及conversations获取会话,再在工作台私信选接收账号/会话 + 2. 核对对方UID、消息正文、方向/时间,非文本样本核对类型占位 + 3. 停留已选会话超过20秒查看10秒GET消息,再离开页签查看timer停止 +- 预期:真实入站事件与消息关联且不串号;页面10秒读消息是当前轮询,不是平台事件监听证明;无会话不能输入发送,不存在附件/自动聊天入口。 + +#### OP-03 人工私信发送与平台证据 [UI/REAL] + +- 前置:OP-02真实会话;S1或A作为明确发送者和完整文案已批准。 +- 操作: + 1. 输入文本点确认发送,检查确认框账号/UID/完整文案,取消一次 + 2. 重新确认一次,记录operation/key/execute/evidence + 3. 在收件方平台查看消息、正文及发送人,刷新本系统消息列表和操作记录 +- 预期:成功必须发送人与收件人准确,平台消息可查且系统出站消息不重复;成功清草稿/key,失败/不明保留,不自动聊天。 + +#### OP-04 草稿、切换、迟到响应与幂等 [UI/API/FAULT] + +- 前置:两账号各有真实会话、两评论;无新增写授权时只测草稿/取消。 +- 操作: + 1. 分别输入不同草稿,切账号/会话先取消再确认;刷新后切回检查各自草稿与key + 2. F2快速切换账号/会话,观察消息迟到响应归属 + 3. 对已完成的OP-01/03用原body原key重复create,仅在明确终态用原ID execute核验不重发;改body保留原key观察冲突 +- 预期:草稿按评论或账号+会话隔离,切换确认可取消;同key同body复用操作,不同body409。uncertain不执行此重复execute步骤;其禁止重试另按OP-05。 + +#### OP-05 创建/执行失败、未知结果和恢复 [UI/REAL/FAULT] + +- 前置:一次故障测试写有明确授权与收件方在线;保留原key。 +- 操作: + 1. F1只阻断operations/{id}/execute,使create成功但执行未发出;恢复后先GET操作,确认未执行并再次人工确认方可继续 + 2. 另独立授权写在实际execute发出后F3停gateway,保存未知/错误状态 + 3. 恢复gateway,只读查operation和平台结果,等待至少两个分钟观察,不点击重试、不换key +- 预期:创建成功不等于发送;明确未发出的请求恢复须再次确认;执行结果未知保持uncertain/待核验,不能自动重发或伪造成功;失败原因和原key可追踪。 + +#### OP-06 人工点赞、关注 API [API/REAL] + +- 前置:附录F operation;真实W/K/U1和S1已登录;每种动作独立一次授权。 +- 操作: + 1. 逐项建立source=manual的like_comment、like_work、follow操作,填写内部K/W及真实target_uid;记录201但尚不execute + 2. 人工核对body与目标后POST execute一次 + 3. 从真实平台核对点赞/关注状态和evidence,再用同操作ID读取结果 +- 预期:三类动作实际生效且证据准确;无UI按钮时使用API不编造页面入口;已点赞/已关注应只确认既有状态不反向取消;每项独立记录。 + +#### OP-07 转发明确不支持、目标与身份拒绝 [API/REAL] + +- 前置:真实测试W、已批准拒绝验证;附录F。 +- 操作: + 1. 创建带文案repost并确认execute一次,检查gateway代码和目标作品 + 2. 分别以错误评论所属作品、错误作者UID、自己目标、跨平台账号构造operation或gateway预览,不进行未校验写 + 3. 登出/换真实浏览器身份后对已创建未执行操作execute,随后由所有者恢复登录 +- 预期:当前带文案转发明确REPOST_TEXT_UNSUPPORTED且不得产生转发,不宣称完整转发能力;身份/目标不匹配拒绝,不能拿内部ID当平台ID写给他人。 + +#### OP-08 操作记录及边界状态 [UI/API/FAULT] + +- 前置:上述操作产生succeeded/failed/blocked/uncertain等状态;附录F。 +- 操作: + 1. 打开操作记录按account_id读取,逐条核对完整状态、时间和原因;GET单operation查看evidence + 2. F1阻断列表,恢复后只点读取重试;F10补充processing/未知枚举仅观察展示 + 3. 在DevTools Console临时将crypto.randomUUID与crypto.getRandomValues都覆写为undefined(仅禁用randomUUID仍有安全回退);尝试打开人工确认但不授权发送,随后整页刷新恢复原生crypto +- 预期:状态不折叠为成功;页面没有执行/自动重试/删除按钮。无法生成安全key时应阻止发送并提示;仅浏览器注入分支单独标记,不替代真实运行证据。 + +### 5.16 真实事件监听与自动响应 + +#### EVT-01 首次监听、历史基线与四类通知 [REAL] + +- 前置:A真实logged_in、运行代际有效;自动策略先停用;U1可产生评论/点赞/关注/转发通知。 +- 操作: + 1. 留存A平台已有历史通知,再启动/重建本轮监听,观察gateway baseline与控制面日志 + 2. 边界确认后U1依次触发四类各一条获准真实通知,记录event_key/type/UID/work/comment及平台时间 + 3. GET /api/creator/events?account_id=A 对照通知,确认旧历史只做baseline不触发operation +- 预期:来源为真实页面通知监听,不是人工POST事件或轮询平台通知接口;事件身份和时间可追踪,缺UID/时间/边界不允许自动写。转发入站通知与系统不支持带文案转发出站是两件事。 + +#### EVT-02 实时性与页面可见性 [REAL] + +- 前置:EVT-01真实新通知;UI打开对应评论/私信/操作页;所有时钟校准。 +- 操作: + 1. 录制平台产生时刻、gateway_received_at、received_at、processing_started_at与实际页面首次可见时刻 + 2. 生成获准评论或私信事件,观察页面是否无需人工刷新即可看到;重复三次但每次独立授权 + 3. 计算收到至处理/可见耗时,单列平台推送延迟;不调用display接口伪造UI时间 +- 预期:以实测记录处理≤5秒/可见≤30秒作为实时链路质量检查,超时如实失败;无事件页面、无自动展示路径时记能力缺口,不把API写displayed_at当看见。该阈值是测试观察目标,不声明当前源码保证。 + +#### EVT-03 断连重连、边界与代际替换 [REAL/FAULT] + +- 前置:真实A监听,策略先停用;F3/F7。 +- 操作: + 1. F3停止gateway,U1在断线期间产生一条获准通知,随后恢复 + 2. 观察open/close/error/reconnected/baseline与退避;边界后再产生一条新通知 + 3. 停止重建浏览器使generation变化,GET旧事件并核对新订阅唯一 +- 预期:断线历史/边界不明不补发;只有明确新边界后新事件可自动动作;旧订阅停止,无两个账号/代际串用。缺平台连续性证据不能标“无丢失恢复成功”。 + +#### EVT-04 事件去重、确认与崩溃恢复 [REAL/FAULT] + +- 前置:获准单事件写或策略停用;F4;已有真实event_key。 +- 操作: + 1. 在真实事件已入库后F4中断控制面,恢复监听并观察gateway未确认通知是否重投 + 2. 重复读取events/operations及平台记录,对比event_key和operation id + 3. 若捕捉processing中断则等待超过2分钟及一次10秒调和,核对stale recovery +- 预期:同平台/接收账号/event_key只有一个持久事件,不因重投自动重写;processing过期变uncertain保留冷却,不假成功。未触发ack丢失/processing窗口的子项记录阻塞,不注入假成功。 + +#### EVT-05 顺序策略和四事件匹配 [REAL] + +- 前置:A大号、S1/S2关系有效、获准低风险候选文案/动作;四类真实触发均可用。 +- 操作: + 1. 按position建立两条匹配策略,启用;U1产生对应真实新事件 + 2. 核对选择首个可用策略,只一个execution_account/action及平台结果 + 3. 下一独立UID/冷却结束后停用首条或让其缺目标,再触发;分别更换四类event_types验证过滤 +- 预期:按当前策略顺序选首个满足条件动作,不对同事件执行整串动作;无匹配明确unmatched、大号关闭ignored,不能因首个执行失败临时换小号补发。 + +#### EVT-06 共享冷却、候选与人工例外 [REAL] + +- 前置:A冷却先保存默认86400证据,再获准设为测试60秒;U1/U2;候选两条均批准。 +- 操作: + 1. U1触发首条动作,冷却内再触发不同事件/不同策略;检查无第二平台写 + 2. U2同类事件可以独立触发;自然等待U1冷却结束再触发一条 + 3. 冷却内另经OP人工逐次确认对U1回复一次;结束恢复原冷却并停策略 +- 预期:同平台大号+UID跨小号/事件/动作共享冷却,文案从候选中选一条;不同UID独立,人工不受自动冷却阻止。随机样本只证明来自候选,不以少量样本声称均匀。 + +#### EVT-07 AI生成失败、写失败与冷却保留 [REAL/FAULT] + +- 前置:无候选、有统一AI要求且真实Bailian已配置;测试失败触发已批准。 +- 操作: + 1. 启用策略,U1产生新事件并核对真实AI文本及唯一平台写证据 + 2. 下一独立UID试验前取消AI审批,触发新事件,记录AI失败和冷却;恢复审批后同UID再次触发 + 3. 另一独立UID的已授权动作中用F3制造失败/不明,恢复后同UID再触发 +- 预期:AI按统一要求生成实际文本;AI失败/动作失败/不明都保留冷却,不换小号补发;无候选无统一要求时不发送。供应商/网关恢复不能自动补发旧事件。 + +#### EVT-08 执行前状态变化与串行 [REAL/FAULT] + +- 前置:至少两个获准新事件,S1同执行账号;可捕捉前一个动作在途,F3可选。 +- 操作: + 1. 前一操作在途时产生第二事件,记录收到与排队情况 + 2. 第二条执行前停用策略/解除关系/关闭大号/将小号禁言(每项独立轮次),观察操作和平台实际结果 + 3. 恢复各原配置,确认旧事件不因此自动重发 +- 预期:同账号写串行但接收不应被慢写阻塞;执行前重新校验最新状态,已不允许的写blocked;未捕捉到等待窗口不能声称已验证状态竞争。 + +### 5.17 API-only 契约补充 + +#### API-01 作品写入与来源关联 [API] + +- 前置:仅隔离测试数据;附录F导入样例,sources为已存在A/C;不用于替代REAL采集。 +- 操作: + 1. POST works一条API前缀作品,记录201及内部ID + 2. 同platform/work_key再次POST同body,再改为另一合法source,GET详情与来源过滤 + 3. 试未知来源/非法计数/缺发布时间并读取结果 +- 预期:同作品去重,合法多来源保留,未知字段/来源拒绝;发布时间缺失保留待核验而非造时间。这些记录清楚标API数据,不算平台采集通过。 + +#### API-02 指标写入、缺失值与计划 [API] + +- 前置:隔离环境、API-01 合法来源账号;另用附录 F-work-metric 创建独立作品 WM(不得复用缺发布时间的 W),发布时间 P 已标 verified,且在当前 metric_age_seconds 监测窗口内。保存完整 settings;本例放在 REAL 指标观察结束后,不能与其并行。使用当轮 UTC 时间且服务器时钟同步;不依赖后台调度。 +- 操作: + 1. 令 P 为本轮当前时间减 120 秒,初始 metric_age_seconds 大于 120 秒并留足执行余量;若不满足,保存原设置后完整 PUT settings 调整。创建 WM 后,在 P < T1 <= 服务端当前时间的条件下,POST `/api/creator/works/{WM}/metrics`,body 为附录指标样例并替换 collected_at=T1(含 likes=0、comments_count=null)。GET WM 详情与 metrics,记录快照及 next_metric_at + 2. 对 WM 同 T1 重复提交相同值;另提交 P < T0 < T1 的旧时间,及负数、超 int64、非法时间、未来时间各独立请求,读取快照和最新值。有效后续快照若另行补测,必须等待实际时间到达 next_metric_at,不能伪造未来时间 + 3. 完整 PUT settings,仅将 metric_age_seconds 缩短为 60 秒,使 WM 超龄;GET WM,核对 next_metric_at 为空及 metric_stop_reason=monitoring_age_reached,快照保留。恢复本轮保存的完整 settings,再读取确认设置已恢复 + 4. 单独对 API-01 的缺发布时间作品 W 提交一次当前时间指标并读详情/metrics,核对计数可保存但不产生监测快照,next_metric_at 为空,原因为 published_at_pending_verification;本子项不能替代 WM 的正常/超龄验收 +- 预期:WM 首次生成真实存储快照,重复 T1 不增加点;迟到旧快照被拒绝且不覆盖最新值,null 不同于 0,非法数值/时间被拒绝;缩短窗口后停止原因明确。W 的缺时间分支独立记录;两类人工导入均不证明真实平台刷新。 + +#### API-03 评论导入与关系校验 [API] + +- 前置:API-01作品,附录F comment。 +- 操作: + 1. POST top_level评论后GET单条及按work过滤;同comment_key重复提交 + 2. 试unknown类型、缺author_uid,确认可保留但不具备人工写目标 + 3. 提交非法comment_type、另平台work或不存在work +- 预期:合法导入持久且去重,未知作者不丢正文、不允许冒名发送;非法关联拒绝;不通过导入伪造真实一级评论采集成功。 + +#### API-04 事件记录、处理与显示时间 [API] + +- 前置:附录F event;仅隔离、无启用策略账号或baseline=true;不执行真实写。 +- 操作: + 1. POST events同body两次,记录201/200及duplicate;GET按account_id查询 + 2. 用同事件POST events/process,因baseline或大号关闭只观察ignored/基线结果 + 3. POST events/{id}/display后回读displayed_at;另建唯一API事件key,baseline=false且comment事件缺UID,核对blocked且无操作;再试非法事件类型/未知账号 +- 预期:记录去重且display时间可更新;API处理不证明监听,也不证明页面已显示。不得对活动自动策略发送人工构造event/process触发未授权写。 + +#### API-05 消息导入、去重与会话隔离 [API] + +- 前置:附录F message,API专用账号,不用于OP-02真实入站验收。 +- 操作: + 1. POST inbound文本消息,GET conversations?account_id及对应messages + 2. 原platform_message_key重复POST;同peer_uid另一账号再导入一条 + 3. 试非法direction/sent_state/空peer_uid/不匹配平台,读页面测试数据标识 +- 预期:同消息去重,会话按账号+peer隔离;非法数据拒绝;该入口仅存储不发送平台消息,不能伪造出站succeeded证明真实发送。 + +#### API-06 公开边界、JSON与错误分类 [API] + +- 前置:只用附录请求样例和隔离数据;不发REAL execute。 +- 操作: + 1. 在各类POST/PUT复制合法body分别加入unknown字段、尾随第二对象、错误类型;试空body与超过1MiB + 2. GET各详情不存在ID,试POST路径拼错/不支持方法,记录实际HTTP和body + 3. 正确body再次只读核验原记录,检查服务日志无Cookie/token/账号密码 +- 预期:字段错误400、资源不存在404、冲突409、依赖不可用503等按对应handler语义可辨;不把HTML SPA兜底当API成功。gateway Docker依赖可能502,不能强求所有模块统一503。 + +### 5.18 清理 + +#### END-01 停止业务并核验真实副作用 [UI/REAL] + +- 前置:本轮所有写操作和平台证据账本完整;保留未决uncertain记录。 +- 操作: + 1. 停用本轮自动策略、关闭大号模式、暂停竞品监测;读取确认停用 + 2. 逐账号按授权在平台人工删除RUN测试评论/可撤回消息/测试转发、取消测试新增点赞/关注;不可撤回项登记,不自动取消测试前已有关系 + 3. 暂停测试账号,取消尚未执行Mock任务;对uncertain只留证不execute +- 预期:不再产生新自动动作;平台清理每项有记录,无法清理明确遗留;不为清理而假核验未知结果为成功/未执行。 + +#### END-02 资源、配置与证据归档 [UI/API/FAULT] + +- 前置:END-01;所有备份和RUN资源清单。 +- 操作: + 1. 按3.2恢复全部网络/配置/文件/Overrides;回收测试浏览器容器,核对Profile保留 + 2. 删除未引用镜像/网关(网关用API);停用测试出口;恢复原settings/策略/业务状态并只读核对 + 3. 需彻底销毁时,先停止专用Compose部署,由负责人逐一核对RUN容器/网络/卷后删除本轮数据卷和Profile;导出脱敏报告 +- 预期:只清本轮资源,禁止全局docker prune或不核对就down -v;回收后仍保留环境binding会阻止删除被引用网关/镜像,应登记保留或在获批整套测试库销毁时一起清理,不伪造永久删除API。原始敏感证据受限,最终报告脱敏。 + +## 6. API 覆盖及请求样例 + +以下目录是第5节用例的执行附录,不额外计算用例数。每个写接口必须使用指定用例的前置与授权,不能把目录当成可直接批量运行的脚本。`无`表示无请求 body。所有对象样例均为合法 JSON 结构,里面的 A/S1/C/W/K/R 等必须替换为账本真实内部 ID;平台数字 UID、作品 key 和 comment key另取真实值。返回字段不要全量复制进严格输入接口。除明确 API 补充数据外,优先使用真实采集/监听输出;标记 `RUN-api-only` 的样例绝不能进入 REAL 通过统计。 + +### 附录 A:网关登记与镜像 + +| 方法 / 路径 | body或查询样例 | 入口 / 用例 | +| --- | --- | --- | +| GET `/api/gateways` | 无 | UI、GW-01 | +| POST `/api/gateways` | `{"name":"e2e-gw","endpoint":"http://docker-gateway:8081","token":""}`;显式token从私密文件替换 | UI、GW-01/03 | +| PUT `/api/gateways/{G}` | `{"name":"e2e-gw-renamed","endpoint":"http://docker-gateway:8081","token":""}` | UI、GW-02 | +| DELETE `/api/gateways/{G}` | 无;只删除未引用项 | **API可用,UI接线失败待复现**,GW-04/05 | +| GET `/api/browser-images` | 无 | UI、IMG-01 | +| POST `/api/browser-images` | `{"version":"1-e2e","image_ref":"registry.example.invalid/test/browser:approved","note":"RUN","enabled":true}`;image_ref必须换已登记真实digest | UI、IMG-01 | +| PUT `/api/browser-images/{V2}` | `{"image_ref":"registry.example.invalid/test/browser:approved","note":"RUN编辑","enabled":false}`;不传version | UI、IMG-02 | +| DELETE `/api/browser-images/{V2}` | 无 | UI、IMG-03 | + +### 附录 B:网络出口 + +| 方法 / 路径 | body或查询样例 | 入口 / 用例 | +| --- | --- | --- | +| GET `/api/network-exits` | 无 | UI、NET-01 | +| GET `/api/network-exits/{P1}` | 无 | UI、NET-05 | +| POST `/api/network-exits` | 使用下方对象;协议分别参数化四种,host/IP/地区替换为真实测试值 | UI、NET-01/02 | +| POST `/api/network-exits/{P1}/check` | 无 | UI、NET-03/04 | +| POST `/api/network-exits/{P2}/disable` | 无;停用不可通过check恢复 | UI、NET-06 | + +```json +{"protocol":"socks5","host":"proxy.example.invalid","port":1080,"username":"","password":"","expected_public_ip":"192.0.2.10","expected_region":"测试地区"} +``` + +示例地址为保留测试地址,不是可用代理;不可直接拿它做健康正向用例。真实密码只进入本地受限请求文件。没有出口编辑/删除/启用接口;不使用旧 `credential_reference` 样例。 + +### 附录 C:账号与 Phase A + +| 方法 / 路径 | body或查询样例 | 入口 / 用例 | +| --- | --- | --- | +| POST `/api/phase-a/accounts` | `{"name":"RUN账号","platform":"douyin","platform_account_key":"123456789","tags":["RUN"],"cookies":""}` | UI、AC-01/02 | +| GET `/api/phase-a/accounts` | 无 | UI、AC-01 | +| GET `/api/phase-a/accounts/{A}` | 无 | UI、AC-03 | +| POST `/api/phase-a/accounts/{A}/pause` | 无 | UI、AC-04 | +| POST `/api/phase-a/accounts/{A}/resume` | 无 | UI、AC-04 | +| POST `/api/phase-a/accounts/{A}/revoke` | 无 | **API-only**、AC-07 | +| POST `/api/phase-a/drafts` | `{"account_id":"A","content":"RUN Mock 文本\n第二行"}` | UI、AC-05 | +| GET `/api/phase-a/drafts` | `?account_id=A` | UI、AC-05 | +| GET `/api/phase-a/drafts/{D}` | 无 | UI、PH-01 | +| POST `/api/phase-a/confirmations` | `{"draft_id":"D","account_version":1,"draft_version":1}`;版本用实时读取值 | UI、PH-01/03 | +| GET `/api/phase-a/confirmations` | `?draft_id=D` | **API补充确认列表**、PH-01 | +| GET `/api/phase-a/confirmations/{Q}` | 无 | **API-only详情**、PH-01 | +| POST `/api/phase-a/tasks` | `{"confirmation_id":"Q"}` | UI、PH-02 | +| GET `/api/phase-a/tasks` | `?account_id=A&draft_id=D&state=queued` | UI,draft_id仅API筛选、PH-05 | +| GET `/api/phase-a/tasks/{T}` | 无 | UI、PH-05 | +| GET `/api/phase-a/attempts/{AT}` | 无 | UI、PH-04/05 | +| POST `/api/phase-a/tasks/{T}/verify` | `{"result":"not_executed"}`;另两值succeeded/failed | UI、PH-06/07 | +| POST `/api/phase-a/tasks/{T}/resume` | 无 | UI、PH-06/08 | +| POST `/api/phase-a/tasks/{T}/finish` | 无 | UI、PH-07 | +| POST `/api/phase-a/tasks/{T}/cancel` | 无 | **API-only**、PH-09 | +| POST `/api/phase-a/mock/execute` | `{"worker_id":"e2e-worker-1","outcome":"succeeded"}`;另三值failed/uncertain/policy_hold | **API-only、MOCK**、PH-04/10 | +| GET `/api/phase-a/audit` | `?account_id=A&task_id=T&attempt_id=AT&browser_env_alias=e2e-env&network_exit_id=P1&event_type=task_finished&from=2026-09-13T00%3A00%3A00Z&to=2026-09-13T23%3A59%3A59Z&page=1&page_size=25`;按本轮UTC替换时间,逐个条件再组合 | UI、AUD-01~04 | + +### 附录 D:环境 + +| 方法 / 路径 | body或查询样例 | 入口 / 用例 | +| --- | --- | --- | +| GET `/api/browsers` | 无 | UI、ENV-04 | +| GET `/api/browsers/{E1}` | alias作为路径,不是账号ID | UI、ENV-04 | +| POST `/api/browsers` | 下方完整对象 | UI、ENV-01~03 | +| POST `/api/browsers/{E1}/start` | 无 | UI、ENV-05 | +| POST `/api/browsers/{E1}/stop` | 无 | UI、ENV-05 | +| POST `/api/browsers/{E1}/upgrade` | `{"version":"V2"}` | UI、ENV-06/07 | +| POST `/api/browsers/{E1}/rebind` | `{"network_exit_id":"P2"}` | **API-only**、ENV-07 | +| DELETE `/api/browsers/{E1}` | 无;仅回收容器 | UI、ENV-05/09 | + +```json +{ + "alias":"e2e-env","name":"RUN环境","gateway":"G","image_version":"V1","account_id":"A","network_exit_id":"P1", + "fingerprint":{"seed":1000,"platform":"windows","platform_version":"11.0.0","brand":"Chrome","brand_version":"132.0.6834.159","hardware_concurrency":4,"lang":"zh-CN","accept_lang":"zh-CN,en-US","timezone":"Asia/Shanghai","disable_spoofing":"font,audio"} +} +``` + +最小对象只保留 `fingerprint.seed`,直连 `network_exit_id` 为空字符串。不接受客户端自己添加代理参数;`PUT /api/browsers/{E1}` 不是环境编辑功能。重绑要求有效出口ID,空值不能切回直连。 + +### 附录 E:采集设置、资料与策略 + +| 方法 / 路径 | body或查询样例 | 入口 / 用例 | +| --- | --- | --- | +| GET `/api/creator/settings` | 无 | UI、SET-01 | +| PUT `/api/creator/settings` | E-settings完整12字段 | UI、SET-01~04 | +| GET `/api/creator/accounts` | 无 | UI、STR-01 | +| GET `/api/creator/accounts/{A}/profile` | 无;不是 `/accounts/{A}` | UI、STR-01 | +| PUT `/api/creator/accounts/{A}/profile` | E-profile | UI、STR-01/07 | +| POST `/api/creator/accounts/{A}/login-result` | `{"status":"manual_required","reason":"RUN需账号所有者人工登录","actual_platform_account_key":""}`;仅negative状态;logged_in用于拒绝验证 | **API-only**、AC-06、STR-07 | +| POST `/api/creator/accounts/{A}/big-account` | `{"enabled":true}` / false | UI、STR-03 | +| GET `/api/creator/relations` | `?big_account_id=A` | UI、STR-03 | +| POST `/api/creator/relations` | `{"big_account_id":"A","small_account_id":"S1","enabled":true}`;false解除 | UI、STR-03/05 | +| GET `/api/creator/accounts/{A}/strategies` | 无 | UI、STR-04 | +| POST `/api/creator/accounts/{A}/strategies` | E-strategy | UI、STR-04 | +| PUT `/api/creator/strategies/{strategy_id}` | E-strategy全对象,改position等字段 | UI、STR-05 | +| POST `/api/creator/strategies/{strategy_id}/enable` | 无 | UI、STR-05 | +| POST `/api/creator/strategies/{strategy_id}/disable` | 无 | UI、STR-05 | +| DELETE `/api/creator/strategies/{strategy_id}` | 无 | UI、STR-05 | + +E-settings(只作结构样例;恢复时使用本轮保存的原值): + +```json +{"lookback_days":30,"new_work_interval_seconds":1800,"metric_initial_interval_seconds":3600,"metric_multiplier":2,"metric_max_interval_seconds":86400,"metric_age_seconds":2592000,"ai_provider":"","ai_model":"","ai_configured":false,"transcription_provider":"","transcription_model":"","transcription_configured":false} +``` + +E-profile: + +```json +{"login_username":"RUN测试用户","password":"","real_name_status":"unknown","real_name":"","identity_number":"","note":"RUN","business_status":"normal","big_account":false,"reply_requirements":"仅回复已批准测试内容","cooldown_seconds":86400} +``` + +资料 PUT 需要保留本轮真实 `big_account` 等原值,不可把示例 false 发到活跃大号。密码空表示不更新;真密码不写入报告。实名状态为 `unknown/not_real_name/recorded`;人工业务状态为 `normal/muted/banned/deleted`,不以中文label猜枚举。 + +E-strategy: + +```json +{"execution_account_id":"S1","position":1,"enabled":false,"event_types":["comment"],"action":"reply_comment","target_type":"user","candidate_texts":["RUN已批准候选一","RUN已批准候选二"]} +``` + +`like_comment` 使用 `target_type=comment`,`like_work/repost` 使用 `work`;其他动作服务端规范为 `user`(回复仍须实际comment/work目标)。`event_types` 为 comment/like/repost/follow;UI不配置自动DM聊天。示例默认停用,获准真实事件测试时才显式启用。 + +### 附录 F:竞品、内容、素材、线索、事件与消息 + +| 方法 / 路径 | body或查询样例 | 入口 / 用例 | +| --- | --- | --- | +| GET `/api/creator/competitors` | `?platform=douyin` | UI、COL-01 | +| POST `/api/creator/competitors` | F-competitor | UI、COL-01 | +| GET `/api/creator/competitors/{C}` | 无 | **API-only详情**、COL-01/02 | +| POST `/api/creator/competitors/{C}/pause` | 无 | UI、COL-02 | +| POST `/api/creator/competitors/{C}/resume` | 无 | UI、COL-02 | +| POST `/api/creator/competitors/{C}/sync` | `{"account_id":"A"}` | UI、COL-02/03/09 | +| GET `/api/creator/works` | `?platform=douyin&source_type=competitor&source_id=C&published_after=2026-09-01T00%3A00%3A00Z&published_before=2026-09-14T00%3A00%3A00Z&min_likes=0&min_comments=0&min_shares=0`;时间换本轮窗口 | UI仅平台/计数,其余**API-only筛选**,COL-07 | +| POST `/api/creator/works` | F-work;仅API补充数据 | **API-only导入**、API-01 | +| GET `/api/creator/works/{W}` | 无 | **API-only详情**、COL-07 | +| GET `/api/creator/works/{W}/metrics` | 无 | **API-only快照**、COL-08、API-02 | +| POST `/api/creator/works/{W}/metrics` | `{"collected_at":"2026-09-13T12:00:00Z","likes":0,"comments_count":null,"shares":1}`;当轮时间 | **API-only导入**、API-02 | +| GET `/api/creator/works/{W}/material` | 无 | UI、MAT-01 | +| POST `/api/creator/works/{W}/material/select` | 无 | UI、MAT-01 | +| POST `/api/creator/works/{W}/material/process` | 无;会真实下载/处理文件 | UI、MAT-02~04 | +| POST `/api/creator/works/{W}/material/rewrite/confirm` | `{"requirement":"RUN保留事实,使用测试口播风格"}` | UI、MAT-05/06 | +| PUT `/api/creator/works/{W}/material/rewrite` | `{"title":"RUN人工编辑标题","script":"RUN人工编辑口播正文"}` | UI、MAT-05/06 | +| GET `/api/creator/comments` | `?platform=douyin&work_id=W` | UI、LEAD-03/07 | +| POST `/api/creator/comments` | F-comment | **API-only导入**、API-03 | +| GET `/api/creator/comments/{K}` | 无 | **API-only详情**、LEAD-07 | +| GET `/api/creator/rules` | 无,或 `?enabled_only=true` | UI及**API-only启用过滤**、LEAD-01/07 | +| POST `/api/creator/rules` | F-rule | UI、LEAD-01 | +| GET `/api/creator/rules/{R}` | 无 | **API-only详情**、LEAD-07 | +| PUT `/api/creator/rules/{R}` | F-rule全对象 | UI、LEAD-02 | +| POST `/api/creator/rules/{R}/enable` | 无 | UI、LEAD-02 | +| POST `/api/creator/rules/{R}/disable` | 无 | UI、LEAD-02 | +| GET `/api/creator/rule-results` | `?comment_id=K&rule_id=R` | **API-only结果详情**、LEAD-04/07 | +| GET `/api/creator/leads` | `?platform=douyin` | UI、LEAD-04/06 | +| POST `/api/creator/comments/{K}/analyze` | `{"rule_id":"R"}` | UI、LEAD-03~05 | +| GET `/api/creator/events` | `?account_id=A` | **API-only**、EVT、API-04 | +| POST `/api/creator/events` | F-event | **API-only导入**、API-04;不证明监听 | +| POST `/api/creator/events/process` | F-event;可触发真实写,API补充仅baseline/无启用策略账号 | **API-only**、API-04 | +| POST `/api/creator/events/{event_id}/display` | 无 | **API-only**、API-04;不作为实际页面可见证据 | +| GET `/api/creator/operations` | `?account_id=S1` | UI、OP-08 | +| POST `/api/creator/operations` | F-operation | UI回复/私信;其他动作**API-only**、OP-01~07 | +| GET `/api/creator/operations/{operation_id}` | 无 | **API-only详情**、OP-04/05/08 | +| POST `/api/creator/operations/{operation_id}/execute` | 无;仅在逐次确认/已批准API动作后执行 | UI或API、OP-01~07 | +| GET `/api/creator/conversations` | `?account_id=A` | UI、OP-02 | +| GET `/api/creator/conversations/{conversation_id}/messages` | 无 | UI、OP-02/03 | +| POST `/api/creator/messages` | F-message;仅存储,不发平台消息 | **API-only导入**、API-05 | + +F-competitor(主页与标识换为C真实资料;这里不是一键解析真实身份): + +```json +{"platform":"douyin","platform_account_key":"C真实稳定标识","nickname":"RUN竞品","avatar_url":"","homepage_url":"https://www.douyin.com/user/C真实sec_user_id"} +``` + +F-work(仅API补充;source_id必须是已有合法A;不可拿示例媒体地址做真实处理): + +```json +{"platform":"douyin","work_key":"RUN-api-only-work-1","source_type":"owned","source_id":"A","author_name":"RUN-api-only","title":"RUN-api-only测试作品","body":"仅验证存储,不是采集结果","published_at":null,"published_at_status":"pending_verification","original_url":"https://www.douyin.com/video/123456789","cover_url":"","likes":0,"comments_count":null,"shares":0} +``` + +F-work-metric(API-02 专用独立作品 WM;其余字段同 F-work。以下时间必须替换为本轮 UTC 当前时间减 120 秒,并保证初始监测窗口足够长;verified 只代表本条 API 测试数据的显式输入,不证明真实采集已验证发布时间): + +```json +{"platform":"douyin","work_key":"RUN-api-only-metric-work-1","source_type":"owned","source_id":"A","author_name":"RUN-api-only","title":"RUN-api-only指标测试作品","body":"仅验证指标存储与计划","published_at":"2026-09-13T11:58:00Z","published_at_status":"verified","original_url":"https://www.douyin.com/video/123456789","cover_url":"","likes":0,"comments_count":null,"shares":0} +``` + +F-comment(W取API-01输出;REAL用例必须取真实采集K): + +```json +{"platform":"douyin","comment_key":"RUN-api-only-comment-1","work_id":"W","author_uid":"123456789","author_name":"RUN-api-only","content":"RUN-api-only想了解测试商品","published_at":null,"comment_type":"top_level"} +``` + +F-rule: + +```json +{"name":"RUN线索规则","enabled":true,"source_type":"all","topic":"测试商品","include_keywords":["了解","咨询"],"exclude_keywords":["广告"],"ai_requirement":"只判断明确咨询测试商品的评论,不执行发送"} +``` + +F-event(仅隔离API补充;不篡改真实事件时间/状态): + +```json +{"platform":"douyin","receiving_account_id":"A","event_key":"RUN-api-only-event-1","event_type":"comment","baseline":true,"interactor_uid":"123456789","comment_id":"","work_id":"","message_text":"","platform_event_at":null} +``` + +F-operation(内部K/W来自真实采集;target_uid为评论真实作者数字UID;key由前端或API测试客户端安全随机生成,示例key只说明字段,不可多条动作复用): + +```json +{"idempotency_key":"manual-本轮安全随机唯一键","source":"manual","action":"reply_comment","platform":"douyin","account_id":"S1","target_uid":"123456789","target_comment_id":"K","target_work_id":"W","text":"RUN已批准的一次测试回复"} +``` + +其他动作每项单独生成key: + +| action | 应填目标字段 | text | execute预期 | +| --- | --- | --- | --- | +| dm | target_uid;comment/work省略 | 已批准非空文案 | 真实收件方可见、消息证据 | +| like_comment | target_uid、target_comment_id、target_work_id | 空 | 正确评论被点赞,不取消已点赞 | +| like_work | target_uid(已核对的作品作者数字UID)、target_work_id;comment可省略 | 空 | 正确作品被点赞 | +| follow | target_uid | 空 | 正确账号被关注,不取消已关注 | +| repost | target_uid(已核对的作品作者数字UID)、target_work_id | 已批准非空文案 | 当前明确失败 `REPOST_TEXT_UNSUPPORTED`,零转发副作用 | + +所有 action 在创建阶段均要求非空 target_uid。另分别省略 like_work/repost 的 target_uid 提交创建请求,预期 400 且不产生可执行操作;此拒绝子项不得作为正向点赞或转发 `REPOST_TEXT_UNSUPPORTED` 边界的输入。 + +F-message(仅隔离API存储,platform_message_key带API标记;message_at改本轮时间): + +```json +{"platform":"douyin","account_id":"A","peer_uid":"123456789","peer_name":"RUN-api-only","platform_message_key":"RUN-api-only-message-1","direction":"inbound","message_type":"text","text":"RUN-api-only仅测试存储","sent_state":"received","message_at":"2026-09-13T12:00:00Z"} +``` + +### 附录 G:gateway 内部领域路由 + +这些接口不经 `/api`;独立实验用例才直接调用,正常业务优先从控制面进入。`GATEWAY_BASE` 的可达方式见3.1。除 `GET /v1/browsers` 外,领域GET/DELETE也要提交 JSON body及Content-Length,不能照普通GET省略。 + +**代际获取**:控制面 `GET /api/browsers/{E1}` 返回对象内运行记录的 binding_version(先按实际JSON层级读取),与 gateway `GET /v1/browsers` 中同alias的 `id`、`network_id`、`network_exit_id` 共同核验;`id`是Docker runtime ID,不是控制面 runtime_instance_id。实际字段回读与Docker标签一致后再填请求。不存在时不得随意填 `1`/假ID来做成功测试。 + +G-generation(start/stop/remove仅这三字段,不能混入network_exit_id): + +```json +{"binding_version":1,"runtime_id":"实际Docker容器ID","network_id":"实际Docker网络ID"} +``` + +G-douyin-base(cookies/get/identity/action/events均在此对象上加各自字段;直连出口为空,但仍须真实network_id): + +```json +{"binding_version":1,"runtime_id":"实际Docker容器ID","network_id":"实际Docker网络ID","network_exit_id":"P1"} +``` + +| 方法 / 路径 | 请求样例 / 在base上追加字段 | 用例 | +| --- | --- | --- | +| GET `/healthz` | 无、无需token,204 | SYS-01 | +| GET `/v1/browsers` | 无 | GATE-01/02 | +| POST `/v1/browsers` | G-create | GATE-02 | +| POST `/v1/browsers/{alias}/start` | G-generation;要求非空有效network_id,停止态未联网容器不满足该前置 | GATE-02 | +| POST `/v1/browsers/{alias}/stop` | G-generation | GATE-02 | +| DELETE `/v1/browsers/{alias}` | G-generation;缺失容器专项可不填runtime/network,但必须按已保存代际核验 | GATE-02 | +| POST `/v1/browsers/{alias}/proxy` | G-proxy | GATE-03 | +| POST `/v1/browsers/{alias}/douyin/cookies` | G-douyin-base + `"cookies":[{"name":"sessionid","value":"仅在私密请求文件填入","domain":".douyin.com","path":"/"}]` | GATE-04 | +| POST `/v1/browsers/{alias}/douyin/get` | G-douyin-base + `"url":"https://www.douyin.com/aweme/v1/web/user/profile/self/?aid=6383&device_platform=webapp"` | GATE-04 | +| POST `/v1/browsers/{alias}/douyin/identity` | G-douyin-base + `"expected_account_key":"实际UID或已核实账号标识"` | AC-06、GATE-04 | +| POST `/v1/browsers/{alias}/douyin/action` | G-action;confirm默认false,不得直接把预览改true绕开授权 | GATE-05、OP-07 | +| POST `/v1/browsers/{alias}/douyin/events` | G-douyin-base + `"expected_uid":"真实数字UID"` | GATE-06 | +| GET `/v1/browsers/{alias}/douyin/events` | body=G-douyin-base;query `?limit=100&wait=25`;确认 `?ack=实际delivery_id&limit=1&wait=0` | GATE-06 | +| DELETE `/v1/browsers/{alias}/douyin/events` | body=G-douyin-base | GATE-06 | + +受限作品/评论读取在 G-douyin-base 中增加 url: + +- 作品:`https://www.douyin.com/aweme/v1/web/aweme/post/?sec_user_id=实际sec_user_id&count=20&max_cursor=0`;下一页仅使用真实返回cursor。 +- 一级评论:`https://www.douyin.com/aweme/v1/web/comment/list/?aweme_id=实际平台work_key&count=20&cursor=0`;下一页同理。 +- 不允许其他host、额外参数、任意CDP或脚本。源码当前允许非负数字分页,不采用旧文档“只能max_cursor=0”的描述。 + +G-create(独立实验alias,不与ENV共用;镜像换真实摘要。`stopped=true`仅允许直连;运行态实验需要受控网络并明确授权): + +```json +{"alias":"e2e-gate-only","name":"RUN gateway实验","image":"registry.example.invalid/test/browser:approved","cmd":["--fingerprint=1000","about:blank"],"volume":"creatorhub-profile-e2e-gate-only","binding_version":1,"network_exit_id":"","network_exit":{},"stopped":true} +``` + +G-proxy: + +```json +{"binding_version":1,"runtime_id":"实际Docker容器ID","network_id":"实际Docker网络ID","network_exit_id":"P1","network_exit":{"protocol":"socks5","host":"proxy.example.invalid","port":1080,"username":"","password":""}} +``` + +G-action(gateway字段使用**平台**标识,不是内部K/W;仅预览): + +```json +{"binding_version":1,"runtime_id":"实际Docker容器ID","network_id":"实际Docker网络ID","network_exit_id":"P1","expected_uid":"真实发送账号UID","action":"reply_comment","target_uid":"真实作者UID","target_comment_id":"真实平台comment_key","target_work_id":"真实平台work_key","text":"RUN已批准文本","confirm":false} +``` + +GET带body调用示例(仅在后续执行时,`BODY_FILE`为替换后的G-douyin-base,认证配置含Bearer): + +```bash +curl --silent --show-error --config "$GATEWAY_AUTH_FILE" \ + -X GET -H 'Content-Type: application/json' --data-binary @"$BODY_FILE" \ + --dump-header "$EVIDENCE/headers.txt" --output "$EVIDENCE/body.json" \ + --write-out '%{http_code}\n' "$GATEWAY_BASE/v1/browsers/$ALIAS/douyin/events?limit=100&wait=25" +``` + +## 7. 源码已知边界与待验证风险 + +这里不写执行结论。首次实际执行必须按相应用例存证,不得把风险描述复制成“已复现”。 + +| 项目 | 基线事实 / 风险 | 对应判定 | +| --- | --- | --- | +| 首次已验证登录闭环 | 新账号unknown;公开login-result拒绝logged_in;采集/写/监听又要求logged_in。人工浏览器登录到控制面资料的可达路径需验证 | AC-06;不能改库解决测试前置 | +| 网关UI删除 | provider仅允许删除browser-images;页面网关删除未正确接通 | GW-04失败与GW-05 API成功分开 | +| 线索人工联系 | 线索页未渲染回复编辑区、没有自动切评论页 | LEAD-06,不能把手动绕路当通过 | +| 规则错误区、依赖失败 | 多处辅助列表失败可能退化空数据/准备提示 | UI-06、LEAD-02、ENV-03 | +| 仿写 | 确认只保存要求;PUT缺Content-Type,但服务端直接JSON解码;切换/确认后表单一致性需实测 | MAT-05/06,不期待自动生成 | +| 竞品与指标目标 | canonical账号转换与目标作者之间存在需核验的路径 | COL-03/08,正向必须正确采C,不采执行账号冒充 | +| 媒体链 | 原始URL可能为网页、音轨临时后缀与格式、transcript字段内容及页面展示需核验 | MAT-02,要求有效媒体/音轨/真实正文,不以状态通过 | +| 带文案转发 | 当前脚本明确REPOST_TEXT_UNSUPPORTED | OP-07验证明确拒绝;不宣称正向支持 | +| 通知实时性 | 有真实通知监听代码;控制面取gateway队列与UI每10秒读私信是不同机制;display API不是UI自动上报 | EVT-01~04,保留真实外部依赖与时限证据 | +| 未知hold | 页面警告“不提供恢复”与allowed_action按钮可能冲突 | PH-08仅UI异常响应注入检查,不对假响应执行写 | +| 直连升级/重绑 | create/start支持直连,不代表upgrade空出口和rebind切直连支持 | ENV-07记录实际限制 | +| 接口/页面范围 | 无退出、永久环境删除、作品详情UI、操作记录重发、新建会话或自动聊天入口 | 不编造按钮;目录中API-only补足现有后端功能 | + +## 8. 结果记录、证据与通过标准 + +### 8.1 每例结果模板 + +复制下表,每例及每个参数化子项各一行。不要把多协议、四种Mock结果、六类动作合并成一个“通过”。 + +| RUN / 用例 / 子项 | 层级 | HEAD / 镜像digest | 执行人 / UTC起止 | 前置账号与资源ID | 授权单 | 实际有序操作 | HTTP/operation/event/Attempt ID | 实际UI与平台结果 | 证据路径 | 状态 | 缺陷/阻塞及恢复清理 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| 待填写 | UI/API/REAL/MOCK/FAULT | 待填写 | 待填写 | 脱敏ID | 无写填不适用 | 记录实际步骤,不只复制计划 | 无则说明原因 | 不以“正常”代替事实 | 脱敏截图/响应/日志索引 | 未执行 | 待填写 | + +单例详细记录: + +```text +用例: +前置满足情况 / 数据真实来源: +授权动作与次数(含平台清理授权): +步骤1 实际操作、时间、结果: +步骤2 实际操作、时间、结果: +步骤3 实际操作、时间、结果: +请求方法/路径/脱敏body/HTTP状态: +账号ID / 平台UID / 环境alias / binding_version / runtime_id: +任务 / confirmation / attempt / operation / idempotency_key / event_key: +预期与实际差异: +平台侧独立核验: +故障注入具体命令与时刻 / 恢复命令与时刻: +证据索引(不得包含明文凭据): +结论:通过 / 失败 / 阻塞 / 未执行 / 经批准不适用 +遗留风险与负责人: +清理确认: +``` + +实时事件另附:平台事件时间、gateway收到、控制面收到、开始/完成处理、UI实际首次可见、平台推送延迟、处理延迟、可见延迟。页面无展示入口则写“没有可观察入口”,不手工填displayed_at制造≤30秒。 + +证据至少包括:对应HEAD/digest、实际URL、关键步骤截图、脱敏请求响应、服务关联日志、平台侧独立截图或ID、故障恢复记录;素材附真实文件校验(`ffprobe`格式/时长/采样率)、转写正文与参考文稿差异。状态 `succeeded` 但缺平台写后证据/媒体实物,不能通过REAL用例。 + +### 8.2 状态与验收门槛 + +1. **通过**:前置真实且授权有效,全部步骤预期满足,有独立可复核证据,重复/失败分支及清理均有记录。 +2. **失败**:实际行为与预期不符,包括静默吞错、串账号、重复写、错误目标、假成功、界面现有入口无法继续。已知源码风险复现仍是失败。 +3. **阻塞**:缺真实账号/登录闭环、媒体/供应商、可控代理、平台挑战待人工、故障窗口未触发等;写明原因、需要谁提供什么。不得记通过或随意不适用。 +4. **不适用**:仅需求已明确排除且负责人书面确认的子项;小红书没有编入用例总数。不得把当前已实现但真实未验证的能力标不适用。 +5. 模块通过要求全部适用子项通过;全量通过要求全部范围内模块通过、无未关闭的错误目标/重复写/数据丢失/伪成功/关键入口阻断,全部真实写逐项可核验。接口补充、MOCK及UI注入分别统计,不能抵扣REAL阻塞。 +6. 已确认不支持的带文案转发可以通过“拒绝边界”检查,但总体报告必须显著保留正向不支持结论;不得据此宣布具备全六类真实写能力。 +7. 首次登录、网关UI删除、线索联系、媒体或实时展示等若阻塞/失败,即使其余模块通过,也只报告“已完成部分功能验证”,不能称“当前全量E2E通过”。 +8. 问题修复后换新HEAD重新执行失败用例及关联回归,保留旧结果,不把本基线报告改成新版本已通过。 + +### 8.3 汇总模板 + +| 模块 | 总用例/子项 | 通过 | 失败 | 阻塞 | 未执行 | 批准不适用 | REAL通过/总数 | 主要遗留 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| 按第4节逐模块填写 | 待填 | 0 | 0 | 0 | 待填 | 0 | 0/待填 | 尚未执行 | + +发布结论应列:本轮实际覆盖、明确未覆盖、失败/阻塞项、剩余真实副作用与资源、配置是否恢复、证据位置、允许后续执行范围。**本次文档交付只代表静态计划完成,不代表任何功能已经执行或通过。** diff --git a/docs/e2e-test-report-20260914.md b/docs/e2e-test-report-20260914.md new file mode 100644 index 0000000..38c54c3 --- /dev/null +++ b/docs/e2e-test-report-20260914.md @@ -0,0 +1,253 @@ +# CreatorHub E2E 功能测试执行报告 + +- 计划:`docs/e2e-test-plan.md` +- 范围:抖音当前实现;不含小红书、性能压测、RBAC/多租户 +- 用例:122/122 已登记结果 +- 执行结论:**不是整体通过**。当前结果为 `PASS 32`、`FAIL 19`、`BLOCKED 71`。 +- `FAIL`:已观察到与计划预期不一致的实际行为。 +- `BLOCKED`:需要真实平台、健康代理、生产 AI/转写、账号凭据,或需要停止共享资源;未用伪造数据替代。 + +## 证据 + +- `[E]` 本轮脱敏补充证据:`docs/e2e-evidence-20260914.md` +- `[U]` browser-harness 路由录制:`/home/rogee/.config/browser-harness/agent-workspace/recordings/creatorhub-e2e-final/`,事件索引为 `events.jsonl` +- `[A]` 控制面 API/Phase A 脱敏报告:`/home/rogee/.pi/agent/sessions/--home-rogee-Workspace-creator-hub--/subagent-artifacts/outputs/2cbcddb6-c347-41d0-a6f7-356dccd81a3e/api-e2e.txt` +- `[R]` 回归门禁报告:`/home/rogee/.pi/agent/sessions/--home-rogee-Workspace-creator-hub--/subagent-artifacts/outputs/2cbcddb6-c347-41d0-a6f7-356dccd81a3e/regression.txt` + +## 逐例结果 + +### SYS + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| SYS-01 | PASS | [R][U] healthz/API 入口和主要静态页面可达;healthz 204。 | +| SYS-02 | PASS | [R][E] 非法日志级别、密码、主密钥、参数等在副作用前被拒绝;help/构建通过。 | +| SYS-03 | PASS | [A][E] 非法 gateway 配置 400;无 Docker socket 的一次性 gateway 非零退出并报告依赖错误。 | +| SYS-04 | BLOCKED | [E] 隔离 control-plane 重启后数据可读;共享 gateway/Profile 重启未执行。 | +| SYS-05 | BLOCKED | [E] 隔离 PostgreSQL 停止时读取为 500,恢复后 200;RUN 规则保存和结构化日志关联未完成。 | +| SYS-06 | BLOCKED | [R][E] 关停模拟和 Docker socket 归属通过;开发模式完整启动/映射未执行。 | + +### UI + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| UI-01 | BLOCKED | [U][E] 空表单禁用、密码遮挡已见;页面自身提交正确 Basic 凭据未能独立证明。 | +| UI-02 | FAIL | [E] 错误凭据提交后超过 19 秒仍显示“登录中”,未显示 401 文案或清理状态。 | +| UI-03 | BLOCKED | [U] 列表/详情/任务/草稿等路由可达;360px、前进后退完整矩阵未留证。 | +| UI-04 | BLOCKED | 未取得键盘下拉、标签去重和全部基础表单的独立证据,不判通过。 | +| UI-05 | FAIL | [U][E] 确认弹窗/回收操作多次冻结或超时;忙碌禁用子项通过但整体失败。 | +| UI-06 | FAIL | [U] 工作台“规则/线索”页签偶发空白,加载失败与空态不能稳定区分。 | +| UI-07 | BLOCKED | 窄屏、键盘焦点、复制和完整可访问性检查未执行。 | + +### GW + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| GW-01 | BLOCKED | [A][U] 现有登记、列表和认证读取通过;新登记、重名、token 展示/复制流程未完整执行。 | +| GW-02 | BLOCKED | 未在独立未引用 gateway 上完成改名和错误 token 恢复。 | +| GW-03 | BLOCKED | [A] API 非法字段 400;UI 断网保存、表单保留和恢复未完整留证。 | +| GW-04 | FAIL | [U][E] 页面删除接线落入当前 provider 限制,未形成预期 gateway DELETE 成功链。 | +| GW-05 | PASS | [A] 引用中的 gateway 删除返回冲突并保留引用;未执行资源破坏。 | + +### IMG + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| IMG-01 | PASS | [A][U] 镜像版本创建、字段边界和非法输入验证通过。 | +| IMG-02 | PASS | [U][A] 禁用/重新启用镜像并回读候选状态通过。 | +| IMG-03 | PASS | [A][U] 未引用镜像删除成功;引用资源保留;取消无删除副作用。 | +| IMG-04 | BLOCKED | 不可拉取镜像的独立环境创建与恢复未执行。 | + +### NET + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| NET-01 | BLOCKED | 无健康真实代理端点,未创建带凭据的真实出口。 | +| NET-02 | PASS | [A] 空 host、越界端口、未知资源等非法请求被拒绝,无半条记录。 | +| NET-03 | BLOCKED | 无健康代理,未执行真实出口检测或身份不符对照。 | +| NET-04 | BLOCKED | 无健康代理且禁止直连回退的真实场景未执行。 | +| NET-05 | BLOCKED | 无可用出口绑定和故障读取场景,未声称绑定恢复。 | +| NET-06 | BLOCKED | 未停用共享出口,也没有专用 P2 与排队任务。 | + +### AC + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| AC-01 | PASS | [A][U] 抖音账号建档、trim/tag 和默认授权/暂停状态通过;未把空 Cookie 当登录。 | +| AC-02 | PASS | [A][U] 重复、非法平台/UID 和未知合法标识边界通过;临时账号已撤销。 | +| AC-03 | FAIL | [E] 账号记录为 active/authorized,但 creator capability 解析仍因 credential 缺失失败,不能判 ready。 | +| AC-04 | PASS | [A][U] 暂停/恢复、版本关联及不自动恢复旧 hold 的控制面流程通过。 | +| AC-05 | BLOCKED | [A] 草稿链可建;UI 断网创建、完整失败保留和资源 ready 前置未完整执行。 | +| AC-06 | BLOCKED | [E] gateway identity 真实返回 UID `99491952055`;控制面 credential/首次可达性未满足,未伪造 logged_in。 | +| AC-07 | PASS | [A] revoke 204,临时账号失去运行资格;未重建授权。 | + +### ENV + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| ENV-01 | BLOCKED | 未创建新的专用直连环境,避免改变共享浏览器/Profile。 | +| ENV-02 | BLOCKED | 无健康代理和真实公网 IP 对照,未执行高级指纹环境。 | +| ENV-03 | PASS | [A][U] seed/alias 等边界被拒绝;创建环境页面及依赖提示可达。 | +| ENV-04 | PASS | [A][U] 列表/详情读取通过;未将页面刷新当主动状态探测。 | +| ENV-05 | PASS | [A][U] 已观察共享环境启停/恢复和重复动作边界,最终运行实例恢复。 | +| ENV-06 | BLOCKED | 未在共享环境上执行升级/Profile 保留测试。 | +| ENV-07 | BLOCKED | 无直连/代理双环境和健康 P2,未执行升级重绑。 | +| ENV-08 | BLOCKED | 未对共享运行实例制造并发启动/升级竞态。 | +| ENV-09 | BLOCKED | 未停止共享 gateway 或强制移除共享浏览器容器。 | +| ENV-10 | PASS | [A] 未知动作、非法版本、无效 alias 等 API 输入明确拒绝。 | + +### GATE + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| GATE-01 | PASS | [A] 无 token/错误 token、非法 body、过大 body、未知路径和正常列表边界已验证。 | +| GATE-02 | BLOCKED | 未在独立 gateway 上完整创建、启停、删除真实实验容器。 | +| GATE-03 | BLOCKED | 无健康代理和隧道目标,未测试 proxy/代际恢复。 | +| GATE-04 | FAIL | [E] identity 读取成功,但受限作品读取得到 HTML web shell/空 detail,不是稳定 JSON;Cookie 注入未完成。 | +| GATE-05 | FAIL | [E] 六类 preview 中 follow 请求失败;confirmed like/repost 得到 `TARGET_MISMATCH`,未得到计划要求的明确 repost 拒绝码。无平台写成功被计入。 | +| GATE-06 | BLOCKED | [E] 事件读取曾因 CDP `Runtime.evaluate` 失败;未启动真实订阅/取件确认。 | + +### PH + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| PH-01 | FAIL | [A][U] API 版本/确认链通过;UI 勾选核对后确认/入队按钮仍不能稳定启用。 | +| PH-02 | FAIL | [A][U] API 同 confirmation 幂等入队通过;对应 UI 入队链受 PH-01 按钮状态故障影响。 | +| PH-03 | PASS | [A] 旧 draft version 返回 409,新版本重新确认/入队成功。 | +| PH-04 | PASS | [A] succeeded、failed、uncertain→needs_confirmation、policy_hold 和非法 outcome 均有明确 Mock 结果。 | +| PH-05 | BLOCKED | 任务状态过滤、空态和全部详情链接未完成独立 UI 留证。 | +| PH-06 | PASS | [A] uncertain→verify(not_executed)→resume→单次 Mock execute 通过。 | +| PH-07 | PASS | [A] uncertain 任务的 succeeded/failed 核验与 finish 可区分、可审计。 | +| PH-08 | BLOCKED | 未暂停共享账号、未停止共享代理/gateway,也未注入未知 hold。 | +| PH-09 | PASS | [A] queued/policy_hold cancel 204;终态任务 cancel 明确拒绝。 | +| PH-10 | BLOCKED | [A] 两 worker 至多一次领取通过;崩溃/租约过期未因共享资源限制执行。 | + +### AUD + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| AUD-01 | PASS | [A][U] Mock 动作链、task/attempt/runtime 关联和脱敏审计可读。 | +| AUD-02 | BLOCKED | 多条件、日期、深链和非法 RFC3339 的完整矩阵未执行。 | +| AUD-03 | BLOCKED | 未专门生成超过 25 条审计并验证当前页 CSV。 | +| AUD-04 | BLOCKED | 未在共享运行栈阻断 audit GET 后完成恢复核验。 | + +### SET + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| SET-01 | PASS | [A][U] 默认值、白名单设置读取/保存/恢复通过。 | +| SET-02 | BLOCKED | 数值全边界、审批不完整、设置未知字段/尾随 JSON 的完整用例未独立执行。 | +| SET-03 | BLOCKED | 当前 AI/转写未配置;AI 分析 503 已观察,但真实供应商成功/恢复未验证。 | +| SET-04 | FAIL | [E] `metric_age_seconds=60` 保存 200 后,超龄作品仍保留未来 `next_metric_at` 且无停止原因。 | + +### STR + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| STR-01 | BLOCKED | 未在测试账号上执行密码/实名/业务资料完整保存和敏感字段核验。 | +| STR-02 | BLOCKED | 未完成双账号切换与迟到保存竞态。 | +| STR-03 | BLOCKED | 未在双大号/双小号和跨平台样本上完成关系唯一性流程。 | +| STR-04 | BLOCKED | 六动作策略候选配置未完成独立 UI/API 矩阵。 | +| STR-05 | BLOCKED | 策略排序、删除、解除关系和恢复链未完成独立 E2E。 | +| STR-06 | BLOCKED | 两段保存失败与切换竞态未在 UI 中注入。 | +| STR-07 | BLOCKED | 资料枚举/业务限制/登录结果的完整 API/UI 矩阵未完成。 | + +### COL + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| COL-01 | PASS | [A][U][E] 竞品登记、主页链接候选和状态读取通过;临时竞品已暂停。 | +| COL-02 | BLOCKED | 无可用真实采集账号,sync 前置无法完成;失败已记录为 503 credential resolution。 | +| COL-03 | BLOCKED | 竞品真实目标、分页和一级评论未采集。 | +| COL-04 | BLOCKED | 自有账号后台采集未执行。 | +| COL-05 | BLOCKED | 回溯、周期、checkpoint 和断点恢复未执行。 | +| COL-06 | BLOCKED | 未做登出/错身份/挑战的真实采集实验。 | +| COL-07 | FAIL | [U][A] API 作品详情/过滤可读,但工作台规则/线索区域偶发空白,整体页面验收失败。 | +| COL-08 | BLOCKED | 未获得真实平台指标和等待窗口。 | +| COL-09 | BLOCKED | 未执行真实同步并发、重复来源和读取故障矩阵。 | + +### MAT + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| MAT-01 | PASS | [E] 素材选择接口成功且未自动开始处理。 | +| MAT-02 | BLOCKED | 无真实可下载视频、音轨和转写供应商。 | +| MAT-03 | BLOCKED | 无真实无音轨/无语音样本。 | +| MAT-04 | BLOCKED | 未制造真实媒体、磁盘或供应商失败。 | +| MAT-05 | FAIL | [E] 未处理素材的仿写确认/更新返回 409,不能保存要求和人工稿。 | +| MAT-06 | FAIL | [E] 当前部署 `material/process` 返回 405,处理/仿写边界无法按计划推进。 | + +### LEAD + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| LEAD-01 | PASS | [E] 规则创建、关键词、列表、详情和非法输入链通过。 | +| LEAD-02 | PASS | [E] 规则编辑、启用/停用和错误返回可见;删除不在当前能力内。 | +| LEAD-03 | FAIL | [U][E] 工作台规则/线索页签偶发空白,一级评论选择/分析入口不能稳定使用。 | +| LEAD-04 | BLOCKED | 未配置真实 AI,未做 owned/competitor 完整线索判定。 | +| LEAD-05 | BLOCKED | AI 503 已观察,但重复分析/禁用规则与恢复矩阵未完整执行。 | +| LEAD-06 | BLOCKED | 没有真实 UID 线索,未验证人工联系入口。 | +| LEAD-07 | PASS | [E] 单评论、单规则、过滤和只读分析结果接口可读;未产生平台写。 | + +### OP + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| OP-01 | BLOCKED | 无可核验真实评论目标和 connector credential,未执行评论回复。 | +| OP-02 | BLOCKED | API 会话存储通过,但没有真实入站事件,不能替代平台私信验收。 | +| OP-03 | BLOCKED | 未执行真实私信发送和收件方平台核验。 | +| OP-04 | BLOCKED | 未具备两个真实会话/评论,未执行完整草稿切换与迟到响应。 | +| OP-05 | BLOCKED | 未执行真实 gateway 中断后的未知写结果;不自动重试。 | +| OP-06 | BLOCKED | 未执行真实点赞/关注;preview 不作为成功证据。 | +| OP-07 | FAIL | [E] 错误/自目标被 `TARGET_MISMATCH` 拒绝,但 confirmed repost 未返回明确 `REPOST_TEXT_UNSUPPORTED`。 | +| OP-08 | BLOCKED | 未完成真实 operation 状态、crypto 禁用和完整 UI 边界矩阵。 | + +### EVT + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| EVT-01 | BLOCKED | 未建立真实监听基线,也未产生四类平台通知。 | +| EVT-02 | BLOCKED | 无真实事件和页面可见时间戳,未测 5 秒/30 秒。 | +| EVT-03 | BLOCKED | 未停止共享 gateway/浏览器执行断连重连。 | +| EVT-04 | BLOCKED | 未制造真实 ack/processing 中断和恢复窗口。 | +| EVT-05 | BLOCKED | 未建立真实大号/小号策略和四类通知。 | +| EVT-06 | BLOCKED | 未产生真实自动动作,未验证共享冷却/候选/人工例外。 | +| EVT-07 | BLOCKED | 未配置 AI,也未执行真实写失败/不确定场景。 | +| EVT-08 | BLOCKED | 未捕获真实写在途和执行前状态变化。 | + +### API + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| API-01 | FAIL | [E] 当前补测中未知 `owned` source 仍返回 201;去重/合法多来源通过,但未知来源预期应拒绝。 | +| API-02 | FAIL | [A][E] 快照、去重、迟到/非法值通过;缩短监测年龄后计划未停止,`next_metric_at`/原因错误。 | +| API-03 | PASS | [E] 评论导入、去重、详情、过滤、缺作者保留和关联校验通过。 | +| API-04 | PASS | [E] 合法 comment baseline 201/200 去重、process、display 和缺 UID blocked 均通过;此前错误 payload 的 400 不计入。 | +| API-05 | PASS | [E] 消息导入/去重、会话读取和同 peer 跨账号隔离通过;非法字段拒绝。 | +| API-06 | FAIL | [E] body/大小/资源/方法边界通过,但拼错 API 路径和 `/api/creator/profiles` 返回 200 HTML,不符合公开 JSON 边界。 | + +### END + +| 用例 | 状态 | 结果与证据 | +| --- | --- | --- | +| END-01 | BLOCKED | [E] 自动策略已停用、临时竞品暂停;没有真实平台写账本可做平台侧清理。 | +| END-02 | FAIL | [E] 临时账号/竞品/规则/隔离项目已清理或停用;API 作品、评论、指标、消息、事件无公开删除 API,只能保留 RUN 残余,未满足完全清理。 | + +## 当前缺陷与外部前置 + +1. **P1:** UI 错误凭据请求长期停留“登录中”,没有可见 401 错误。 +2. **P1:** connector credential 解析失败,导致真实竞品/自有采集和平台写操作无法进入。 +3. **P1:** gateway 受限读取得到 HTML/空 detail;当前真实作品数据不足以完成采集与写目标校验。 +4. **P1:** 事件读取出现 CDP `Runtime.evaluate` 失败,实时监听、去重、重连和自动响应均无证据。 +5. **P2:** 指标监测年龄变更没有重排/停止超龄计划。 +6. **P2:** `material/process` 当前部署为 405,素材处理及仿写依赖链无法进入。 +7. **P2:** 工作台规则/线索页签偶发空白。 +8. **P2:** API 未知路径出现 SPA HTML 200;应返回清晰 JSON 404/405。 +9. **P2:** confirmed repost 未得到明确 `REPOST_TEXT_UNSUPPORTED`,仅得到目标不匹配。 + +## 清理与状态 + +- 未停止、删除共享 Compose 服务、共享数据卷或共享业务资源。 +- 未引用的临时镜像已删除,保留的验收镜像仍为 enabled;临时竞品已 pause;测试规则已 disable;临时账号已 revoke;隔离 Compose 已销毁,容器/卷/网络均为 0。 +- settings 已恢复原值;未输出或归档任何 Cookie、密码、token、主密钥或原始平台响应。 +- API-only RUN 记录因没有公开删除接口而保留;报告没有把这些记录当作 REAL 验收证据。