Files
codex-app-server/verification/resident-audit-summary.md
host 6525bcafd0 audit: resident website loop architecture and code quality to 10/10
Fix F1 name race with partial unique index, F2 pause/end mid-poll race with guarded updates, F3 redirect/numeric-IP SSRF, F4 quota prefix check, F5 duplicate row_get, F6 audit ternary; S1 unused import, S2 backoff doc, S3 defensive tearDown. Directed 20 pass, full 1700 pass.
2026-11-01 19:58:03 +00:00

11 KiB
Raw Permalink Blame History

常驻监听网站闭环:独立架构与代码质量审核报告

审核员非实现者。审核对象:网站闭环 worktree ~/workspace/codex-app-server-resident-website-loop,分支 feat-resident-website-loop,头 23725f9(父 561b389,基底 网站版 0722ca3,origin/main 622c51e)。本审核在独立 worktree ~/workspace/codex-app-server-resident-audit(新分支 feat-resident-website-loop-audit,从 23725f9 起)上做,闭环 worktree、resident-task worktree、泛化 worktree、主 checkout (feat-repo-picker)一律未动。

0. 评分标准(先定标准,再打分)

只评架构与代码质量两项,满分各 10 分。控制台 UI、真实外网、 生产 PG、双进程抢单实测、其它探针是其它维度/后续项,本轮不做, 也不用它们冒充或无故扣这两项的分;但若某项确实卡住架构或代码 质量本身,列为 blocker,不擅自定。

架构 10 分标准

  • A1 分层干净:resident 模块自有状态机,与任务状态机、自动化 定义层互不干扰;server 只做路由/权限/审计,worker 只做驱动 边界调用;无循环依赖。
  • A2 状态机可推理:running/paused/ended、暂停保现场、恢复续跑、 结束终态 409、失败退避、配额暂停不结束的语义在所有路径一致, 且并发下不被竞态破坏(认领、改名、暂停/结束中途轮询)。
  • A3 驱动与认领正确:服务端不起定时器是明说的,实际驱动在 worker 轮次边界;claim 条件 UPDATE 是防重复的唯一关口;崩后 不锁死。
  • A4 快照/变化语义干净:轮询廉价、仅变化建任务、首次只建基线、 每次轮询可查;变化摘录与游标推进在同一事务边界内。
  • A5 安全边界在正确层:URL 校验、超时、1MB 截断、SSRF 防护不 只在创建时校验一次,抓取路径(包括重定向)也要守住;v1 的 DNS 解析后校验缺口必须明说,不得假装已解决。
  • A6 可扩展结构:网站是本轮唯一用例,但快照/抓取与状态机/认领 不应缠成一团;未来加探针时状态机与驱动骨架不应重写(本轮 不实现其它探针,只审结构)。

代码质量 10 分标准

  • Q1 命名、函数长度与复杂度可读;长函数(run_due)分支清晰, 不靠注释掩盖逻辑。
  • Q2 无重复、无死代码、无测试值渗入生产代码;复用已有口径 (自动化 claim/配额/审计、环境名唯一索引先例)而不是另起一套。
  • Q3 错误处理诚实:失败、配额耗尽、配额检查失败三条路不混淆; 审计与轮询记录不静默丢失;异常不炸驱动循环。
  • Q4 测试可读、可隔离、可复现:本地 HTTP/DNS/no_proxy 等测试 手段干净还原、无环境泄漏;断言指向行为而非实现细节摆设。
  • Q5 静态检查:居民差分内 ruff E、F 干净(仓库惯用 % 格式、 宽泛 except 等不在仓库门禁内的规则不计入;基底已有的 E、F 不计入本轮)。

1. 改动前分数

  • 架构:9.0 / 10
  • 代码质量:9.0 / 10

基底是好的:分层、状态机、claim、配额复用、轮询可查、测试 隔离(DNS/no_proxy 在 loop 测试里干净还原)都属实,定向 15 项 基线全过(见第 4 节)。扣分只来自下面逐项 findings,不是整体 推倒重来。

2. Findings 清单(改动前)

严重

  • F1 名称唯一性是先查后插、无数据库约束:create_watch / update_watch 先 SELECT 查重再 INSERT/UPDATE,两个并发请求 可同时通过检查、插出同项目同名 running 监听;server 的 environments 已有先例:CREATE UNIQUE INDEX … WHERE status != 'archived'。本轮用同款部分唯一索引 WHERE status != 'ended'(已结束名可重用)+ 完整性错误转 ValueError 修复。
  • F2 暂停/结束与进行中轮询竞态:run_due 认领后只读一次状态, 之后若用户暂停/结束,失败/基线/未变化/配额/变化分支的 UPDATE 均不带状态条件,会把 paused/ended 行的 next_poll_at 改回 未来值、并可能在用户已结束之后仍建出变化任务。修复:认领后 复查状态;全部终局 UPDATE 带 status='running' 条件,条件 不满足时回滚、不建任务、不记轮询。

一般

  • F3 抓取路径 SSRF 只守了创建时:default_fetch 用默认 opener, 重定向目标不校验,公开 URL 重定向到内网地址可绕过创建校验; 另 localhost.、单整数/十六进制/前导零等非规范 IP 写法可绕过 字面 IP 检查。修复:重定向处理器逐跳校验(相对跳转先 urljoin 再校验);校验时归一化主机(去尾点、*.localhost 挡掉)并拒绝 非规范数字 IP 写法。DNS 解析后校验仍属 v1 缺口,继续列为已知 偏差,不假装已解决。
  • F4 配额门判定靠子串:\"quota_check_failed\" not in gate 把 配额门返回文本当协议用,超限文本一旦含该子串即误判。配额门 的真实契约是前缀(quota_check_failed: / quota_exceeded: / None),修复为 startswith 判定,并补 changed_quota_check_failed 的定向测试(该分支此前无测试)。
  • F5 row_get 重复造轮:resident 自带与 automations.row_get 逐字 同语义的 row_get,却已从 automations 导入另外两个函数。修复: 直接导入 automations.row_get,删本地定义。
  • F6 server 审计动作名嵌套三元:_resident_transition 里 \"ended\" if … else action + \"d\" if … else \"resumed\" 可读性差, 且改动时易错。修复为显式动作映射字典,审计字符串不变。

建议

  • S1 test_resident.py 导入了未用的 time(ruff F401,居民差分 内唯一 E、F 问题)。删除。
  • S2 退避文档与代码不一致:_backoff_seconds 文档写“30、60、 120……秒”,代码实际下次轮询是 now + interval + backoff。 行为本身合理(不比间隔更频繁),文档误导。修复文档,行为不动。
  • S3 loop 测试 tearDown 不够防御:setUp 中途失败时 tearDown 访问未建属性会掩盖原始失败。修复为 getattr 防御。

已核查、不是问题(不扣分)

  • 审计行“写在 commit 之后会丢”:核查 _auto_audit_row 本身 执行 INSERT 后自己 commit,失败/配额暂停/变化三处审计行在 模拟关闭连接后仍可查,不是缺陷。
  • server/worker 全量 ruff E、F 的其余项(如 worker.py:2781/2787 的 F821、server.py:10293 的 E501)经核对均为基底已有或由居民 插入导致的行号位移,非居民新增代码,不计入本轮。
  • 仓库默认 ruff 全规则的 39 项(如 UP031 % 格式)与仓库惯用 写法冲突,不在仓库门禁内,不计入。

3. 修复(全部关闭,每项有对应测试或定向复核)

  • F1 名称唯一性:ensure_resident_tables 新增部分唯一索引 idx_resident_watches_name ON resident_watches(project_id, name) WHERE status != 'ended'(server environments 同款口径); create/update 的 INSERT/UPDATE 包完整性错误转 ValueError (sqlite3.IntegrityError / PostgresIntegrityError,调用方仍 返回 400)。测试:索引存在断言、绕过查重直接插报 IntegrityError、改名撞名报 ValueError。
  • F2 暂停/结束中途轮询:认领后复查状态(非 running 直接返回 None,不改行);新增 _guarded_watch_update,失败/基线/ 未变化/配额检查失败/变化推进游标的终局 UPDATE 全部带 status='running' 条件,条件不满足时回滚、不建任务、不记 轮询;变化分支先受保护推进游标、再建任务。测试:抓取回调 里经第二连接暂停监听,run_due 返回 None、无任务、游标与 next_poll_at 保持暂停态、轮询数不变。
  • F3 抓取路径 SSRF:新增 _SafeRedirectHandler,重定向逐跳 urljoin 后复用 validate_target_url,不合格抛 ValueError 不跟随;default_fetch 改走 build_opener(默认处理器含 ProxyHandler,no_proxy 行为与 urlopen 同款);校验归一化 主机(去尾点、挡 .localhost)并新增 _is_noncanonical_ numeric_host 拒绝单整数/十六进制/前导零八进制等非规范 数字 IP 写法。测试:localhost.、.localhost、2130706433、 0x7f000001、0177.0.0.1、0x7f.0.0.1 均报 ValueError,规范 公网 IP 与带尾点域名仍放行;相对重定向跟随、私有绝对重 定向报 ValueError(DNS 映射测试主机,同 loop 测试口径)。
  • F4 配额门判定:\"quota_check_failed\" not in gate 改为 gate.startswith(\"quota_check_failed\"),与配额门前缀契约 对齐。测试:注入返回 quota_check_failed: boom 的配额门, 变化轮询记 changed_quota_check_failed、状态仍 running、 游标不动、失败数 1、下次 = now + 间隔 + 30、无任务。
  • F5 row_get 重复:删 resident 本地定义,直接导入 automations.row_get,内部调用点一字未动,模块依赖说明 同步更新。
  • F6 server 审计动作名:嵌套三元改为显式映射字典 {pause: paused, resume: resumed, end: ended},审计字符串 不变,服务端测试的审计断言仍过。
  • S1 删 test_resident.py 未用 time 导入;S2 _backoff_seconds 文档改为“退避增量,下次 = now + 间隔 + backoff”,行为不动; S3 loop 测试 tearDown 改为 getattr 防御,setUp 中途失败不 再掩盖原始失败。

4. 测试数字(全部本轮实测,无删断言、无 skip、无改默认值)

  • 定向基线(改动前):cloud.tests.test_resident + test_resident_server + test_resident_website_loop = 15 项全过。
  • 定向改动后:同三文件 = 20 项全过(基线 15 + 新增 5:URL 变体、唯一索引、配额检查失败、中途暂停、重定向),4.450 秒; ruff E、F 在居民差分 4 文件上全部通过。
  • 全量(CI 同款三条 discover,改动后、报告提交前跑出,之后 无任何代码或文案改动):顶层 tests 105 项全过;cloud/tests 1551 项全过、9 跳过(384.252 秒);deploy/tests 44 项全过 (单独重跑确认);合计 1700 项、0 失败、9 跳过。对账:闭环 基线 1695(105 + 1546 + 44)+ 新增 5 = 1700,无测试丢失、 无新失败。
  • 覆盖率:本仓库 CI 无覆盖率门禁,不虚构覆盖率变化;新增 5 项定向测试即上述全量的一部分。

5. 复评分数

  • 架构:10 / 10
  • 代码质量:10 / 10

复评依据:F1/F2 两项严重 findings 已由数据库约束与状态条件 UPDATE 从机制上关闭(非仅文档说明),并有定向测试锁定; F3 安全边界已从“创建时一次校验”补到“抓取重定向逐跳校验” 与非规范 IP 写法;F4/F5/F6/S1/S2/S3 全部关闭且测试全过。 剩余的已知偏差(控制台 UI、全文 hash 抖动、DNS 解析后 SSRF、 真实外网/生产 PG/双进程抢单未验)属其它维度/后续项,已在 第 6 节单独列出,不计入本轮两项分数,也不被用来冒充已完成。

6. 剩余 blocker 与未做事项

  • 未做:未 push、未合并、未跑 deploy.py、未部署;不做其它探针、 不接控制台 UI、不做生产 PG 与双进程抢单实测。
  • 已知偏差(其它维度,不计入本轮两项分数):控制台 UI 未接; 变化判定为全文 hash、无选择器提取,动态页面抖动可误报; SSRF v1 不做 DNS 解析后校验;真实外网、生产 PG、双进程抢单 未验。