# 现行用户操作流程(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::r`。 ## 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/-/`(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 <快照根> `。 ## 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 | 回填演练 + 目录契约 **【新】** | 出事可验证地回填;换机器只改一处配置 |