 可以，按你选的 1A/2B/3B，我建议的落地方案是：
                                                                                                                            
  - Convex：自托管 Docker Compose（官方）                                                                                   
  - 对象存储：MinIO（S3 兼容）                                                                                              
  - 鉴权：固定“开发用户”（仅开发态），所有权限校验先按这个用户走                                                            
  - 后端：不再以 FastAPI/Celery 为主链路，长任务改为 Convex action + scheduler；如后续需要 OCR/RAG 重计算，再让 Convex      
    action 去调用现有 services/* HTTP 服务                                                                                  
                                                                                                                            
  下面是我建议的“可执行迁移流程设计”（按阶段推进，每一阶段都能跑通）：                                                      
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ## 一、部署方案（Windows 本机）                                                                                           
                                                                                                                            
  ### A. 运行组件                                                                                                           
                                                                                                                            
  1. convex-backend（端口：3210 + 3211 actions）                                                                            
  2. convex-dashboard（端口：6791）                                                                                         
  3. minio（端口：9000 S3 API，9001 Console）                                                                               
  4. minio-init（启动时自动建 bucket）                                                                                      
                                                                                                                            
  ### B. 目录规划（建议）                                                                                                   
                                                                                                                            
  - infra/convex/                                                                                                           
      - docker-compose.yml（Convex backend + dashboard + MinIO）                                                            
      - .env（只放本机，不提交；或提交 .env.example）                                                                       
      - README.md（写清启动端口与初始化）                                                                                   
                                                                                                                            
  ### C. 关键环境变量（Convex backend 使用 MinIO 作为 S3 存储）                                                             
                                                                                                                            
  Convex 自托管支持把导出/导入/模块/用户文件/搜索索引都放到 S3，并允许通过 S3_ENDPOINT_URL 连接 MinIO。你将配置这些         
  bucket（示例名）：                                                                                                        
                                                                                                                            
  - convex-snapshot-exports                                                                                                 
  - convex-snapshot-imports                                                                                                 
  - convex-modules                                                                                                          
  - convex-user-files                                                                                                       
  - convex-search-indexes                                                                                                   
                                                                                                                            
  并在 backend 容器里设置（示例）：                                                                                         
                                                                                                                            
  - AWS_REGION=us-east-1                                                                                                    
  - AWS_ACCESS_KEY_ID=<minio key>                                                                                           
  - AWS_SECRET_ACCESS_KEY=<minio secret>                                                                                    
  - S3_ENDPOINT_URL=http://minio:9000                                                                                       
  - S3_STORAGE_EXPORTS_BUCKET=...（以及其余 4 个）                                                                          
                                                                                                                            
  > 这样后续你在 Convex 里用文件能力（上传/存储/取 URL）会自然落到 MinIO，不需要再引入 Supabase Storage 或自写一套 presigned  > 上传逻辑。                                                                                                              
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ## 二、迁移总体策略（符合“先跑通但都换掉”）                                                                               
                                                                                                                            
  你的项目目前最大的问题不是“后端”，而是数据访问散落在 Next Route Handlers + Supabase。迁移应以 “把 Supabase 数据面替换成   
  Convex” 为主线，同时把鉴权先简化为固定用户。                                                                              
                                                                                                                            
  我建议采用“门面不变、内核替换”的方式：                                                                                    
                                                                                                                            
  - 保留现有 wolai-frontend/src/app/api/**/route.ts 路由不变（前端 UI 不用立刻大改）                                        
  - 逐个把这些 route handler 内部从 supabase.* 改为 convex query/mutation/action                                            
  - 用一个总开关 USE_CONVEX=1 控制，方便随时切回 Supabase 对照（你没有用户数据，回退成本也接近 0）                          
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ## 三、阶段化详细流程（每阶段验收点明确）                                                                                 
                                                                                                                            
  ### 阶段 0：盘点与冻结范围（半天内）                                                                                      
                                                                                                                            
  目标：明确“哪些模块先迁、哪些先不动”，避免一次改爆。                                                                      
                                                                                                                            
  - 以 CODE_INDEX.md 为基准，确认实际运行入口是 wolai-frontend/（不是根目录 src/）。                                        
  - 先只迁：documents / workspaces / workspace_members / mindmap / background_tasks（足够跑主流程）                         
  - 暂不迁或延后：luckysheet_ws（你现在也没实际测试/用户）                                                                  
                                                                                                                            
  验收：列出一张迁移模块清单（我可以直接在仓库里生成 infra/convex/MIGRATION.md，你确认后再动代码）。                        
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ### 阶段 1：Convex + MinIO 跑起来（不改业务代码）                                                                         
                                                                                                                            
  目标：本机基础设施 ready。                                                                                                
                                                                                                                            
  - 在 infra/convex/ 放置 compose，docker compose up -d                                                                     
  - 生成 admin key：docker compose exec backend ./generate_admin_key.sh                                                     
  - 在 wolai-frontend/.env.local 配：                                                                                       
      - CONVEX_SELF_HOSTED_URL=http://127.0.0.1:3210                                                                        
      - CONVEX_SELF_HOSTED_ADMIN_KEY=...                                                                                    
      - USE_CONVEX=1                                                                                                        
                                                                                                                            
  验收：                                                                                                                    
                                                                                                                            
  - Dashboard 能打开：http://localhost:6791                                                                                 
  - MinIO Console 能打开：http://localhost:9001                                                                             
  - Convex CLI 能连上自托管（下一阶段会做）                                                                                 
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ### 阶段 2：在 wolai-frontend/ 初始化 Convex 项目（最小 demo）                                                            
                                                                                                                            
  目标：让前端工程具备 convex/ 目录与生成类型的能力。                                                                       
                                                                                                                            
  - 安装 convex 依赖                                                                                                        
  - 初始化 wolai-frontend/convex/（schema + demo function）                                                                 
  - 跑一次 npx convex dev（自托管模式，指向 CONVEX_SELF_HOSTED_URL）                                                        
                                                                                                                            
  验收：写一个 ping query，Next.js 页面/route 能调用到并返回结果。                                                          
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ### 阶段 3：引入“固定开发用户”与权限骨架（替代 Supabase Auth/RLS）                                                        
                                                                                                                            
  目标：所有数据访问都通过同一套“开发用户上下文”注入，避免到处散落假逻辑。                                                  
  建议实现方式：                                                                                                            
                                                                                                                            
  - wolai-frontend/src/lib/auth/devUser.ts：                                                                                
      - getDevUser() 固定返回 { userId, email, name }（从 .env.local 读取，默认常量）                                       
  - Convex functions 不接受“任意 userId 参数”，而是由 route handler 统一注入（现在固定，未来替换为真实 auth）               
                                                                                                                            
  权限策略（先最小化）：                                                                                                    
                                                                                                                            
  - 所有写操作：要求 workspace_members 存在（你可以先自动把 dev 用户加入默认 workspace）                                    
  - 所有读操作：同上                                                                                                        
  - 未来接入真实 auth 时，只需要把 getDevUser() 替换为 getAuthedUser()，Convex 侧的权限函数不变                             
                                                                                                                            
  验收：不依赖 Supabase token，也能跑通“创建默认 workspace + 创建文档”。                                                    
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ### 阶段 4：迁移核心数据模型与最小 CRUD（documents/workspaces）                                                           
                                                                                                                            
  目标：主流程跑通（侧边栏、打开文档、保存）。                                                                              
                                                                                                                            
  - 在 Convex schema 中创建对应集合（建议保留你现有 UUID 作为业务 id 字段，并建立唯一索引，避免 URL/引用大改）              
  - 实现 queries/mutations：                                                                                                
      - workspaces.getOrCreateDefaultForUser                                                                                
      - documents.listByWorkspace                                                                                           
      - documents.getById                                                                                                   
      - documents.create                                                                                                    
      - documents.updateContent（含 raw_text/index_status 等你现在写回字段）                                                
                                                                                                                            
  然后改 wolai-frontend/src/app/api/documents/**/route.ts 内部实现：                                                        
                                                                                                                            
  - 先只改：create/content/save/title/options/list 等最常用路径                                                             
  - 暂时保留 Supabase 版本分支（USE_CONVEX 开关）                                                                           
                                                                                                                            
  验收：你打开应用后能创建/读取/保存文档（数据落在 Convex），且不再访问 Supabase 表。                                       
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ### 阶段 5：迁移 mindmap 与任务（替换 Celery/trigger 的思路）                                                             
                                                                                                                            
  目标：把“异步/任务/进度”统一到 Convex。                                                                                   
                                                                                                                            
  - background_tasks：做成 Convex 表                                                                                        
  - startOcr：mutation 创建任务记录，然后 scheduler.runAfter() 触发 action                                                  
  - ocrPipeline：action 模拟 OCR（对齐你现在 wolai-backend/app/workers/tasks.py 的行为：更新进度、回写文档内容、任务        
    completed）                                                                                                             
                                                                                                                            
  验收：                                                                                                                    
                                                                                                                            
  - 前端调用“OCR/任务”相关 API 能返回 taskId                                                                                
  - 任务状态能轮询/订阅（先轮询即可）                                                                                       
  - 不再需要 wolai-backend 的 Celery 才能完成基本链路                                                                       
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  ### 阶段 6：文件存储（MinIO + Convex file storage）                                                                       
                                                                                                                            
  目标：后续做媒体/附件时不会再回到 Supabase Storage。                                                                      
                                                                                                                            
  - 保持 Convex backend 已配置 S3（MinIO）                                                                                  
  - 在 Convex 里实现：                                                                                                      
      - files.generateUploadUrl                                                                                             
      - files.saveMeta（把文件与 document/workspace 关联）                                                                  
      - files.getUrl（用于展示/下载）                                                                                       
                                                                                                                            
  验收：能上传一个文件到 Convex file storage（底层落 MinIO），并在页面拿到可访问 URL。                                      
                                                                                                                            
  ———                                                                                                                       
                                                                                                                            
  到目前为止，你已经跑通了“文档/附件 + Convex 自部署”这条主链路；接下来要做的事，本质上是：把
  USE_CONVEX=1 时仍在走 Supabase 的那些模块逐步“替换或下线”，直到项目真的只依赖 Convex。                
                                                                                                        
  - 先确认“还剩哪些 Supabase 依赖”                                                                      
      - wolai-frontend/src/ 下仍有大量 Supabase 路由/工具在用：mindmap、references（RPC）、onlyoffice、 
        luckysheet、ai-agent、sidebar、search(recent) 等（目前大概率是“Supabase 分支/兜底分支”）。      
      - services/ingest_service/ 仍通过 Supabase REST 做任务/索引/清理（属于后续 RAG/索引链路）。       
      - 根目录 src/ 也还有 Supabase 用法（更像历史/备用 Next 工程，若不参与桌面构建可先不动）。         
  - 按你“尽量一体化绑死 Convex”的优先级，建议下一步这样排                                               
      1. 鉴权/权限从“固定用户”升级为可扩展的真实方案：否则后面所有“按用户/工作区隔离”都只能靠约定。     
         Convex Auth 是官方路线之一，但对 Next.js server 侧支持仍在演进中，需要你接受一定不稳定/适配成  
         本。citeturn0search1                                                                        
      2. 把仍依赖 Supabase Storage 的功能全部切到 Convex Files：你已经验证 Dashboard Files 可见；下一步 
         是把 luckysheet/onlyoffice 等涉及上传/签名 URL 的地方也迁掉（或临时 501 下线），保证           
         USE_CONVEX=1 时不会再触发 Supabase Storage。citeturn0search5
      3. 把“搜索/索引/推荐”从 Postgres/RPC 思路迁到 Convex：文档搜索走 Convex 全文检索；RAG/embedding 走         Vector Search（注意向量检索需要在 action 里跑）。citeturn0search2turn0search4              
      4. 把 services/ingest_service 的“队列/任务状态机”迁出 Supabase：要么先停用该服务；要么改成 Convex 
         内部的任务表 + actions + scheduler（这样系统更一体化）。                                       
      5. 做运维闭环（自部署必需）：明确 Docker 卷备份/恢复策略（Convex 也在推进更易用的数据备份/恢复能  
         力，但你仍应以卷级备份为底线）。citeturn0search3                                            
  - 关于“Convex 组件”与你项目的适配结论                                                                 
      - Convex “Components”适合把通用能力（比如协作编辑、鉴权、工作流）做成可插拔模块，并且支持隔离/复  
        用；你的项目属于“练手快速迭代”，很适合用组件化方式逐块替换 Supabase 逻辑。citeturn1search0   
      - Files 这一块：Convex 的 Files 更像“一个大池子/大桶”，不强调文件夹；你要的“按用户/工作区区分、路 
        径/目录视图”，仍建议用业务表字段（workspace_id、user_id、path）来实现管理与展示，这是最贴合你“一        体化 + 不引入外部对象存储”的路线。citeturn0search5  
    checklist:
  - M1（已完成）：documents/workspaces/media/search 全链路 Convex 化 + 冒烟回归                         
  - M2（已完成）：Mindmap 数据与接口迁移（/api/mindmap/**、/api/mindmap-trash/empty），落到 Convex（优先复用      
    documents.mindmap_data）                                                                            
  - M3（已完成）：References（页面引用/反链）迁移（/api/references/record、/api/references/backlinks），补齐目前的    占位实现                                                                                            
  - M4（已完成）：AI Agent（/api/ai-agent/run、/api/ai-agent/client-tool-result）去 Supabase 化（鉴权/读写文档/工 
    具回调）                                                                                            
  - M5（待继续）：Online Table / Luckysheet（/api/tables/**、/api/luckysheet/**）迁移或在 Convex 模式下先禁用（给 
    出明确 UI 提示）                                                                                    
  - M6（待继续）：OnlyOffice（/api/onlyoffice/*）迁移或在 Convex 模式下先禁用（同上）                             
  - M7（待继续）：服务侧（services/ingest_service 等）去 Supabase 化：任务表/状态机迁到 Convex jobs/actions（或先 
     停用该链路）                                                                                        
  - M8（未开始）：鉴权从“固定用户”升级为可扩展方案（仍保持 Convex 一体化）                                        
  - M9（未开始）：运维闭环：Convex 数据/Files 卷备份恢复、日志与健康检查、启动脚本收敛                            
                                                                                                        
  我刚做完的（你现在的代码状态）                                                                        
                                                                                                        
  - 补齐 documents 的最后缺口：wolai-frontend/src/app/api/documents/embed/route.ts:1 已支持 Convex。    
  - 抽了一个路由侧通用 helper：wolai-frontend/src/lib/convex/route.ts:1（统一拿 auth+client）。         
  - M7 进展：已把“自动入库/LightRAG 触发”迁到 Convex jobs/actions 的最小骨架（支持 document/mindmap/media 三类入库任务），并在 Convex 模式下默认关闭 services/ingest_service 的 Supabase 轮询入库（避免继续依赖 Supabase）。
    - 触发入库（开发用）：POST wolai-frontend/src/app/api/dev/ingest/enqueue/route.ts:1
    - 查询任务：GET wolai-frontend/src/app/api/dev/jobs/demo/route.ts:1（传 id）
    - Convex action 需要环境变量：LIGHTRAG_URL / LIGHTRAG_API_KEY（运行在 Convex 侧）
    - 自动触发（Convex 侧）：保存页面/导图会 debounce enqueue 入库任务（wolai-frontend/convex/_utils/ingestJobs.ts:1）
    - 已移除 ingest_service 内与 Supabase 相关代码（不再包含 Supabase 客户端/配置/轮询入库实现）
  - “最近访问”已落库到 Convex：wolai-frontend/convex/schema.ts:1 新增 user_recent_pages；wolai-frontend/    convex/recents.ts:1 + 接入 wolai-frontend/src/app/api/search/recent/route.ts:1、wolai-frontend/src/ 
    app/api/search/documents/route.ts:1。                                                               
  - 回归脚本已扩展并跑通：pw-tests/scripts/e2e_convex_smoke.py:1；最新产物 pw-tests/artifacts/convex-   
    smoke-20260116-194415.png:1、pw-tests/artifacts/convex-smoke-console-20260116-194415.log:1。        
                                                                                                        
  接下来我建议从 M2（Mindmap）开始做：它目前是 Convex 模式下仍“纯 Supabase 路由”的最大功能块。你希望优先
  做 Mindmap，还是先做 AI Agent/OnlyOffice/表格？

  ———

  ## 补充规格：编辑器“移动/嵌入到...”按 wolai 机制复刻（同页嵌入先禁止）

  ### 0. 结论（本次明确的产品语义）

  - “嵌入到...” = **块引用（同步编辑）**：目标页面插入“嵌入引用块”，引用源块；源块仍留在原位置。
  - “移动到...” = **移动块本体**：源块（含子树）从当前页面移到目标页面；块 ID 保持不变。
  - **同页嵌入先禁止**：当目标页面 = 源块所在页面时，禁止“嵌入到...”（避免递归/复杂边界）。

  > 说明：当前代码里（CustomSideMenu/sidebar）做的是“把块变成子页面 + 插入 pageReference”，这不等价于 wolai 的块引用/块移动，需要整体重做。

  ### 1. 术语

  - 源块（sourceBlock）：用户在编辑器里选中的那个块（BlockNote block），有稳定 `blockId`。
  - 源页面（sourceDoc）：包含源块的页面（document）。
  - 目标页面（targetDoc）：用户在弹窗里选择的页面。
  - 块引用（blockReference）：一种特殊块，指向 `targetBlockId`，显示/编辑代理到源块。

  ### 2. 行为规格（可直接转成 pw-tests 验收点）

  #### 2.1 “移动到...”（Move）

  - 触发：块左侧拖拽菜单 → “移动/嵌入到...” → 选“移动到” → 选目标页面。
  - 结果：
    - 源页面：源块（含 children 子树）消失。
    - 目标页面：插入源块子树（MVP 先插在末尾）。
  - 不变量：
    - 源块 `blockId` 不变（未来引用/链接仍指向同一块）。
    - 子树结构保持不变（children 仍挂在源块下）。
  - 限制：
    - 选择目标页面为当前页面：视为 no-op（提示“已在当前页面”或直接关闭）。
    - 无权限/不存在：失败提示。

  #### 2.2 “嵌入到...”（Embed）

  - 触发：块左侧拖拽菜单 → “移动/嵌入到...” → 切换“嵌入到” → 选目标页面。
  - 结果：
    - 源页面：源块保持原位。
    - 目标页面：新增一个 `blockReference`（display=embed），`targetBlockId = 源块.blockId`（MVP 先插在末尾）。
  - 同步编辑：
    - 在目标页面的嵌入引用中编辑内容，实际修改的是源块（刷新源页面可见变化）。
  - 删除语义：
    - 删除目标页面里的引用块，只移除“引用”，不删除源块本体。
  - 跳转语义（先对齐 wolai 思路，后续可微调）：
    - 嵌入引用块本体不强制“点击跳转”；但在块菜单提供“跳转到原块”动作。
  - 限制：
    - **同页嵌入禁止**：`targetDocId === sourceDocId` 时直接禁止（UI 禁用 + API 双重校验）。
    - 无权限/不存在：失败提示。

  ### 3. 数据结构设计（MVP，兼容你当前“整页 content JSON”）

  #### 3.1 新增块类型：blockReference（区分于 pageReference）

  - `type: "blockReference"`
  - `props`（建议）：
    - `targetBlockId: string`（必填）
    - `display: "inline" | "embed"`（MVP 用 embed）
    - `alias?: string`（行内引用别名，后续再做）

  #### 3.2 块索引（block_index）——用于从 blockId 反查所在页面

  因为块仍存放在 `documents.content` 内（整页 JSON），为了实现：
  - “跳转到原块”
  - “嵌入引用渲染/编辑时找到源块”

  需要一个索引集合（Convex 表）：
  - `block_index { blockId, documentId, workspaceId, updatedAt }`

  维护方式（MVP）：
  - 每次保存页面 content 时（documents.save / documents.updateContent），解析 blocks，批量 upsert 索引。
  - Move 操作需要同时更新源/目标页的索引（或依赖后续 save 再修正，但建议 move 立刻修正）。

  #### 3.3 引用边（可选，但很有用）

  - `reference_edges { sourceDocumentId, targetBlockId, createdAt }`
  - 用途：反链面板（Backlinks）、统计、权限校验辅助。

  ### 4. API 设计（建议新增 blocks 维度接口，避免滥用 documents/embed）

  > 目标：把“块移动/块引用”从“创建子页面 + pageReference”的错误语义中解耦出来。

  #### 4.1 `POST /api/blocks/move`

  - 入参：`{ sourceDocumentId, blockId, targetDocumentId, position?: "end" }`
  - 行为：从 sourceDoc content 移除 block 子树，追加到 targetDoc content；更新索引。

  #### 4.2 `POST /api/blocks/embed`

  - 入参：`{ sourceDocumentId, blockId, targetDocumentId, position?: "end" }`
  - 行为：校验非同页；在 targetDoc content 追加 `blockReference(targetBlockId=blockId, display="embed")`。

  #### 4.3 `GET /api/blocks/get?blockId=...`

  - 返回：`{ documentId, block, path? }`
  - 用途：渲染引用块、跳转到原块、hover 预览（后续）。

  #### 4.4 `POST /api/blocks/patch`（嵌入引用的同步编辑）

  - 入参：`{ blockId, patch }`（MVP 可先做 `replaceBlock`：提交完整 block JSON）
  - 行为：定位源块所在文档，修改该块内容并保存；广播刷新（后续可用 Convex 订阅优化）。

  ### 5. UI / 交互设计（与现有 MoveEmbedPickerDialog 的对接）

  - 仍复用现有 `MoveEmbedPickerDialog` 做“选页面”能力。
  - 在“嵌入到”模式下：
    - Picker 直接排除当前页面（`excludeIds=[currentDocumentId]`），并在选中时二次校验。
  - 行为完成后的反馈：
    - Move：toast “已移动到 XXX”
    - Embed：toast “已在目标页面末尾插入引用块”

  ### 6. pw-tests 验收用例（最小集合，锁定行为不跑偏）

  - `move_basic`：A 页面块 → Move 到 B；断言 A 不存在、B 存在，且块 `blockId` 未变化。
  - `embed_basic`：A 页面块 → Embed 到 B；断言 A 仍存在、B 出现 `blockReference(targetBlockId=...)`。
  - `embed_edit_sync`：在 B 的嵌入引用中编辑 → 刷新 A → 断言源块同步变化。
  - `embed_same_page_forbidden`：Embed 目标选择当前页 → UI 提示/不可选，且服务端拒绝。
  - `embed_delete_only_reference`：删除 B 的引用块 → A 源块仍存在。

  ### 7. 迁移实施顺序（避免一次性大爆炸）

  1) 先落地 `blockReference` 块类型与只读渲染（不做同步编辑）。
  2) 上 `block_index` 并在保存 content 时维护；补齐 `GET /api/blocks/get`。
  3) 实现 `POST /api/blocks/embed` + UI 接入（替换旧 documents/embed 的错误语义）。
  4) 实现 `POST /api/blocks/move`（跨文档移动块子树）。
  5) 最后做 `POST /api/blocks/patch`，实现嵌入引用的同步编辑与限制（删除语义/跳转）。
