Files
jerryandClaude Fable 5 5024a12947 P5/M6: KB 加密工具验证完成 + 操作指南(定版后执行)
- 加密工具双模式往返验证通过(字段级 properties_json / 整文件 parquet)
- 取消真实加密执行:数据库未定版,中间副本已清理,kb.key 保留
- tooling/KB_ENCRYPT_GUIDE.md:完整操作步骤/踩坑记录/解密验证/流水线接入
- 踩坑固化:Qdrant 必须 snapshot API(禁 rsync 活动卷);Neo4j 5.15 community
  不支持在线 dump,走 frozen 目录冷拷;canonical 库不在 KB 交付内

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 17:10:02 +08:00

4.6 KiB
Raw Permalink Blame History

KB 加密与打包操作指南(agent 专用)

适用时机:数据库定版后执行。定版前数据库持续增长,不做真实加密。 本指南对应方案 §五(Knowledge 设计);工具均已通过加密往返验证(2026-08-31)。

一、工具清单(tooling/)

工具 作用
kb/encrypt_kb.sh 一键:快照/冷拷 → 断言加密 → 单一 tar → sha256 → 计数清单
kb/kb_encrypt_backfill.py AES-256-GCM 加密器,两种模式(见下)
crypto/init_keys.sh 生成 KB 主密钥(已生成:build/2.0.0/kb.key,勿重复生成)

二、加密语义(已确认)

数据 处理 原因
Qdrant 向量(70G) 明文,snapshot API 导出 检索数学需要
raw_export.jsonl(9.5G) properties_json 字段 AES-256-GCM 断言全文
assertions.parquet(2.7G) 整文件 AES-256-GCM(--file-encrypt) 断言导出
Neo4j normalized data(8.2G) 明文冷拷(frozen 目录) 存储引擎限制;08-24 起无写入
registry JSONL(17M) 明文(仅论文元数据,无断言文本) 无敏感字段

加密格式:enc:v1:<b64 nonce>:<b64 ciphertext>(字段级=字符串,文件级=二进制)。解密见文末。

三、执行步骤(数据库定版后)

cd /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new

# 0. 预检:磁盘余量 ≥200G;密钥存在
df -h /home | tail -1
ls -la tooling/build/2.0.0/kb.key   # 若无 → VERSION=2.0.0 bash tooling/crypto/init_keys.sh

# 1. 一键执行(全部步骤,耗时约 1–2 小时,建议 setsid 后台)
bash tooling/kb/encrypt_kb.sh 2.0.0

分步执行(排查问题时)

# ① Qdrant 快照(70G,约 20–60 分钟;POST 后轮询容器目录)
curl -X POST http://127.0.0.1:27333/collections/plant_srt_pc2025_v3_20260817_normalized/snapshots
# 完成后从容器拷贝(文件出现在 /qdrant/snapshots/<collection>/)
docker cp <qdrant容器>:/qdrant/snapshots/plant_srt_pc2025_v3_20260817_normalized/<name>.snapshot tooling/build/2.0.0/knowledge-stage/

# ② Neo4j 冷拷(frozen 目录,rsync 8.2G)
# ③ 断言导出加密(9.5G jsonl 字段级 + 2.7G parquet 整文件)
python3 tooling/kb/kb_encrypt_backfill.py \
  --input <raw_export.jsonl> \
  --output tooling/build/2.0.0/knowledge-stage/assertions/raw_export.enc.jsonl \
  --key-file tooling/build/2.0.0/kb.key --fields properties_json
python3 tooling/kb/kb_encrypt_backfill.py \
  --input <assertions.parquet> \
  --output tooling/build/2.0.0/knowledge-stage/assertions/assertions.parquet.enc \
  --key-file tooling/build/2.0.0/kb.key --file-encrypt

# ④ 单一 tar(不压缩)+ sha256
tar -C tooling/build/2.0.0/knowledge-stage -cf tooling/build/2.0.0/knowledge-2.0.0.tar .
sha256sum tooling/build/2.0.0/knowledge-2.0.0.tar > tooling/build/2.0.0/knowledge-2.0.0.tar.sha256

四、关键约束(踩坑记录)

  1. 绝不 rsync 活动挂载卷——Qdrant 70G 存储是 27333 容器在线库,直拷会撕裂数据。必须走 snapshot API。Neo4j 5.15 community 不支持在线 dump(neo4j-admin database dump 拒绝运行库),只能用 frozen 目录冷拷(08-24 后无写入已核实)。
  2. canonical 库(18788, 14G)不在 KB 交付内——它是 SDK KG 浏览依赖,不是 QA 检索链(NEO4J_URI=19788)。
  3. kb.key 权限 600,离线备份——丢失无法解密已交付包。密钥在 tooling/build/2.0.0/kb.key(gitignored)。
  4. 计数校验:解密安装后由 QA backend_guard 验证,期望值见 tooling/build/2.0.0/EXPECTED_COUNTS.json(papers=31207 / canon_entities=3820996 / asserts=8246875 / norm_entities=6316654 / points=12963472)。
  5. registry JSONL 顶层无断言文本字段(实测:paper_id/title/doi/pmid/pmcid…),断言文本在 Qdrant payload(evidence/best_evidence)与 staging 的 raw_export.jsonl——加密目标已按实测调整。

五、解密验证(交付后 QA)

import base64, json
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = base64.b64decode(open("tooling/build/2.0.0/kb.key").read().strip())
aesgcm = AESGCM(key)
# 字段级
enc = rec["properties_json"]; _, n, ct = enc.split(":")
pt = aesgcm.decrypt(base64.b64decode(n), base64.b64decode(ct), None).decode()
# 文件级
blob = open("assertions.parquet.enc","rb").read(); _, n, ct = blob.split(b":")
pt = aesgcm.decrypt(base64.b64decode(n), base64.b64decode(ct), None)

六、定版后接入打包流水线

encrypt_kb.sh 已预留为 tooling/build_all.sh 的子步骤(方案 §六):编译 SDK+3 agent → 审计 → 冒烟 → encrypt_kb.sh → assemble → SHA256SUMS → 泄露检查。定版后只需在 build_all.sh 中启用该步骤(当前标注 SKIP_KB=1 占位)。