Files
mnote/design/10-review/done/01-rust-kernel-web-review.md
T
lix-2026 d1d19f755c docs(design): 归档 10-review 到 done
将 10-review 的 01-06 文档统一迁入 done/,根目录 README 收缩为索引。

补充各历史审查稿的归档说明,并把 06 的活跃引用改到 done/ 下,避免后续重复把已完成审查当成当前待办。
2026-05-14 16:30:13 +08:00

122 lines
12 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.
# Rust Kernel / Web 实现偏差审查
> 执行状态:已归档到 `design/10-review/done/`。本文保留为历史审查快照,当前活跃口径以 `./06-execution-checklist-and-acceptance.md` 为准。
## 范围
本次只审查 Rust kernel / protocol / bridge-runtime / mnote-web / storage-convex-bridge 与当前设计主线的一致性。
重点对照设计:
- `ARCHITECTURE.md`
- `design/01-05-current-priority-overview.md`
- `design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md`
- `design/01-tree-first-graph-kernel/process/1-1-tree-first-graph-kernel-checklist-v2.md`
- `design/02-convex-rust-long-term-architecture/process/2-tree-first-graph-convex-rust-long-term-architecture-v1.md`
- `design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md`
- `design/03-rust-web/process/3-1-rust-web-long-term-checklist-v2.md`
- `design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md`
- `design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md`
- `design/04-tree-domain/done/4-6-tree-command-protocol-cutover-stage2-v1.md`
重点代码:
- `rust/crates/core-protocol/`
- `rust/crates/core-domain/`
- `rust/crates/bridge-runtime/`
- `rust/crates/mnote-web/`
- `rust/crates/storage-convex-bridge/`
## 结论
Rust kernel / protocol / bridge-runtime / mnote-web 的主干方向与当前设计基本一致:`core-protocol` 已有统一 kernel node / edge / projection / page aggregate 协议;`bridge-runtime` 已能执行 kernel query / command / projection`mnote-web` 已持有 3000 主入口、文档页 shell、`/api/page-aggregate/:id`、tree command、`/api/tree/events`、Search shell 等关键接缝;`storage-convex-bridge` 明确把 `tree.*` / `page.*` 等语义命令映射到底层 Convex mutation。
主要偏差不是“Rust 主线没有落地”,而是当前仍存在几类收口缺口:
1. 部分 Rust Web 主路径仍会静默合成 fallback / fixture 数据,和 `Runtime Fallback 退场` 的激进口径不完全一致。
2. Page Aggregate 对外标记为 `KernelProjection`,但 Rust Web 仍先取 `documents.meta/content` 再在 runtime 内拼成聚合;这是合理过渡实现,但“单一 kernel 真源”口径容易被写得过满。
3. Tree realtime 已有正式 SSE 主链,但实现仍偏轮询 bridge overviewWS 仍是 snapshot/resync 骨架,尚未成为完整实时主链。
4. Legacy / compat 能力默认大多关闭,但配置位、proxy 辅助函数和兼容源枚举仍在,设计文档中“全部退场”的勾选状态可能偏乐观。
## 关键发现表格
| 编号 | 分类 | 严重度 | 发现 | 证据 |
| --- | --- | --- | --- | --- |
| RK-01 | 未完成 | 中 | Kernel projection 仍主要从 `sidebar.dataset.list` 这一份 Convex 数据集构建,广义 node pool / reference edge / summary/index 真相层尚未完全独立。 | `rust/crates/mnote-web/src/routes/snapshot_support.rs:27` 定义 `sidebar.dataset.list``:93` 先加载 sidebar dataset 再执行 `kernel.project_view``rust/crates/bridge-runtime/src/lib.rs:8010` 后续由 sidebar 数据构建 subtree`:8111` 再转为 projection。 |
| RK-02 | 实现偏差 / 风险 | 高 | Rust Web 主路径仍存在静默 fallbackworkspace shell 在 projection 加载失败时无条件合成最小 workspace/documentssidebar/filetree 在 `allow_dev_fixtures` 时合成开发数据;Search 在 Convex query 失败时返回内置搜索数据。这与 `3-15-runtime-fallback-retirement` 的“默认不再 fallback”口径冲突。 | `rust/crates/mnote-web/src/routes/web_shell.rs:2379``:2401` 无条件 fallback 最小 dataset`:2432``:2461` 合成 sidebar dev dataset`:2493``:2519` 合成 filetree dev dataset`rust/crates/mnote-web/src/routes/search.rs:233``:247` 搜索失败后走 `fallback_search_dataset`。 |
| RK-03 | 方向变化 / 文档滞后 | 中 | Page Aggregate 已由 Rust Web 暴露正式 route,但实现仍是先读 `documents.meta/content`,再把 joined data 交给 `page.aggregate.get` 生成 projection。代码对外 source 标成 `KernelProjection`,但底层仍是 meta/content join 的迁移形态;需要文档明确这是 Rust runtime adapter,而非完整 kernel storage 真源。 | `rust/crates/mnote-web/src/routes/web_shell.rs:2282``:2315` 先读 meta/content 再执行 `page.aggregate.get``rust/crates/bridge-runtime/src/lib.rs:8246``:8253` 将 source 传为 `PageAggregateSource::KernelProjection``:5303``:5324` 从 meta/content 中抽取 title/content/revision。 |
| RK-04 | 未完成 | 中 | Tree realtime 正式 route 已存在,但当前 SSE 仍通过 polling `bridge.workspace.overview` 生成 snapshot/delta/resyncWS 只发送初始 snapshot,并只支持客户端请求 resync,不是完整主实时链路。 | `rust/crates/mnote-web/src/routes/sse.rs:51``:91` 循环 sleep/poll overview 后生成 delta`rust/crates/mnote-web/src/routes/ws.rs:32` 发送 snapshot`:40``:80` 只处理 resync 或 unsupported ack。 |
| RK-05 | 风险 / 文档滞后 | 低 | Legacy Next compat 默认关闭,但代码仍保留 env-gated proxy 能力、Next proxy 辅助函数和 compat 配置位。若文档继续写“legacy compat 已删除”,会与代码事实不一致;若保留,应写成显式调试/迁移边界。 | `rust/crates/mnote-web/src/app.rs:42``:54` 仍读取 `MNOTE_WEB_LEGACY_NEXT_BASE_URL` / `MNOTE_WEB_ENABLE_LEGACY_NEXT_COMPAT``rust/crates/mnote-web/src/routes/gateway.rs:86``:87` auth API 可转 legacy proxy`:402``:499` legacy proxy 实现仍在;`rust/crates/mnote-web/src/routes/documents.rs:153` 当前 `should_proxy_via_next` 返回 false,但 Next proxy helper 仍保留。 |
| RK-06 | 实现一致 | 低 | Tree command cutover Stage 2 的长期命名面已在 Rust route / bridge / storage mapping 中落地,`documents.*` 仍作为 alias/底层 Convex mutation 名称存在,和 Stage 2A/2B 过渡口径基本一致。 | `rust/crates/storage-convex-bridge/src/mapping.rs:37``:43` 映射 `tree.*``:52``:68` 保留 `documents.*` / `page.*` alias`rust/crates/mnote-web/src/tree_shell/dispatcher.rs:16``:23` 使用 `tree.*``rust/crates/mnote-web/src/routes/tree.rs:7634` 附近测试确认 documents alias 映射仍存在。 |
| RK-07 | 实现一致 | 低 | Debug shell 默认关闭,符合 `3104`/debug 壳默认退场口径。 | `rust/crates/mnote-web/src/routes/mod.rs:120``:124` 仅在 `enable_debug_shell_routes` 时挂 `/tree``/document-debug`;同文件测试 `:142``:184` 验证默认 404。 |
## 证据
### 1. Kernel / projection 已落地,但底层仍主要基于 sidebar dataset
- `rust/crates/core-protocol/src/kernel.rs:7``:42` 定义 `KernelNodeType``KernelEdgeType``KernelProjectionKind`
- `rust/crates/mnote-web/src/routes/kernel.rs:62``:85` 暴露 projection route,并经 `load_projection_snapshot` 获取投影。
- `rust/crates/mnote-web/src/routes/snapshot_support.rs:27``:47` 固定 `sidebar.dataset.list` 为数据获取入口。
- `rust/crates/bridge-runtime/src/lib.rs:8119``:8137` 在没有 root 时由当前数据构建 subtree,再生成 projection`file_tree` 另走 `build_file_tree_projection_result`
判断:这符合 `1-1` 中“真实主线已落地,但更广义 node pool/reference edge 仍后续”的口径,不应被写成“尚未开始”;也不应被写成“完整 kernel 真源已闭环”。
### 2. Runtime fallback 仍在主路径附近
- `rust/crates/mnote-web/src/routes/web_shell.rs:2379``:2401`workspace shell projection 加载失败时合成 `active_workspace_id``workspaces``documents`
- `rust/crates/mnote-web/src/routes/web_shell.rs:2432``:2461``allow_dev_fixtures` 时合成 sidebar dev dataset。
- `rust/crates/mnote-web/src/routes/web_shell.rs:2493``:2519``allow_dev_fixtures` 时合成 filetree dev dataset。
- `rust/crates/mnote-web/src/routes/search.rs:233``:247`:搜索 Convex 查询失败后执行 `fallback_search_dataset(workspace_id)`
判断:这与 `design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md` 的“默认运行时不再 fallback / 不静默降级”存在偏差。尤其 Search fallback 会产生看似真实的固定结果,风险高于空状态降级。
### 3. Page Aggregate 是 Rust route,但仍是迁移期 adapter
- `rust/crates/mnote-web/src/routes/mod.rs:53``:56` 挂载 `/api/page-aggregate/{document_id}`
- `rust/crates/mnote-web/src/routes/web_shell.rs:2264``:2319` 构建 aggregate。
- `rust/crates/bridge-runtime/src/lib.rs:5291``:5442` 从 meta/content 形状构建 `PageAggregateProjection`
- `rust/crates/core-protocol/src/page_aggregate.rs:4``:10` 协议层仍保留 `KernelProjection``CompatMetaContentJoin``Fixture` 三种 source。
- `rust/crates/mnote-web/src/page_aggregate/builder.rs:66` 默认 source 仍是 `CompatMetaContentJoin`,但当前检索未发现该 builder 进入主要 route 主路径。
判断:当前代码已摆脱 TS builder runtime 主链,但还不是“页面域全部直接来自独立 kernel storage 真源”。文档应保留“Rust-first Page Aggregate 过渡态”的精确口径。
### 4. Tree realtime 主链已成立,但不是完整实时闭环
- `rust/crates/mnote-web/src/routes/mod.rs:113` 挂载 `/api/tree/events``:114` 挂载 `/api/stream/events``:115` 挂载 `/api/realtime/ws`
- `rust/crates/mnote-web/src/routes/sse.rs:127``:146``/api/tree/events``x-mnote-web-owner: mnote-web``x-mnote-tree-stream-owner: rust-web`
- `rust/crates/mnote-web/src/routes/sse.rs:51``:91` 通过 sleep/poll bridge overview 发现变化。
- `rust/crates/mnote-web/src/routes/ws.rs:32``:80` WebSocket 当前只发 snapshot,并响应 resync 请求。
判断:这与 `3-3` 中“已完成 route / snapshot / delta / resync 基础,WS 尚未成为主链,live cache 未完全统一”一致;若 `3-15` 写成 tree realtime 补偿链已完全删除,则偏乐观。
### 5. Compat / legacy 未成为默认主链,但未完全删除
- `rust/crates/mnote-web/src/app.rs:42``:54` 仍读取 legacy Next 相关环境变量,默认 `enable_legacy_next_compat` 为 false。
- `rust/crates/mnote-web/src/routes/gateway.rs:86``:87` 在 compat 开启且配置 legacy base URL 时,`/api/auth` 可走 legacy proxy。
- `rust/crates/mnote-web/src/routes/documents.rs:153` 当前 `should_proxy_via_next` 返回 false,说明文档 API 默认不走 Next proxy。
判断:代码实际状态更像“默认关闭、残留显式迁移/调试能力”,不是“所有 legacy proxy 代码已删除”。
## 建议优先级
### P0
- 移除或显式隔离 Search 的 `fallback_search_dataset`。失败时应返回明确错误或空 projection,并带可观测错误头;不要返回固定假结果。
-`load_workspace_shell_projection` 的无条件合成 dataset 做决策:若用于首屏容错,应在响应或 contract 中显式标记 degraded;若严格执行 fallback 退场,应改为失败或空树,不再伪装成真实 workspace projection。
### P1
-`allow_dev_fixtures` 相关 fallback 全部加上更明确的 debug/dev 标识,并确认 `desktop:hot` / 3000 默认启动链不会误开。
- 补一条 Rust Web smokeConvex/query 不可用时,搜索、Sidebar、filetree 不应返回假业务数据。
- Page Aggregate 文档补一句:当前 Rust route 已是主读链,但底层仍通过 Rust runtime adapter 消费 meta/content substrate;完整页面域单一真源仍在推进。
### P2
- Tree realtime 后续应把 SSE polling overview 与真正 domain event stream 的边界写清楚,并继续推进 page subtree / filetree / preferred snapshot 同一 live cache。
- Legacy Next proxy 若仍需保留,建议统一命名为 explicit migration/debug boundary;若不再需要,后续单独删除 proxy helper、配置位和测试样例,避免和 `3-15` 的退场状态长期冲突。
- `PageAggregateSource::CompatMetaContentJoin` / `Fixture` 是否继续保留在 `core-protocol` 需要架构决策:保留则标记为迁移态 source;删除则需先确认没有测试、local folder、fixture 依赖。
## 修改的文件路径
- `/mnt/Data1T/mnote/design/10-review/done/01-rust-kernel-web-review.md`