跳到主要内容

编程验收

AI 改完代码能上线吗:按风险审查权限、测试与数据恢复

从实际 diff 开始,按风险检查权限、数据恢复与失败场景;加入本站分类链接遮挡的真实修复、16场景复测和离线对照材料,附发布记录模板。

编写: AI Codex · 更新 · 14 分钟 · 内容方法与 AI 辅助说明

AI 改完代码后,是否能上线要看改动范围、关键失败场景和恢复路径的证据。构建成功、页面能打开、AI 自己说“已完成”,都不能单独作出这个判断。 先按影响选检查,再把未验证项明确留在发布记录里。

本文面向已有项目的发布前审查,原审查资料复核日期为 2026-10-10;下方本站定位缺陷案例记录于 2026-11-06。权限和数据库示例是本站编写的教学场景,不是发现于读者项目的漏洞,也不是工具实测报告。如何给 AI 写首次任务,见 第一次让 AI 改代码;这里从交付后的改动开始。

先确认审查的是哪个版本

先读仓库的发布说明,记录目标环境、当前线上版本、拟发布代码与配置。工作区有别人尚未完成的修改时,不要为了得到“干净状态”而重置或提交它们;先明确哪些属于本次交付。

下面几条命令只查看本地状态,适合普通 Git 工作区:

git status --short
git diff --stat
git diff
git diff --cached --stat
git diff --cached

按 Git 官方 diff 文档,普通 git diff 比较工作区与暂存区,--cached 查看暂存区相对提交的变化。因此只看其中一份会漏改动。未跟踪文件需要按 status 列表另读;分支上已经提交的修改,还要与确认过的基准提交比较。测试记录应对应最终准备发布的版本,测试后又修改关键路径就要重新验证受影响部分。

读 diff 时,把每个文件归到需求、测试、依赖、配置或迁移。额外依赖、锁文件大改、关闭检查、删除测试、改权限或新增环境变量,都要有与本次目标对应的解释。不要因为文件由 AI 生成,就跳过它。

按影响选择检查深度

下表是工作分配建议,不是全项目安全认证。Google 的代码审查指南 强调设计、用户行为、边界和并发问题;这里把这些原则转成发布前可记录的对象。

改动范围 至少检查什么 需要升级审查的信号
文案、间距、静态导航 目标页面、手机显示、链接和键盘操作 实际改到了提交逻辑或权限
表单、接口、后台任务 正常、无效输入、失败、超时和重复处理 数据落库或外部动作无法撤回
身份、权限、缓存隔离 服务端授权、不同账号与资源的访问边界 只隐藏按钮,或只测管理员
数据库与部署配置 新旧版本兼容、数据核对、恢复步骤 删列、默认值覆盖旧数据、缺少恢复证据

低影响改动用针对性的检查即可,不必为改一行文案堆出一套镜像测试。涉及权限或数据时,则不能用截图替代行为证据。同一改动跨多行时,按影响更大的那行决定审查深度。

示例一:按钮隐藏了,接口仍能删别人的记录

假设需求是“成员只能删除自己创建的草稿”。AI 在前端根据创建者隐藏删除按钮;管理员的正常操作也通过了。这两项都不足以证明服务端落实了规则。

在自有测试环境准备账号 A、账号 B、各自的草稿,以及一个按产品规则不允许删除的已发布对象。使用测试数据和项目测试客户端,不在真实用户数据上试删。

请求者与对象 期望结果 应保留的证据
A 删除 A 的草稿 允许且只影响该对象 响应、对象状态、审计记录
A 直接请求删除 B 的草稿 拒绝且对象不变 服务端拒绝及前后状态
B 访问或修改 A 的对象 按权限规则拒绝 对象、账号和动作的对应记录
未登录请求删除 拒绝且无副作用 身份检查结果与数据状态
A 删除不允许删除的已发布对象 按业务规则拒绝 状态规则与记录未变

允许请求返回的具体状态码由接口约定决定;拒绝可能采用 403 或隐藏对象存在性的 404。验收重点是权限与副作用,不是背某一个状态码。

OWASP 授权指南 要求默认拒绝,并对每次请求检查具体对象或功能的权限。随机 ID、客户端校验和按钮可见性不能代替这个检查。还要检查同一数据的列表、导出、后台任务和缓存路径,避免一个入口正确、另一个入口泄露。

如果这里只能访问前端仓库,应记录“服务端权限未验证”,保留发布阻碍,不能把前端测试标成整个功能通过。

示例二:改字段后,回退代码不等于恢复数据

假设把文章的 published 布尔字段改成 status。直接新增默认 draft 的字段再删除旧字段,可能让历史已发布文章变成草稿;即使新代码能启动,也不代表迁移正确。旧代码还可能依赖已被删除的列。

Prisma 的扩展与收缩说明 展示了分阶段引入新结构、迁移数据和客户端、最后移除旧结构的思路。这里采用这一审查思路,不提供可直接用于生产库的 SQL;锁表、事务和回填方式需按实际数据库决定。

阶段 发布前需要回答的问题 阻断信号
扩展 加新字段后,旧应用还能读写吗? 新约束使旧写入失败
回填 旧值如何映射?空值如何处理? 把所有历史行直接设为同一默认值
并行运行 回填期间的新写入由谁同步? 只复制一次,之后两列持续分歧
切换读取 新路径与旧路径的业务结果一致吗? 行数相同但发布状态不同
收缩 旧客户端和任务是否全部退出? 回退版本仍读取将删除的字段

用脱敏的代表性数据在隔离环境演练,比较状态分布、关键对象、空值和新旧路径,而不只比较总行数。遇到部分失败,记录哪些阶段已完成以及如何继续,不能盲目把整个迁移重复执行。

恢复方案也要分开写:代码可以回到哪个版本;数据可以恢复到什么时点;备份之后的新写入如何保留或补偿;恢复由谁执行。备份文件存在不等于恢复成功,应该有可用性验证和恢复演练证据。已经丢失且没有备份的数据,不会因为 Git 回退而回来。

测试通过后,还要读测试到底断言了什么

先运行项目要求的检查,再针对改动补关键场景。类型检查说明类型约束是否满足,构建说明产物能否生成,行为测试说明特定条件下的结果;它们不能互相代替。

看似绿色的结果 需要追加的审查
权限测试通过 是否只测了自己的对象或管理员?
迁移测试通过 是否只有空库,没有历史行和并行写入?
新增测试全部通过 是否把真实接口替换成总返回成功的模拟对象?
原来的失败消失 是否删除断言、跳过测试或放宽了预期?
UI 截图正常 键盘、手机、加载失败和禁用状态是否正确?

能安全复现的缺陷,应证明关键检查在旧行为下会失败、修复后通过。必要时用单独的测试副本,不要为复现去破坏工作区或生产状态。已有基线故障与本次新增故障分开记录;“环境不具备”仍然是未运行,不是通过。

让另一位审查者或 AI 帮忙读 diff 可以增加发现问题的机会,但其结论应指出具体路径、触发条件和证据。多份“看起来没问题”不能替代一个确实执行过的负例。

本站真实案例:筛选正确,旧分类链接仍被导航遮挡

2026-11-06,我们在本站提示词库的发布前检查中发现 PL-QA-01:旧分类链接选中了正确分类,但分类按钮和结果起点被固定导航遮挡。这属于上表的低影响界面改动,需要针对定位的浏览器检查;它不降低权限、数据迁移等高风险改动的审查要求。此处记录真实项目缺陷与修复,没有比较模型或提示词,不能用来证明某个提示词提升了效果。

先自己复现遮挡,再看修复

打开离线定位对照页,也可保存 HTML后用浏览器打开。它只有 HTML/CSS,无脚本、无外部资源、无表单,不需要 Key 或剪贴板。它重现的是滚动遮挡机制,不包含本站筛选逻辑,也不是原始测试页面。

  1. 点击顶部“失败 / Before”。分类按钮会滚到页面顶部,被固定导航盖住;向上滚动一点,能找到刚才被盖住的按钮。
  2. 点击“修复 / After”。目标按钮留出 100px 滚动间距,应完整位于导航下方。两种状态的差别是分类按钮有没有对应的 scroll-margin-top。
  3. 把视口缩窄到 390×844,再分别点击两个入口。以按钮和首张卡片是否可见判断,不以 URL 的 hash 是否变化判断。示例没有运行自动判定;如果观察不同,请记录浏览器、视口和实际现象。

若在自己的项目复测完整路径,先准备独立测试副本:直接打开带分类 hash 的新页面;再输入一个无匹配结果的查询,通过页内链接或地址栏只改变 hash,确认没有刷新成新文档。等待滚动稳定,检查查询是否清空、分类与数量是否正确,以及分类按钮和首卡是否都在导航下方。已修复的本站线上页面不用于展示旧失败,不需要回退生产。

原因与最小修复

旧实现只给模板卡片 .prompt 设置滚动留白,分类 hash 的实际目标却是带 data-library-filter 的按钮。筛选断言因此仍可通过,但定位可见性失败。修复只将已有 100px 留白应用到分类按钮,没有修改筛选逻辑、模板正文或复制控制器。

修复前:

#prompt-library .prompt {
  scroll-margin-top: 100px;
}

修复后:

#prompt-library .prompt,
#prompt-library [data-library-filter] {
  scroll-margin-top: 100px;
}

这是项目真实差异的格式化摘录。CSS 滚动规范说明 scroll-margin 可用于调整滚动定位区域。100px 是本站当前布局沿用的数值,不是所有网站通用的导航高度;换字体、缩放或导航布局后应重新检查。

旧候选的桌面直接加载 #writing 时,结果为正确的 3 条,但按钮顶部约 −0.02px、底部 43.98px,导航底部 73px,整个按钮被盖住;首卡顶部 65.98px,也有约 7px 被挡。旧候选还记录了残留搜索切换 #image、#agent 的同类失败;没有旧版完整16场景逐项失败表,不能写成“修复前16项全失败”。

16个场景实际复测了什么

历史复测:16 个场景全部通过,桌面与模拟手机各 8 个。 2026-11-06,独立测试在 macOS 的 Chromium 中,对四个分类分别检查了两种入口:直接打开分类链接,以及无匹配搜索后切换分类链接。每个场景的查询都已清空,活动分类和结果条数符合预期。

  • 桌面 1200×800:8/8。 导航底部为 73px,分类按钮范围为 99.98–143.98px,首卡从 165.98px 开始。
  • 模拟手机 390×844:8/8。 导航底部为 65px,分类按钮范围为 100.20–144.20px,首卡从 217.20px 开始。

两个视口里,按钮完整位于导航下方,首卡起点可见,页面没有横向溢出。这些是滚动位置稳定超过 350ms 后记录的 CSS 像素,保留两位小数。可查看完整 16 场景脱敏记录(JSON),逐项核对入口、分类、条数和坐标。这些历史数据来自本站候选版本,不是上方简化对照页的输出。

修复后的源码与前一候选比较,仅这一条 CSS 选择器改变,其余353个源文件逐字节相同。独立复测重新构建,并检查上述16项及代表性首屏、模板定位;前一候选的类型检查、28项测试和站点审计沿用已有结果,没有把它们说成在本次重新执行。当天发布后的同组16项定位检查也通过;发布检查与候选复测是不同证据。

结果和未覆盖项分开写

本案例说明:筛选结果正确,不等于读者到达了可见的阅读位置。 对此类改动,把“目标和内容都出现在固定导航下方”写成独立验收条件即可,不需要引入新测试平台。

本轮手机是视口模拟,未测实体手机、Safari、屏幕阅读器或全部缩放组合。16项定位检查不证明整个站点无缺陷,也不证明提示词质量、用户增长或商业效果。

用发布记录作出通过或阻断决定

下载 中英文发布验收记录模板。它是待填写的工作表,不含预先勾选的通过项。每项写检查对象、命令或操作、环境、实际结果、证据位置和未验证边界,不把密钥或真实用户数据放进去。

上线前至少能回答:

  1. 本次交付解决哪个行为,哪些文件与配置属于发布范围?
  2. 最重要的禁止行为是否被阻止,失败是否会留下错误数据或重复动作?
  3. 必需检查是否在最终版本运行?未运行项的原因是否影响发布?
  4. 线上配置和权限是否具备,回退代码与恢复数据分别怎么做?
  5. 发布后检查哪些 URL、关键路径和异常指标,由谁负责发现问题并停止扩大影响?

可阻断条件包括跨账号访问未验证、迁移会覆盖未知历史值、关键失败路径没有证据、恢复方案与当前数据结构不兼容。不要把这些项改名为“后续优化”来换取通过。小范围发布也需要明确暴露范围和停止条件,不意味着风险自动消失。

如果改动包含 AI 输出入库,继续使用 结构化输出验收;包含超时重发和外部动作时,核对 重试与业务幂等。本文的表格是建议执行的审查,不代表已替你的项目执行这些检查。

继续解决下一个问题