Files
ai-contract-platform/project-docs/V2-P1-04.1-reviewable-playbook-fallback-versions-2026-08-23.md
T
yuqei 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
feat: deliver governed contract platform and async AI tasks
2026-08-26 12:53:47 +08:00

165 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# V2 P1-04.1 可审阅 Playbook 兜底合同新版本实施与 UAT 报告
日期:2026-08-23
状态:已完成,隔离 UAT 通过。
## 1. 目标与验收结论
P1-04.1 的目标是把企业 Playbook 兜底从“直接修改正文”升级为“生成候选版本、审阅差异、明确采用”,确保系统不会在用户没有确认的情况下静默覆盖当前合同正文。
验收结论:通过。
- 一键生成的是独立候选版本,不会修改 `contracts.body_content`。
- 候选版本自动打开原文/新文差异审阅界面。
- “确认采用为当前正文”默认禁用,用户必须勾选明确确认。
- 采用请求必须同时携带 `confirmed=true` 和已审阅的候选正文 SHA-256。
- 当前正文、合同状态或候选摘要发生变化时,系统停止采用并转人工处理。
- 采用成功后原正文仍保留为历史版本,可继续查看、比较和取证。
## 2. 两阶段状态机
```text
审查快照命中规则
|
v
生成候选版本 candidate --------> 当前合同正文保持不变
|
| 用户打开差异、勾选确认、提交候选哈希
v
显式采用 adopted --------------> 候选正文成为当前正文
|
+------------------------> 原正文继续保留在版本历史
任一状态/正文/哈希冲突 --------> conflict + 审计证据 + 人工接管
```
兼容既有数据:历史 `succeeded` 执行记录继续按已采用处理,不要求回写迁移。
## 3. 产品与交互改造
### 3.1 生成候选
- 原“应用企业兜底文本”按钮改为“生成可审阅新版本”。
- 一次点击完成规则快照校验、候选正文生成、候选版本落库和审计记录。
- 生成成功后立即展示红绿差异,并明确提示“当前正文尚未修改”。
- 关闭差异对话框后,页面显示“候选版本待审阅 / 原正文未修改”。
### 3.2 明确采用
- 差异对话框同时显示原正文和候选版本的删除/新增内容。
- 采用按钮默认禁用;只有勾选“我已审阅原正文与候选版本差异”后才可点击。
- 用户可选择“暂不采用”,候选版本保留,当前正文不变。
- 采用后显示“兜底版本已采用”,下一步引导为“重新发起审查验证企业兜底文本”。
### 3.3 版本历史
- 候选未采用时标记“候选待审阅”。
- 采用后标记“已确认采用”。
- 版本列表保留原版本与候选版本,可分别查看正文并与当前版本比较。
- 候选生成或采用后,版本面板通过页面事件立即刷新,无需用户手动刷新页面。
## 4. 后端安全边界
### 4.1 生成阶段
- 锁定当前租户的合同记录。
- 校验审查任务成功、快照 ID、快照摘要、规则版本和来源正文哈希。
- 校验合同处于 `draft`、`reviewing` 或 `rejected`。
- 生成 `playbook_fallback_candidate` 版本与执行台账,不更新当前合同正文。
- 写入 `playbook_fallback_candidate_created` 审计事件,记录原文与候选正文哈希。
### 4.2 采用阶段
- 新接口:`POST /api/v1/contracts/{contract_id}/playbook-fallbacks/{execution_id}/adopt`。
- 仅具备合同编辑权限的账号可以调用。
- 请求必须提交 64 位候选正文 SHA-256 和字面值为 `true` 的确认字段。
- 在数据库事务中锁定合同和候选执行记录。
- 再次校验租户、合同状态、当前正文哈希、候选版本来源和候选正文哈希。
- 全部通过后才更新当前正文,并把候选版本标记为已采用。
- 写入 `playbook_fallback_adopted` 审计事件和采用人、采用时间。
### 4.3 冲突与幂等
- 候选生成使用租户级幂等键,重复请求不会重复创建版本。
- 已采用候选再次提交采用请求时安全重放,不重复修改正文。
- 候选生成后如果有人编辑了当前正文,采用操作返回 `conflict`,当前正文保持编辑后的内容。
- 冲突记录包含 `requires_manual_handoff=true`、当前正文哈希和期望正文哈希。
- 文件审查仍保持只读,不自动改写原始附件。
## 5. 隔离 UAT 证据
### 5.1 环境与账号
- 租户:`uat-playbook-20260823`(Playbook 隔离 UAT)。
- 法务/租户管理员:`uat.legal.20260823@example.test`。
- 独立审批人:`uat.approver.20260823@example.test`。
- 两个账号为独立用户,报告不记录密码。
### 5.2 验收对象
- 合同:`contract-a9323e1ded7f`。
- 标题:`UAT P1-04.1 可审阅兜底版本合同`。
- 审查任务:`review-045068122a21`。
- 快照:`playbook-snapshot-045068122a21`。
- 快照摘要:`4b66f02e671ecfbdb7fd42784aa1db2ad4020ca4654e8998530be10c0f273a4e`。
- 执行记录:`playbook-fallback-c3c35c792911`。
- 候选版本:`version-970c07ed14bd`。
- 最终执行状态:`adopted`。
### 5.3 Chrome 可视化验收
1. 法务账号创建包含“承担全部且无限责任”的合同并完成 AI 审查。
2. 页面命中租户规则 `UAT 禁止无限责任`,聚合快照显示 1 条可用兜底。
3. 点击“生成可审阅新版本”后自动打开差异对话框:
- 原无限责任表述显示为删除内容;
- 企业兜底文本显示为新增内容;
- 页面明确显示“当前正文尚未修改”;
- 确认采用按钮默认禁用。
4. 关闭差异对话框后,正文预览仍显示原无限责任表述,证明候选生成没有覆盖正文。
5. 切换独立审批账号:
- 可以查看候选待审阅状态和版本证据;
- 看不到生成、审阅、采用或编辑按钮。
6. 切回法务账号,打开候选差异并勾选确认,随后采用:
- 当前正文切换为企业兜底文本;
- 页面显示“兜底版本已采用”;
- 下一步提示为重新发起审查。
7. 版本面板显示版本 1 和版本 2:
- 版本 2 标记“已确认采用”;
- 打开版本 1 仍能完整看到原无限责任正文。
## 6. 主要实现位置
- 状态与请求模型:`yuqei-contract-platform/services/contract-api/src/yuqei_contract_api/enterprise_playbook.py`
- 候选生成与采用事务:`yuqei-contract-platform/services/contract-api/src/yuqei_contract_api/sqlalchemy_playbook_fallback_orchestration.py`
- API 路由:`yuqei-contract-platform/services/contract-api/src/yuqei_contract_api/api/review.py`
- 数据模型:`yuqei-contract-platform/services/contract-api/src/yuqei_contract_api/persistence/models.py`
- 数据库迁移:`yuqei-contract-platform/services/contract-api/migrations/versions/20260823_0052_add_playbook_candidate_adoption.py`
- 前端差异与确认:`yuqei-contract-platform/apps/contract-web/src/app/contracts/[id]/apply-playbook-fallback-button.tsx`
- 版本证据展示:`yuqei-contract-platform/apps/contract-web/src/app/contracts/[id]/contract-version-panel.tsx`
- Web 采用代理:`yuqei-contract-platform/apps/contract-web/src/app/api/contract-platform/contracts/[id]/playbook-fallbacks/[executionId]/adopt/route.ts`
- OpenAPI:`yuqei-contract-platform/packages/contract-openapi/openapi.yaml`
## 7. 自动化、迁移与构建
- 后端核心回归:98 项通过。
- 新增断言覆盖:候选生成不改正文、未确认请求拒绝、候选采用、采用幂等、租户隔离、审批人无编辑权限、生成前漂移冲突、生成后漂移冲突。
- 前端测试:全部通过。
- TypeScript 类型检查:通过。
- Python `compileall`:通过。
- OpenAPI YAML 解析:通过。
- Next.js 生产构建:通过,114 个页面路由完成构建。
- PostgreSQL 迁移:`20260823_0052 (head)`。
- 全新 SQLite 数据库从 0 到 `0052` 完整迁移:通过。
非阻断告警:测试环境仍有 Starlette `TestClient` 上游弃用提示,以及 Windows `.pytest_cache` 已存在导致的缓存写入提示,不影响测试结果和产品功能。
## 8. 当前运行状态与下一步
- 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` 的采用后验收页面。
建议后续进入 P1-04.2:支持一次审阅多个规则候选、逐条勾选或跳过、组合差异预览,以及候选版本主动撤销;仍应保持“未经明确确认不更新当前正文”的发布门槛。