194 lines
9.8 KiB
Markdown
194 lines
9.8 KiB
Markdown
# [recycle] 发布前源代码审计
|
||
|
||
> 更新时间:2026-04-16
|
||
>
|
||
> 审计范围:`/mnt/Data1T/mnote`
|
||
|
||
## 1. Bridge 入口与日志回查
|
||
|
||
### 1.1 最小查询与写入入口
|
||
|
||
当前已确认的 bridge 主线入口:
|
||
|
||
- 查询:
|
||
- `src/app/api/documents/content/route.ts`
|
||
- `src/app/api/documents/meta/route.ts`
|
||
- `src/app/api/sidebar/route.ts`
|
||
- 写入:
|
||
- `src/app/api/documents/title/route.ts`
|
||
- `src/app/api/documents/stats/route.ts`
|
||
- `src/app/api/documents/options/route.ts`
|
||
- `src/app/api/documents/save/route.ts`
|
||
- `src/app/api/blocks/patch/route.ts`
|
||
- `src/app/api/onlyoffice/callback/route.ts`
|
||
|
||
### 1.2 日志与事件落账
|
||
|
||
当前已确认:
|
||
|
||
- `src/lib/documents/metadata-command-adapter.ts` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||
- `src/lib/documents/save-command-adapter.ts` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||
- `src/app/api/blocks/patch/route.ts` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||
- `src/lib/documents/media-asset-command-adapter.ts` 会在 ONLYOFFICE callback 成功写回后尝试复用同一 bridge log 落账
|
||
- `src/lib/documents/bridge-log.ts` 会同时写入:
|
||
- `bridgeLogs.recordCommandLog`
|
||
- `bridgeLogs.recordDomainEvent`
|
||
- 回查入口:
|
||
- `src/app/api/bridge/request/route.ts -> bridgeLogs.listByRequest`
|
||
- `src/app/api/bridge/trace/route.ts -> bridgeLogs.listByTrace`
|
||
|
||
结论:
|
||
|
||
- bridge 的最小查询、最小写入、日志生成、事件生成和错误返回已经形成源码闭环。
|
||
|
||
## 2. 保存口径审计
|
||
|
||
当前正文与页面元信息主写链如下:
|
||
|
||
- `documents.save -> api.documents.updateContent`
|
||
- `documents.title.update -> api.documents.updateTitle`
|
||
- `documents.stats.update -> api.documents.updateStats`
|
||
- `documents.options.update -> api.documents.updateOptions`
|
||
- `blocks.patch -> 读取文档内容后回写 api.documents.updateContent`
|
||
|
||
OnlyOffice 写回:
|
||
|
||
- `src/app/api/onlyoffice/callback/route.ts -> media.assets.replace_storage -> api.mediaAssets.replaceStorageFromUpload`
|
||
|
||
结论:
|
||
|
||
- 页面正文、页面元信息、块补丁与 OnlyOffice 附件写回最终都以 Convex mutation 为主事实写入点。
|
||
- 当前未发现把页面/块主真相改写到 `mnote-rust`、本地缓存目录或其他派生目录的主写链。
|
||
|
||
## 3. `trace_id` / `request_id` / `workspace_id` / `page_id` 一致性
|
||
|
||
### 3.1 前端与 route
|
||
|
||
- `buildDocumentBridgeContext()` 统一生成 `requestId`、`traceId`、`workspaceId`
|
||
- `buildDocumentBridgeContextWithActor()` 可为 ONLYOFFICE callback 这类无用户 cookie 的服务端回调显式注入 `actor/source`
|
||
- `buildDocumentCommandEnvelope()` 统一挂载 `commandId`、`target.pageId`
|
||
- `documents.title/stats/options/save` 均将 `normalizedDocumentId` 作为 `target.pageId`
|
||
- `onlyoffice/callback` 会把 `asset.document_id` 作为 `target.pageId`,并透传 `workspaceId`
|
||
|
||
### 3.2 日志落账
|
||
|
||
- `recordBridgeCommandArtifacts()` 使用同一 `context.requestId`、`context.traceId`
|
||
- `workspaceId` 统一取 `target.workspaceId` 或 `context.workspaceId`
|
||
- `targetPageId` 统一落到 command log
|
||
- domain event payload 同时记录 `request_id`、`trace_id`、`command_id`、`command_name`
|
||
|
||
### 3.3 当前辅助验证
|
||
|
||
- `src/lib/documents/bridge.test.ts` 已覆盖:
|
||
- `target.pageId = doc_1`
|
||
- `executeSaveBridgeCommand` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||
- 返回结果保留 `req_1`、`trace_1`
|
||
- `src/app/api/onlyoffice/callback/route.test.ts` 已覆盖:
|
||
- callback 成功路径会调用 `executeMediaAssetWritebackBridgeCommand`
|
||
- `storageId`、`assetId`、`documentId`、`workspaceId` 会进入 `media.assets.replace_storage` envelope
|
||
|
||
结论:
|
||
|
||
- `trace_id`、`request_id`、`workspace_id`、`page_id` 在 route、adapter、bridge log、回查入口之间已有统一口径。
|
||
|
||
## 4. 禁止事项复查
|
||
|
||
### 4.1 不双仓并行
|
||
|
||
- 主仓脚本与文档已统一指向 `/mnt/Data1T/mnote`
|
||
- `wolai-frontend/src`、`wolai-frontend/convex`、`rust/` 下未发现直接依赖 `/mnt/Data1T/mnote-rust` 的运行时代码路径
|
||
|
||
### 4.2 不跨仓链接
|
||
|
||
- 排除 `node_modules`、`.next`、`.venv`、`rust/target` 等构建产物后,主仓源码范围内未发现跨仓符号链接
|
||
|
||
### 4.3 不复制第二套产品前端壳
|
||
|
||
- 主仓保留的是既有 `wolai-frontend` 主壳
|
||
- 历史仓对象页壳与第二套 sidebar 仅在文档中被标记为禁止误复制范围
|
||
|
||
### 4.4 不把对象页壳 / diagnostics / smoke 页带入主线
|
||
|
||
- 当前主仓 `wolai-frontend/src/app` 下未发现新增的 `diagnostic` / `smoke` 页面目录
|
||
- 历史仓相关页面已在边界文档中明确列入禁止误复制清单
|
||
|
||
### 4.5 不散落多个 Rust 源码根
|
||
|
||
- 主仓顶层 `Cargo.toml` 仅存在 `rust/Cargo.toml`
|
||
- 其余 crate `Cargo.toml` 均位于 `rust/crates/*`
|
||
|
||
## 5. 运行态复核结果与最终结论
|
||
|
||
本审计只能关闭源码可验证项,但截至 2026-04-16,发布前运行态复核已经补齐五条直接证据:
|
||
|
||
- 已复跑 `scripts/task019-document-ui-regression.js`,文档页标题、正文、保存、刷新、回查链通过。
|
||
- 已复跑 `scripts/task021-mindmap-ui-regression.js`,Mindmap 全屏页的新增子节点、删除子节点、保存链、刷新回查与 `requestId/traceId` 元信息同步通过。
|
||
- 已复跑 `scripts/task022-onlyoffice-ui-regression.js`,ONLYOFFICE `9.3.1` 基线下的打开、插件桥、callback 写回、forcesave 与 `storage_id` 变化通过。
|
||
- 已通过 `pnpm exec vitest run src/lib/ai-agent/runtime/runAgent.test.ts`,补齐 `docs_search -> docs_read` 的 AI runtime 调用证据。
|
||
- 已通过 `bash /mnt/Data1T/mnote/rust/scripts/task049-cli-smoke.sh`,补齐 CLI 主链的最小真实执行验收。
|
||
|
||
当前已不再存在阻塞发布的 CLI / AI 运行态尾项。
|
||
|
||
补充核验结果:
|
||
|
||
- `cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -p bridge-runtime` 已通过。
|
||
- `wolai-frontend` 相关定向 `eslint` 当前无 error,仅剩仓库既有 warnings,不构成本轮发布阻塞。
|
||
|
||
仍然要求环境满足的前置条件:
|
||
|
||
- 浏览器回归环境可访问 `http://127.0.0.1:3000`
|
||
- `MNOTE_ONLYOFFICE_PROBE_DOCX=/tmp/mnote-onlyoffice-probe/probe.docx` 可用
|
||
- 已登录态可通过 `/auth` 或测试账号快速登录建立
|
||
|
||
## 6. 旧 TS 执行面割接清单
|
||
|
||
当前源码审计之外,还需要看“哪些 TS route 还能留,哪些只是历史兼容”。
|
||
|
||
本轮已新增:
|
||
|
||
- `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`
|
||
|
||
该文档已把主仓当前执行面明确分成四类:
|
||
|
||
- `RUST_OWNER`
|
||
- `TS_TRANSPORT_KEEP`
|
||
- `TS_COMPAT_PENDING`
|
||
- `TS_LEGACY_DELETE`
|
||
|
||
其中当前仍需要长期观察但不再构成主链阻塞的旧面主要包括:
|
||
|
||
- `src/app/api/documents/embed/route.ts`
|
||
- `src/app/api/mindmap-ai/**`
|
||
|
||
其中页面旧面在 2026-04-16 的最终口径如下:
|
||
|
||
- `src/app/api/documents/create-child/route.ts` 已改走 `documents.create`
|
||
- `src/app/api/documents/empty-trash/route.ts` 已改走 `documents.emptyTrashByWorkspace`
|
||
- `src/app/api/documents/purge/route.ts` 已改走 `documents.purge`
|
||
- `src/app/api/documents/template/route.ts` 已改走 `documents.template`
|
||
- `src/app/api/documents/embed/route.ts` 已改走 `documents.save`,但目标页面插入位与 `pageReference` block 组装仍在 TS,因此继续按 `TS_COMPAT_PENDING` / 产品编排壳维护
|
||
- `src/app/api/mindmap/[docId]/route.ts` 与 `src/app/api/mindmap/[docId]/[mindmapId]/route.ts` 的 `DELETE/PATCH` 已改走 `mindmaps.delete/restore/purge`
|
||
- `src/app/api/mindmap-trash/empty/route.ts` 已改走 `mindmaps.emptyTrashByWorkspace`
|
||
- `src/app/api/blocks/*` 现网主链实际统一走 `src/lib/blocks/block-command-adapter.ts`;`src/lib/documents/block-command-adapter.ts` 应视为遗留兼容 helper,而非现网主执行面
|
||
- `src/app/api/ai-agent/run/route.ts` 的核心工具主链现在已经统一走 Rust tool runtime:`docs_search`、`docs_read`、`search_web`、`image_read`、`slash_run` 不再保留 TS 真执行兜底
|
||
|
||
结论:
|
||
|
||
- 当前可以说“Rust 已成为 mnote 的主业务执行平面”。
|
||
- 仍保留的 TS 路径只剩 `TS_TRANSPORT_KEEP`、少量 `TS_COMPAT_PENDING` 产品编排壳与冻结的 `TS_LEGACY_DELETE` 清单。
|
||
- 第一批 `TS_LEGACY_DELETE` 已不再阻塞这轮 release readiness;它们现在的要求是“保持纯壳 / 冻结 helper,不允许反向长出新的业务规则”。
|
||
|
||
最终 release readiness 口径:
|
||
|
||
- 若按源码审计口径:可以说明“Rust 已成为 mnote 的唯一业务执行平面”,同时明确仍保留 `TS_TRANSPORT_KEEP` 与少量产品编排壳。
|
||
- 若按完整发布口径:文档页、Mindmap、OnlyOffice、AI runtime、CLI smoke 的 Phase 8 scoped gate 已闭合,可以给出最终完成结论。
|
||
- 后续维护口径:剩余 `TS_TRANSPORT_KEEP` / `TS_LEGACY_DELETE` 只属于长期清理与边界维护,不再构成第二套业务执行平面。
|
||
|
||
补记:
|
||
|
||
- 2026-04-15 已复跑 `scripts/task019-document-ui-regression.js`,确认文档页标题、正文、保存与刷新回查通过。
|
||
- 2026-04-15 已复跑 `scripts/task021-mindmap-ui-regression.js`,确认新增/删除节点、保存链、刷新回查与 `requestId` / `traceId` 元信息同步通过。
|
||
- 2026-04-15 已复跑 `scripts/task022-onlyoffice-ui-regression.js`,在升级后的 ONLYOFFICE `9.3.1` 基线上确认 `oo_insert_text` 插件桥、`同步保存`、callback 写回与 `storage_id` 变化仍然通过;本次 callback 最终写回已不再由 route 直接调用 `api.mediaAssets.replaceStorageFromUpload`,而是先经 `media.assets.replace_storage` bridge 命令再落到 Convex。
|
||
- 2026-04-16 已通过 `src/lib/ai-agent/runtime/runAgent.test.ts`,确认 `docs_search -> docs_read` 的运行态工具链顺序、事件流与结果归一化闭合。
|
||
- 2026-04-16 已通过 `rust/scripts/task049-cli-smoke.sh`,确认 `sidebar/page/block/search/tool/mindmap` 主链 CLI 真实执行闭合。
|