Files
ai-contract-platform/project-docs/V2-database-code-refactor-decision-2026-06-28.md
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

13 KiB
Raw Permalink Blame History

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 建议拆分为:

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 建议拆分为:

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 硬化。这样重构不是边跑边猜,而是有清晰的数据库落点和验收门槛。