Files
ai-contract-platform/project-docs/V2-database-code-refactor-decision-2026-06-28.md
T
yuqei a3bb78e06b
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 16m35s
release: freeze V2 release candidate
2026-07-12 15:32:24 +08:00

339 lines
13 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.
# AI 合同平台 V2 数据库与代码重构决策
日期:2026-06-28
## 结论
当前 V2 的总体方向是正确的:代码已经拆成合同平台、AI 中台、基础设施三块,文档和 compose 也已经把数据库目标收口为 `yuqei_contract`、`yuqei_ai`、`yuqei_ops` 三库。
但当前落地状态还没有达到“最佳长期方案”的要求,主要问题不是功能是否能跑,而是环境权威性、数据库边界、代码模块边界和模型长期可维护性还不够清晰。继续新增业务功能前,应该先做一轮非破坏性的治理和重构准备。
本轮不建议删除任何数据库,也不建议继续临时新建数据库。下一步应该先确定唯一权威 V2 环境,再迁移、验证、归档临时库。
## 已核验的当前状态
### 文档目标状态
V2 数据库最终边界:
| 数据库 | 归属 | 主要内容 | 连接变量 |
| --- | --- | --- | --- |
| `yuqei_contract` | `yuqei-contract-platform` | 合同、审批、附件元数据、审查任务业务结果、合同事件、模板/条款/规则管理 | `CONTRACT_API_DATABASE_URL` |
| `yuqei_ai` | `yuqei-ai-platform` | 模型配置、Prompt、知识库、RAG、向量、AI Trace、质量评测、配置执行 | `AI_PLATFORM_DATABASE_URL`、`YUQEI_WORKER_DATABASE_URL` |
| `yuqei_ops` | `yuqei-infra` | 发布记录、备份记录、运行审计、监控扩展预留 | 后续运维服务独立配置 |
这比 V1 的单库模型更合理。V1 中合同业务、AI、知识库、商业化、治理、发票、审批等全部堆在 `ai_contract_platform` 这类单体库里,不适合作为 V2 长期生产模型。
### 远端 192.168.3.90 当前状态
只读检查结果显示:
| 位置 | 数据库/环境 | 状态判断 |
| --- | --- | --- |
| 宿主机 PostgreSQL `5432` | `ai_contract_platform` | 旧版/历史单体库,47 张表,迁移头为 `20260619_0045`,有 `generated_contracts`,没有 V2 `contracts` |
| 宿主机 PostgreSQL `5432` | `yuqei_contract` | 临时 V2 合同测试库,12 张表,迁移头为 `20260628_0017`,有 `contracts` 和 `legal_change_impact_scans` |
| 宿主机 PostgreSQL `5432` | `yuqei_ai` | 不存在 |
| 宿主机 PostgreSQL `5432` | `yuqei_ops` | 不存在 |
| Docker smoke | `yuqei-contract-v2-smoke-*` | 容器和卷存在,但当前停止;Postgres 映射端口为 `15432`,卷为 `yuqei-contract-v2-smoke_postgres-data` |
因此不能把宿主机 `5432/yuqei_contract` 直接认定为完整 V2 数据库。它只是合同平台部分测试库,缺少 V2 目标中的 `yuqei_ai` 和 `yuqei_ops`。
## 当前设计问题
### 1. 数据库环境权威性不清
现在同时存在:
- V1/旧单体库:`ai_contract_platform`
- 临时 V2 合同测试库:`yuqei_contract`
- 停止状态的 V2 Docker smoke 环境
风险是开发者不知道本地/测试/准生产应该连哪一个库,后续迁移可能打到错误环境。最危险的不是“多了一个库”,而是没有一个明确登记表说明每个库的身份、用途、负责人、迁移头和是否允许写入。
### 2. 三库目标没有在宿主机 5432 上完整落地
宿主机只看到 `yuqei_contract`,没有 `yuqei_ai`、`yuqei_ops`。这说明如果当前本地后端连的是宿主机 5432,它只验证了合同 API 的一部分,没有验证 AI 中台和 worker 的真实 PostgreSQL 数据边界。
### 3. 本地 Contract API 示例仍默认 SQLite
`yuqei-contract-platform/services/contract-api/.env.example` 和 README 仍把 SQLite 放在默认示例里。SQLite 可以保留用于轻量单测,但对 V2 当前阶段来说,开发联调和验收应该默认指向 PostgreSQL,否则很容易出现“本地能跑,PostgreSQL 才暴露问题”的情况。
### 4. 健康检查不足以证明数据库结构正确
当前健康接口更多检查配置和后端类型,不足以证明:
- 连接的是不是预期数据库名。
- Alembic version 是否等于当前 head。
- 核心表是否存在。
- PostgreSQL 扩展 `pg_trgm`、`vector` 是否就绪。
这也是之前容易误判“后端已启动但模板/法律资产数据为空”的原因。
### 5. 合同平台代码模块过大
当前核心文件规模:
- `yuqei_contract_api/contracts.py`:约 7300 行。
- `yuqei_contract_api/main.py`:约 1500 行。
`contracts.py` 同时承载 Pydantic schema、SQLAlchemy model、内存仓储、SQLAlchemy 仓储、demo seed、模板生命周期、法律资产生命周期、文件、审批、审计、备份、权限、通知等多个领域。
这已经不适合继续叠功能。短期能跑,长期会让迁移、测试、审查和性能优化变慢。
### 6. AI 平台仓储也过于集中
当前核心文件规模:
- `yuqei_ai_platform_api/repository.py`:约 6100 行。
- `yuqei_ai_platform_api/main.py`:约 1200 行。
AI 平台已经有知识库、Prompt、Provider、AI Trace、质量闭环、worker runtime、pgvector 检索等能力,但仓储层仍集中在一个大文件里。继续扩展法规库、黄金样本、质量评测和运营后台时,应拆成独立领域模块。
### 7. 部分数据库模型仍偏 MVP
合同库仍有一些不适合长期作为事实字段的列:
- `status_label`
- `status_tone`
- `next_action`
- `next_actions`
这些更适合由 API serializer/BFF/前端根据状态和角色推导。数据库应保存事实状态,例如 `lifecycle_status`、`review_status`、`approval_status`、`signing_status`、`archive_status`。
`review_tasks.risk_items`、`citations`、`primary_sources`、法律影响扫描 payload 等 JSON 字段可以作为快照,但高频筛选、统计、排序和权限判断字段应逐步结构化。
### 8. 合同生命周期表还不完整
V2 已经补了模板、条款、规则、审查推荐、法律影响扫描等功能,但合同生命周期的长期模型还没有完全稳定:
- 缺少正式 `contract_versions` 表承载正文版本。
- 审批仍主要依赖 timeline,缺少 `approval_instances`、`approval_steps`、`approval_actions`。
- 合同正文仍在 `contracts.body_content`,后续应迁到版本表或对象存储快照。
- 软删除、创建人、更新人、部门、组织等字段还没有在全部核心表统一。
### 9. 安全与数据治理仍需硬化
需要继续补齐:
- PostgreSQL RLS 或至少数据库层租户隔离策略。
- 合同库与 AI 库使用不同账号和最小权限。
- Provider/OCR/API key 入库加密或改由密钥服务托管。
- 审计事件 append-only 约束和篡改检测。
- AI Trace 脱敏、保留周期、归档策略。
## 推荐的目标方案
### 数据库权威方案
推荐将 V2 数据库环境分成三类,避免混用:
| 环境 | 目的 | 推荐状态 |
| --- | --- | --- |
| 本地单测 | 快速单元测试 | 可继续 SQLite/fake repository,但只覆盖纯逻辑 |
| 本地/远端联调 | Codex 浏览器和开发调试 | 必须 PostgreSQL,连接明确登记的 V2 dev/smoke 三库 |
| 准生产 smoke | 发布前验收 | 使用 Docker smoke 环境或正式 staging PostgreSQL,必须同时存在 `yuqei_contract`、`yuqei_ai`、`yuqei_ops` |
当前最稳妥的选择:
1. 先把 `yuqei-contract-v2-smoke` Docker 环境启动并只读核验其三库状态。
2. 如果 smoke 卷中三库和迁移历史完整,将它登记为当前 V2 准生产 smoke 权威环境。
3. 宿主机 `5432/yuqei_contract` 标记为“临时合同测试库”,不要继续作为权威环境扩展。
4. `ai_contract_platform` 标记为“V1/旧单体历史库”,只读保留,用于资产映射和行为对照。
5. 若后续决定不用 Docker smoke,而改用宿主机 5432 作为正式 V2 dev/staging,则必须一次性补齐 `yuqei_contract`、`yuqei_ai`、`yuqei_ops` 三库和独立账号,再把 smoke 作为可重建环境。
### 代码重构目标结构
Contract API 建议拆分为:
```text
yuqei_contract_api/
api/
contracts.py
files.py
review_tasks.py
templates.py
legal_assets.py
legal_fulltext.py
approvals.py
audit.py
admin.py
domain/
contracts.py
review.py
templates.py
legal_assets.py
approvals.py
persistence/
models.py
session.py
repositories/
contracts.py
files.py
review_tasks.py
templates.py
legal_assets.py
audit.py
services/
contract_lifecycle.py
template_lifecycle.py
clause_recommendation.py
legal_change_impact.py
audit_integrity.py
seed/
demo_data.py
```
AI Platform 建议拆分为:
```text
yuqei_ai_platform_api/
api/
providers.py
prompts.py
knowledge.py
ai_runs.py
quality.py
workers.py
domain/
providers.py
prompts.py
knowledge.py
ai_runs.py
quality.py
persistence/
models.py
session.py
repositories/
providers.py
prompts.py
knowledge.py
ai_runs.py
quality.py
workers.py
services/
retrieval.py
trace.py
quality_gate.py
ingestion.py
```
拆分原则:
- API 层只负责路由、鉴权、参数和响应。
- service 层负责业务编排。
- repository 层只负责数据库读写。
- domain/schema 层不依赖 FastAPI。
- migration 只从 persistence models 或明确 migration 脚本演进,不从大杂烩文件隐式生成。
## 重构执行顺序
### Phase A:数据库环境治理
目标:先消除“连错库”的风险。
任务:
1. 新增 V2 数据库环境登记表,记录每个库的用途、连接入口、迁移头、是否权威、是否允许写入。
2. 新增只读检查脚本,能输出远端 DB 清单、表数量、Alembic head、核心表存在性。
3. 启动并核验 Docker smoke 环境,确认 `15432` 下是否存在 `yuqei_contract`、`yuqei_ai`、`yuqei_ops`。
4. 决定权威开发/准生产库。
5. 本地后端只连接权威 V2 PostgreSQL,不再用临时 SQLite 作为功能验收依据。
验收标准:
- 文档中明确唯一 V2 dev/smoke 权威库。
- `ai_contract_platform` 标记为旧库,不再作为 V2 写入目标。
- 临时 `5432/yuqei_contract` 有归属说明,未确认前不继续扩展。
- 健康/检查脚本能显示当前连接数据库名和迁移头。
### Phase B:运行时安全检查
目标:应用启动和健康检查能发现错误数据库。
任务:
1. Contract API 增加 `/api/v1/runtime/schema-check`。
2. AI Platform API 增加 `/api/v1/runtime/schema-check`。
3. 检查项包括数据库名、Alembic version、核心表、PostgreSQL 扩展。
4. staging/production 环境禁止 SQLite,禁止 auto create,禁止 demo seed。
验收标准:
- 连接旧 `ai_contract_platform` 时 schema check 必须报错。
- 连接缺表或迁移头落后的库时 schema check 必须报错。
- Docker smoke 健康检查从“服务 alive”升级为“服务 alive + schema ready”。
### Phase C:代码模块化拆分
目标:先拆结构,不改接口行为。
任务:
1. 将 `contracts.py` 中 SQLAlchemy model 移到 `persistence/models.py`。
2. 将 Contract API repository 按合同、文件、审查、模板、法律资产、审计拆分。
3. 将路由从 `main.py` 拆到 `api/*`,由 `create_app` 注册。
4. 将 AI Platform repository 按 Provider、Prompt、Knowledge、AI Run、Quality、Worker 拆分。
5. 保持现有 API path、响应结构和测试不变。
验收标准:
- 拆分后功能测试全通过。
- 单文件不再继续承载多个领域。
- 新增功能只能落到对应领域模块,不再向大文件继续堆。
### Phase D:数据库模型硬化
目标:把 MVP 表逐步收敛到生产模型。
任务:
1. 新增 `contract_versions`,合同正文版本化。
2. 新增正式审批模型:`approval_instances`、`approval_steps`、`approval_actions`。
3. 将 UI 展示字段从长期事实表中逐步迁出或转为派生字段。
4. 为核心表补齐 `tenant_id`、`created_by`、`updated_by`、`deleted_at`。
5. 将高频 JSON 查询字段结构化,JSON 只保留快照和扩展。
6. AI 库补齐 `tenant_id`、保留周期、归档策略和敏感字段加密策略。
验收标准:
- 合同列表、审批待办、统一搜索、AI Trace、知识库检索不依赖 JSON 全表扫描。
- 合同正文修改有版本历史。
- 审批动作可追溯到步骤、人员、时间、结果。
- 数据库字段表达事实,不表达 UI 文案。
### Phase E:V1 资产迁移策略
目标:吸收 V1 优秀资产,但不复制 V1 单体结构。
任务:
1. 模板、条款、规则、黄金样本、精选法律全文通过导入脚本迁入 V2 新模型。
2. 每类资产都保留 V1 source id、导入批次、版本、hash。
3. V1 表结构不直接搬入 V2。
4. V1 数据库只读保留,作为迁移源和行为对照。
验收标准:
- V2 可独立从空库迁移到 head,再导入 V1 精选资产。
- 导入可重复执行,具备幂等性和差异报告。
- V1 与 V2 数据边界清楚,不出现一半沿用旧表、一半新表的混合状态。
## 立即不做的事
- 不删除 `ai_contract_platform`。
- 不删除或覆盖 `5432/yuqei_contract`。
- 不继续新建第三个、第四个 V2 候选库。
- 不把 V1 的单体 schema 复制到 V2。
- 不在未确认权威库前继续向数据库写入新业务数据。
## 下一步建议
优先执行 Phase A:
1. 写数据库环境登记表。
2. 写只读 DB 检查脚本。
3. 启动并检查 Docker smoke 数据库三库状态。
4. 决定权威 V2 dev/smoke 库。
这个阶段完成后,再开始代码模块化和 schema 硬化。这样重构不是边跑边猜,而是有清晰的数据库落点和验收门槛。