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

124 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 现行用户操作流程(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 天)**
```bash
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
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 | 回填演练 + 目录契约 **【新】** | 出事可验证地回填;换机器只改一处配置 |