- 归档 OnlyOffice live bridge、Page AI、mindmap、design governance 与相关 bug 条目 - 补齐 MinerU OCR 后端 runtime 合同与 smoke/test 基线 - 收口 ChatOnly/Doubao、ObjectIdentity、Page Aggregate compat 与 runtime owner 文档口径 验证: - cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1 - cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_bridge -- --test-threads=1 - git diff --check - git diff --cached --check - codegraph index . --force && codegraph status . - codegraph sync . && codegraph status .
5.2 KiB
5.2 KiB
5-36 OnlyOffice local-folder 编辑保存 callback 契约
状态
- 状态:done
目标
为 local-folder Office 编辑保存建立 callback 写回契约。P1 可以先落设计和测试骨架;若实现,必须覆盖 status 2/6 的下载写回和路径安全。
原因
ONLYOFFICE 官方保存链路要求 callback status === 2 或 status === 6 时,集成后端下载 body.url 并写回原文件。此前 mnote-web callback 仍代理 legacy Next,local-folder 写回未闭环。本轮已补齐 local-folder callback 写回路径。
允许修改
rust/crates/mnote-web/src/routes/onlyoffice.rsrust/crates/adapter-onlyoffice/src/lib.rs- 相关单测
- 如需记录设计,可补充本 checklist
禁止事项
- 不绕过 allowed roots 写任意路径。
- 不在没有冲突保护时覆盖用户无关文件。
- 不强行删除 legacy callback 代理。
Checklist
- 明确 local asset callback 定位:callback URL 携带
rootUri/path/sessionId/token,并用 bridge session 校验 asset match。 - status 非 2/6 时返回
{ "error": 0 },不写文件。 - status 2/6 时下载 rewritten
body.url。 - 写回前校验目标路径属于当前 local root allowed roots。
- 写回后写入原始本地文件;后续页面刷新由现有 local-folder watcher / projection refresh 感知。浏览器编辑保存端到端 smoke 另列后续验收,不作为本 bug 阻塞项。
- 编辑入口仍保留 guard,不让用户误解为完整协作编辑能力已产品化。
验收
cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_callback -- --test-threads=1cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_local_callback -- --test-threads=1cargo test --manifest-path rust/Cargo.toml -p adapter-onlyoffice callback_preparation -- --test-threads=1- 后续浏览器编辑保存验收需单独设计,不纳入 P0。
本轮执行记录
-
2026-06-01:Codex 复核当前实现并补齐 callback 写回回归测试。
OnlyOfficeCallbackQuery已携带root_uri/path/session_id/token。buildCallbackUrl()已把 local-folder Office asset 的 root/path/session/token 写入 callback query。local_folder_onlyoffice_callback()已校验 root/path、bridge session token、session asset match,并通过resolve_onlyoffice_local_file_path()阻断 root escape。- status 2/6 通过
prepare_callback()rewrite 后下载body.url并写回原始本地文件;非 2/6 返回成功且不写文件。 - 新增/确认测试覆盖:
onlyoffice_local_callback_rejects_unauthenticated_local_writeonlyoffice_local_callback_writes_status_two_body_to_original_fileonlyoffice_local_callback_writes_status_six_body_to_original_fileonlyoffice_local_callback_rejects_root_escape_pathonlyoffice_local_callback_ignores_non_write_status
- 验证通过:
cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_callback -- --test-threads=1cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_local_callback -- --test-threads=1cargo test --manifest-path rust/Cargo.toml -p adapter-onlyoffice callback_preparation -- --test-threads=1
-
2026-05-21:Reasonix worker C 分析完成。 结论:本轮不应实现完整写回。
阻塞输入缺口:
- callback URL 当前只携带
assetId和userId,缺少rootUri和path。buildCallbackUrl()在onlyoffice.rs页脚 JS 中硬编码只传两个参数。- 对于 local-folder asset(assetId
local:asset:path/to/file.docx),无法从 assetId 推导 rootUri。 - 没有 rootUri 就无法
resolve_onlyoffice_local_file_path→ 无法安全写回。
adapter-onlyoffice的prepare_callback不感知 local-folder 路径。OnlyOfficeCallbackPreparationInput没有 rootUri / path 字段。prepare_callback只做下载 URL rewrite 和 session 定位,不含路径校验。
- callback Rust handler 的
proxy_legacy_onlyoffice_json目前代理 legacy Next;local-folder 无 legacy 时返回 NOT_IMPLEMENTED。
实现写回所需的最小增量(下轮实现):
page()页脚的buildCallbackUrl():检测 local asset,追加rootUri和pathquery 参数。OnlyOfficeCallbackQuerystruct:增加root_uri: Option<String>和path: Option<String>。callback()handler:检测到 local asset 时(assetId 含local:/local-file:前缀),从 query 提取 rootUri 和 path,调用resolve_onlyoffice_local_file_path校验路径在 allowed roots 内。adapter-onlyoffice:在OnlyOfficeCallbackPreparationInput和prepare_callback增加 local path 字段。- status 2/6:下载 rewritten body.url,写回校验过的本地路径。
- status 非 2/6:返回
{"error": 0},不写文件。
当前 guard 状态:
- Worker B 已在
layout.rs中实现withOfficeEditModeGuard:confirm 对话框 +data-mnote-last-office-edit-mode-requested/data-mnote-last-office-edit-mode-guard数据属性。 - 编辑入口在 local-folder writeback 未闭环时带 guard 提示,符合安全策略。
- callback URL 当前只携带