Files
mnote/bugs/05-editor-mainline/done/2026-05-21-office-edit-sign-plugin-gap-review-v1.md
T
lix-2026 1882db7681 收口 MNote P0 P1 P2 审查尾项
- 归档 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 .
2026-06-01 09:29:12 +08:00

122 lines
7.6 KiB
Markdown
Raw 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.
# Office local-first 预览、编辑与插件噪音缺口审查 v1
## 状态
- 状态:done
## 背景
本轮只审查 OnlyOffice 与 MNote local-first 工作区之间的三个接口缺口:
1. `/api/media/sign` 对 local-folder asset 返回 404。
2. Office 附件默认只读,但需要三点菜单提供“使用编辑模式打开”。
3. OnlyOffice 自定义 annotation 插件存在 404 / pageerror 噪音。
上一轮浏览器验证已经确认:中文 docx 上传后可在 resource tab 中只读打开,`errorCode=-18` 的 WebSocket 连接问题已通过 doc key 安全化和 `/onlyoffice-server` 反代修复。因此本轮不把“只读预览可见”重新定义为失败。
## 官方依据
Context7 查询 `/onlyoffice/api.onlyoffice.com` 得到的关键口径:
- `editorConfig.mode` 支持 `"view"` / `"edit"`,只是初始化编辑器模式。
- 保存必须配置 `editorConfig.callbackUrl`,后端在 callback `status === 2``status === 6` 时下载 `body.url` 并写回文件,成功返回 `{ "error": 0 }`
- `onRequestEditRights` 是 view 模式切 edit 的官方事件;触发后集成方必须以 edit mode 重新初始化编辑器。
- 插件通过 `editorConfig.plugins.autostart``editorConfig.plugins.pluginsData` 连接;annotation / custom assistant 类插件 404 属于可选插件加载链路,不等于主文档渲染失败。
## 代码现状
- `rust/crates/mnote-web/src/routes/media.rs``/api/media/sign` 当前只服务 Convex media asset,内部查询 `mediaAssets:getById` / `mediaAssets:refreshUrl`。local-folder asset 形如 `local:asset:<path>`,不在 Convex media 表中,所以返回 404 是现状契约不匹配。
- `rust/crates/mnote-web/src/routes/onlyoffice.rs``/onlyoffice` 页面在 `resolveAssetUrlAndKey()` 中只要有 `assetId` 就请求 `/api/media/sign`;失败后静默保留传入的 `fileUrl`。这就是“当前 view 模式不阻断打开”的原因。
- local-folder Office 预览已经可以直接使用 `/api/local-folder/files/open?rootUri=...&path=...` 作为 `fileUrl`,不需要经过 `/api/media/sign`
- `/api/onlyoffice/callback` 已由 `5-36` 补齐 local-folder `status 2/6 -> 下载 body.url -> 原文件覆盖写回` 的后端契约;legacy Next 代理仍保留为 cloud/compat 边界。
- `layout.rs` / browser runtime 已提供“使用编辑模式打开”入口,默认打开保持 `mode=view`,显式 edit 保留 guard。
- annotation/custom assistant 插件噪音已由 `5-37` / `5-40` 分类:插件噪音不等于主文档失败,真实 `errorCode=-18`、WebSocket 失败或 iframe 空白不能被噪音掩盖。
## 根因判断
### 1. `/api/media/sign` local-folder 404
根因不是权限失效,而是端点 ownership 错位:`/api/media/sign` 是历史 Convex media asset 签名端点,local-folder 文件已经有 local open route,二者不应混用。
P0 目标不是让 `/api/media/sign` 接管所有本地文件,而是让 OnlyOffice local 路径不再无意义请求该端点,避免误导日志和后续测试。
### 2. 编辑模式入口
OnlyOffice `mode=edit` 并不等于 MNote 已支持保存。没有 callback 写回闭环时,直接默认编辑会制造“看似能改、实际不能保存”的假功能。
P0 目标:
- 默认打开仍为 `view`
- 菜单提供“使用编辑模式打开”入口。
- 编辑入口必须带 guard:清楚标记为实验能力,或在 local-folder writeback 未闭环时阻止/提示。
P1 目标是实现 local-folder callback 写回;该项已由 `5-36` 完成后端契约。
### 3. annotation 插件 404 / pageerror
插件链路属于可选增强。若配置了 autostart / pluginsData 但静态资源不存在,会产生 404 或 pageerror。只要正文渲染和 OnlyOffice 主 WebSocket 正常,这不是打开失败。
P0 目标:
- 不把可选插件 404 当成 Office 打开失败。
- 不让缺失插件反复污染测试结论。
- 若当前 MNote 并未真正依赖 annotation 插件,则应禁用 autostart 或明确过滤为 non-critical。
## Checklist 拆分
- `5-34-local-folder-media-sign-office-url-contract-v1.md`
- P0OnlyOffice local-folder 打开不再请求 `/api/media/sign`
- P1:补回归测试,确认 local asset 仍可只读打开。
- `5-35-office-edit-mode-menu-and-guard-v1.md`
- P0:正文附件与文件树资源菜单增加“使用编辑模式打开”。
- P0:默认打开保持只读。
- P0:若保存闭环未完成,编辑入口必须有 guard / 实验标记。
- `5-36-onlyoffice-local-edit-save-callback-contract-v1.md`
- P1local-folder callback 写回。
- P1:覆盖 status 2/6、下载 URL rewrite、路径权限、冲突保护。
- `5-37-onlyoffice-annotation-plugin-noise-policy-v1.md`
- P0:定位 annotation 404 来源。
- P0:禁用无效 autostart / pluginsData 或把该类错误降级为 non-critical 测试噪音。
## 不做事项
- 不默认以 edit 模式打开 Office。
- 不在没有保存闭环时承诺“Office 可编辑保存”。
- 不把 local-folder 文件任意暴露给 `/api/media/sign`,除非经过 rootUri / workspace / allowed roots 校验。
- 不把 annotation 插件 404 等同于主文档渲染失败。
## 验收要求
- `cargo test -p mnote-web -- --test-threads=1`
- `codegraph sync .` 后确认索引健康。
- Reasonix clean browser 测试:全新 browser context,登录测试账号,上传 `/home/lix/Downloads/重庆发展特殊化妆品可行性报告_政府汇报版.docx`,打开默认只读,截图确认内容可见;打开三点菜单确认编辑入口;点击编辑入口后截图和日志证明行为符合 guard / edit URL 预期。
- Codex 必须复核 Reasonix 的 `result.json` 和截图,再自行做一次浏览器截图核查。
## 当前执行结论
- P0 已处理:
- local-folder Office 打开跳过 `/api/media/sign`,继续使用 `/api/local-folder/files/open`
- Office 默认打开为 `mode=view`
- 菜单提供“使用编辑模式打开”,进入前有实验 guard。
- 已存在 Office resource tab 从 view 切 edit 会刷新同一 iframe URL,不再只激活旧 tab。
- annotation/custom assistant 插件 404 已归类为 non-critical noise,不作为主文档打开失败。
- P1 已拆分并收口:
- `5-36`local-folder Office edit/save callback 写回后端契约已完成,覆盖 status 2/6、非写状态、未认证、路径越界。
- `5-35``onRequestEditRights` 事件会重新初始化为 `mode=edit` URL,不只 reload 当前 view。
- 本 umbrella review 仅作为缺口审查和拆分记录归档;后续真实 Office 编辑保存端到端浏览器验收若发现新问题,应另建具体 bug。
- 浏览器证据:
- Reasonix`tmp/reasonix-office-view-edit-plugin-2026-05-21/result.json` 与截图。
- Codex`tmp/codex-office-view-edit-plugin-2026-05-21/result.json``01-office-view-mode.png``02-office-edit-mode.png`
- 2026-06-01 验证:
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_page -- --test-threads=1`
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_callback -- --test-threads=1`
- `cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_local_callback -- --test-threads=1`
- `cargo test --manifest-path rust/Cargo.toml -p adapter-onlyoffice callback_preparation -- --test-threads=1`
- `node --check scripts/task463-onlyoffice-resolver-smoke.js`
- `MNOTE_UI_BASE_URL=http://127.0.0.1:3301 MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3301 node scripts/task463-onlyoffice-resolver-smoke.js`
- `node --check scripts/task518-onlyoffice-real-iframe-session-scope-smoke.js`
- `MNOTE_WEB_SMOKE_BASE_URL=http://127.0.0.1:3301 node scripts/task518-onlyoffice-real-iframe-session-scope-smoke.js`