Files
knowledge-governance/docs/OPERATIONS_RUNBOOK.md
T
姚章浩 f8faed0b21 feat(release): 发布到生产一键完成(建批+锁定+授权合成一个动作)
用户的反馈是对的:上一轮只砍掉了"冻结/锁定"两个按钮,但一条文档从"已批准"到"发出"实际仍要
~9 次交互(找条目→勾选→填名→建批→滚到清单→找批次→授权→输语句→提交),因为"批次仪式"本身
还留在路径上。

- 新端点 POST /api/v1/release-batches/publish-now:在同一操作里先建批(SealImmediately,冻结
  即锁定)再授权生产发布,返回 {batch, execution}。
- 不放松任何约束:请求门禁(403)、备份恢复验证门禁(412)、管理员身份(401)、固定确认语句(400)、
  发布前快照硬门禁(409)、建批门禁(422) 全部沿用既有实现,无旁路;名称可省(服务端固定回退名,
  保证重放指纹一致)。
- 界面:审核行上直接「发布到生产」(管理员 + 门禁开启时显示),工具栏支持选中多条一次发布;
  复用既有确认弹窗(固定语句)。批次名不再是必经步骤。
- 实测(面板):点行级按钮 → 输 `publish-to-production` → 提交 → 批次 rb-bee80550…(sealed)
  + 执行 rx-3d831129…(completed, 项级 verified) → 页面回滚 rx-43835fac…(rolled_back, absent)。

测试:publish_now_test.go(四道关卡 + 组合调用 + 名称回退)与 reviewRelease.test.ts(请求体/回传/错误原因);
Go 26 包、前端 183 条全过。
2026-10-10 15:48:30 +08:00

10 KiB
Raw Blame History

现行用户操作流程(Runbook)

按"实际干活顺序"排列的现在的操作流程。标注:**【新】本期新增(含本次会话与 f4e1ecc/6496ee3/9155bd3 的 dws 取件)|【变】既有流程本期有改动|【既有】**未变,仍照旧走。 逐条验收证据请看 docs/USER_FLOWS_ACCEPTANCE.md;细节规则看各自专题文档。

统一入口 http://127.0.0.1:8088/(测试栈,右侧面板可直接操作)。角色:管理员 / 文档工程师 / 只读。


0. 开工前:环境与凭据自检

项 怎么做 成功标志
测试/生产 WeKnora 系统设置 → 服务配置 生产端"已启用 · 可提交生产请求";测试端探测正常
钉钉取件凭据 【新】 容器内 HOME=/data/home dws auth status --readonly -f json authenticated:true、refresh_token_valid:true(必须带 HOME=/data/home,否则误报未登录)
备份主机接线 系统设置 → 存储与备份 "目标主机 weknora-test · 已连接"

【新】dws 凭据续期(30 天轮换,到期前 7 天)

dws auth login --device     # 目标机执行,本人浏览器授权
dws wiki +space-list --limit 1 -f json   # 真实调用验证,期望 ok:true

出现 code=credentials → 立即停批,不要重试风暴;授权后 --retry-failed 续跑。


1. 取件(内容进来)【变:钉钉优先走 dws】

  1. 登录 → 来源与目录 → 选内容来源(钉钉知识库 / 国内工业 AList / PP 清单)。
  2. 展开目录、勾选要取的条目 → 取件(后台入队)。
  3. 看 解析监控:应出现"处理中"。
  • 钉钉来源现在优先用 dws 取字节(adoc→导出 docx,axls→转 xlsx,其余→drive 直下),不再依赖浏览器扫码会话;仅当 dws 报可重试错误(429/5xx/超时/连接层/服务端导出失败/dws 缺失)才回落老路径。
  • 平台侧判定全部保留(后缀路由、PPT 必须 PDF 双胞胎、magic、大小上限、sha256、spool 原子写、空壳检查)——dws 只取字节。
  • 想强制只用 dws 或完全绕过:ARTIFACT_DINGTALK_FETCHER=dws|legacy(默认 auto)。
  • 在线文档并发不要超过 4(当前配置 2 ✓)。
  • 失败进 死信,可"重排";轮次键 artifact-fetch:<version>:r<n>。

2. 标注与目录范围 【既有】

来源与目录 → 勾选 → 标记 对内 / 对外 / 不需要(目录级标记决定整目录)。

  • 路由到哪个测试库由 系统设置 → 测试知识库绑定 决定;不需要 不入库。

3. 发布准备:勾选 → 建批 → 锁定 【变:P0-1 建批时冻结 + P0-2 自动批准】

发布管理 → 审核要发布的知识:

  • 最快路径(推荐,单个或几条):在已批准那条上直接点 发布到生产 → 输入固定语句 → 提交。服务端在同一个动作里完成「建批(冻结+锁定)→ 授权生产发布」,无需填批次名、无需先建批再锁定。
  • 需要一批多条时:勾选 → 填批次名 → 创建并锁定清单(建批即锁定),再到发布清单点 授权发布。
  • 不再需要 生成新版本 / 确认冻结:服务端在"建批这一下"把当前实时计划冻结成一份已确认版本并绑定该批次。 语义不变——批一旦建立,清单/摘要/验收轮次/目标库绑定全部不可变、回滚按它走;变的只是"谁在什么时候按固化键"。
  • 同一份计划复用同一版本(摘要一致即复用),所以连续建批不会堆版本;计划变了才新建一版。
  • 审核:TEST_AUTO_REVIEW_POLICY = off | internal(默认,仅对内)| all。默认下对内知识验收通过即由系统批准 (审核记录 reviewer_ref=system:auto),对外仍需人工;策略可在容器环境变量调整,界面上只读展示当前值。 人工随时可驳回/改判;系统只允许写"第一条"审核,永远不会覆盖人工结论。
  • 建批即锁定:清单在建批那一刻冻结并立即密封,批次不可再改;锁定后才能授权生产发布。锁定 ≠ 上线。
  • 批量批准按人工身份记录(reviewer=当前登录人),人工可以推翻自己先前的驳回;系统自动批准(system:auto)永远只写第一条、不覆盖任何人工结论。

4. 待入库 → 处理 【既有】

文档工作台/待入库列表 → 选中 → 开始处理 → 上传 → 解析 → 索引 → completed。

  • 监控在 解析监控:处理中 / 需要你出手 / 需下架 / 死信 / 已完成 / 知识库差异 / 知识库解析进度。

5. 发布/导入之前:必须先留档(硬门禁)****【新】

目标库现场必须先留档,否则发布被拒(release_target_snapshot_missing,不可重试,目标库一行不碰)。

bash scripts/target_kb_snapshot.sh          # 默认云内执行;PG 8 表 + 该库在 ES 的全部文档
  • 产出:$KB_BACKUP_ROOT/target-kb-snapshots/<UTC>-<kb8>/(PG JSONL + es_documents.jsonl.gz + MANIFEST.json(sha256/每库 ES 计数) + export.sql + README.md)。
  • 实测:2 分 52 秒(ES 字节留目标主机);PULL_ES=1 拉回本机则 19 分 40 秒。
  • 门禁自动核验"覆盖该库 + 24h 内 + PG 与 ES 两层齐备 + 哈希可校验";复核用 go run ./cmd/guardcheck <快照根> <kb_id>。

6. 授权发布 → 读回验证 【变:页面通道】

发布管理 → 授权发布 → 逐字输入确认语句 publish-to-production → 确认执行。

  • 双闸(请求门禁 + 备份恢复门禁)+ 执行门禁;页面不录入/不显示 token,也没有"一键发布"。
  • 执行完成后看 查看结果:completed + verified;目标库出现该文档。

7. 回滚 / 重排 【变:页面通道】

  • 回滚:查看结果 → 回滚 → 确认语句 rollback-production-release。回滚后目标库该知识停用(不删知识行),wiki 页保持。
  • 重排失败执行:失败项 → 重排 → 确认语句 retry-production-release(只重置失败项;verified/rolled_back 保持;不改写历史 AuthorizedBy)。

8. 系统设置里现在要维护什么

审核策略目前由容器环境变量 TEST_AUTO_REVIEW_POLICY 控制(api 与 worker 共用 compose 锚点,默认 internal)。 界面上「审核要发布的知识」标题下方会显示当前生效值。

分区 谁 现在要管什么
服务配置 管理员 测试地址 / 生产地址 / 生产 ID / 知识库 ID(保存时真探活,无效才拒)
测试知识库绑定 管理员 标注往哪个测试库路由(对内 ≠ 对外)
生产知识库绑定 管理员 源库 → 目标库映射(发布写哪个生产库)
存储与备份 【新】 管理员 定时时间 + 储存天数(+每月归档、启用开关)→ 保存并下发到主机;另有 重新下发当前设置、立即备份一次;页面显示主机上实际生效的计划、cron 条目、最近一次结果与"已一致/待下发"
刷新策略 文档工程师 文档/资源刷新间隔、停滞判定、finalizing 时长(版本化 + 原子切换)
成员与角色 管理员 成员与 viewer/engineer/admin

9. 备份与恢复运维 【新】

层 怎么做 频率/现状
导入前留档(PG 行 + ES 文档) scripts/target_kb_snapshot.sh 每次发布前(2m52s)
硬门禁 自动(发布链已内置) 每次写目标库前
整库逻辑备份(自管,落在自己机器) 页面 立即备份一次,或主机 logical-backup.sh 每天 03:30 / 保留 7 天 / 每月另留 3 份(33 秒 / 742.6 MiB / 8 库 / 失败 0)
ES 快照 仓库 kb_backup + SLM kb-hourly(3 天)/kb-daily(7 天) 自动;首个快照 36 秒 / 4.7 GB
OSS 版本控制 桶 dobot-weknora-test 已开启 覆盖/删除可按 VersionId 回滚
RDS 托管备份 阿里云控制台自管(按决定:本期不做) —
目录契约 【新】 scripts/backup_layout.sh(任意主机同一份) /srv/kb-backups/{target-kb-snapshots,rds-logical,es-snapshots,logs}
回填演练 【新】 python3 scripts/restore_drill.py --snapshot-dir <留档> --target-url <本地测试库> 13,539 行回填、抽样逐字段一致、残留 0

换主机(测试云主机 → 未来生产云主机):① 新机跑同一份 backup_layout.sh;② compose 的 ES 挂载源与留档挂载源指向 $KB_BACKUP_ROOT;③ 门禁配置 target_snapshot.root 保持容器内路径不用改;④ 授权发布前先跑一次留档。

10. 出事了怎么恢复(按事故类型,越快越靠前)

事故 首选 耗时
某 KB 的 wiki/元数据被覆盖 留档回填(restore_drill.py 同法,或快照 README.md 的 SQL) 秒~分钟
检索/向量异常、索引误删 ES 快照 restore(kb_backup)或按 es_documents.jsonl.gz 以 _id 重建 分钟
OSS 对象被覆盖/删除 OSS 版本控制回滚单对象/前缀 秒~分钟
整库改坏要带走一份 自管逻辑备份 pg_restore -d <库> -j4 <库>.dir 分钟~十分钟
整实例级、要回到某个时刻 RDS 快照 / PITR → 新实例 → 按 KB 取行 10~30 分钟

本次新增/变化速查(对照旧流程)

# 变化 影响你的操作
1 钉钉取件走 dws 【新】 取件不再依赖扫码会话;但凭据 30 天要续期(runbook 见 §0)
2 发布前必须留档(PG+ES)【新】 发布前多一步 target_kb_snapshot.sh,否则门禁拒发
3 整库逻辑备份定时 【新】 在 系统设置 → 存储与备份 设时间与储存天数(保存即下发主机 cron)
4 生产动作页面通道 【变】 授权发布/重排/回滚在页面上、各需逐字确认语句
5 目标知识库可选 【变】 生产库绑定里可分别指定对内/对外目标库(不再要求同 ID)
6 wiki 归属门禁 【变】 共享知识库发布不再整库清空:只替换本包拥有的页面
7 回填演练 + 目录契约 【新】 出事可验证地回填;换机器只改一处配置