Files
mnote/bugs/07-ai/done/7-28-markdown-edit-selection-scope-not-enforced-v1.md
lix-2026 a2cb1338c8 chore: 保存当前架构收口与 bug 修复快照
归档本轮 P0/P1 bug 修复、设计审查迁移、AI selection scope 收口与 stream contract 调整,并保留当前 05 主线迁移起点。
2026-05-18 17:01:35 +08:00

50 lines
3.1 KiB
Markdown
Raw Permalink 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.
# 7-28 [done][bug] markdown_edit 未强制 selection 允许块边界
> 发现时间:2026-05-18
>
> 状态:`[done]`
>
> 关联主线:`07-ai`
## 1. 问题定义
页面 AI context 已经可以携带 `allowedTargetBlockIds`,用于表达 `scope=selection` 时本次 run 允许修改的块集合。但 `mnote.doc.markdown_edit` 当前只按文本 search/replace 写回,不检查最终变化的 block 是否落在允许集合内。
如果 fast workflow 或未来调用者传入了过宽的 `pageText`,模型返回了选区外文本的 search/replace,服务端仍可能写入选区外块。
## 2. 证据
- [page_ai_workflow.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/page_ai_workflow.rs:91) fast workflow 调用 `mnote.doc.markdown_edit`
- [page_ai_workflow.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/page_ai_workflow.rs:299) 读取了 `allowedTargetBlockIds`,但未传给写工具或参与校验。
- [hermes_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_client.rs:2860) 工具指导要求 `scope=selection` 时只能修改 `allowedTargetBlockIds` 内的块。
- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:1220) `markdown_edit` 生成 `changedBlocks` 后直接 dry-run 或写回,没有 selection 范围校验。
## 3. 影响
- 页面 AI 对选中文本执行编辑时,服务端缺少最终兜底边界。
- 上下文构造或模型输出一旦漂移,选区外块可能被写入。
-`mnote.block.*` 已有 `allowedTargetBlockIds` / blockId 前置条件相比,`markdown_edit` 的写入安全边界较弱。
## 4. 修复
- [page_ai_workflow.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/page_ai_workflow.rs:91) fast workflow 将 `aiContext.allowedTargetBlockIds` 透传给 `mnote.doc.markdown_edit`
- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:855) `mnote.doc.markdown_edit` 在生成 `changedBlocks` 后,如果存在 `allowedTargetBlockIds` / `selectedBlockIds`
- 任何带 `blockId` 的变更必须属于允许集合。
-`blockId` 的 insert/full_content 变更在 selection scope 下拒绝,避免无法归属的选区外写入。
- [hermes_tools.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_tools.rs:2308) 增加 route 测试:`allowedTargetBlockIds=["p_2"]` 时替换 `p_1` 必须返回 `mnote_markdown_edit_target_out_of_scope`
- [page_ai_workflow.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/page_ai_workflow.rs:742) 增加 fast workflow 测试:模型输出修改 `p_1`,而 selection 只允许 `p_2`,必须被服务端拒绝。
## 5. 验证
```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web markdown_edit_rejects_selection_out_of_scope -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web block_edit_workflow -- --nocapture
cargo fmt --manifest-path rust/Cargo.toml --all -- --check
```
结果:
- `hermes_tools_markdown_edit_rejects_selection_out_of_scope``1 passed`
- `block_edit_workflow_forwards_allowed_target_blocks_to_markdown_edit``1 passed`
- Rust workspace format check 通过。