feat: align local-first workspace direction
Document the VSCode-like local-first product shape, demote Convex to a control-plane role, and retire stale architecture drafts. Add local workspace migration/export references plus smoke coverage for no-Convex managed workspace startup, local markdown title/body/options persistence, asset upload behavior, and Convex fixture export. Verification: git diff --cached --check; node scripts/check-local-first-convex-guard.js --staged; node scripts/task444-convex-workspace-export-local-fixture-smoke.js; node scripts/task166-local-first-managed-workspace-no-convex-smoke.js; node scripts/task167-local-markdown-title-body-options-no-convex-smoke.js
This commit is contained in:
+86
@@ -0,0 +1,86 @@
|
||||
# 2-3 [process] Local Workspace Access Control 产品化 checklist v1
|
||||
|
||||
> 创建时间:2026-05-19
|
||||
>
|
||||
> 当前状态:`PROCESS`
|
||||
>
|
||||
> 上位依据:
|
||||
> - `/mnt/Data1T/mnote/design/02-convex-rust-long-term-architecture/done/2-2-local-first-workspace-convex-control-plane-v1.md`
|
||||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||||
> - `/mnt/Data1T/mnote/CURRENT_ARCHITECTURE.md`
|
||||
>
|
||||
> 目标:把已存在的 admin / owner / grant 本地目录权限模型产品化,形成管理员可管理、agent 可复用、全入口不绕过的控制面。
|
||||
|
||||
---
|
||||
|
||||
## 1. 当前已具备底座
|
||||
|
||||
- [x] 管理员身份支持 `MNOTE_ADMIN_USER_IDS`。
|
||||
- [x] 目录授权文件默认位置为 `/mnt/Data1T/Mnote_data/control-plane/access-policy.json`。
|
||||
- [x] 本地目录访问已有 admin / owner / grant 三层模型。
|
||||
- [x] 普通用户不能访问未授权目录。
|
||||
- [x] read grant 只能读,write grant 可写。
|
||||
- [x] 读路径使用 `ensure_local_workspace_read_access`,写路径使用 `ensure_local_workspace_access`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 本轮 P0:最小管理员控制面 API
|
||||
|
||||
- [x] A1. 新增 `GET /api/admin/access-policy`。
|
||||
- 目标:管理员查看当前策略、策略文件路径、有效管理员来源和 grant 列表。
|
||||
- 验证:单测覆盖非管理员 403、管理员可读。
|
||||
- 实现:`rust/crates/mnote-web/src/routes/local_folder_source.rs` + `rust/crates/mnote-web/src/routes/mod.rs`。
|
||||
- [x] A2. 新增 `POST /api/admin/access-policy/validate-root`。
|
||||
- 目标:管理员输入 `rootUri` 或 `rootPath` 后返回 canonical path / rootUri,并拒绝不存在或非目录路径。
|
||||
- 验证:单测覆盖合法目录、非法路径。
|
||||
- [x] A3. 新增 `POST /api/admin/access-policy/grants`。
|
||||
- 目标:管理员添加用户目录授权,写入 `access-policy.json`。
|
||||
- 字段:`userId`、`rootUri/rootPath`、`permission=read|write`、`recursive`、`capabilities=[ai|share]`。
|
||||
- 验证:单测覆盖创建 grant、重复 grant 拒绝、非管理员拒绝。
|
||||
- [x] A4. 新增 `DELETE /api/admin/access-policy/grants/{grantId}`。
|
||||
- 目标:管理员删除授权。
|
||||
- 验证:单测覆盖删除后普通用户失去对应访问权。
|
||||
|
||||
---
|
||||
|
||||
## 3. P1:权限覆盖审计
|
||||
|
||||
- [x] B1. 审计 local folder open / default workspace / file open / asset upload。
|
||||
- 结论:default workspace 走 owner manifest;asset upload 走 write access;file open 已从 write access 收口为 read access,并补 `local_file_open_allows_read_grant` / root escape 单测。
|
||||
- [x] B2. 审计 page body write / documents compat save / title / options。
|
||||
- 结论:`/api/page-body/write`、`documents/save`、title、options 在 local source 下统一走 `ensure_local_workspace_access` 后写本地 markdown / metadata。
|
||||
- [x] B3. 审计 tree command / trash / restore / purge。
|
||||
- 结论:tree snapshot 读路径走 read access;create / rename / copy / trash / restore / purge 写路径走 write access;已有 tree command local folder 单测覆盖。
|
||||
- [x] B4. 审计 Hermes / Reasonix run allowed roots 与 AI tools。
|
||||
- 结论:Hermes/Reasonix local ACP session 创建和 run 写入本地 private jsonl 前走 write access;`mnote.doc.fetch` 直接本地文件读取改走 `ensure_local_path_read_access`;`mnote.page.get` 传递 `sourceKind/rootUri` 并校验 `aiAccessScope.allowedResourceIds`。
|
||||
- [x] B5. 审计 shared AI session read/write 不扩大 workspace 权限。
|
||||
- 结论:AI tool 层补 `aiAccessScope.allowedResourceIds` 校验;共享只读场景下 markdown edit 仍禁止写入,验证见 `hermes_tools_markdown_edit_shared_read_is_forbidden`。
|
||||
|
||||
---
|
||||
|
||||
## 4. P2:后续产品化
|
||||
|
||||
- [ ] C1. 管理员 UI:列表、添加、删除、validate root。
|
||||
- [ ] C2. agent changed files / diff 审计落盘。
|
||||
- [ ] C3. 权限策略变更 audit 记录。
|
||||
- [ ] C4. share / ai capability 接入真实执行路径。
|
||||
|
||||
---
|
||||
|
||||
## 5. 本轮验证包
|
||||
|
||||
- [x] `cargo fmt --check --all`
|
||||
- [x] `cargo test -p mnote-web local_access_policy -- --nocapture`
|
||||
- [x] `cargo test -p mnote-web local_workspace_access -- --nocapture`
|
||||
- [x] `cargo test -p mnote-web local_folder -- --nocapture`
|
||||
- [x] `npm run check:local-first-convex-guard`
|
||||
- [x] `git diff --check -- <changed-files>`
|
||||
|
||||
补充验证:
|
||||
|
||||
- [x] `cargo test -p mnote-web local_path_read_access -- --nocapture`
|
||||
- [x] `cargo test -p mnote-web local_file_open -- --nocapture`
|
||||
- [x] `cargo test -p mnote-web hermes_tools_doc_fetch -- --nocapture`
|
||||
- [x] `cargo test -p mnote-web hermes_tools_page_get -- --nocapture`
|
||||
- [x] `cargo test -p mnote-web hermes_client_local_acp -- --nocapture`
|
||||
- [x] `cargo test -p mnote-web hermes_tools_markdown_edit_shared_read_is_forbidden -- --nocapture`
|
||||
-500
@@ -1,500 +0,0 @@
|
||||
# 2 [process] Convex 保留前提下的 Tree-First Graph 长期架构方案 v1
|
||||
|
||||
> 更新时间:2026-04-22
|
||||
>
|
||||
> 当前优先级入口:
|
||||
> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md`
|
||||
>
|
||||
> 关联文档:
|
||||
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-1-rust-web-long-term-checklist-v2.md`
|
||||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
这份文档用于固定一个容易在讨论中被混淆的问题:
|
||||
|
||||
> **当 mnote 沿着 Tree-First Graph 与 Rust 主导路线继续重构时,是否要拆掉当前本地自托管 Convex。**
|
||||
|
||||
本文件给出的结论是:
|
||||
|
||||
- **不建议把 Convex 从当前主线中拆掉。**
|
||||
- **长期要收口的是“语义主导权”和“统一执行面”,不是物理上把 Convex 替换掉。**
|
||||
- **Convex 继续保留为本地自托管的存储 / 实时 / 文件底座;Rust 负责统一 kernel 语义、命令、查询、投影与页面承载。**
|
||||
|
||||
这份文档要解决的不是短期修 bug,而是长期架构方向误判的问题。
|
||||
|
||||
---
|
||||
|
||||
## 2. 先给结论
|
||||
|
||||
结论固定为四句:
|
||||
|
||||
### 2.1 不拆 Convex
|
||||
|
||||
当前仓库里的 Convex 不是一个“外部云黑盒”,而是本地自托管主线的一部分。
|
||||
|
||||
在当前语境下,它承担的不是单一数据库职责,而是接近下面这些能力的组合:
|
||||
|
||||
- 结构化持久化主链
|
||||
- 实时订阅能力
|
||||
- 与文件 / 对象存储协作的业务底座
|
||||
- 当前已经跑通的部署、权限、工具与调试体系
|
||||
|
||||
因此,**长期不建议为了“Rust 化”而先把 Convex 拆掉。**
|
||||
|
||||
### 2.2 要收口的是语义,而不是先替换底座
|
||||
|
||||
长期真正应该统一的是:
|
||||
|
||||
- 树结构真相定义权
|
||||
- node / edge / subtree / projection 语义
|
||||
- 命令入口
|
||||
- 查询入口
|
||||
- 审计 / 版本 / trace 口径
|
||||
- 页面投影分发口径
|
||||
|
||||
这些都应逐步收口到 Rust kernel,而不是继续散落在:
|
||||
|
||||
- 前端页面层
|
||||
- Next route 层
|
||||
- 临时 compat adapter
|
||||
- 多套 tree / sidebar 拼装逻辑
|
||||
|
||||
### 2.3 长期正确形态是“Rust 驾驭 Convex”
|
||||
|
||||
长期推荐形态不是:
|
||||
|
||||
- Rust 替代 Convex
|
||||
|
||||
而是:
|
||||
|
||||
- **Convex 继续作为 storage / realtime substrate**
|
||||
- **Rust 成为 tree-first graph kernel 的唯一语义拥有者**
|
||||
|
||||
也就是说:
|
||||
|
||||
> **Convex 保留底座,Rust 收口语义,前端只消费稳定 projection。**
|
||||
|
||||
### 2.4 当前主要问题不是 Convex 性能,而是前端主链边界错误
|
||||
|
||||
当前页面体感与树实时体验不理想,主因不是 Convex 不够快,而是:
|
||||
|
||||
- 主页面首屏错误依赖实验性 Rust compat/sidebar 路径
|
||||
- Sidebar 主数据链路从 Convex 实时订阅退化成 HTTP 拉取
|
||||
- Tree shell 仍是实验壳,不是真实时订阅主链
|
||||
- 树逻辑仍有一部分散落在前端拼装层
|
||||
|
||||
所以当前修正重点应当是:
|
||||
|
||||
- **恢复前端主路径的实时链路**
|
||||
- **限制实验壳进入首屏关键路径**
|
||||
- **继续把树语义收回 Rust kernel**
|
||||
|
||||
而不是直接怀疑 Convex 物理底座本身。
|
||||
|
||||
---
|
||||
|
||||
## 3. 与已有 Tree-First Graph 文档的关系
|
||||
|
||||
`/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md` 已经明确固定了四层边界:
|
||||
|
||||
1. 事实源:`tree-first graph kernel`
|
||||
2. 投影:`sidebar tree / file tree / read view / search / mindmap`
|
||||
3. 编辑器:`BlockNote / Mindmap canvas / OnlyOffice`
|
||||
4. 外挂:AI、评论、历史、回链等
|
||||
|
||||
其中关键规则已经写得非常清楚:
|
||||
|
||||
- 事实源只在 kernel
|
||||
- 投影不拥有对象真相
|
||||
- 编辑器不等于对象模型
|
||||
- 外挂只消费 kernel 或 projection
|
||||
|
||||
这份文档在该边界上进一步明确一件事:
|
||||
|
||||
> **这里的“kernel 是事实源”并不要求物理上先废弃 Convex。**
|
||||
|
||||
更准确地说:
|
||||
|
||||
- **kernel 是语义事实源**
|
||||
- **Convex 是当前推荐继续保留的物理存储与实时底座**
|
||||
|
||||
因此,长期路线不是“两个事实源并存”,而是:
|
||||
|
||||
- **一个语义真相:Rust kernel**
|
||||
- **一个底层持久化 / 实时底座:Convex**
|
||||
|
||||
---
|
||||
|
||||
## 4. 长期推荐分层
|
||||
|
||||
## 4.1 Convex Substrate
|
||||
|
||||
Convex 长期保留为底层能力面,职责包括:
|
||||
|
||||
- 主数据持久化
|
||||
- 附件与对象存储协作
|
||||
- 当前态读写落账
|
||||
- 实时订阅能力
|
||||
- 当前 deployment / auth / tooling 基础设施
|
||||
|
||||
这层不应再承载散落的页面级语义。
|
||||
|
||||
### 4.1.1 Convex 保留,但不再继续承担“上层树语义拼装”
|
||||
|
||||
长期应避免继续新增:
|
||||
|
||||
- 前端专用临时树拼装逻辑
|
||||
- 只为某个页面壳存在的 query 契约
|
||||
- 与 Rust kernel 并行演化的第二套页面结构规则
|
||||
|
||||
---
|
||||
|
||||
## 4.2 Rust Kernel
|
||||
|
||||
Rust kernel 长期应成为:
|
||||
|
||||
- node / edge / subtree / projection 的唯一语义拥有者
|
||||
- 唯一命令入口
|
||||
- 唯一查询语义入口
|
||||
- 唯一排序 / 子树 / 引用 / 投影规则来源
|
||||
- 唯一版本 / trace / audit 规则来源
|
||||
|
||||
### 4.2.1 当前应重点收口的 kernel 语义
|
||||
|
||||
优先级最高的是:
|
||||
|
||||
- `sidebar_tree`
|
||||
- `page_tree`
|
||||
- `file_tree`
|
||||
- `read_view`
|
||||
- `mindmap projection`
|
||||
- `search_results`
|
||||
|
||||
也就是说,前端不应再拥有:
|
||||
|
||||
- 页面树结构的独立真相
|
||||
- 文件树行语义的独立真相
|
||||
- Sidebar 视图拼装的独立真相
|
||||
|
||||
它们都应回到 Rust kernel 定义,再由底层数据承接。
|
||||
|
||||
---
|
||||
|
||||
## 4.3 Rust Web
|
||||
|
||||
Rust Web 层长期继续按 `axum` 方向推进,职责包括:
|
||||
|
||||
- API
|
||||
- SSR 页面壳
|
||||
- SSE / WS
|
||||
- projection 请求分发
|
||||
- 鉴权上下文、workspace 上下文、trace 注入
|
||||
- 为前端 islands 提供稳定读取与流式协议
|
||||
|
||||
### 4.3.1 Rust Web 的定位
|
||||
|
||||
Rust Web 不是第二套业务内核。
|
||||
|
||||
它应当:
|
||||
|
||||
- 承接 Web transport
|
||||
- 调用 Rust kernel
|
||||
- 利用底层 Convex 数据与实时能力
|
||||
- 给页面壳输出稳定 projection
|
||||
|
||||
它不应:
|
||||
|
||||
- 在 route 层重新发明树语义
|
||||
- 在 compat 层长期保存第二套逻辑
|
||||
|
||||
---
|
||||
|
||||
## 4.4 View Shell
|
||||
|
||||
长期页面模型继续建议:
|
||||
|
||||
- server-first
|
||||
- 阅读优先
|
||||
- 少量 islands hydration
|
||||
|
||||
也就是:
|
||||
|
||||
- 页面先出来
|
||||
- 阅读先可用
|
||||
- 局部交互再进浏览器
|
||||
- 编辑器最后挂载
|
||||
|
||||
这与 `/mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md` 的方向一致。
|
||||
|
||||
---
|
||||
|
||||
## 4.5 Browser Islands
|
||||
|
||||
浏览器端长期只保留必要交互壳:
|
||||
|
||||
- Sidebar 交互
|
||||
- 文件树交互
|
||||
- 搜索交互
|
||||
- AI bridge panel
|
||||
- Mindmap 交互
|
||||
- `BlockNote` 编辑岛
|
||||
|
||||
浏览器端不再承担对象真相定义。
|
||||
|
||||
---
|
||||
|
||||
## 5. 长期运行原则
|
||||
|
||||
长期固定以下原则:
|
||||
|
||||
### 5.1 不拆 Convex 主底座
|
||||
|
||||
- 不为了“Rust 化”先拆掉当前自托管 Convex。
|
||||
- 不引入新的第二主数据库去与 Convex 长期双写对抗。
|
||||
- 不让本地缓存、本地 SQLite、浏览器存储升级为主事实层。
|
||||
|
||||
### 5.2 Rust 拥有语义主导权
|
||||
|
||||
- 新增树规则、页面结构规则、引用规则、投影规则,只能进 Rust kernel。
|
||||
- 不再把新的业务规则继续写回前端布局层、Next route 层或 compat adapter。
|
||||
|
||||
### 5.3 前端不再定义树真相
|
||||
|
||||
- 前端只能消费 projection。
|
||||
- 前端可做乐观更新,但必须以 Rust 定义的命令/投影契约为准。
|
||||
- 不再允许多个 tree adapter 在前端各自维护独立结构语义。
|
||||
|
||||
### 5.4 实验壳不进入首屏关键主链
|
||||
|
||||
- Rust tree shell、compat sidebar 等实验路径,在未完成稳定实时协议前,不允许阻塞主页面首屏。
|
||||
- 任何实验壳都必须有明确 fallback,且 fallback 不影响用户进入页面。
|
||||
|
||||
---
|
||||
|
||||
## 6. 当前实现审计
|
||||
|
||||
以下结论基于 2026-04-17 当前仓库代码,而不是早期方案假设。
|
||||
|
||||
## 6.1 当前已经落地的部分
|
||||
|
||||
### 6.1.1 Sidebar 主链已恢复为“Convex live 优先,HTTP fallback 兜底”
|
||||
|
||||
当前主数据链路不是“默认退化成 HTTP 拉取”。
|
||||
|
||||
已确认:
|
||||
|
||||
- `useSidebarData` 先走 `useConvexSidebarData`
|
||||
- `useConvexSidebarData` 内部使用 Convex `useQuery`
|
||||
- 只有没有 live subscription 且允许 fallback 时,才启用 `/api/sidebar` + React Query
|
||||
|
||||
这说明当前 Sidebar 主链已经回到:
|
||||
|
||||
- Convex realtime substrate 为主
|
||||
- HTTP route 仅作兜底和兼容
|
||||
|
||||
### 6.1.2 `/api/sidebar` 已不是旧 compat 主路径,而是 Rust query envelope + Convex transport
|
||||
|
||||
当前 `/api/sidebar` 在 Convex 模式下会:
|
||||
|
||||
1. 建立 `buildDocumentBridgeContext`
|
||||
2. 构造 `sidebar.dataset.list` query envelope
|
||||
3. 解析 Rust bridge query plan
|
||||
4. 通过 Convex client 执行 transport
|
||||
5. 再映射回前端 `SidebarInitialData`
|
||||
|
||||
这意味着当前服务端查询链路已经是:
|
||||
|
||||
- Rust 负责 query 语义与 envelope
|
||||
- Convex 负责底层执行与数据承接
|
||||
|
||||
不是旧意义上的“前端自己拼 sidebar 数据”。
|
||||
|
||||
### 6.1.3 Tree shell 已被收紧为显式开关,默认关闭
|
||||
|
||||
当前运行时边界已经改成:
|
||||
|
||||
- 浏览器公开 runtime 已不再暴露 `mnoteWebBaseUrl / mnoteWebTreeShellEnabled`
|
||||
- `mnote-web` 默认监听地址已改为 `127.0.0.1:0`,不再默认绑定 `3104`
|
||||
- `/tree`、`/document-debug` 仅在 `MNOTE_WEB_ENABLE_DEBUG_SHELL_ROUTES=1` 时注册
|
||||
- legacy tree shell / document runtime smoke 必须显式传入 `MNOTE_WEB_SMOKE_BASE_URL`
|
||||
|
||||
这说明 tree shell 当前定位已经收口为“显式 debug/runtime 对照壳”,不再是默认首屏主链。
|
||||
|
||||
### 6.1.4 第一批 tree command 已接入 Rust command envelope
|
||||
|
||||
当前至少以下页面树命令已经接入 bridge / envelope 主链:
|
||||
|
||||
- `documents.create`
|
||||
- `documents.title.update`
|
||||
- `documents.move`
|
||||
- `documents.delete`
|
||||
- `documents.restore`
|
||||
- `documents.purge`
|
||||
|
||||
其中 `create / rename / move` 已进一步收成共享 `tree-command-client`,并被 Sidebar、DocumentContent 等主入口复用;`CustomSideMenu` 已退到 `recycle/` 历史参考区。
|
||||
|
||||
### 6.1.5 Rust Web 正式实时树事件流已经有方案文档,但还不是运行中主链
|
||||
|
||||
`design/rust-web-tree-realtime-event-stream-v1.md` 已经明确:
|
||||
|
||||
- Convex 是 realtime substrate
|
||||
- Rust 是 semantic owner
|
||||
- Rust Web 负责正式 SSE / WS transport
|
||||
|
||||
但当前仓库里真正运行中的树主链,仍然不是这套正式 stream。
|
||||
|
||||
## 6.2 当前仍存在的差距
|
||||
|
||||
### 6.2.1 Tree shell 仍然是显式实验壳,不是正式主链壳
|
||||
|
||||
当前 tree shell 已被明确降级为:
|
||||
|
||||
- 显式开关
|
||||
- iframe + `postMessage`
|
||||
- ready timeout fallback
|
||||
|
||||
因此它现在适合作为:
|
||||
|
||||
- picker / filetree / tree viewer 的增强壳
|
||||
- UI 协议验证壳
|
||||
|
||||
而不是首页或 Sidebar 首屏前提。
|
||||
|
||||
### 6.2.2 Tree stream 已接入正式 consumer,但 delta 真相还不是最终形态
|
||||
|
||||
当前已经落地:
|
||||
|
||||
- Rust Web `workspace / subtree` snapshot stream
|
||||
- `snapshot / delta / resync` 协议
|
||||
- 前端 `useSidebarTreeStream` 正式 consumer
|
||||
|
||||
但当前 `delta` 仍是前端基于已有 `sidebar dataset builder` 做最小重建,不是 Rust 直接下发的细粒度 projection delta 真相。
|
||||
|
||||
### 6.2.3 页面 subtree 仍以本地 projection 组装为主
|
||||
|
||||
当前文档页已去掉 synthetic projection id,但正文 subtree 仍主要由前端本地 `buildPageSubtreeProjection` 生成。
|
||||
|
||||
这意味着:
|
||||
|
||||
- Sidebar / file tree 的 projection 契约已明显收口
|
||||
- 文档正文 `page_tree / read_view` 仍未完全切成 Rust server-first projection
|
||||
|
||||
### 6.2.4 SSR 页面壳已经验证边界,但 server-first 分发仍有继续收口空间
|
||||
|
||||
当前已经确认:
|
||||
|
||||
- Rust Web `kernel projection` 路由可通过测试
|
||||
- 首页 smoke 继续证明 3000 主链不依赖 3104 可用
|
||||
- `(app)` 首屏仍维持“先可进入页面”的安全边界
|
||||
|
||||
但服务端侧边栏首屏数据仍是安全优先的稳定路径,并未把所有读取都强制切成 Rust Web 首选。
|
||||
|
||||
### 6.2.5 代码层还有存量 warnings
|
||||
|
||||
当前相关 lint 均为 `0 error`,但仍保留一些历史 warning,主要集中在:
|
||||
|
||||
- `sidebar.tsx`
|
||||
- `recycle/wolai-frontend/src/components/editor/menus/CustomSideMenu.tsx`
|
||||
|
||||
这些不是本批必须修复的主链 bug,但后续仍应继续压缩。
|
||||
|
||||
---
|
||||
|
||||
## 7. 与目标架构的差距结论
|
||||
|
||||
如果按“Convex 保留底座,Rust 收口语义,前端只消费 projection”来打分,当前状态更接近:
|
||||
|
||||
- Convex substrate:成立
|
||||
- Rust command/query envelope:已进入主路径
|
||||
- 前端首屏不依赖实验壳:成立
|
||||
- Rust Web 正式 realtime snapshot stream:已成立
|
||||
- Sidebar 主路径消费统一 stream/projection:已成立
|
||||
- 页面 subtree / read view 完整 server-first projection:仍未完全成立
|
||||
|
||||
因此当前真正剩余的差距,不再是“是否拆 Convex”,而主要变成下面两点:
|
||||
|
||||
1. 页面正文 subtree / read view 仍有一部分语义停留在前端本地 projection。
|
||||
2. tree stream 的长期目标仍应继续从“snapshot + 最小 delta”推进到“Rust 直接分发更稳定的 projection/delta 真相”。
|
||||
|
||||
---
|
||||
|
||||
## 8. Checklist
|
||||
|
||||
下面 checklist 分成“当前已完成”和“后续待完成”,后续维护时应优先更新这里。
|
||||
|
||||
## 8.1 当前已完成
|
||||
|
||||
- [x] 固定长期口径:不拆 Convex,保留为 storage / realtime substrate。
|
||||
- [x] 固定长期口径:Rust 作为 tree-first graph 的 semantic owner。
|
||||
- [x] Sidebar 主链恢复为 Convex `useQuery` live subscription 优先,HTTP fallback 只作兜底。
|
||||
- [x] `/api/sidebar` 已接入 Rust query envelope,并通过 Convex transport 执行。
|
||||
- [x] 浏览器公开 runtime 已移除 `mnoteWebBaseUrl / mnoteWebTreeShellEnabled`。
|
||||
- [x] legacy tree shell / document runtime 已降级为显式 debug smoke,不再混入默认主链。
|
||||
- [x] `create / rename / move` 已接入 shared tree command client。
|
||||
- [x] `create / title.update / move / delete / restore / purge` 已接入 Rust bridge / command envelope 主链。
|
||||
- [x] 已产出 `tree-command-envelope-cutover-stage1-v1.md`,明确第一批命令收口边界。
|
||||
- [x] 已产出 `rust-web-tree-realtime-event-stream-v1.md`,明确正式实时树事件流分层方案。
|
||||
|
||||
## 8.2 本批新增完成项
|
||||
|
||||
### P0:主链边界继续固定
|
||||
|
||||
- [x] 首页、Sidebar 与文档页首屏继续保持“不依赖 `3104` tree shell 或 compat viewer 才能进入”。
|
||||
- [x] tree shell 已继续固定为显式增强能力,不再回流为默认主路径。
|
||||
- [x] 首页 smoke、Sidebar live 优先与 tree shell fallback 回归检查已补到当前 harness 主链。
|
||||
|
||||
### P1:tree command 收口继续推进
|
||||
|
||||
- [x] `delete / restore / purge` 已统一走 shared tree command client。
|
||||
- [x] `pageReference` 删除路径已移出组件内直调 route,改走共享 command client。
|
||||
- [x] `embed` 已切成独立 `documents.embed` Rust page-tree command,而不再停留在 `documents.save` 过渡语义。
|
||||
- [x] `copy-tree` 已收口到 shared tree command client,并保持 Rust bridge command 主链。
|
||||
|
||||
### P2:树规则与 projection 契约继续回收
|
||||
|
||||
- [x] `targetParentId / sortOrder / subtree move legality` 已形成可测试的统一前端边界,并通过 Rust/bridge 相关回归验证。
|
||||
- [x] `sidebar_tree / page_tree / file_tree` 的主路径 projection 契约已继续统一,去掉主路径 synthetic projection fallback。
|
||||
- [x] Sidebar / picker / host 主路径已继续压缩本地树真相,只消费统一 projection。
|
||||
- [x] compat / fallback 中重复的主路径树拼装已继续清理,避免再把旧树真相带回主链。
|
||||
|
||||
### P3:Rust Web 正式 realtime 主链已打通第一阶段
|
||||
|
||||
- [x] Rust Web 已落地正式 `workspace / subtree` snapshot stream,不再是 placeholder。
|
||||
- [x] 已建立 `snapshot + delta + resync` 的前后端基础协议。
|
||||
- [x] Sidebar 已接入 `useSidebarTreeStream` 正式 consumer。
|
||||
- [x] tree stream 真实连接路径已对齐 Rust Web `/api/stream/events`,修复了前端错误连接 `/api/tree/events` 的运行时 bug。
|
||||
|
||||
### P4:页面壳与 QA 收口
|
||||
|
||||
- [x] Rust Web `kernel projection` SSR 路由已通过测试,主链继续保持 server-first 页面壳与安全 fallback。
|
||||
- [x] 文档页 subtree 已移除 synthetic projection id,避免前端继续暴露自造 projection 标识。
|
||||
- [x] 前端全量测试已恢复通过,`AiAgentPanel` 过期断言已更新为当前稳定语义。
|
||||
- [x] 本批相关 smoke、vitest、cargo test、eslint 已全部通过既定 validation。
|
||||
|
||||
### 后续演进观察
|
||||
|
||||
下面这些仍是后续长期演进方向,但不再作为本批 checklist:
|
||||
|
||||
- 页面正文 `page_tree / read_view` 仍应继续向 Rust server-first projection 收口。
|
||||
- tree stream 仍可继续从“snapshot + 最小 delta”推进到更稳定的 Rust 侧 projection/delta 分发。
|
||||
- 若后续要让 Rust Web 承接更多 SSR 数据分发,应继续坚持“3104 不可用时 3000 仍能进入页面”的安全边界。
|
||||
- 现有 lint warnings 仍需后续逐步清理,但不影响当前批次主链验收。
|
||||
|
||||
---
|
||||
|
||||
## 9. 最终固定口径
|
||||
|
||||
截至当前仓库状态,可以固定为:
|
||||
|
||||
> **mnote 的长期路线不是拆掉 Convex,而是在 Convex 继续作为底层 substrate 的前提下,让 Rust 逐步拿回 tree-first graph 的 query、command、projection 与 realtime 语义主导权。**
|
||||
|
||||
当前已经完成的是:
|
||||
|
||||
> **主路径边界已基本纠正,tree shell 已降级为显式实验增强,Sidebar 与第一批 tree command 已进入 Convex substrate + Rust envelope 主链。**
|
||||
|
||||
未来还需要完成的是:
|
||||
|
||||
> **让树规则真正从前端退出,并让 Rust Web 的正式 realtime transport 接住统一主链。**
|
||||
Reference in New Issue
Block a user