a3bb78e06b
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 16m35s
257 lines
9.8 KiB
Markdown
257 lines
9.8 KiB
Markdown
# AI 合同平台 V2 Phase 3 Slice 3.4 UI 展示字段派生设计评审
|
||
|
||
## 背景
|
||
|
||
本次继续对齐《AI 合同平台 V2 下一阶段开发优化方案》和 Phase 3 schema 硬化设计评审。
|
||
|
||
Slice 3.1 已完成 `contract_versions`。
|
||
Slice 3.2 已完成正式审批模型。
|
||
Slice 3.3 已完成治理字段和软删除,并已在权威 V2 smoke PostgreSQL/Docker 环境验证到 Alembic head `20260630_0021`。
|
||
|
||
Slice 3.4 的目标不是新增业务页面,也不是立即删除数据库字段,而是把 `status_label`、`status_tone`、`next_action`、`next_actions` 这类 UI 展示字段逐步从事实表中迁出,转为 domain/serializer 派生。
|
||
|
||
## 当前问题
|
||
|
||
`contracts` 表仍保存以下 UI 展示字段:
|
||
|
||
- `status_label`
|
||
- `status_tone`
|
||
- `next_action`
|
||
- `next_actions`
|
||
|
||
这些字段目前还被以下路径使用:
|
||
|
||
- 合同列表和合同详情响应。
|
||
- 工作台待办卡片。
|
||
- dashboard 状态统计标签。
|
||
- 统一搜索文档的 `status_label`、`summary` 和 `search_text`。
|
||
- 审批、审查、文件上传、条款修复等状态流副作用。
|
||
- 前端 TypeScript service 和 OpenAPI schema 兼容字段。
|
||
|
||
直接删除字段风险较高,因为前端和搜索仍需要这些响应字段。
|
||
|
||
## 设计原则
|
||
|
||
1. 不在 Slice 3.4 第一片删除数据库列。
|
||
2. 不改变现有 API 响应字段名。
|
||
3. 不改变前端读取字段方式。
|
||
4. 先把派生规则集中到 domain/serializer 层。
|
||
5. 旧字段暂时保留为兼容缓存,用于灰度和回滚。
|
||
6. 当数据库缓存值与派生值不一致时,响应层优先使用派生值,并记录 warning。
|
||
7. `status_label` 和 `status_tone` 可以直接从 `status` 强派生。
|
||
8. `next_action` 和 `next_actions` 需要分阶段迁出,因为当前它们既包含状态默认动作,也包含少量合同上下文提示。
|
||
|
||
## 第一片实现边界
|
||
|
||
新增 `contract_display.py`,集中维护:
|
||
|
||
- `ContractDisplayFields`
|
||
- `CONTRACT_DISPLAY_BY_STATUS`
|
||
- `derive_contract_display`
|
||
- `status_label_for_status`
|
||
- `status_tone_for_status`
|
||
|
||
第一片 read-switch:
|
||
|
||
- 合同列表响应:`status_label`、`status_tone` 优先派生。
|
||
- 合同详情响应:`status_label`、`status_tone` 优先派生。
|
||
- 合同详情响应:`next_action`、`next_actions` 对已知旧状态默认文案做派生修正。
|
||
- 统一搜索文档:合同类文档的 `status_label`、`summary`、`search_text` 使用派生结果。
|
||
- in-memory dashboard:状态标签从 `status` 派生。
|
||
|
||
第一片暂不做:
|
||
|
||
- 不删除 `contracts.status_label` 等旧列。
|
||
- 不移除写路径中的旧字段写入。
|
||
- 不修改 OpenAPI 字段。
|
||
- 不修改前端字段名。
|
||
- 不把所有合同特定 `next_action` 强制覆盖成状态默认值。
|
||
|
||
## next_action 分阶段策略
|
||
|
||
`next_action` 当前有两类含义:
|
||
|
||
1. 状态默认动作,例如“审批人处理”“修改后重新提交”“准备签署与归档”。
|
||
2. 业务上下文提示,例如“法务确认付款和验收条款”“补充租赁期限后提交”“跟踪履约节点”。
|
||
|
||
第一片只覆盖明显属于旧状态默认文案、且与当前 `status` 不一致的缓存值。
|
||
|
||
后续要把 `next_action` 完全派生,需要先从结构化事实中提取上下文:
|
||
|
||
- 审批实例和待办步骤。
|
||
- 最新审查任务状态。
|
||
- 未完成义务任务。
|
||
- 条款修复动作。
|
||
- 合同版本/草稿编辑状态。
|
||
|
||
## 验收标准
|
||
|
||
第一片验收:
|
||
|
||
- 当数据库中 `status_label/status_tone` 与 `status` 不一致时,合同列表和详情响应返回派生值。
|
||
- 当数据库中 `next_action/next_actions` 是已知旧状态默认文案且与当前 `status` 不一致时,合同详情响应返回派生默认动作。
|
||
- 合同搜索文档重建后使用派生的 `status_label`。
|
||
- 现有合同工作流测试继续通过。
|
||
|
||
后续完整验收:
|
||
|
||
- 合同列表、详情、搜索、工作台展示不依赖手工维护 UI 文案。
|
||
- 数据库字段表达业务事实,UI 文案集中在代码映射层。
|
||
- PostgreSQL smoke 环境中搜索重建、合同列表、详情、workspace 抽样均通过。
|
||
|
||
## 回滚策略
|
||
|
||
第一片只新增集中派生层并切换响应读取,不删除旧列。
|
||
|
||
如出现前端展示异常,可以回滚 mapper/search 对 `derive_contract_display` 的调用,数据库旧字段仍可继续支撑响应。
|
||
|
||
## 后续拆分建议
|
||
|
||
1. 权威 V2 smoke PostgreSQL 环境复跑合同列表、详情、搜索、workspace、runtime schema-check 抽样。
|
||
2. 稳定后再评审是否进入 cleanup migration,删除或降级旧 UI 缓存列。
|
||
|
||
## 第二片实施记录
|
||
|
||
本次已实现 `ContractActionContext`,将 `next_action` 和 `next_actions` 从“状态默认 + 旧缓存兼容”推进到“状态 + 结构化上下文”派生。
|
||
|
||
新增上下文来源:
|
||
|
||
- 最新审查任务状态:`queued`、`running`、`succeeded`、`failed`。
|
||
- 审查风险项是否存在未处理风险。
|
||
- 审查风险项是否已有 `repair_status=applied` 的条款修复记录。
|
||
- 正式审批模型中的 pending approval instance/step。
|
||
- 未完成履约任务的首个待处理节点。
|
||
|
||
派生优先级:
|
||
|
||
1. 已应用条款修复:提示“复核已应用的条款修订”。
|
||
2. 审查任务排队或运行中:提示“等待法律审查结果”。
|
||
3. 审查失败:提示“重新发起法律审查”。
|
||
4. 审查完成且存在未处理风险:提示“处理审查风险并应用推荐条款”。
|
||
5. 审查完成且存在风险但无需条款修复:提示“根据审查结果修改或提交审批”。
|
||
6. 正式审批待办:提示“等待审批人审批”。
|
||
7. 已审批、已签署、已归档阶段存在未完成履约任务:提示具体履约节点。
|
||
8. 否则回落到 `status` 默认动作。
|
||
|
||
接入范围:
|
||
|
||
- SQLAlchemy 合同列表响应。
|
||
- SQLAlchemy 合同详情响应。
|
||
- 工作台待办响应。
|
||
- 统一搜索文档同步/重建。
|
||
- transition 写路径的即时响应。
|
||
|
||
仍未做:
|
||
|
||
- 未删除 `contracts.status_label/status_tone/next_action/next_actions` 旧列。
|
||
- 未移除旧写路径对 UI 缓存字段的写入。
|
||
- 未修改 OpenAPI 和前端字段名。
|
||
- 未把合同版本/草稿编辑状态纳入 `ContractActionContext`。
|
||
|
||
验证:
|
||
|
||
```powershell
|
||
python -m compileall -q yuqei-contract-platform\services\contract-api\src\yuqei_contract_api
|
||
python -m pytest yuqei-contract-platform\services\contract-api\tests -q
|
||
```
|
||
|
||
结果:完整 Contract API 测试通过。
|
||
|
||
## 远端 PostgreSQL / Docker smoke 验证记录
|
||
|
||
验证环境:
|
||
|
||
- 服务器:`192.168.3.90`
|
||
- Compose project:`yuqei-contract-v2-smoke`
|
||
- Contract API:`http://192.168.3.90:18100`
|
||
- PostgreSQL 数据库:`yuqei_contract`
|
||
- 部署 artifact:`project-docs/qa-artifacts/v2-smoke-docker-deploy/2026-06-30T16-40-34`
|
||
|
||
执行命令:
|
||
|
||
```powershell
|
||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File yuqei-infra\scripts\deploy-v2-smoke-docker.ps1 -UseSshpass -AllowDirtyWorktree -KeepRemoteBackup
|
||
```
|
||
|
||
结果:
|
||
|
||
- Docker smoke:通过。
|
||
- Web、Contract API、AI Platform API health endpoints:通过。
|
||
- AI golden sample asset gate:通过,90 samples、6 suites、16 checks。
|
||
- Remote database baseline:`yuqei_contract`、`yuqei_ai`、`yuqei_ops` 均存在。
|
||
- Contract review worker smoke:通过。
|
||
|
||
`/api/v1/runtime/schema-check` 抽样结果:
|
||
|
||
- 顶层状态:`warning`。
|
||
- `database_backend`:`ok`,PostgreSQL。
|
||
- `database_name`:`ok`,当前数据库为 `yuqei_contract`。
|
||
- `alembic_version`:`ok`,actual/head 均为 `20260630_0021`。
|
||
- `core_tables`:`ok`,检查 20 张核心表。
|
||
- `governance_columns`:`ok`,检查 11 张表、36 个治理字段。
|
||
- `postgres_extensions`:`ok`,已安装 `pg_trgm`。
|
||
- `display_cache_consistency`:`warning`,检查 12010 条未软删除合同记录,发现 8000 条旧 UI 缓存字段与派生值不一致。
|
||
|
||
样例:
|
||
|
||
```text
|
||
perf-contract-000001:status_tone
|
||
perf-contract-000004:status_label
|
||
perf-contract-000005:status_tone
|
||
perf-contract-000006:status_label,status_tone
|
||
perf-contract-000007:status_tone
|
||
```
|
||
|
||
处理说明:
|
||
|
||
- 本片只做只读检查,不自动修复旧缓存。
|
||
- 本片不删除 `contracts.status_label/status_tone/next_action/next_actions` 旧列。
|
||
- 为避免报告型 `warning` 误伤容器健康状态,Contract API Docker healthcheck 已调整为只在 schema-check 顶层状态为 `error` 时失败;`warning` 继续保留在 runtime schema-check 报告中供后续治理。
|
||
|
||
## 第三片实施记录
|
||
|
||
本次已将 display cache consistency 纳入 Contract API runtime schema-check。
|
||
|
||
新增检查项:
|
||
|
||
- `display_cache_consistency`
|
||
|
||
检查范围:
|
||
|
||
- 只读扫描 `contracts` 表中未软删除记录。
|
||
- 对比旧缓存字段与 `derive_contract_display` 派生值:
|
||
- `status_label`
|
||
- `status_tone`
|
||
- `next_action`
|
||
- `next_actions`
|
||
|
||
返回策略:
|
||
|
||
- 全部一致:`status=ok`。
|
||
- 存在不一致:`status=warning`,不自动修复。
|
||
- `contracts` 表缺失:`status=warning` 并标记 skipped,由 `core_tables` 继续负责报 `error`。
|
||
|
||
返回 details:
|
||
|
||
- `checked_rows`
|
||
- `mismatch_count`
|
||
- `sample_limit`
|
||
- `samples`:最多 5 条,格式为 `contract_id:field1,field2`。
|
||
|
||
本片仍不做:
|
||
|
||
- 不写库。
|
||
- 不修复旧缓存。
|
||
- 不删除旧列。
|
||
- 不改变 OpenAPI 和前端字段。
|
||
|
||
验证:
|
||
|
||
```powershell
|
||
python -m compileall -q yuqei-contract-platform\services\contract-api\src\yuqei_contract_api
|
||
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_health.py::test_runtime_schema_check_warns_for_local_sqlite_auto_created_schema yuqei-contract-platform\services\contract-api\tests\test_health.py::test_runtime_schema_check_errors_for_missing_core_tables yuqei-contract-platform\services\contract-api\tests\test_health.py::test_runtime_schema_check_warns_for_stale_contract_display_cache -q
|
||
python -m pytest yuqei-contract-platform\services\contract-api\tests -q
|
||
```
|
||
|
||
结果:完整 Contract API 测试通过。
|