Files
knowledge-governance/docs/P8_PRODUCTION_KB_MAPPING_ACCEPTANCE.md
T
姚章浩 6440e3f679 feat(release): 发布目标知识库可选(源库 → 目标库映射)
- 迁移 000044:production_kb_bindings + release_item_executions.target_knowledge_base_id
- 系统设置新增「生产知识库绑定(对内/对外)」:从生产 WeKnora 实际列表选库,
  保存时真校验(不存在拒收;生产端不可达只提示并如实回报),仅管理员可改
- 执行计划按绑定解析目标库并冻结进 release_item_executions;空目标直接拒收;
  已发布过的条目保留原目标(重试/回滚回到同一处)
- DocumentBundle.RemapKnowledgeBase:knowledges/chunks/knowledge_tags/wiki_pages/
  wiki_folders 的 knowledge_base_id 与 ES 文档字段改写为目标库,重算表/文档摘要并重新封装
- 契约比对改为「声明的映射对」(KnowledgeBaseMapping),其余字段继续 fail-closed
- 契约检查器 / 目标身份 / 验证器全部走映射后的目标库;对象通道无需改写
- Compose 拆分:数据面接线 compose.release-sim.yaml + 两道门禁 compose.release-gates.yaml
- 测试:RemapKnowledgeBase 全通道/无操作/fail-closed、映射契约、绑定接口、RBAC、真实 PG 集成
2026-10-08 15:41:13 +08:00

4.5 KiB
Raw Blame History

P8 目标知识库可选(源库 → 目标库映射)开发与验收

缺口

发布链路把「测试库」与「生产库」绑成同一个 KB ID,全链路 fail-closed:

  • contract_inspector 用 route.knowledge_base_id 读目标契约,且要求它等于发布项的测试库 ID;
  • manifest.Validate / sidecar_publisher / verifier 断言 KnowledgeBaseID == item.TestKnowledgeBaseID;
  • postgres_import.prepareSnapshot 逐行断言 knowledge_base_id == identity.KnowledgeBaseID;
  • search_import.searchHitMatches 断言文档 knowledge_base_id == identity.KnowledgeBaseID。

因此只能发布到与测试库同 ID 的「镜像库」,无法选择目标端已有真实库(如「对内知识库-wiki」)。

目标

  1. 系统设置新增「生产知识库绑定(对内 / 对外)」,从目标(生产)WeKnora 实际列表里选目标库,保存时真校验。
  2. 发布执行时按绑定把 KB 身份从源库改写到目标库,三通道(PostgreSQL / Elasticsearch / 对象)与官方 API 验收一致收敛。
  3. 保持 fail-closed 语义:映射关系是显式声明并被冻结的,未绑定时退回同 ID 语义(目标库不存在则在契约检查阶段即失败)。

契约变更(唯一一处放宽)

原来比较 manifest.Contract.KnowledgeBaseID == target.KnowledgeBaseID; 现在比较声明的映射对(releasebundle.KnowledgeBaseMapping):

manifest.Contract.KnowledgeBaseID == mapping.SourceKnowledgeBaseID   (源:测试库)
target.KnowledgeBaseID            == mapping.TargetKnowledgeBaseID   (目标:生产库)
其余字段(版本 / migration / tenant / 检索引擎 / 模型 / 维度 / ES mapping SHA)继续必须相等

映射来源:release_item_executions.target_knowledge_base_id(执行开始时按 production_kb_bindings 解析并落库冻结),审计可见、重试复用。已在生产发布过的条目保留原目标(重试/回滚回到同一处),未发布过的按当前绑定。

落点

层 改动
迁移 000044 production_kb_bindings(单行 active,对内/对外目标库)+ release_item_executions.target_knowledge_base_id
系统设置 新增「生产知识库绑定(对内 / 对外)」,从生产 WeKnora 实际列表选库;保存时真校验(不存在→400 拒收;生产端不可达→只提示并如实回报 production_connected=false)
API GET/PUT /api/v1/production-kb-bindings、GET /api/v1/production-kb-bindings/options
执行计划 StartExecution 解析映射并冻结进 plan 与 release_item_executions;空目标直接拒收
快照改写 DocumentBundle.RemapKnowledgeBase:5 张带 KB 列的表 + ES 文档 knowledge_base_id 改写为目标库,重算表/文档摘要并重新封装(Seal);其余字段按原字节透传(嵌入向量不动)
目标身份 targetIdentities / 契约检查器 / 验证器 / PlanItem.TargetBase() 全部走映射后的目标库
对象通道 不改:对象 key = weknora/<tenant>/<knowledge_id>/<asset>,无 KB 段(实测穷举)
Compose compose.release-sim.yaml(数据面接线,无门禁)+ compose.release-gates.yaml(两道门禁,须人工授权叠加)

改写面(实测穷举)

源库行里 KB ID 只出现在 knowledge_base_id 这一个字段(每行 1 处):

表 / 位置 是否有 KB 列 处理
knowledges / chunks / knowledge_tags / wiki_pages / wiki_folders 有(各 1 处) 改写为目标库 ID,并重算表摘要
resources / resource_bindings / knowledge_tag_relations 无 不改(按 knowledge/handle 关联)
Elasticsearch _source.knowledge_base_id 有 改写为目标库 ID,并重算文档摘要
对象存储 locator storage://<backend>/oss://<bucket>/weknora/<tenant>/<knowledge>/<asset> 无 KB 段 不改(仅按目标 backend/bucket 重写)

验收点

  1. go test ./...、go vet、前端 tsc + vitest 全绿;迁移 44 up/down 往返可用。
  2. 单元/集成:映射生效后 knowledges/chunks/wiki_pages 的 KB 列、ES 文档字段均为目标库;摘要随改写重算;未绑定退回同 ID。
  3. 界面:系统设置可选目标库(列真实库名),保存时对目标 WeKnora 真校验(无效 ID 拒绝);发布管理显示本次目标库。
  4. 真实跨环境:1 份文档发布到目标库 → 三通道读回一致 → 官方 API 检索命中 → 撤权后零命中 → 回滚恢复。