86 lines
5.2 KiB
Markdown
86 lines
5.2 KiB
Markdown
# 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)。
|