chore: retire remaining convex infrastructure

- move self-hosted Convex infra and root placeholder into recycle

- update architecture docs to remove active infra/convex deployment guidance

- extend local-first Convex guard to block retired infra regressions
This commit is contained in:
lix-2026
2026-05-22 19:31:20 +08:00
parent 47e224d419
commit 42fb58310c
13 changed files with 61 additions and 21 deletions
+3 -3
View File
@@ -40,8 +40,8 @@
Rust Web route、transport、compat、tree shell、projection 分发先看这里。
- `/mnt/Data1T/mnote/wolai-backend/app/`
辅助后端、异步处理、接口配合先看这里。
- `/mnt/Data1T/mnote/infra/convex/`
Convex 自托管服务基础设施先看这里;只服务显式 cloud source / compat / sync replica 或历史数据导出,不再被 `desktop:hot` / `dev:hot` 默认启动链路要求。
- `/mnt/Data1T/mnote/recycle/20260522-convex-runtime-retirement/infra/convex/`
Convex 自托管服务基础设施已软删除到回收区;只作为显式 cloud source / compat / sync replica 或历史数据导出的历史对照,不再被 `desktop:hot` / `dev:hot` 默认启动链路要求。
- `/mnt/Data1T/mnote/src/components/onlyoffice/`
只在处理 OnlyOffice 静态资源、插件或兼容问题时进入。
- `/mnt/Data1T/mnote/recycle/`
@@ -124,7 +124,7 @@
- 前端开发(已迁移至 Rust SSR):`npm run desktop:hot` 启动后直接访问 `http://localhost:3000`
- 前端检查:Rust 测试 `cargo test -p mnote-web`Rust SSR 与 API),旧 React 前端已移入 recycle
- 后端开发:`cd /mnt/Data1T/mnote/wolai-backend && uvicorn app.main:app --reload --port 8000`
- Convex 自托管:仅在显式 cloud / compat / sync replica 或历史导出场景参考 `/mnt/Data1T/mnote/infra/convex/README.md`
- Convex 自托管:仅在显式 cloud / compat / sync replica 或历史导出场景参考 `/mnt/Data1T/mnote/recycle/20260522-convex-runtime-retirement/infra/convex/README.md`
## 默认测试账号
+2 -2
View File
@@ -49,8 +49,8 @@
`convex/` functions 源码已退役并软删除到这里;不再作为 active deploy source。历史 `schema.ts``aiSessions.ts`、Auth functions 仅用于审计 / 迁移对照,默认控制面已由 Rust SQLite control-plane 承接。
- `/mnt/Data1T/mnote/recycle/wolai-frontend/convex/`
已随 wolai-frontend 移入 recycle,不允许作为当前 Convex deploy fallback。
- `/mnt/Data1T/mnote/infra/convex/`
Convex 自托管服务基础设施;只服务显式 cloud source / compat / sync replica 或历史数据导出,不再被 `desktop:hot` / `dev:hot` 默认启动链路要求。
- `/mnt/Data1T/mnote/recycle/20260522-convex-runtime-retirement/infra/convex/`
Convex 自托管服务基础设施已软删除到回收区;只作为显式 cloud source / compat / sync replica 或历史数据导出的历史对照,不再被 `desktop:hot` / `dev:hot` 默认启动链路要求。
- `/mnt/Data1T/mnote/wolai-backend/`
辅助后端与异步处理,不是当前页面主链。
+2 -2
View File
@@ -27,7 +27,7 @@
| `rust/crates/mnote-cli/` | CLI tool (`sidebar dataset`, `page get/create/title/save/move`, `block insert/patch`) |
| `rust/crates/storage-convex-bridge/` | Convex compat / cloud source / sync-replica bridge for Rust |
| `recycle/20260522-convex-runtime-retirement/convex/` | Retired root Convex functions source retained for audit / migration reference |
| `infra/convex/` | Docker Compose for self-hosted Convex backend, used only for explicit cloud/compat/sync-replica paths |
| `recycle/20260522-convex-runtime-retirement/infra/convex/` | Retired self-hosted Convex backend compose kept only for historical cloud/compat/sync-replica reference |
| `infra/onlyoffice/` | Docker Compose for OnlyOffice |
| `scripts/` | Node.js dev/build scripts + Playwright smoke tests |
| `design/` | Architecture design documents organized by domain |
@@ -64,7 +64,7 @@
- **Local-first default**: start from Rust `mnote-web`, LocalFS/local_folder projection, Page Aggregate, File Tree, Resource Tree, and SQLite control-plane auth/session/actor. Use Convex paths only for explicit cloud source, compat, sync-replica, migration, or rollback work.
- **Smoke test pattern**: standalone Playwright scripts under `scripts/task-*.js` using a shared harness (`ensureAuthenticated`, `createTempDocument`, `cleanupDocuments`). All use `"use strict"` and `require("playwright")` (`scripts/task110-page-title-single-truth-smoke.js:1-4`).
- **Rust workspace**: edition 2021, resolver "2", MIT license. All crates inherit workspace version (`rust/Cargo.toml:2-8`).
- **Convex boundary**: root `convex/` has been retired to `recycle/20260522-convex-runtime-retirement/convex/`; do not recreate it as an active deploy source without a new architecture decision. `recycle/wolai-frontend/convex` is also historical. Keep Rust `transport/convex.rs` and `storage-convex-bridge` as explicit cloud/compat boundaries; do not mechanically delete them with the retired functions source.
- **Convex boundary**: root `convex/` has been retired to `recycle/20260522-convex-runtime-retirement/convex/`; `infra/convex/` has been retired to `recycle/20260522-convex-runtime-retirement/infra/convex/`; do not recreate either as an active deploy source without a new architecture decision. `recycle/wolai-frontend/convex` is also historical. Keep Rust `transport/convex.rs` and `storage-convex-bridge` as explicit cloud/compat boundaries; do not mechanically delete them with the retired functions source.
- **AI editing path**: local-first Markdown editing should prefer `currentFile + selection + allowedRoots / aiAccessScope + agent native patch/diff + watcher sync`. `mnote.doc.*` / `mnote.block.*` are cloud, remote, compat, or complex-structure helpers.
- **Bug tracking**: bugs organized by design domain directory (e.g. `bugs/04-tree-domain/process/`), moved to `done/` when fixed (`bugs/README.md`).
- **Design docs**: organized by domain in `design/`, with `process/` (in-progress) and `done/` (completed) subdirs (`design/README.md`).
@@ -55,7 +55,7 @@ codegraph status
已更新说明:
- `infra/convex/README.md`
- `recycle/20260522-convex-runtime-retirement/infra/convex/README.md`
- `AGENTS.md`
- `REASONIX.md`
@@ -104,7 +104,7 @@ npm ls --depth=0 --json
- `home/`
- `.sandbox-home`
- `.sandbox-tmp`
- `.convex-tmp`
- `recycle/20260522-convex-runtime-retirement/local-state/.convex-tmp`
当前该回收目录体积约 `912K`
@@ -230,4 +230,3 @@ find -L node_modules -maxdepth 2 -type l -printf 'BROKEN %p -> %l\n'
- 不从 `recycle` 中回退引用运行时代码。
- 新增 CodeGraph 主索引排除项时,应优先判断其是否属于参考代码、生成缓存、测试输出、回收区或本地辅助功能。
- 后续依赖变化后应重新运行 `pnpm install`,CodeGraph 在代码变化后需要重建或等待 watcher 更新;若排除规则变化,需显式重新初始化 / 重建索引。
@@ -530,7 +530,7 @@
- `rust/crates/mnote-web/src/routes/local_access_policy.rs`
- `rust/crates/mnote-web/src/routes/hermes_client.rs`
- `rust/crates/core-protocol/src/ai.rs`
- `infra/convex/`
- `recycle/20260522-convex-runtime-retirement/infra/convex/`(历史 Convex 自托管对照;不作为 active 部署入口)
### 9.2 参考代码位置
@@ -1040,9 +1040,9 @@ local-first 下,AI 的长期主路径不是继续发明一套 MNote 专用编
#### G. 控制面收口与旧数据迁移
- [x] G1. 历史 Convex 控制面字段边界冻结;当前默认控制面已替换为 SQLite。
- 文件:`infra/convex/``rust/crates/mnote-web/src/transport/convex.rs`
- 文件:`recycle/20260522-convex-runtime-retirement/infra/convex/``rust/crates/mnote-web/src/transport/convex.rs`
- 完成定义:新增 Convex 调用只能属于显式 cloud source、compat、migration 或 sync replica;默认 auth、membership、share grants、sync state、AI policy、ACP/Hermes runtime session 走 Rust SQLite control-plane。
- 完成证据:`infra/convex/README.md``docker-compose.yml` 已明确 Convex 自托管仅作为显式 cloud source / compat / sync replica 或历史数据导出;`transport/convex.rs` 保留为 cloud/compat transport 边界;`scripts/check-local-first-convex-guard.js --self-test` 已通过,并新增 active `convex/` 目录防重新引入未标注 documents/media 主存储表或函数。
- 完成证据:`recycle/20260522-convex-runtime-retirement/infra/convex/README.md``docker-compose.yml` 已明确 Convex 自托管仅作为显式 cloud source / compat / sync replica 或历史数据导出;`transport/convex.rs` 保留为 cloud/compat transport 边界;`scripts/check-local-first-convex-guard.js --self-test` 已通过,并新增 active `convex/` `infra/convex` 退役目录回流拦截,防重新引入未标注 documents/media 主存储表或函数。
- [x] G2. 旧 Convex workspace 导出为 local workspace。
- 文件:新增迁移脚本,优先放 `scripts/``tools/`
- 验证:fixture workspace 导出后包含 `.md`、assets、`.mnote/page-ids.json`
@@ -790,7 +790,7 @@ Ownership
- [x] `/api/realtime/ws` 能收到控制面事件。
- [x] AI allowed roots 不扩大到未授权目录。
- [x] `NEXT_PUBLIC_CONVEX_URL=http://127.0.0.1:9` 时 local-first 主路径 smoke 通过。
- [x] `infra/convex` 不再被 `npm run desktop:hot` 或默认启动链路要求。
- [x] `infra/convex` 已软删除到 `recycle/20260522-convex-runtime-retirement/infra/convex/`不再被 `npm run desktop:hot` 或默认启动链路要求。
- [x] 根 `convex/` functions 源码已软删除到 `recycle/20260522-convex-runtime-retirement/convex/``scripts/run-convex-deploy.js` 已随之归档。
- [x] `package.json` / npm lock / pnpm lock 已移除只服务根 Convex functions 的 `@auth/core``@convex-dev/auth``convex` 依赖。
- [x] 文档更新,明确 Convex 只作为历史迁移源或显式 legacy 兼容入口。
@@ -850,6 +850,6 @@ Ownership
- 根 `convex/` 已按软删除规则移动到 `recycle/20260522-convex-runtime-retirement/convex/`,只作为历史审计 / 迁移对照素材。
- `scripts/run-convex-deploy.js` 已移动到 `recycle/20260522-convex-runtime-retirement/scripts/run-convex-deploy.js`;默认仓库不再提供根 Convex functions deploy 入口。
- `package.json``package-lock.json``pnpm-lock.yaml` 已移除只服务根 Convex functions 的 `@auth/core``@convex-dev/auth``convex` 依赖。
- `npm run desktop:hot``npm run dev:hot` 均已确认只启动 Rust `mnote-web` hot 链路,不启动 Convex`infra/convex` 仍保留为显式 cloud / compat / sync replica 服务基础设施。
- `npm run desktop:hot``npm run dev:hot` 均已确认只启动 Rust `mnote-web` hot 链路,不启动 Convex`infra/convex` 已软删除到 `recycle/20260522-convex-runtime-retirement/infra/convex/`,只作为历史对照,不再作为默认启动链路或 active 服务基础设施。
- `gateway.rs` 已移除旧 Convex Auth action proxy / username lookup / auth response cookie helper,默认 `/api/auth` 只走 SQLite session。
- `scripts/check-local-first-convex-guard.js` 更新为拦截重新新增根 `convex/schema.ts``auth.ts``users.ts``aiSessions.ts`,防止退役 functions 源码回流默认控制面。
@@ -163,7 +163,7 @@
当前仓库状态下:
- `infra/convex/`承载自托管 Convex backend/dashboard 的 Docker 与说明,不是 functions/schema 源目录;
- `recycle/20260522-convex-runtime-retirement/infra/convex/`保留自托管 Convex backend/dashboard 的 Docker 与说明作为历史对照,不是 functions/schema 源目录;
- `wolai-frontend/convex/` 已不在当前工作区可读路径中,不能作为新的实现落点;
- `recycle/wolai-frontend/convex/` 只作为历史参考;
- 本轮历史执行曾在仓库根 `convex/` 建立 ACP-local runtime store 的最小 functions/schema,并让 `scripts/run-convex-deploy.js` 优先以仓库根作为 Convex CLI cwd;当前这些源码和脚本已退役到 `recycle/20260522-convex-runtime-retirement/`
@@ -210,7 +210,7 @@ struct MessageRow {
### 4.2 现有代码改动范围
- **历史项**:曾新增/修改根 `convex/` 相关 schema / functions,承接 ACP-local session/runtime 记录、用户隔离查询、TTL 清理;当前默认应改 Rust SQLite control-plane schema/API`infra/convex/` 只负责显式 cloud / compat 服务部署
- **历史项**:曾新增/修改根 `convex/` 相关 schema / functions,承接 ACP-local session/runtime 记录、用户隔离查询、TTL 清理;当前默认应改 Rust SQLite control-plane schema/API`infra/convex/` 已软删除到 recycle,只负责历史对照,不再作为 active 服务部署
- **修改** `acp_session_manager.rs` — 按架构决策写入 ACP-local 消息或只写 runtime/event 索引
- **修改** `hermes_client.rs` — 新增 session 管理 route handlers
- **修改** `routes/mod.rs` — 注册新 route
@@ -359,7 +359,7 @@ Phase CP2 用户体验)
- `node scripts/run-convex-deploy.js`:历史验证通过;当时部署入口已避免用根最小 `convex/` 覆盖完整本地 Convex schema。当前默认启动链路不再部署 Convex。
- `node` 提取并 `new Function(SIDEBAR_TREE_JS)`:通过。
- `npx convex --version`1.39.1。
- `CONVEX_TMPDIR=/mnt/Data1T/mnote/.convex-tmp npx convex codegen --dry-run --typecheck try`:通过
- 历史验证:`CONVEX_TMPDIR=/mnt/Data1T/mnote/.convex-tmp npx convex codegen --dry-run --typecheck try` 曾通过;当前 `.convex-tmp` 已软删除到 `recycle/20260522-convex-runtime-retirement/local-state/.convex-tmp`,不再作为 active codegen 临时目录
- Playwright browser smoke`127.0.0.1:3000` 页面内 fetch 创建两个用户的 ACP session,并验证 list/detail/resume/rename/delete 与用户隔离,全部通过;测试数据已调用 delete 清理。
- 回归收口:`tree_command_purge_uses_tree_command_protocol` 中 purge 请求未携带排序,返回 `sortOrder: null` 符合当前 route 语义,已同步修正测试断言。
- 回归收口:`hermes_client` / `hermes_tools` / `page_ai_workflow` 测试统一使用 crate 级 Hermes 环境锁,避免完整并发测试时互相修改 `HERMES_HOME` / `MNOTE_WEB_HERMES_*`
@@ -21,7 +21,7 @@
- `design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md`
- `design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md`
- `design/05-editor-mainline/done/5-5-1-page-aggregate-contract-v1.md`
- `infra/convex/README.md`
- `recycle/20260522-convex-runtime-retirement/infra/convex/README.md`
- `wolai-frontend/convex/`
- `rust/crates/storage-convex-bridge/`
- `rust/crates/mnote-web/src/transport/convex.rs`
@@ -36,7 +36,7 @@
整体方向与设计主线基本一致:Convex 没有被拆掉,仍承担本地自托管存储、文件和实时底座;Rust Web 已注册 `/api/page-aggregate/:document_id``/api/tree/events`;前端 tree stream 已直接使用 `EventSource("/api/tree/events")`Next 的 `/api/documents/page``/api/mnote-web/stream` 已明确作为 410 compat 边界退场。
但当前实现仍是明显过渡态,主要问题集中在三处:
但当前实现仍是明显过渡态,主要问题集中在三处;本文里的 `infra/convex` 现在应按历史对照理解,因为自托管 compose 已软删除到 recycle,不再作为 active 部署入口
1. Page Aggregate 读链虽然是 Rust endpoint,但实际数据仍由 `documents:getMeta` + `documents:getContent` 分别取回后在 bridge-runtime 中拼 projection`source` 标识存在“看起来比真实实现更 canonical”的风险。
2. Rust Web 的 `/api/documents/title``/api/documents/options` 与 Next route 的 page write adapter 在 bridge artifact 记录上不一致;tree stream 依赖 bridgeLogs 时,Rust page write 路径可能漏掉 command/domain event。
@@ -155,7 +155,7 @@ tree command route 是一致的:
正向证据:
- `infra/convex/README.md` 明确自托管 Convex backend/dashboard、HTTP Actions 和文件存储。
- `recycle/20260522-convex-runtime-retirement/infra/convex/README.md` 明确自托管 Convex backend/dashboard、HTTP Actions 和文件存储的历史对照口径
- `wolai-frontend/convex/schema.ts:35``:91``documents` 表继续承接页面结构、正文、页面设置、统计字段。
- `wolai-frontend/convex/schema.ts:121``:162``media_assets``_storage` 字段保留文件底座。
- `rust/crates/storage-convex-bridge/README.md:5``:13` 明确 bridge 只做协议到 Convex 读写请求映射,不复制主事实层、不维护第二数据库。
+41
View File
@@ -69,6 +69,17 @@ const RETIRED_ROOT_CONVEX_PATHS = [
},
];
const RETIRED_CONVEX_INFRA_PATHS = [
{
name: "Convex 自托管 infra",
pattern: /^infra\/convex(?:\/|$)/,
},
{
name: "根 storage-convex-bridge 占位文件",
pattern: /^storage-convex-bridge$/,
},
];
// ─── SQLite 迁移期 forbid ───────────────────────────────────
// 在 SQLite 控制面迁移阶段(Phase 1-5),新增 Convex 控制面代码
// users/workspaces/sessions/policies/audit/outbox/share 等)
@@ -122,6 +133,7 @@ function usage() {
"",
`如需保留明确的 cloud/compat 直连,请在同一新增行加入 ${WAIVER}`,
"根 convex/ functions 源码已退役;如确需新增显式 cloud/compat Convex functions,应先放到明确的辅助目录并更新 guard。",
"infra/convex 自托管基础设施已退役到 recycle;不要重新引回 active 路径。",
`SQLite 迁移期中新增 Convex 控制面代码(users/workspaces/grants/share 等)需加 ${MIGRATION_PERIOD_WAIVER} 标注迁移例外。`,
].join("\n");
}
@@ -179,6 +191,10 @@ function isRetiredRootConvexPath(filePath) {
return RETIRED_ROOT_CONVEX_PATHS.some((entry) => entry.pattern.test(filePath));
}
function isRetiredConvexInfraPath(filePath) {
return RETIRED_CONVEX_INFRA_PATHS.some((entry) => entry.pattern.test(filePath));
}
function isAllowedRuntimeAdapter(filePath) {
return (
filePath === "rust/crates/mnote-web/src/transport/convex.rs" ||
@@ -280,6 +296,15 @@ function checkLine(row) {
];
}
if (isRetiredConvexInfraPath(row.filePath)) {
return [
{
...row,
reason: `${RETIRED_CONVEX_INFRA_PATHS.find((entry) => entry.pattern.test(row.filePath)).name} 已软删除到 recycle;不要重新引回 active 路径或默认启动链路。`,
},
];
}
if (!isRuntimePath(row.filePath) || isAllowedRuntimeAdapter(row.filePath)) {
if (!isActiveConvexPath(row.filePath)) {
return [];
@@ -347,6 +372,16 @@ function runSelfTest() {
lineNumber: 1,
text: " workspaces: defineTable({",
},
{
filePath: "infra/convex/docker-compose.yml",
lineNumber: 1,
text: "services:",
},
{
filePath: "storage-convex-bridge",
lineNumber: 1,
text: "",
},
];
const violations = rows.flatMap(checkLine);
const labels = violations.map((item) => item.filePath);
@@ -374,6 +409,12 @@ function runSelfTest() {
if (!labels.includes("convex/workspaces_migration.ts")) {
throw new Error("self-test 失败:未拦截迁移期新增 Convex 控制面 workspaces 代码");
}
if (!labels.includes("infra/convex/docker-compose.yml")) {
throw new Error("self-test 失败:未拦截退役的 Convex infra 回流");
}
if (!labels.includes("storage-convex-bridge")) {
throw new Error("self-test 失败:未拦截根 storage-convex-bridge 占位文件回流");
}
console.log(JSON.stringify({ ok: true, guard: "local-first-convex", selfTest: true }, null, 2));
}