1d85329a6a
Build and Test Quality Gate / Contract Web typecheck and build (pull_request) Successful in 9m12s
Build and Test Quality Gate / Isolated Alibaba and Tencent KMS gateway (pull_request) Failing after 4m53s
Build and Test Quality Gate / Python tests and Contract API migration (pull_request) Failing after 24m55s
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 8m42s
9.7 KiB
9.7 KiB
V2 P1-04.2 多规则 Playbook 组合候选实施与隔离 UAT 报告
日期:2026-08-23
状态:已完成,自动化、迁移、生产构建和双账号 Chrome UAT 均通过。
1. 目标与结论
本轮把 P1-04.1 的“单条规则候选版本”扩展为“一个审查快照内的多规则组合候选”,支持:
- 对每条有兜底文本的规则逐条选择“采用”或“跳过”。
- 跳过时强制填写原因,形成可追溯业务决定。
- 将所有采用项按快照优先级顺序合并为一个候选合同版本。
- 在同一个差异界面审阅组合正文和逐条决定。
- 主动撤销候选版本,再调整选择重新生成。
- 未经明确确认不更新当前正文;撤销、冲突均不覆盖当前正文。
验收结论:通过,可进入受控企业试点。
2. 产品状态机与业务规则
审查成功 + 多条规则有兜底文本
|
v
逐条决定 apply / skip(skip 必须有原因)
|
v
生成组合候选 candidate --------> 当前正文不变
| |
| +--------> withdrawn,当前正文不变,可重新生成
|
+-----------------------> conflict,停止采用并保留证据
|
| 审阅组合差异 + 勾选确认 + 候选 SHA-256
v
adopted ------------------------> 候选正文成为当前正文
原正文、撤销候选和逐条决定继续保留
核心约束:
- 请求必须覆盖快照中全部可用兜底规则,不能遗漏,也不能提交快照外规则。
- 至少采用一条规则;全部跳过不生成无意义候选版本。
- 跳过原因至少 2 个字符,并写入候选台账、审查命中结果和审计证据。
- 同一快照同一时刻最多保留一个待审阅候选;采用或撤销后才能重新生成。
- 合并顺序使用不可变快照中的规则优先级,不读取后来变化的在线规则。
- 生成和采用阶段均校验租户、合同状态、快照摘要、来源正文哈希、候选正文哈希和候选版本来源。
- 文件审查继续保持只读取证,不能自动改写上传附件。
3. 后端实施
3.1 领域模型与数据表
新增组合候选请求、逐条决定、候选项、候选聚合和撤销请求模型。新增 playbook_combined_candidates 表,保存:
- 租户、合同、审查任务、快照 ID 和快照摘要;
candidate / adopted / withdrawn / conflict状态;- 原正文和候选正文 SHA-256;
- 候选合同版本 ID;
- 已采用规则、跳过规则及原因、逐条替换次数与每步正文哈希;
- 创建、采用、撤销的人员与时间;
- 租户级幂等键和安全元数据。
数据库迁移为 20260823_0053,已在现有 PostgreSQL 和全新 SQLite 数据库从 0 到 head 验证。
3.2 事务与安全边界
- 生成时锁定合同,验证成功审查、快照摘要、正文漂移和候选唯一性。
- 禁用条款按快照记录的命中表述精确替换;其他规则按企业兜底区块追加。
- 只新增候选合同版本,不更新
contracts.body_content。 - 采用时再次锁定合同和候选,验证显式确认、候选哈希、版本来源和当前正文漂移。
- 采用成功后一次性更新当前正文、版本生命周期和审查规则命中状态。
- 撤销只更新候选与版本生命周期,不删除版本、不修改当前正文。
- 组合候选读写全部按租户隔离;审批人等只读角色可以查看,但不能生成、撤销或采用。
3.3 API 与审计
新增接口:
GET /api/v1/contracts/{contract_id}/playbook-candidatesPOST /api/v1/contracts/{contract_id}/playbook-candidatesPOST /api/v1/contracts/{contract_id}/playbook-candidates/{candidate_id}/adoptPOST /api/v1/contracts/{contract_id}/playbook-candidates/{candidate_id}/withdraw
新增审计事件:
playbook_combined_candidate_createdplaybook_combined_candidate_adoptedplaybook_combined_candidate_withdrawnplaybook_combined_candidate_conflict
OpenAPI 已补齐全部路径、请求、响应和审计枚举,引用完整性检查为 0 个缺失引用。
4. 前端实施
- 合同详情页在同一审查快照下展示“组合候选决策”。
- 每条规则都有独立采用/跳过选择;选择跳过后即时显示原因输入框。
- 缺少跳过原因或没有任何采用项时,生成按钮保持禁用。
- 生成成功后自动打开组合差异,顶部明确显示采用数、跳过数和“当前正文尚未修改”。
- 差异下方再次展示逐条决定,避免用户只看正文而忽略跳过项。
- 确认采用按钮默认禁用,必须勾选“已审阅组合差异与逐条决定”。
- 待审阅候选可填写撤销原因并撤销;撤销后保留历史版本并恢复逐条选择界面。
- 只读审批人可打开差异,但不会渲染生成、撤销、确认或采用控件。
- 版本面板新增组合候选生命周期标签:候选待审阅、已确认采用、已撤销、冲突已停止。
- P1-04.1 历史单规则候选继续按原流程显示,不要求迁移或重做。
5. 隔离 Chrome UAT 证据
5.1 环境与对象
- 租户:
uat-playbook-20260823(Playbook 隔离 UAT) - 法务/租户管理员:
uat.legal.20260823@example.test - 独立审批人:
uat.approver.20260823@example.test - 合同:
contract-a9323e1ded7f - 审查任务:
review-c347f26a88e0 - 快照:
playbook-snapshot-c347f26a88e0 - 快照摘要:
b885f2c7008c793e022e0ba80a0f34580bd81a1a4cf931f665082c45ab265035 - 规则一:
approval-rule-711b817a3ac4,UAT 禁止默认转委托,v1 - 规则二:
approval-rule-a09af1c22f5e,UAT 禁止双重争议路径,v1
5.2 首个候选:采用一条、跳过一条、撤销
- 候选:
playbook-candidate-2388b453492b - 版本:
version-256c0b9be4c6,版本号 3 - 决定:采用规则一;跳过规则二。
- 跳过原因:
等待业务确认争议解决路径 - 组合差异只展示规则一的替换,逐条决定同时展示一条采用和一条跳过。
- 生成后正文预览仍显示原文,证明没有静默覆盖。
- 撤销原因:
UAT 验证逐条选择后重新组合 - 最终状态:候选
withdrawn,版本标签“已撤销”,当前正文仍不变。
5.3 第二个候选:采用两条、跨角色审阅、明确采用
- 候选:
playbook-candidate-d85b0bc88b37 - 版本:
version-84cec7225d4c,版本号 4 - 决定:两条规则均采用,每条精确替换 1 次。
- 审批人账号可以打开组合差异并看到两条采用决定,但没有编辑、撤销、确认勾选或采用按钮。
- 法务账号打开同一候选,勾选明确确认后采用。
- 最终状态:候选
adopted,版本标签“已确认采用”。 - 当前正文包含两条企业兜底文本,不再包含两条原禁用表述。
- 版本历史同时保留版本 1、P1-04.1 的版本 2、已撤销版本 3 和已采用版本 4。
- 合同审计记录完整包含两次创建、一次撤销和一次采用事件。
5.4 失败恢复附带验证
UAT 首次发起新审查时,常驻 Review Worker 尚未重启加载最新审计事件类型,读取上一阶段的候选采用审计后退出。任务被明确标记失败,随后通过页面“重新排队”恢复并成功完成,retry_count=1。这同时验证了既有 P0-07 失败重试链路。
发布要求:包含审计事件类型或领域模型变更时,Contract API 与 Review Worker 必须作为同一发布单元滚动重启,不能只热更新 Web/API 源码。
6. 自动化、契约、迁移与构建结果
- 后端核心回归:99 项通过。
- 新增覆盖:多规则采用/跳过、跳过原因、候选不改正文、主动撤销、重新生成、显式确认、采用、版本生命周期、跨租户 404、审批人写操作 403。
- 前端测试:37 项通过。
- TypeScript
tsc --noEmit:通过。 - Python
compileall:通过。 - OpenAPI YAML 解析与
$ref完整性:通过,64 条路径、97 个 schema、0 个缺失引用。 - PostgreSQL:
20260823_0053 (head)。 - 全新 SQLite:从 0 到
20260823_0053完整迁移通过。 - Next.js 生产构建:通过,114 个页面路由完成构建。
git diff --check:通过;仅存在仓库既有的 Windows 行尾转换提示。
非阻断告警:测试环境仍有 Starlette TestClient 上游弃用提示,以及 Windows .pytest_cache 已存在导致的缓存写入提示,不影响测试结果或运行功能。
7. 当前运行状态
- Web:
http://127.0.0.1:3000,监听中。 - Contract API:
http://127.0.0.1:8100,启用 Web 代理鉴权,监听中。 - AI API:
http://127.0.0.1:8101,监听中。 - Review Worker:运行中。
- Chrome:保留在法务账号的合同
contract-a9323e1ded7f采用后验收页。
8. 已知限制与 P1-04.3 建议
- 精确片段替换会原样保留命中片段前后的标点;如果规则管理员在兜底文本中重复填写句号,组合结果可能出现连续标点。下一步应在规则发布前增加“样本文本试替换”和标点边界预警,但不应在采用阶段静默改写法务配置文本。
- 当前差异采用逐行展示,长段落内的多个短替换仍会显示整行变化。下一步可增加段内词级高亮,同时继续保留完整正文哈希取证。
- 当前组合候选以一个审查快照为边界。下一步可增加规则依赖/互斥校验、合并冲突矩阵和管理员规则发布前 dry-run。
- 建议把“API 与 Worker 同版本重启”“0053 迁移完成”“99 项后端回归”“双角色只读/编辑隔离”纳入 P1-04.2 发布门禁。
建议下一阶段进入 P1-04.3:规则发布前样本文本试运行、标点和上下文边界预警、规则依赖/互斥关系、组合冲突解释与词级差异高亮。