Files
blackbird/dnfs2/README.md
qing 9b6aa39b94 fix(dnfs2): update_note 成环检测(修复已知限制 L-1)
新增 _is_descendant 祖先走查:改 pid 时从新父节点沿 pid 链逐级向上,
命中自身即拒绝(自引用/移入自身子树均成环,子树不可达);深度上限 64
+ visited 集防存量脏数据死循环,db 错误 fail-closed 抛 500。
README 已知限制 L-1 移入安全修复表。
2026-08-13 04:10:35 +08:00

3.4 KiB
Raw Permalink Blame History

dnfs2 — C++20 树状网络文件系统

dnfs 的 C++ 重实现,接口与 Python dnfs 完全兼容,修复 P0/P1 安全问题。基于 libhttp + libmsg + boost::json。

架构

ca :8443 (验签 /whoami,验签通过后经 gateway 转发)
   │  Bearer Token
   ▼
dnfs2 :8006 ──pymsg──► db2 :8005 (execute 路由) ──► SQLite
   │                     ▲
   │                  libmsg (RpcClient)
   └──HTTP──► ai_review :8007 (内容审核)
  • HTTP 服务: libhttp HttpServer(Boost.Beast 异步,多线程)
  • Token 验签: HttpClient POST ca /whoami(CLI 参数 --gateway-url 指向 ca:8443),fail-closed(503)
  • 数据操作: libmsg RpcClient 调 db2 execute 路由
  • 内容审核: HttpClient POST ai_review /review,fail-closed
  • 异步日志: libmsg AsyncQueue → db2 Logs 表

接口

路由 鉴权 说明
POST /get_notes 否(可选 Token,用于 can_operate) 返回子节点数组
POST /add_note 是 校验 Token → 父节点存在 → AI 审核 → 插入
POST /delete_note 是 校验 Token → 检查子节点 → 所有权 → 删除
POST /update_note 是 校验 Token → 所有权 → 父节点存在 → AI 审核 → 更新

请求/响应 JSON 格式与 Python dnfs 完全一致,前端零改动。

配置

纯 CLI + 环境变量 + 默认值,不依赖 confs。

配置项 CLI 参数 环境变量 默认值
绑定地址 --host / --addr / -a LISTEN_ADDR 127.0.0.1
监听端口 --port / -p LISTEN_PORT 8006
工作线程 --threads / -t — 4
数据库地址 --db-host DB_HOST 127.0.0.1
数据库端口 --db-port DB_PORT 8005
数据库超时 --db-timeout — 10
AI 审核URL --review-url REVIEW_URL http://127.0.0.1:8007/review
AI 审核超时 --review-timeout — 10
ca 验签URL --gateway-url GATEWAY_URL http://127.0.0.1:8443/whoami
网关超时 --gateway-timeout — 5
日志级别 --log-level — info
实例名 --instance — dnfs2

优先级: CLI > 环境变量 > 默认值

构建

./_set.sh    # 编译
./_run.sh    # 运行

依赖: libhttp, libmsg, boost::json, OpenSSL, libcurl

安全修复(相比 Python dnfs)

编号 问题 修复方案
P0-4 父节点删除 TOCTOU + 未检查 success 统一封装 _call_db() 检查 success 后再访问 data
P1-6 请求体无限制 server.setMaxBodySize(10MB)
P1-7 log_client 配置不一致 日志客户端复用主配置
P1-8 update_note 改 pid 未校验父节点 pid≠0 时校验父节点存在
P1-9 db RPC 未启用启动等待 RpcClient(retry_on_refused=true)
P1-11 note_id 无强制类型转换 显式 as_int64() + 类型校验
L-1 update_note 允许创建循环 _is_descendant 祖先走查:拒绝新父节点为自身或位于自身子树内(深度上限 64,防存量环死循环)

已知限制(P2,设计决策不修复)

  • L-2: delete_note TOCTOU 残余(需 db2 事务支持)
  • L-4: 无速率限制(gateway/WAF 职责)
  • L-5: title/content 无最大长度校验
  • L-6: AI 审核不可用时阻断写入(fail-closed 设计决策)