a3bb78e06b
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 16m35s
141 lines
4.3 KiB
Markdown
141 lines
4.3 KiB
Markdown
# AI 合同平台 V2 Phase 3 Slice 3.1 合同版本表实施记录
|
||
|
||
日期:2026-06-30
|
||
|
||
## 本次范围
|
||
|
||
本次按 Phase 3 schema 硬化设计评审的 Slice 3.1 实施 `contract_versions`。
|
||
|
||
已完成:
|
||
|
||
- 新增 Contract API Alembic migration:`20260630_0019_add_contract_versions.py`。
|
||
- 新增 SQLAlchemy model:`ContractVersionModel`。
|
||
- Runtime schema check 核心表清单加入 `contract_versions`。
|
||
- 合同创建时写入初始版本。
|
||
- 合同正文更新时写入新版本。
|
||
- 条款推荐/一键修订应用后写入新版本。
|
||
- `/api/v1/contracts/{contract_id}/versions` 改为读取真实版本表。
|
||
- `/api/v1/contracts/{contract_id}/versions/version-current-{contract_id}` 保留当前版本别名兼容。
|
||
- `contracts.body_content` 继续保留为兼容缓存,没有删除旧字段。
|
||
- 补充合同版本历史和租户隔离测试。
|
||
|
||
未做:
|
||
|
||
- 未删除 `contracts.body_content`。
|
||
- 未进入审批模型、风险项结构化、资产发布快照等后续 Phase 3 slice。
|
||
|
||
## 数据模型
|
||
|
||
新增表:`contract_versions`
|
||
|
||
核心字段:
|
||
|
||
- `id`
|
||
- `tenant_id`
|
||
- `contract_id`
|
||
- `version_no`
|
||
- `version_label`
|
||
- `body_content`
|
||
- `body_hash`
|
||
- `source_type`
|
||
- `source_id`
|
||
- `created_by`
|
||
- `change_summary`
|
||
- `metadata`
|
||
- `created_at`
|
||
- `published_at`
|
||
|
||
核心约束:
|
||
|
||
- `tenant_id + contract_id + version_no` 唯一。
|
||
- `tenant_id + contract_id + created_at` 索引。
|
||
- `contract_id + version_no` 索引。
|
||
- `source_type + source_id` 索引。
|
||
|
||
## 兼容策略
|
||
|
||
本次仍保持 `contracts.body_content` 作为当前正文缓存:
|
||
|
||
- 详情接口继续返回 `ContractDetail.body_content`。
|
||
- 前端合同详情、编辑、版本对比无需改 API path。
|
||
- 版本列表返回真实历史版本。
|
||
- 旧的 `version-current-{contract_id}` 仍作为当前正文别名保留。
|
||
|
||
## 验证结果
|
||
|
||
已通过:
|
||
|
||
```powershell
|
||
python -m compileall -q yuqei-contract-platform/services/contract-api/src/yuqei_contract_api
|
||
python -m compileall -q yuqei-contract-platform/services/contract-api/migrations
|
||
python -m pytest yuqei-contract-platform/services/contract-api/tests/test_contract_workflow.py::test_contract_versions_endpoint_returns_current_persisted_body yuqei-contract-platform/services/contract-api/tests/test_tenant_isolation.py::test_tenant_isolation_contract_versions -q
|
||
python -m pytest yuqei-contract-platform/services/contract-api/tests -q
|
||
```
|
||
|
||
Alembic head 检查:
|
||
|
||
```text
|
||
20260630_0019
|
||
```
|
||
|
||
本地临时 SQLite 空库迁移到 head 已通过,并确认 `contract_versions` 表存在。
|
||
|
||
权威 V2 smoke PostgreSQL / Docker 环境验收已通过:
|
||
|
||
```powershell
|
||
$env:SSHPASS='<remote-root-password>'
|
||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File yuqei-infra\scripts\deploy-v2-smoke-docker.ps1 -UseSshpass -AllowDirtyWorktree -KeepRemoteBackup -SkipSmoke
|
||
```
|
||
|
||
部署结果:
|
||
|
||
- 远端环境:`192.168.3.90:/opt/apps/ai-contract-platform-v2-smoke`
|
||
- Compose project:`yuqei-contract-v2-smoke`
|
||
- 部署产物:`project-docs/qa-artifacts/v2-smoke-docker-deploy/2026-06-30T12-26-13`
|
||
- 脚本结果:`V2_SMOKE_DOCKER_DEPLOY_PASS`
|
||
- Contract API:`http://192.168.3.90:18100` healthy
|
||
- Contract Web:`http://192.168.3.90:13000` healthy
|
||
- AI Platform API:`http://192.168.3.90:18101` healthy
|
||
|
||
Runtime schema check 抽样:
|
||
|
||
```text
|
||
status=ok
|
||
database=yuqei_contract
|
||
backend=PostgreSQL
|
||
actual=20260630_0019
|
||
expected_head=20260630_0019
|
||
core_tables checked_count=17
|
||
```
|
||
|
||
远端 PostgreSQL 抽样:
|
||
|
||
```text
|
||
contract_api_alembic_version = 20260630_0019
|
||
contract_versions exists = true
|
||
contract_versions total = 12007
|
||
smoke contract versions:
|
||
smoke-phase3 | contract-d4854c4bd1ec | 1 | v1 | contract_create
|
||
smoke-phase3 | contract-d4854c4bd1ec | 2 | v2 | contract_update
|
||
```
|
||
|
||
版本 API 抽样:
|
||
|
||
```text
|
||
POST /api/v1/contracts
|
||
PATCH /api/v1/contracts/{contract_id}
|
||
GET /api/v1/contracts/{contract_id}/versions
|
||
GET /api/v1/contracts/{contract_id}/versions/version-current-{contract_id}
|
||
|
||
contract_id=contract-d4854c4bd1ec
|
||
version_total=2
|
||
latest version=v2
|
||
initial version=v1
|
||
latest body matches patched body=true
|
||
current alias body matches patched body=true
|
||
```
|
||
|
||
## 下一步
|
||
|
||
Slice 3.1 已完成本地和权威 V2 smoke PostgreSQL 验收。建议下一步进入 Phase 3 Slice 3.2:正式审批模型 `approval_instances` / `approval_steps` / `approval_actions` 的设计确认与第一片迁移实现。
|