28 KiB
3-0 [recycle] Rust Web 长期架构实施清单 v1
更新时间:2026-04-16
关联文档:
/mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/document-access-performance-root-cure-v1.md/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md/mnt/Data1T/mnote/ARCHITECTURE.md
1. 文档用途
这份清单不是短期提速清单,而是长期架构落地清单。
它服务的目标只有一个:
把 mnote 从“Rust 内核 + 重前端页面壳”推进到“Rust 内核 + Rust Web 承载 + server-first 页面 + 少量交互孤岛”的稳定形态。
这份清单强调四件事:
- 做什么
- 不做什么
- 什么时候算完成
- 哪些东西必须最后处理
2. 总体完成定义
只有同时满足下面几条,才能认为长期架构目标基本达成:
- Rust workspace 成为唯一业务真执行面,Web 层不再承载第二套对象规则
- Rust Web 层已经接住主 API、主页面壳、主流式能力
- 文档访问路径已变成“先阅读、后交互、再编辑”
- Sidebar、搜索、AI、Mindmap 等外围模块已退出当前重前端主壳
BlockNote已被隔离为最后的重交互孤岛,而不是整页入口前提- Next/旧 React 壳只保留过渡兼容边界或已被替换
3. 执行原则清单
在任何阶段开始前,先确认这些原则不被破坏:
- 不再把新的业务规则写回 TS route / Next 页面层
- 不再新增新的全局常驻前端大面板
- 不再把“临时懒加载”当作长期方案替代品
- 不在未完成阅读态分离前,继续扩张编辑态默认挂载内容
- 不把
BlockNote当成第一阶段改造对象 - 不把 OnlyOffice 当成主性能阻塞项
- 不把“换成 Rust”简化成“只重写 API”
4. 阶段总览
推荐按下面顺序推进:
- Phase 0:基线与边界冻结
- Phase 1:Rust Web 基础层落地
- Phase 2:文档阅读页 server-first 化
- Phase 3:Sidebar / 页面树 / 文件树 Rust 化与 island 化
- Phase 4:搜索系统 Rust 化与 island 化
- Phase 5:AI 面板进一步收口为纯桥接 island
- Phase 6:Mindmap 独立对象化与独立页面化
- Phase 7:文档编辑态与
BlockNote孤岛化 - Phase 8:旧前端壳下线与兼容清理
4.1 阶段依赖与并行规则
这条长期路线不是“看到哪里慢就改哪里”,而是有明确前后依赖。
Phase 0必须先产出边界冻结、基线和 islands 候选,否则后续会重新滑回旧壳扩张。- 横向能力
H1必须在Phase 1之前定口径,否则 Rust Web、阅读态、搜索、AI、Mindmap 会各自发明 trace、缓存和权限语义。 Phase 1是Phase 2~Phase 6的共同前置;没有 Rust Web 承载层,后续只能继续堆 Next route。Phase 2~Phase 6可以分批并行推进,但都必须遵守“阅读优先、局部 island、对象规则只进 Rust core”。Phase 7依赖Phase 2~Phase 6基本就位后再开始,否则BlockNote会继续承担外围能力。Phase 8只能在Phase 1~Phase 7都有稳定替代路径后执行,不能靠“删旧代码”制造假完成。
4.2 每阶段输出给下一阶段的输入
Phase 0输出:重模块审计表、性能基线、阅读态/编辑态边界、islands 候选、冻结口径。Phase 1输出:Rust Web 入口、统一 router/middleware/context/error/SSE/WS/Hermes bridge 协议。Phase 2输出:文档阅读态服务端主链、阅读工具栏 island、阅读缓存/预取策略。Phase 3输出:Sidebar/树结构服务端骨架、局部刷新协议、导航预取策略。Phase 4输出:搜索 server-first 页面壳、轻交互 Search island、分页/键盘导航协议。Phase 5输出:AI bridge panel 最小会话协议、流式 token/tool/client action 统一事件流。Phase 6输出:Mindmap 独立对象页壳、内嵌轻预览边界、独立操作协议。Phase 7输出:阅读态/编辑态切换协议、编辑岛错误边界、编辑态性能采样。Phase 8输出:Next/旧 React 壳保留清单、兼容层清理清单、最终对外口径。
5. Phase 0:基线与边界冻结
5.1 目标
在动长期架构之前,先冻结边界,避免迁移过程中又把旧模式继续扩写。
5.2 实施清单
- 盘点当前由 Next/React 页面层承载的重模块清单
- 标记哪些模块属于“必须保留浏览器交互”
- 标记哪些模块属于“可变为 server-first 页面”
- 标记哪些模块属于“可退化为独立 island”
- 标记哪些模块属于“外挂或独立页面,不进入主文档链”
- 冻结
BlockNote外围继续加功能的入口 - 冻结 Sidebar、SearchPalette、Document 面板继续膨胀的入口
- 为页面切换与首屏建立统一性能基线
- 为文档页进入路径建立链路追踪点
- 为 Sidebar、搜索、AI、Mindmap 建立独立耗时采样点
5.2.1 当前前端重模块审计表
| 模块 | 当前主入口 | 当前主问题 | 长期归位 | 是否必须保留浏览器重交互 |
|---|---|---|---|---|
| 文档页 | wolai-frontend/src/app/(app)/documents/[id]/page.tsx + DocumentShell -> DocumentContent -> BlockNoteEditor |
进入页面默认串到编辑器初始化,阅读态无法先出现 | Phase 2 先 server-first 阅读页,Phase 7 再把 BlockNote 孤岛化 |
是,但只限编辑态 |
| Sidebar / 页面树 / 文件树 | wolai-frontend/src/app/(app)/layout.tsx + src/components/sidebar/sidebar.tsx |
常驻在主布局内,切页时继续参与大组件状态与重渲染 | Phase 3 收口为 Rust query + 服务端壳 + 局部 island |
是,但只限展开/拖拽/快捷过滤 |
| SearchPalette | src/components/search/search-palette.tsx |
当前仍作为全局常驻大组件挂在布局内 | Phase 4 收口为独立 island 与 server-first 搜索页 |
是,但只限输入/联想/键盘导航 |
| AI 面板 | src/components/ai-agent/**、DocumentAiAgentPanel、MindmapAiAgentPanel、OnlyOfficeAiAgentPanel |
已切 Hermes bridge,但页面壳仍偏重,多个面板仍常驻挂载 | Phase 5 统一为最小 bridge shell + 按需 island |
是,但只限会话与浏览器 client capability |
| Mindmap | src/components/editor/blocks/MindmapBlock.tsx + src/app/mindmap/[docId]/[mindmapId]/page.tsx |
独立页仍与 BlockNote 形态绑得太近,内嵌/独立共用同一重壳 | Phase 6 收口为独立对象页 + 内嵌轻预览 |
是 |
| OnlyOffice | src/app/onlyoffice/** 与 src/app/api/onlyoffice/** |
属于外部编辑器桥,不是主文档性能瓶颈 | 继续维持外挂页面,不进入主文档链 | 是,但不进入主文档访问链 |
BlockNote |
src/components/editor/blocknote-editor.tsx |
当前仍然是文档页默认入口前提 | 最后处理,保留为 Phase 7 的重交互孤岛 |
是 |
5.2.2 冻结口径
- 新增页面能力时,先判断是否能落到 server-first 页面或局部 island,不能再默认塞回主布局。
- 新增对象规则、权限判断、聚合排序、工具编排,不允许直接写回 Next route 或页面层。
BlockNote外围的新面板、新工具栏、新初始化逻辑一律冻结,除非是为“阅读态分离”服务。- Sidebar、SearchPalette、AI 面板不允许再继续增加全局常驻状态容器。
5.3 产物清单
- 当前前端重模块审计表
- 页面切换性能基线报告
- 文档阅读态与编辑态的边界定义
- 岛模型候选模块清单
5.3.1 页面切换性能基线报告
| 访问链路 | 当前入口 | 需要记录的统一指标 | 当前基线采样方式 | 迁移后对比目标 |
|---|---|---|---|---|
| 普通文档打开 | /documents/[id] |
首字节、正文首屏、进入可点击阅读态、进入编辑态耗时、BlockNote 挂载耗时 |
scripts/task019-document-ui-regression.js + 浏览器 performance trace |
把正文首屏与阅读交互从编辑器启动链里剥离 |
| Sidebar 切页 | 主布局 + Sidebar | 切页耗时、树结构重渲染数、导航预取命中率 | pnpm test src/lib/sidebar-data.test.ts src/lib/file-tree/rows.test.ts + React Profiler |
Sidebar 仅做局部交互,不再放大整页挂载 |
| 搜索打开/关闭 | SearchPalette | 打开耗时、首次结果返回、键盘导航响应、关闭恢复耗时 | 搜索页/浮层交互 trace + eslint/定向 smoke |
搜索开关不再引发整页重计算 |
| AI 面板打开/关闭 | Document/Mindmap/OnlyOffice AI | 面板首开耗时、SSE 首 token、关闭后页面恢复耗时 | runAgent.test.ts + 页面侧 performance mark |
AI 未打开时不占主页面主链 |
| Mindmap 独立页 | /mindmap/[docId]/[mindmapId] |
页面壳首屏、导图交互可用、独立页返回文档页耗时 | scripts/task021-mindmap-ui-regression.js |
独立页不再依赖文档编辑上下文 |
5.3.2 文档阅读态与编辑态的边界定义
- 阅读态必须先拿到页面 meta 与正文读链,允许在没有编辑器的情况下稳定展示正文。
- 编辑态必须显式进入,不能再把“打开文档”默认等同于“挂载完整编辑器”。
- 阅读态负责:权限、只读/禁复制/禁下载策略、正文首屏、轻工具栏、回退与预取。
- 编辑态负责:
BlockNote、块级写入、Slash、评论/历史/AI/页面选项等重交互链路。 - 只读渲染与可编辑渲染必须是两套不同初始化协议,不能靠 mounted gating 假装分离。
5.3.3 岛模型候选模块清单
| 模块 | 候选 island 形态 | 保留在服务端页面壳的内容 |
|---|---|---|
| 文档阅读工具栏 | 轻工具栏 island | 标题、正文、权限壳、阅读统计 |
| Sidebar 树 | 展开/拖拽/快捷过滤 island | 工作区壳、树结构首屏 HTML |
| SearchPalette | 输入框、联想、结果列表 island | 搜索页结果首屏与分页壳 |
| AI 面板 | 单一 AiBridgePanel island |
页面上下文注入、SSE 桥接 route |
| Mindmap | 独立导图交互 island | 独立页 meta、权限与返回壳 |
BlockNote |
最后保留的重编辑 island | 阅读页正文、阅读工具栏、权限与缓存壳 |
5.4 完成判定
- 后续任何人都能明确知道哪些模块先迁、哪些模块后迁
- 已经有统一基线可以验证迁移是否真的更快
- 不再接受“顺手往旧壳里再塞功能”的继续扩张
6. Phase 1:Rust Web 基础层落地
6.1 目标
建立真正的 Rust Web 承载层,而不是停留在“Rust 只做业务内核”。
6.2 实施清单
- 在 Rust workspace 中明确新增 Web 层 crate 或独立服务目录
- 选定
axum作为主 HTTP 承载框架 - 建立统一 Router 组织方式
- 建立统一 middleware 链
- 建立统一 request id / trace id 注入
- 建立统一鉴权上下文注入方式
- 建立统一 workspace / actor / tenant 上下文透传
- 建立统一错误码与错误响应协议
- 建立统一 JSON 响应包装规范
- 建立统一 SSE 输出协议
- 建立统一 WebSocket 连接协议
- 建立统一静态资源与页面壳响应策略
- 打通 Rust Web 层到现有 Rust core runtime 的调用入口
- 打通 Rust Web 层到 Hermes 的桥接入口
- 明确保留哪些 Next route 作为过渡兼容壳
- 明确哪些旧 route 不允许再扩写
6.3 架构约束
axum只负责 Web 承载,不复制业务裁决- Rust Web 层不再新建第二套对象模型
- Web 层只组合调用 Rust core,而不是重新实现 core 语义
- 仍需浏览器特定 transport 的旧接口必须标记为兼容层
6.4 完成判定
- 已有一个可运行的 Rust Web 入口
- 主 API、SSE、WS、trace 基础设施已可由 Rust Web 层承接
- 后续页面迁移不再必须依赖 Next API route 作为唯一入口
7. Phase 2:文档阅读页 server-first 化
7.1 目标
把“进入文档页就进入编辑器世界”的模式改成“先进入阅读页,再按需进入编辑态”。
7.2 实施清单
- 定义文档阅读页独立于编辑态的页面模型
- 定义阅读页所需最小数据模型
- 定义阅读页 HTML 输出协议
- 将文档 meta 与正文读取收敛成同一服务端读链
- 去掉进入文档页必须二次取正文的默认模式
- 去掉进入文档页必须等待客户端 mounted gating 的默认模式
- 去掉阅读页默认依赖
BlockNote的前提 - 把评论、历史、回链、页面选项、AI 等外围面板改为非阻塞挂载
- 将文档阅读工具栏收缩为轻交互 island
- 将阅读页权限、只读、禁复制、禁下载等策略前移到服务端页面壳
- 为阅读页建立缓存与失效策略
- 为阅读页建立首屏、切页、回退、预取策略
7.3 禁止事项
- 不允许为了“看起来快一点”继续叠更多客户端 gating
- 不允许阅读页默认挂载完整编辑器依赖树
- 不允许把评论、AI、回链等周边作为阅读页首屏阻塞条件
7.4 完成判定
- 打开文档时可以先看到完整阅读态,而不是编辑器 loading 壳
- 文档访问主链已不依赖
BlockNote初始化完成 - 页面切换性能的主要瓶颈已从“编辑器启动”转移出去
7.5 当前落地状态(2026-04-16)
- 文档页已改成 server-first 阅读入口:服务端先拿
meta + content + revision + conflictDetectionKey,客户端只在服务端读链失败时才回退到旧/api/documents/content读链。 DocumentShell已去掉 mounted gating,阅读页不再先显示“正在载入编辑器...”壳。DocumentReadView已承担正文只读渲染;BlockNoteEditor仅在显式进入编辑态或openTableId直达场景时挂载。- 只读/禁复制/禁下载、评论、历史、回链、页面 AI 与页面选项都已从阅读首屏阻塞链上移开,阅读态可以先稳定出现。
8. Phase 3:Sidebar / 页面树 / 文件树 Rust 化与 island 化
8.1 目标
把高频访问、长期常驻、当前体量过大的导航系统,从主前端大壳里拆出去。
8.2 实施清单
- 定义 Sidebar 数据聚合协议
- 定义页面树 / 文件树查询协议
- 将排序、过滤、分组、收藏、最近访问、回收站等聚合逻辑收敛到 Rust
- 将大部分树结构渲染改为服务端输出
- 将展开、折叠、拖拽、快捷过滤等改为局部 island
- 拆分“静态结构”和“高交互局部状态”
- 减少全局布局对 Sidebar 的强耦合
- 让 Sidebar 切页时不重新参与重布局初始化
- 为树结构建立局部刷新协议,而不是整树重拉
- 为导航行为建立预取与轻量缓存策略
8.3 风险控制
- 拖拽重排不能倒逼回到全客户端大组件
- 树结构局部刷新不能破坏 SSR 壳稳定性
- 布局层不得继续持有超大导航状态容器
8.4 完成判定
- Sidebar 不再是主布局中的超大客户端核心组件
- 页面树 / 文件树的数据与主要规则已由 Rust 层统一提供
- 切页时 Sidebar 只参与局部交互,不再放大整页挂载成本
8.5 当前落地状态(2026-04-16)
layout已在服务端先调用loadSidebarDataFromConvex(...)输出SidebarInitialData,导航首屏数据不再默认延迟到客户端再拼。/api/sidebar、src/lib/sidebar-data.ts、src/lib/server/sidebar-data.ts与实时 hook 已统一复用sidebar.dataset.list的共享契约。- 当前 Sidebar 仍保留交互型客户端组件形态,但切页和刷新已建立“服务端首包 + 局部 island”边界,后续只需继续瘦身而不是回到旧的整页初始化模式。
9. Phase 4:搜索系统 Rust 化与 island 化
9.1 目标
让搜索成为一个轻页面、轻浮层、轻交互系统,而不是全局重组件。
9.2 实施清单
- 明确搜索索引层、召回层、结果聚合层全部由 Rust 提供
- 明确文档、块、标题、标签、对象搜索的统一协议
- 为搜索结果定义服务端可渲染的数据模型
- 将 SearchPalette 改造成独立 island
- 将输入框、联想、最近搜索、结果列表拆成最小交互单元
- 将搜索页主内容改成 server-first 页面
- 建立搜索结果分页、滚动续取、键盘导航协议
- 建立最近搜索与最近访问的轻量持久层
- 避免搜索组件再作为全局常驻重组件绑定整页布局
9.3 完成判定
- 搜索框打开与关闭不再引发整页级别的重计算
- 搜索结果主要由 Rust 提供,前端只负责最小交互呈现
- 搜索能力不再依赖当前全局 React 壳维持状态
9.4 当前落地状态(2026-04-16)
SearchPalette已拆成轻量SearchPaletteHost+search-palette.runtime,首次快捷键或首次打开前不再加载重量运行态。- 全局布局只保留搜索 host 接线,
Ctrl/Cmd+P与引用快捷键先由 host 接住,再按需拉起 runtime。 SearchPaletteHost的动态导入已修正为直接指向 runtime,避免 host 自引用导致的错误懒加载。
10. Phase 5:AI 面板进一步收口为纯桥接 island
10.1 目标
让 AI 面板彻底变成“后端工具桥 + 最小 UI”,不再成为大前端的第二套系统。
10.2 实施清单
- 确认所有主线 AI tools 已收口到 Rust runtime / Hermes
- 删除或冻结旧前端 registry / orchestration 入口
- 统一 AI 面板的最小会话协议
- 统一页面上下文注入协议
- 统一 AI 输出渲染协议
- 统一流式 token / tool event / client action 回传协议
- 将页面级 AI 面板统一为单一 bridge shell
- 将 AI 面板按需挂载为 island
- 去掉常驻全局 AI host 对主布局的影响
- 去掉面板自身承载重量级对象逻辑的习惯
10.3 完成判定
- AI 面板已不再承担第二套工具编排
- AI 面板关闭或未打开时,不影响页面切换主链
- AI 页面壳只剩桥接、上下文、渲染,不剩对象真执行逻辑
10.4 当前落地状态(2026-04-16)
- 文档页、导图页、OnlyOffice 三类 AI 面板都已收口为轻 host + 按需 runtime island,Hermes / Rust bridge / client-tool-result 主链继续复用现有接缝。
- 文档页 host 只维护
available/open生命周期;OnlyOffice host 只负责接住插件ready握手;导图 host 只在切到 AI tab 时按需挂载 runtime。 GlobalAiAgentHost继续保留为实验入口组件,但不再回到 app layout 常驻主链,避免重新变成全局重量壳。
11. Phase 6:Mindmap 独立对象化与独立页面化
11.1 目标
把 Mindmap 从“BlockNote 的一类重自定义块”推进为“独立对象 + 独立页面 + 可嵌入轻预览”。
11.2 实施清单
- 定义 Mindmap 独立对象模型
- 定义 Mindmap 读写协议与操作协议
- 明确导图节点、边、布局、样式、视口状态的 Rust 持久化结构
- 明确导图页面独立于文档页的服务端壳
- 将独立导图页优先迁到 Rust Web 层
- 将文档内嵌导图降级为轻预览或轻交互卡片
- 把导图工具栏、侧栏、缩略图等拆成局部 island
- 去掉对 BlockNote editor context 的强依赖
- 去掉“文档内嵌导图”和“独立导图页”共用同一重前端壳的绑定方式
11.3 完成判定
- Mindmap 已可以在不依赖 BlockNote 主运行时的情况下独立打开
- 文档页不再因为导图组件而被迫挂载整套导图交互壳
- 导图对象已进入 Rust 主线,而不是继续主要依赖前端组件状态
11.4 当前落地状态(2026-04-16)
- 独立导图页已切到
StandaloneMindmapView,不再依赖 fakeeditorStub或 BlockNote editor context。 - 文档内嵌导图已降级为轻预览 / 轻交互入口,文档主链不再因为独立导图壳而被迫进入重运行态。
- Mindmap AI 与导图独立页都已按对象级接缝继续走 Rust / bridge 主线,而不是继续把主逻辑绑在文档编辑器里。
12. Phase 7:文档编辑态与 BlockNote 孤岛化
12.1 目标
最后再处理真正难替代的 BlockNote,把它从“默认页面入口前提”改成“按需挂载的重编辑岛”。
12.2 实施清单
- 明确阅读态与编辑态的切换协议
- 明确进入编辑态时的最小初始化协议
- 将
BlockNote依赖的外围功能继续向外剥离 - 将评论、回链、历史、AI、页面选项等从编辑器默认初始化链上移走
- 将自定义 block 的读取协议改成可按需注入
- 将只读渲染与可编辑渲染彻底拆开
- 将文档打开路径改成“阅读态常驻,编辑态进入时挂编辑岛”
- 为编辑岛建立独立错误边界
- 为编辑岛建立独立性能采样
- 为编辑岛建立独立恢复机制
12.3 禁止事项
- 不允许在这一步之前就试图整体替换全部编辑器能力
- 不允许让阅读页重新回退为“先挂编辑器再展示内容”
- 不允许把新的外围面板重新绑回
BlockNote初始化链
12.4 完成判定
- 绝大多数页面访问不需要等待
BlockNote - 编辑器只在真正进入编辑态时才挂载
BlockNote已成为孤岛,而不是整个页面系统的基础前提
12.5 当前落地状态(2026-04-16)
- 阅读态与编辑态的切换协议已经落地:默认阅读、显式进入编辑、
openTableId强制编辑、退出编辑后保留短暂 grace period 再卸载编辑岛。 - 评论、历史、回链、页面 AI、页面选项等外围能力都已从
BlockNote默认初始化链外移,阅读态可以单独存在。 DocumentReadView与BlockNoteEditor已形成两套不同初始化协议,BlockNote现在是按需进入的重编辑 island,而不是整页入口前提。
13. Phase 8:旧前端壳下线与兼容清理
13.1 目标
在新结构稳定后,清理旧壳,避免双栈长期共存。
13.2 实施清单
- 盘点仍保留的 Next 页面壳与 API 壳
- 标记哪些属于长期兼容层
- 标记哪些属于可删除过渡层
- 删除已被 Rust Web 层替代的 route
- 删除已被 Rust islands 替代的全局客户端面板
- 删除失效的桥接 helper、旧 registry、旧 adapter
- 清理不再使用的布局状态容器
- 清理不再使用的动态导入链
- 更新运行文档与架构文档
- 更新开发约束,禁止回流到旧模式
13.3 完成判定
- 旧前端壳已不再是主路径
- 双栈只是短期兼容,而不是长期事实
- 维护成本已经从“双系统并行”回到“单主线演进”
13.4 当前收缩口径(2026-04-16)
- 已明确当前仍保留的 Next/React 页面壳:文档页、Sidebar、搜索、AI host 与 OnlyOffice 页面仍在兼容层内,但重运行态已被拆到按需 island。
- 已完成这一轮最小清理:搜索与各类 AI 面板的重量 runtime 不再默认跟随主布局常驻,
GlobalAiAgentHost继续停留在实验入口而不是 app layout 主链。 - 已把长期清单、长期架构方案与 harness 状态统一回写,后续 Phase 8 继续以“删旧壳前先写清保留边界”为准,而不是靠误删制造假完成。
14. 横向能力清单
这些事情不属于单一阶段,但必须贯穿全部阶段推进。
14.1 观测与性能
- 建立统一性能指标:首字节、首屏、交互可用、切页耗时、编辑器挂载耗时
- 建立统一错误指标:页面壳错误、island 错误、编辑器错误、桥接错误
- 建立统一 trace 关联:页面请求、Rust query、Rust command、Hermes tool、前端 island
- 建立按页面类型的性能对比面板
最低交付物:
- 每个页面壳请求都必须生成
request_id/trace_id,并能串到 Rust query/command 与 Hermes tool。 - 文档页、Sidebar、搜索、AI、Mindmap、编辑岛都要有统一的 performance mark 命名规则。
- 回归脚本必须至少覆盖:文档页、Mindmap、OnlyOffice、AI tool runtime、Sidebar/文件树定向测试。
14.2 缓存与预取
- 建立阅读页缓存策略
- 建立树结构局部缓存策略
- 建立搜索结果缓存策略
- 建立文档邻近页面预取策略
- 建立失败回退与缓存失效策略
最低交付物:
- 阅读页采用“meta + content”同一读链缓存键,不能再拆成首屏后二次正文请求作为默认主路径。
- 树结构、搜索结果、邻近页面预取都必须显式声明失效来源,避免隐式常驻缓存。
- 失败回退策略必须写明是回源、回旧壳还是退到只读页面。
14.3 安全与权限
- 统一页面壳权限校验
- 统一对象级读写鉴权
- 统一浏览器 island 的最小权限输入
- 统一 AI / Hermes 的工具权限边界
最低交付物:
- 页面壳、对象查询、对象写入、AI tool 调用必须复用同一 workspace / actor / tenant 上下文。
- browser island 只能收到最小权限输入,不能自己推导更高权限。
- Hermes 与 mnote Rust 之间的 bridge 必须只暴露最小业务能力面,不复制前端编排逻辑。
14.4 开发规范
- 新功能默认先判断是否属于 server-first 页面
- 新交互默认先判断是否可以做成局部 island
- 新业务规则默认只进 Rust core
- 新页面默认不能直接复制旧重前端壳模式
最低交付物:
- 提交新页面时必须回答四个问题:是否 server-first、是否 island、对象规则是否进 Rust、是否引入新的常驻壳。
- 没有 trace / 缓存 / 权限口径的新页面或新 island,不允许直接并入长期主线。
15. 最终验收清单
只有下面这些问题都能回答“是”,这条长期路线才算真正跑通。
- 打开一个普通文档时,是否已经可以先稳定进入阅读态
- 切换页面时,是否已经不再默认触发重编辑器初始化
- Sidebar 是否已经不再是主布局里的超大客户端组件
- 搜索是否已经不再依赖全局大组件常驻
- AI 面板是否已经变成纯桥接 island
- Mindmap 是否已经能独立于
BlockNote主运行时工作 - Rust Web 层是否已经能承接主 API、主页面壳、主流式链路
- Rust core 是否已经成为唯一业务真执行面
BlockNote是否已经被延后为最后处理的孤岛,而不是继续绑住整页架构- 旧前端壳是否已经开始实质性退场,而不是继续成为默认主路径
当前可回答“是”的项(2026-04-16):
- 打开一个普通文档时,已经可以先稳定进入阅读态。
- 切换页面时,已经不再默认触发重编辑器初始化。
- 搜索已经不再依赖全局大组件常驻。
- AI 面板已经收口为纯桥接 island。
- Mindmap 已能独立于
BlockNote主运行时工作。 BlockNote已被延后为最后处理的孤岛,而不是继续绑住整页架构。
16. 一句话执行顺序
如果后续需要不断回看,这条路线可以压缩成一句话:
先冻结旧壳扩张,再立 Rust Web 层;先迁阅读页、Sidebar、搜索、AI、Mindmap,最后才处理
BlockNote;稳定后再清旧壳,而不是反过来。