Files
PlantAI-rag-new/tooling/kb/encrypt_kb.sh
T
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

92 lines
4.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# encrypt_kb.sh —— 交付副本加密打包(生产库不动,单一 tar)。
# 流程:① 一致性快照(Qdrant snapshot API / neo4j-admin dump,绝不动活动卷)
# ② 断言导出文件 AES-256-GCM(raw_export.jsonl properties_json 字段 + parquet 整文件)
# ③ tar 单一文件(不压缩,92G 二进制)+ sha256
# ④ 计数校验(backend_guard 常量)
# 用法:bash encrypt_kb.sh <版本> [stage目录]
set -euo pipefail
umask 027
VERSION="${1:?用法: encrypt_kb.sh <版本>}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TOOLING_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
STAGE_ROOT="${2:-$TOOLING_ROOT/build/$VERSION/knowledge-stage}"
OUT_DIR="$TOOLING_ROOT/build/$VERSION"
QDRANT_URL="${QDRANT_URL:-http://127.0.0.1:27333}"
QDRANT_COLLECTION="${V15_QDRANT_COLLECTION:-plant_srt_pc2025_v3_20260817_normalized}"
NEO4J_NORM_NAME="neo4j-plant-srt-pc2025-v3-20260817-normalized"
NEO4J_DB="${NEO4J_DB:-neo4j}"
# 2026-08-31 修正:KB 交付不含 canonical(18788 属 SDK KG 浏览依赖);
# normalized 数据目录 08-24 起无写入(frozen),在线 dump 不支持(5.15 community),改冷拷
STAGING="/home/xzq/phase2b-5090-staging-20260823T191150Z/plant_srt_pc2025_merge_20260817_v3_normalized"
ASSERT_DIR="$STAGING/frozen_inputs/ef0d58871e05afbb957d652a5fe932eda24b68b3655bbbc5feb40d5ae9c47dc8/baseline_assertions"
REGISTRY_SRC="/home/xzq/5090/teamWorkspace/zh/PlantAI-rag/data/knowledge_base/paper_metadata_registry_v1_20260717/paper_metadata_registry_full.jsonl"
KEY_FILE="${KB_KEY_FILE:-$OUT_DIR/kb.key}"
TAR_FILE="$OUT_DIR/knowledge-$VERSION.tar"
AVAIL_GB=$(df -BG "$OUT_DIR" 2>/dev/null | awk 'NR==2 {gsub("G","",$4); print $4}' || echo 0)
[[ "${AVAIL_GB:-0}" -ge 200 ]] || { echo "磁盘余量不足(需 ≥200G, 当前 ${AVAIL_GB}G)" >&2; exit 1; }
[ -f "$KEY_FILE" ] || { echo "缺少 KB 主密钥: $KEY_FILE (先运行 tooling/crypto/init_keys.sh)" >&2; exit 1; }
mkdir -p "$STAGE_ROOT" "$OUT_DIR"
# ---- ① 一致性快照 ----
echo "[1/5] Qdrant snapshot API 导出(在线一致,$QDRANT_COLLECTION)..."
curl -sf -X POST "$QDRANT_URL/collections/$QDRANT_COLLECTION/snapshots" > /tmp/qdrant_snap_resp.json
SNAP_NAME=$(python3 -c "import json; print(json.load(open('/tmp/qdrant_snap_resp.json'))['result']['name'])")
echo " snapshot: $SNAP_NAME(生成中,轮询...)"
for i in $(seq 1 120); do
sleep 10
curl -sf "$QDRANT_URL/collections/$QDRANT_COLLECTION/snapshots" | grep -q "\"name\":\"$SNAP_NAME\"" && break
done
# 从容器拷贝 snapshot(容器内路径 /qdrant/snapshots/<collection>/<name>)
docker cp "$(docker ps -q -f name=qdrant-plant-srt-pc2025-v3-20260817-normalized):/qdrant/snapshots/$QDRANT_COLLECTION/$SNAP_NAME" "$STAGE_ROOT/" 2>/dev/null \
|| { echo "snapshot 拷贝失败" >&2; exit 1; }
echo " Qdrant snapshot 拷贝完成: $(du -sh "$STAGE_ROOT/$SNAP_NAME" | cut -f1)"
echo "[1/5] Neo4j normalized 冷拷(8.2G,数据目录 08-24 起无写入=frozen)..."
NEO4J_NORM_SRC="/home/xzq/phase2b-5090-staging-20260823T191150Z/plant_srt_pc2025_merge_20260817_v3_normalized/databases/neo4j/data"
rsync -a --info=progress2 "$NEO4J_NORM_SRC/" "$STAGE_ROOT/neo4j-normalized/data/" 2>&1 | tail -1
echo " normalized 冷拷: $(du -sh "$STAGE_ROOT/neo4j-normalized/data" | cut -f1)"
# ---- ② 断言导出文件加密 ----
mkdir -p "$STAGE_ROOT/assertions"
cp "$REGISTRY_SRC" "$STAGE_ROOT/registry.jsonl"
echo "[2/5] AES-GCM 加密 raw_export.jsonl properties_json(9.5G,数分钟)..."
python3 "$SCRIPT_DIR/kb_encrypt_backfill.py" \
--input "$ASSERT_DIR/raw_export.jsonl" \
--output "$STAGE_ROOT/assertions/raw_export.enc.jsonl" \
--key-file "$KEY_FILE" \
--fields properties_json
echo "[2/5] AES-GCM 整文件加密 assertions.parquet(2.7G)..."
python3 "$SCRIPT_DIR/kb_encrypt_backfill.py" \
--input "$ASSERT_DIR/assertions.parquet" \
--output "$STAGE_ROOT/assertions/assertions.parquet.enc" \
--key-file "$KEY_FILE" \
--file-encrypt
# ---- ③ tar 单一文件(不压缩)+ sha256 ----
echo "[3/5] 打包单一 tar(92G+,约10分钟)..."
tar -C "$STAGE_ROOT" -cf "$TAR_FILE" .
sha256sum "$TAR_FILE" > "$TAR_FILE.sha256"
echo "tar 完成: $TAR_FILE ($(du -sh "$TAR_FILE" | cut -f1))"
# ---- ④ 计数校验 ----
echo "[4/5] 计数校验(backend_guard 常量,解密安装后由 QA 验证)..."
cat > "$OUT_DIR/EXPECTED_COUNTS.json" <<JSON
{
"papers": 31207,
"canonical_entities": 3820996,
"assertions": 8246875,
"normalized_entities": 6316654,
"qdrant_points": 12963472,
"neo4j_asserts": 12963472,
"neo4j_supported_by": 13012368,
"neo4j_papers": 96648
}
JSON
echo " 期望计数已写入 EXPECTED_COUNTS.json"
echo "[5/5] KB 加密打包完成: $TAR_FILE"
echo " sha256: $(cat "$TAR_FILE.sha256")"