86 lines
5.2 KiB
Markdown
Raw Permalink 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.

# SOP — Obsidian Vault 同步 · 部署与运维手册
> 版本:v1.0 · 日期:2026-08-19 · 对应 PRD/SDD/BDD/TDD v1.0
> 面向:部署工程师 / 运维 / 值班支持。按章节顺序执行即可。
---
## 1. 部署前检查单
| # | 检查项 | 命令/位置 | 通过标准 |
|---|---|---|---|
| 1 | 后端配置 `Rag:Obsidian:AllowedRoots` 已配置 | `build-flow.api/src/BuildFlow.Host/appsettings.json` 或环境变量 | 非空数组;为空则所有同步请求被拒(fail-closed) |
| 2 | 容量上限符合预期 | 同上 `MaxFiles` / `MaxFileBytes` / `MaxTotalBytes` | 默认 10000 / 10MB / 512MB |
| 3 | vault 根目录在 API 服务器上真实存在且可读 | `ls -ld <root>` | 存在、运行账号有读权限 |
| 4 | 操作用户具备 `knowledge:write` 权限 | 平台 → 角色权限 | 权限已授予且前端菜单可见 |
| 5 | 文档处理管线正常(同步后文档要切分/向量化) | 观察同步后文档状态从 Pending → Done | 不长时间滞留 Pending |
| 6 | **S3 默认桶已创建**(平台级,缺失时上传报 404「资源不存在」,极具迷惑性) | `GET /api/buckets`(需 `bucket:read`)或直接在 S3 控制台/CLI 确认 `build-flow` 存在 | 桶存在;不存在则先创建:`POST /api/buckets {"name":"build-flow"}`(需 `bucket:write`)或用 S3 密钥 SigV4 `PUT /{bucket}`。默认桶名来自 `file_settings` 表,空表自动播种 `build-flow`(见 `BucketResolver`) |
### 环境变量注入方式(推荐,不入库、不入 git)
```bash
export Rag__Obsidian__AllowedRoots__0=/data/vaults
export Rag__Obsidian__MaxFiles=10000
export Rag__Obsidian__MaxFileBytes=10485760
export Rag__Obsidian__MaxTotalBytes=536870912
```
## 2. 部署步骤
```bash
# 1. 后端
cd build-flow.api
dotnet restore && dotnet build BuildFlow.slnx --no-restore -warnaserror
dotnet test tests/BuildFlow.Rag.Tests --filter "FullyQualifiedName~Obsidian" # 期望 9/9
# 2. 前端
cd build-flow.admin
corepack pnpm install
npm run lint # biome + tsc
npm run build
npm run test:e2e # 期望 12/12(obsidian-sync 4 + create-forms 8)
# 3. 按 §1 注入 AllowedRoots 后启动/重启 API
```
## 3. 功能验证(上线后 5 分钟冒烟)
1. 登录 React 管理端 → 左侧「AI → 知识库」;
2. 任一知识库卡片点「Obsidian 同步」→ 输入白名单内 vault 路径 → 开始同步;
3. 看到结果弹窗(新增/更新/跳过计数)= **功能通**;
4. 立刻再同步一次:Added=0、Updated=0、Skipped=文件数 = **增量对账通**;
5. 输入白名单外路径(如 `/etc`):提示「路径不在允许的根目录内」= **安全门禁通**;
6. 进入知识库文档列表,确认同步进来的文档 SourceType 为 Obsidian 且陆续完成处理。
## 4. 常见故障处置
| 现象 | 可能原因 | 处置 |
|---|---|---|
| 「未配置允许的 Obsidian 根目录」 | `AllowedRoots` 为空 | 按 §1 注入配置并重启 API |
| 「Obsidian 路径不在允许的根目录内」 | 用户输入路径不在白名单下 | 确认路径拼写;确需开放则在 `AllowedRoots` 增加根目录 |
| 「Vault 目录不存在」 | 路径在 API 服务器上不存在 | 在 **API 服务器**上 `ls` 确认;注意路径是服务器路径不是用户本机 |
| 「超过配置上限」(too_large) | 文件数/单文件/总量超限 | 清理 vault 或调高对应上限后重试 |
| 同步成功但文档一直 Pending | 文档处理管线(切分/嵌入)异常 | 查 API 日志 `ProcessDocument` 相关错误;确认嵌入模型服务可达(默认 `localhost:1234`) |
| 401/403 | 未登录或无 `knowledge:write` | 重新登录;找管理员授权 |
| 上传/下载文件报 404「资源不存在」 | S3 默认桶不存在(NoSuchBucket 被包装为 404) | 按 §1 第 6 项创建 `build-flow` 桶后重试(2026-08-19 实测案例,见验收报告 §7.4) |
| 大 vault 同步请求耗时长 | 同步为阻塞调用,按文件数线性 | 正常现象;前端有 loading 防重。勿反复点击/重试 |
## 5. 安全红线(不可绕过)
- **永远不要**把 `AllowedRoots` 配成 `/` 或系统敏感目录;只开放业务 vault 根;
- 不要为图方便关闭符号链接逃逸校验(Scanner 内置,无开关,勿改代码绕行);
- vault 路径来自用户输入但所有访问都在服务端发生 —— 任何"为了方便调试"把路径拼进 shell 命令的行为都可能引入注入,禁止;
- 服务器/中间件凭据只在 `appsettings.Secrets.json`(不入 git)或环境变量,泄漏即轮换。
## 6. 回滚
- 前端:功能为纯增量(Knowledge 页 + 一个组件),回滚 `build-flow.admin` 对应提交即可,无数据迁移;
- 后端:端点校验改动(`Enum.IsDefined`)向后兼容(0-2 行为不变,3-5 从"静默丢弃"变为"生效"),无需回滚动作;
- 同步写入的文档可通过删除知识库或按 `SourceType = Obsidian` 清理,无特殊回滚步骤。
## 7. 例行维护
- 每周抽查一次同步结果计数是否合理(Skipped 长期为 0 可能意味着哈希逻辑失效);
- 关注 Rag.Tests 中 Obsidian 相关 9 个测试在 CI 保持全绿;
- 前端 `npm run test:e2e` 在每次前端发版前必跑(12/12)。