# 原生浏览器环境:验证与手工验收 > **当前状态:单节点代码改造与自动检查通过;真实平台、代理、LAN 和资源验收仍须由授权操作者手工完成。** > 已完成 native gateway、控制面契约、runtime-use lease、Compose/P4 文档和本地单元测试;本文件只记录可复现的验收步骤,不把测试替身当作真实平台证据。 > 方案:[变更评审](native-browser-change-review.md);阶段:[实施计划](native-browser-implementation-plan.md);当次记录:[单节点验证记录](evidence/native-browser-verification-2026-09-18.md)。 ## 1. 验证边界 - 开发者负责单元/契约检查、构建和启动可联调环境;真实功能由用户手工验证,不使用浏览器自动化或脚本代点网页。 - 读取日志、目录占用、进程/端口和系统指标可以使用命令。自动测试中的替身只证明代码行为,不能证明平台登录、监听、发送或真实代理能力。 - 默认不构建/运行 Docker;Compose 仅可作为 PostgreSQL 独立依赖。旧方式对照、资源删除和故障注入必须单独取得用户同意。 - 测试专用账号、Profile、gateway、数据目录及出口;不能强杀用户正在使用的长期账号或清空全机 Docker 资源。 - 任何结果使用“未执行 / 通过 / 失败 / 阻塞”,不得把文档中的期望填成实际结果。 - 若被测 Chrome 由用户的 `chrome.service` 管理,验证只能通过其已开放的 CDP 连接执行只读/交互检查,不得停止、启动、替换或接管该实例;这类结果不能替代 native gateway 的 runtime 生命周期、控制面持久化和资源清理验收。 ## 2. 前置条件和记录表 实施 P0 完成后填写,缺项不得开始破坏性操作: | 项目 | 必填记录 | | --- | --- | | 软件基线 | Git 提交、未提交改动清单、Go/Python/Node/systemd/Xvfb/浏览器版本 | | 机器 | 单节点控制面 C 与 native gateway G 的稳定节点 ID、IP、CPU、内存、磁盘、发行版 | | 账号 | 专用采集账号、自有监听账号;预期平台 UID,勿记录密码/Cookie | | 浏览器 | 原生发行物来源、许可证、校验值、支持的指纹参数和 sandbox 证据;A02 普通升级的已安装源版本/目标版本 | | 路径 | 各机器 Profile 根目录、runtime 根目录、运行清单、日志、控制面素材目录 | | 网络 | 单节点的 HTTP/HTTPS/SOCKS4/SOCKS5 测试出口、协议支持的认证配置、预期出口 IP、CDP 可用情况;只记录配置标识,不记录密码 | | 操作许可 | 是否允许旧 Docker 对照、普通浏览器升级、gateway/控制面重启、任务取消、磁盘故障和测试数据删除;C02/D04 自动响应的测试策略、可控互动/接收账号及授权范围,A10 人工发送另行逐次确认 | | 时限 | task 最大执行时间、续租间隔 20 秒、租约 60 秒、清理预算 30 秒、恢复预算 60 秒 | | 资源预算 | 并发数 1/2、最低可用磁盘 20 GB、日志上限 1 GB;启动 p50/p95 和总内存目标,Profile 缓存预算 20 GB | | 证据位置 | 独立于 runtime 清理目录的本地证据目录,不提交账号敏感数据 | 首轮使用并发 1 和 2、短任务正常清理预算 30 秒、服务恢复预算 60 秒。复杂平台采集的最大时长单独确定,不能因为清理预算而强行截断正常业务。 ## 3. 开发者检查命令 以下命令是交付检查命令;执行结果另记在证据文件,不把未运行的命令当作通过。 ### Go ```bash go test ./... go vet ./... go build -o /tmp/creatorhub-control-plane-check ./cmd/control-plane go test -race ./... go test -coverprofile=/tmp/creatorhub-go.cover ./... go tool cover -func=/tmp/creatorhub-go.cover ``` 要求:测试、vet、build、race 全部成功;单元测试覆盖率至少 65%,同时核对本次生命周期/资源归属模块,不能用高覆盖无关模块掩盖改动遗漏。自动响应须用确定性测试覆盖重启/重连后事件永久去重、原 UID 冷却保持、冷却内新事件不执行、到期只允许新事件及迟到事件不补发(AC-A9、AC-B1);P2 接入新运行身份时即通过这些检查。真实平台结果另外验收。 ### Python gateway ```bash python3 -m venv .venv-gateway .venv-gateway/bin/python -m pip install -r requirements-gateway-dev.lock .venv-gateway/bin/python -m unittest discover -s browser_gateway -t . -p 'test_*.py' .venv-gateway/bin/python -m coverage erase .venv-gateway/bin/python -m coverage run --source=browser_gateway --branch \ -m unittest discover -s browser_gateway -t . -p 'test_*.py' .venv-gateway/bin/python -m coverage report --omit='*/test_*.py' --fail-under=65 ``` 核对实际发现的测试数量;禁止跳过未安装的原生管理依赖后将结果当成全通过。用模拟子进程测试错误分支不等于真机 systemd/Xvfb 验收完成。 ### 前端 ```bash npm --prefix web ci npm --prefix web run test npm --prefix web run test:coverage npm --prefix web run build ``` 覆盖 gateway 不可达、版本缺失、Profile 占用、开始/取消/停止、待清理错误和禁用状态。不要运行浏览器自动化命令代替本节手工验收。 ### 配置与旧路径 ```bash docker compose config --quiet ``` 仅在改动 Compose 时做配置校验,不执行 build/up;保留的 PostgreSQL 开发 Compose 文件也逐份验证。另行检查浏览器 runtime 路径已无 DockerClient/socket、容器/镜像/卷/网络创建、容器 wrapper 入口、旧 image 字段和“原生失败回退 Docker”;PostgreSQL 的独立部署配置不算漏删。 ## 4. 联调启动与访问 ### 已交付设置 - Go 使用 `LISTEN_ADDR`;联调须设置 `0.0.0.0:8082`。 - Vite 当前 `/api` 代理到 `127.0.0.1:8082`,端口 5173。Vite 必须加 `--host 0.0.0.0`,不能只给 localhost 地址。 - native Python gateway 使用 `LISTEN_ADDR=0.0.0.0:8081`,由非 root systemd user service 运行;稳定 `node_id` 从配置或主机身份加载。 - `scripts/dev-backend.mjs` 只启动 PostgreSQL 并检查 `NATIVE_GATEWAY_ENDPOINT`,不会启动浏览器容器。 ### 单节点执行步骤 1. 按部署说明在单节点安装已确认浏览器、Xvfb 和 `creatorhub-browser-gateway.service`。 2. 使用已有、经验证的 PostgreSQL 与凭据配置。不要重新生成现有主密钥;不要把秘密值粘贴到验收报告。 3. 按交付脚本启动单节点 native gateway;在控制面登记真实地址,并核对 `/v1/info` 返回的稳定节点身份。 4. 启动控制面及前端: ```bash # 其余数据库/凭据等必填配置由现有受控环境提供,不在命令行回显秘密。 LISTEN_ADDR=0.0.0.0:8082 go run ./cmd/control-plane # 另一个终端 npm --prefix web run dev -- --host 0.0.0.0 ``` 命令启动后,用 `ip -brief -4 addr` 记录当次实际局域网 IP。用户在另一台设备访问 `http://:5173`;开发者可查看 `http://:8082/healthz`。报告列出单节点 gateway 的实际 Endpoint。 历史观察到的地址不构成可用性证据;实施当天必须重新核实 IP、监听地址和防火墙。 ## 5. 手工功能与清理矩阵 每条记录:操作者、时间、节点、账号/任务/代次、操作、期望、实际、状态、日志/截图/资源清单位置。保留 33 项用例编号;同一用例的重启/升级、协议/认证、节点及恢复场景分别记录子项。必测子项未执行或阻塞时,不能把整个用例标为通过。 ### A. 正常生命周期 | ID | 手工步骤 | 通过条件 | | --- | --- | --- | | A01 | 在 gateway 节点确认 Docker daemon/socket 不参与运行,创建账号环境,选择已安装 native 版本并启动 | 正确 Xvfb/浏览器就绪;未登录时可进入人工登录,不永久停在“正在启动”;无镜像下载、容器、卷或 Docker 浏览器网络操作 | | A02 | 人工完成二维码登录,记录账号、Profile 标识和指纹;先关闭再启动,再停止并从界面普通升级至另一已安装且获准的版本后启动 | 两个子项均保持原 Profile、指纹和登录身份,无意外重新登录;升级后实际浏览器版本等于所选目标版本,不通过重建环境/重新登录冒充保持(AC-E1) | | A03 | 浏览器停止时,从界面启动一次竞品账号采集,等待结束 | 自动创建任务 runtime,结果保存;`T_cleanup` 内进程、display、端口和临时文件释放 | | A04 | 连续采集作品/评论/线索,再打开结果查看 | 数据完整且仍可读;不能因 runtime 清理丢失业务结果或已发布素材 | | A05 | 同节点两个不同账号同时采集 | display、Profile、CDP/代理端口互不冲突;结束一个不影响另一个 | | A06 | 同账号同时发起两个任务;另测人工登录占用该 Profile 时发起采集 | 明确排队或冲突;不出现两个浏览器打开同 Profile,不抢占登录会话 | | A07 | 自有账号保持事件监听,另用采集账号执行并结束任务 | 监听不中断、不串 UID;采集自建资源完全释放 | | A08 | 若批准借入长期 runtime 路径,用对应场景执行任务 | 只删除本任务页面/临时文件/引用;长期 holder 和 runtime 保留,界面如实说明借用 | | A09 | 按下方代理矩阵分别配置四类代理及其支持的认证配置,改变代理或账号绑定后启动采集 | 每个配置下实际浏览器出口、代理版本、指纹时区/语言等正确;身份不符时拒绝动作;不能用单一无认证代理的成功代替其他配置(AC-E3) | | A10 | 仅在用户准备真实接收账号并逐次确认时验证人工回复/私信 | 保持原有确认与身份核对;重复结果不触发重复发送,不确定状态不冒充成功 | A02 验证的是 native 环境内的普通版本升级,不是 Profile 迁移;缺少获准版本时标为阻塞。 代理矩阵适用于 A09/B03:单节点分别列出 HTTP、HTTPS、SOCKS4、SOCKS5,按协议允许的配置验证无认证(如支持)及支持的认证方式;A09 记录成功与实际浏览器出口,B03 记录认证失败(适用时)与网络失败,均不得静默直连或轮换出口。协议本身不支持的认证项说明依据,不作为通过项;缺少测试代理、凭据或尚未实现的承诺能力标为阻塞,不能免测。证据不得包含密码/Cookie。 A10 不能由脚本自动发送,也不能因为只修改 runtime 就免除必要回归;人工逐次确认不能代替 C02/D04 的自动策略验收。 ### B. 全部终态与资源异常 | ID | 手工步骤/经授权的故障注入 | 通过条件 | | --- | --- | --- | | B01 | 任务运行中点击取消 | 业务不永久 running;独立清理继续,`T_cleanup` 内完成或明确待清理 | | B02 | 让测试任务超过已批准最大时长 | 超时可见;lease 释放,任务进程/目录回收,不能继续后台写入 | | B03 | 按代理矩阵逐协议分别制造认证失败(协议支持时)和网络失败;另测无效浏览器路径启动 | 每个适用子项明确失败,无静默直连或出口轮换;已创建的 Xvfb/端口/临时目录逆序回收(AC-E3) | | B04 | 经授权终止该测试 runtime 的浏览器,另测 Xvfb 退出 | 任务失败可见;其余子进程终止;其他 runtime 不受影响 | | B05 | 对测试专用目录制造无法删除条件后结束任务 | 显示“业务结果 + 清理失败”,保留可追溯记录;恢复条件后重试只清资源,不重跑业务 | | B06 | 测试磁盘低于启动阈值;用隔离测试盘验证写满 | 启动前拒绝或运行中明确失败;不删除登录资料/正式素材腾空间;收尾状态可靠 | | B07 | 重复点击取消/停止/清理;再对已结束任务重复操作 | 幂等,不返回虚假的活实例;不会清掉后来启动的新代次 | | B08 | 经授权在 gateway 内已启动、控制面尚未收到回复时中断连接 | 查询同 generation 收敛;没有重复进程、Profile 或资源分配 | | B09 | 长任务超过十分钟,观察续租;让旧执行失去租约后恢复响应 | 当前 holder 继续有效;旧执行不得发布产物、覆盖结果或清理新执行目录 | | B10 | 人为让任务结果保存失败或响应丢失 | 区分确定失败与结果未知;先核对数据库引用,不能误删已发布素材或盲目重试 | ### C. 重启与孤儿恢复 | ID | 步骤 | 通过条件 | | --- | --- | --- | | C01 | 在测试采集运行时,经授权强杀并重启 gateway | 依据 unit+节点+代次核对受管实例;过期任务回收,未过期任务恢复或明确失败;不重复启动 | | C02 | 在已产生自动响应及冷却记录的长期监听账号上,分别重启 gateway、控制面并恢复订阅;按下方恢复子项核对 | 浏览器 Profile 不被删;代理/订阅恢复有证据,失联时间和可能遗漏可见;基线、事件去重记录与原冷却到期时间保留,旧事件不重放,迟到事件不自动补发(AC-A9、AC-B1) | | C03 | 强杀 gateway 后暂不恢复,超过短任务的 unit 最长寿命 | 短任务整组进程退出;临时文件在 runtime 退出或后续核对时回收,不无限占用 | | C04 | 控制面在临时素材下载、音轨提取期间被强杀,再启动 | 控制面处理自己遗留的临时文件;不会要求 gateway 删除控制面路径 | | C05 | 旧素材执行恢复时新执行已完成,触发旧执行发布/清理 | 新正式文件与 DB 引用不变;旧执行只能清理自身未被引用的产物 | | C06 | 经授权重启 gateway 所在测试机器 | 节点身份稳定,旧运行代次不冒充存活;过期短任务不自动重做,登录资料保留;监听恢复或明确提示 | | C07 | 在清理目录旁放置无关文件/符号链接和另一 runtime 记录 | 无关资源不删除;未知归属有明确错误,不能按目录年龄一并清空 | C02/D04 必测恢复子项: - 恢复前记录已处理事件、自动动作结果和 UID 冷却原到期时间;恢复后,同一大号下该 UID 在冷却内产生新互动也不得再次触发自动动作,不因更换小号而绕过。 - 已处理旧事件即使在冷却到期后再次出现,也不能重放;到期后的新事件才可按策略响应,迟到/恢复历史事件默认只记录、不自动补发。无法确认连续性时显示缺口并重新确认边界,不能只以“监听已连接”判通过。 - 保存动作记录及可控接收端证据,确认未发生额外自动动作。真实平台由用户在已授权策略和可控互动/接收账号范围内手工制造互动,观察产品自身自动响应;不向无关用户发送,不用脚本或 Mock 冒充真实平台,也不把自动动作改成人工逐次确认。 - 旧事件重放、到期及迟到等精确边界先由确定性测试证明;真实平台无法复现的子项记为未执行,缺账号/权限/平台能力则记为阻塞,不得用离线检查替代真实证据或将整项标为通过。 C05/B09 的精确竞态先用确定性单元测试证明;真机无法可重复制造时标记该子项未执行,不能用“人工未复现”替代回归测试。测试不得添加面向生产的任意执行接口。 ### D. 多机控制(后续目标,全部未执行) | ID | 步骤 | 通过条件 | | --- | --- | --- | | D01 | 后续目标:两台节点各创建合法唯一环境,分别启动;停止/清理一侧并观察另一侧 | 本目标不执行;保留稳定节点和代数字段,后续目标按契约验收 | | D02 | 后续目标:一台节点失联,另一台正常采集/续租/监听 | 本目标不执行;不得以单节点重启替代跨机证据 | | D03 | 后续目标:带 Profile、运行实例或待清理资源时改变机器归属 | 本目标不执行;不得删除原节点资源 | | D04 | 后续目标:跨节点恢复时旧响应/事件迟到且已有新代次 | 本目标不执行;单节点旧代次保护由 C07 和自动测试覆盖 | | D05 | 后续目标:多节点配置不同出口并按代理矩阵核验 | 本目标不执行;单节点代理适用项在 A09/B03 验收 | | D06 | 后续目标:另一节点未安装账号指定浏览器版本 | 本目标不执行;单节点版本缺失在 A01/B03 验收 | 抖音先完成全部适用用例;小红书按相同生命周期复验。尚未实现的平台能力记为阻塞,不用 Mock、轮询或另一平台成功代替。 ## 6. 磁盘与性能验证 ### 6.1 测量方法 1. 固定机器、浏览器版本、指纹、账号、代理、任务内容、并发和依赖状态;除生命周期方式外尽量保持一致。不要拿不同浏览器或不同网络的结果相减。 2. 冷启动指本次机器/服务启动后的第一次浏览器启动,和后续热启动分开记录;不擅自全机清理 page cache。安装或下载浏览器耗时另列,不混入日常任务启动。 3. 每种方式在并发 1 下至少 20 次有效启动,并在并发 2 下至少 10 组。按相同节奏执行,遵守平台限制。遇验证码/限流单独记录,不删去异常后只展示好看的数值。 4. 时间从用户启动请求被接收到 CDP+代理+账号就绪;另外记录完整任务、终止到资源清理完成耗时。不能只测进程创建或 Xvfb 启动时间。 5. 内存统计整个 runtime 的浏览器子进程、Xvfb、可选桌面,以及 gateway 增量;如有获准的旧基线,旧方案也必须按完整进程树和代理增量的同一口径统计。优先使用 cgroup 峰值或一致口径的 PSS;RSS 合计会重复计算共享页,必须注明。 6. 记录每轮之前、业务结束、清理完成三个时刻:活跃进程/unit、端口、runtime/Profile/日志/素材字节数。使用 `ps`、`ss`、`systemctl show`、`du -sb` 等只读工具;共享内存和 X socket 也须核对。 7. 原生路径连续完成至少 30 个短任务,覆盖取消和失败;再观察一轮长期监听与采集并行。平台受限时可用明确标识的本地测试页面单独测生命周期,但不得拿它替代真实平台功能验收。 建议记录 CSV: ```text mode,node_id,browser_version,concurrency,round,task_id,generation,start_ms,task_ms,cleanup_ms,peak_memory_bytes,tmp_bytes,profile_bytes,log_bytes,material_bytes,result,cleanup_result ``` p50 取中位数;p95 使用排序后第 `ceil(0.95*N)` 个样本并标出 N。至少做两轮实验评估噪声,既报告绝对值也报告比例。 ### 6.2 放行标准 | 项目 | 通过条件 | | --- | --- | | 短任务进程 | 清理完成后,该代次浏览器、Xvfb、桌面及子进程数为 0;合法长期会话单独列出 | | 临时磁盘 | 清理完成后该任务临时目录不存在或为空;重复任务不留下逐轮增长的 runtime/下载/cache/提取临时文件 | | 显示/端口 | 本代次 display/socket/端口释放;不能误删其他合法 X server 的共享目录 | | Profile | 账号身份/登录状态保留;经批准的缓存预算不超标。不宣称持久 Profile 必须字节不变 | | 日志 | 达到已批准保留上限后有界,清理失败诊断可追溯;日志中无 Cookie/密码/验证码 | | 素材 | 正式结果可访问;增长与新增业务结果匹配,不被当垃圾删除 | | 启动与内存 | 达到 P0 批准的具体预算,相比可信旧基线的改善超过重复实验噪声;若没有改善,报告未达到性能目标,不以“取消了 Docker”判通过 | | 故障恢复 | 在批准时间内完成清理或给出明确待处理原因;无永久失管短任务,无跨机误删 | Docker 本身通常不是全部浏览器内存开销的来源;即使启动开销降低,Chromium 的页面和渲染进程仍可能占主要内存。实测不达标就继续定位,不承诺移除 Docker 必然显著省内存。 没有获准运行旧方式、也没有可信旧记录时:原生功能和绝对资源预算可独立验收,**性能改善仍标记“缺基线,未验证”**,不能填写节省百分比。 ## 7. 日志与证据 关键节点应可关联:任务接受、使用权取得/续租、创建意图、unit 启动、显示/CDP/代理/身份就绪、业务提交、停止、删除、待清理、重试和恢复。 每条必要字段:`node_id`、环境/账号内部 ID、`runtime_generation`、任务/执行 token、阶段、耗时、结果、清理 owner 和错误;只记录内部标识,避免平台敏感数据泄漏。 每条失败证据包括: - 节点与任务界面状态,操作时间范围。 - 控制面和对应 gateway 的关联日志。 - runtime unit/进程/端口和目录占用前后对比。 - 业务结果是否提交、清理是否完成、是否需用户介入。 - 重试后能否收敛,以及其他节点/长期账号是否保持正常。 ## 8. 验收记录模板 ```text 提交/日期: 执行者/机器: 用例 ID / 子项(重启或升级、协议/认证/节点、恢复场景): 前置条件及授权: 操作步骤: 预期: 实际: 状态:未执行 / 通过 / 失败 / 阻塞 证据位置: 资源差异: 遗留问题/复测结果: ``` 最终签收分别列出:代码检查、单机生命周期、短任务清理、持久登录、长期监听、多机故障、素材归属、磁盘稳定性、性能对比、各平台真实能力。只有记录充分的项目才勾选通过;失败修复后复测,真正缺少用户授权/账号/机器/发行物时明确标为阻塞。