dsh-obsidian 架构

August 19, 2026 · View on GitHub

DSH Web / Obsidian tab
        │ same-origin fetch

dsh-obsidian Host bridge  /dsh-obsidian/api
  ├─ strict loopback + same-origin guard
  ├─ bounded project scanner (manifests, .git, ext sampling)
  ├─ deterministic knowledge graph (tech/area/topic/dependency edges)
  └─ transport picker: Local REST API → filesystem fallback
        │                        │
        ▼                        ▼
Obsidian Local REST API      vault 文件系统(graph/ 命名空间)
  Bearer <key>               直接写 .md;Obsidian 打开 vault 时索引
  http(s)://127.0.0.1        (无需 REST 插件即可工作)

决策

  1. Obsidian 不负责扫描。 Obsidian 的图谱视图只索引 vault 内的 .md 文件与 [[wiki 链接]]。 dsh-obsidian 负责「本机项目 → 结构化笔记 + 链接」的生成,Obsidian 只负责展示。
  2. 双传输。 REST 优先(Local REST API 插件运行时,写入立即可见,支持 POST /open 跳转); 文件系统直写是离线兜底,Obsidian 打开 vault 时自动索引。两者共享同一套增量状态。
  3. 托管命名空间 graph/ 所有自动生成页面带 <!-- dsh-obsidian:managed --> 标记与 graph/.dsh-obsidian-state.json 状态文件;插件只删除自己托管过的路径,绝不触碰用户手写笔记。 该约定与 harzva-hub 的 harzva_hub_managed 标记互不冲突,可共存于同一 vault。
  4. 确定性图谱。 边来自事实:npm name / workspace:* / file: 依赖、manifest 推断的技术栈、 根目录区域、关键词主题表。不做 LLM 推理,避免虚构关联。
  5. Client 只访问 DSH 同源 /dsh-obsidian/api REST origin 与 API key 只存在于 Host; API key 不出现在任何响应、日志或前端状态里。
  6. 扫描有界。 深度 ≤2、目录预算 600、项目上限 400、每项目扩展名采样 ≤150 文件; 跳过 node_modules/.git/dist/隐藏目录。失败不阻塞 DSH 启动。

安全边界

  • 写入路径白名单 /^graph\/...\.md$/ + resolve() 包含性检查,禁止任何 .. 逃逸。
  • REST origin 必须是 literal loopback HTTP(127.0.0.1/[::1]),禁止凭据、路径与查询串。
  • 变更端点(scan/generate)要求 loopback + same-origin;请求体仅接受空对象 {}
  • repo URL 提取时剥离内嵌凭据;不读取 .env、不发送任何 vault 内容到外部网络。

兼容边界

  • DSH 首个验证目标:0.1.0-rc.6@deepseek-ai/dsh@0.1.0-rc.6 peer 锁定)。
  • Local REST API:依据 coddingtonbear/obsidian-local-rest-api 文档契约集成(GET /PUT|GET|DELETE /vault/{path}Authorization: Bearer); HTTPS 27124 自签证书不适用 Node fetch,默认探测 http://127.0.0.1:27124http://127.0.0.1:27123 (后者需在插件设置里开启 HTTP server)。
  • Obsidian Desktop 目标版本:本机 1.12.7;仅依赖通用的 vault 文件格式与 obsidian://open URI,无版本敏感 API。