a3bb78e06b
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 16m35s
339 lines
13 KiB
Markdown
339 lines
13 KiB
Markdown
# 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 硬化。这样重构不是边跑边猜,而是有清晰的数据库落点和验收门槛。
|