Files
Genarrative/backend-rewrite-tasklist/M0_REPOSITORY_BOUNDARY_DECISIONS_2026-04-20.md

8.0 KiB
Raw Blame History

M0仓库边界决议

日期:2026-04-20

依据来源:

1. 文档目的

这份文档用于持续冻结 M0 中与仓库边界直接相关的决策,避免进入 M1 后再反复改目录、改职责口径。

当前已确认的事项只包含第一条;后续几条会继续在这份文档上追加。

2. 边界决议状态

事项 当前状态 当前结论
Rust 后端新目录名与根目录落位方案 已确认 新 Rust 后端固定为仓库根目录下的 server-rs/,与 server-node/ 同级。
server-node/ 在迁移期继续保留,不提前删除 已确认 server-node/M0 ~ M6 期间持续保留,直到 M7 切流与回退验证完成后再评估清理。
前端第一阶段仍然只访问 Axum不直连 SpacetimeDB 已确认 M0 ~ M6 前端统一只访问 Axum 暴露的 /api/*/healthz、SSE 与静态资源兼容层,不新增直连 SpacetimeDB 原生协议路径。
外部副作用统一收口在 Axum不放进 SpacetimeDB 模块 已确认 OSS、LLM、短信、微信 OAuth、本地文件系统等外部副作用统一落在 Axum/application/infra不进入 SpacetimeDB reducer/module。

3. 已确认决议一:server-rs/ 固定落在仓库根目录

3.1 决议内容

本次重写固定采用以下仓库落位:

  1. 新后端目录名固定为 server-rs/
  2. 目录位置固定在仓库根目录
  3. 与以下目录保持同级:
    • server-node/
    • src/
    • docs/
    • packages/

目标形态:

Genarrative/
├─ server-node/
├─ server-rs/
├─ src/
├─ packages/
├─ docs/
└─ backend-rewrite-tasklist/

3.2 不采用的落位方案

以下方案当前明确不采用:

  1. 不放进 server-node/ 子目录中做“Node + Rust 混编后端”。
  2. 不放进 packages/,避免被前端 package/workspace 语义误导。
  3. 不使用过于泛化的根目录名如 server/backend/,避免和当前 server-node/ 职责混淆。

3.3 这样落位的原因

  1. 与当前重写设计文档、任务清单、后续 M1 crate 规划保持一致。
  2. 允许 server-node/server-rs/ 在迁移期并行存在,便于逐阶段切流。
  3. 让 Rust 工作区边界清晰,不污染现有前端 src/packages/、Vite 工具链。
  4. 后续新增 server-rs/scripts/*Cargo.tomlcrates/* 时路径最直接,不需要额外中间层。

3.4 对后续任务的直接约束

从这一条决议开始,后续任务必须统一按以下路径落位:

  1. M1 的工作区初始化在 server-rs/
  2. Axum 入口在 server-rs/crates/api-server
  3. SpacetimeDB 模块在 server-rs/crates/spacetime-module
  4. 相关脚本在 server-rs/scripts/

4. 本条任务完成定义

当以下条件成立时,这一条边界任务视为完成:

  1. 新 Rust 后端目录名已经书面固定为 server-rs/
  2. 目录位置已经书面固定为仓库根目录
  3. 后续 M1 的工作区初始化不会再出现 server-rs/backend-rs/server/ 等多套候选名并存

5. 已确认决议二:迁移期保留 server-node/

5.1 决议内容

在本次重写迁移期内,旧 server-node/ 固定继续保留,不提前删除、不整体挪位、不提前做破坏性收缩。

保留周期固定为:

  1. M0M6 全阶段
  2. 至少持续到 M7 的以下条件全部满足之后,才允许评估清理:
    • 新后端已切流
    • 旧接口 contract 回归通过
    • 关键主链 smoke 通过
    • 已具备明确回退方案

5.2 保留它的原因

  1. server-node/ 是当前 96 条路由、6 个挂载面、12 个模块的真实对照实现。
  2. 前面已经冻结的路由矩阵、模块迁移清单、SSE 协议、静态资源前缀,都需要它作为回归对照源。
  3. 如果在 M1 ~ M6 提前删除旧实现,就会失去最可靠的回退锚点与 diff 基准。

5.3 迁移期允许做什么

迁移期内允许:

  1. server-rs/ 中逐步补等价实现。
  2. 在文档和 manifest 中继续引用 server-node/ 作为当前系统基线。
  3. 在必要时从 server-node/ 补测试样例、补协议对照、补回归夹具。

迁移期内不允许:

  1. 提前整体删除 server-node/
  2. server-node/ 改成只剩空壳目录
  3. 在还没切流前,把旧服务关键实现批量迁走导致无法对照

5.4 对后续任务的直接约束

从这一条决议开始,后续任务必须遵守:

  1. M1 搭建 server-rs/ 时,不改动 server-node/ 的存在性。
  2. M2 ~ M6 迁移功能时,旧 server-node/ 继续作为验收基线与回退锚点。
  3. 真正评估清理旧 Node 后端的动作,只能放到 M7 切流完成之后。

6. 已确认决议三:前端第一阶段只访问 Axum

6.1 决议内容

M0 ~ M6 迁移期内,前端访问新后端的唯一入口固定为 Axum。

第一阶段允许前端继续访问的面固定为:

  1. /api/*
  2. /healthz
  3. 当前已冻结的 SSE 路由
  4. 当前已冻结的 /generated-* 静态资源兼容前缀

第一阶段明确不做的事:

  1. 不让 Web 前端直接接 SpacetimeDB 原生 HTTP 接口。
  2. 不让 Web 前端直接接 SpacetimeDB 订阅协议。
  3. 不要求前端新增一套“Axum + SpacetimeDB 双后端并行直连”调用模式。

6.2 这样决议的原因

  1. 当前前端已经直接依赖现有 /api/* 路由、response envelope、SSE、/generated-* 路径习惯。
  2. 如果在第一阶段就让前端同时认识 Axum 与 SpacetimeDB会把迁移面从“后端平移”扩大成“前后端协议双重重写”。
  3. Axum 需要承担统一鉴权、cookie、JWT、OSS 签名、错误格式与 contract 兼容职责,这些都不应分散到前端直连多个后端协议。

6.3 对后续任务的直接约束

从这一条决议开始,后续任务必须遵守:

  1. M1 ~ M2 的 Axum 中间件与鉴权必须先跑通,再谈前端联调。
  2. M3 ~ M6 新增的 SpacetimeDB reducer/view 先通过 Axum facade 暴露,不直接要求前端改成原生 SpacetimeDB 客户端。
  3. 若后续要让前端直连 SpacetimeDB只能作为第二阶段优化事项不能混入当前重写主链。

7. 已确认决议四:外部副作用统一收口在 Axum

7.1 决议内容

本次重写固定采用以下边界:

  1. SpacetimeDB 只负责状态、规则、reducer、view、订阅读模型。
  2. Axum/application/infra 统一负责所有外部副作用。

固定收口到 Axum 的外部副作用包括:

  1. 阿里云 OSS 上传、下载、签名、直传凭证
  2. DashScope / Ark / 其他 LLM 请求
  3. 微信 OAuth
  4. 手机验证码短信发送与校验编排
  5. 本地文件系统读写

7.2 明确不允许放进 SpacetimeDB 的内容

以下能力当前明确禁止进入 spacetime-module/

  1. 直接发 HTTP 请求给第三方供应商
  2. 直接访问 OSS SDK
  3. 直接读写本地磁盘
  4. 直接处理 Cookie、回调跳转、multipart 上传
  5. 直接承担供应商重试、熔断、超时与日志策略

7.3 这样决议的原因

  1. 这些能力都强依赖 HTTP 头、Cookie、SDK、签名、超时与日志不适合绑进 SpacetimeDB 模块发布周期。
  2. 当前前端 contract、鉴权、SSE、静态资源兼容都要求一个稳定的 HTTP 边界层Axum 更适合承担这个角色。
  3. 把副作用统一收口到 Axum才能让 SpacetimeDB 保持“状态机真相源”的纯度。

7.4 对后续任务的直接约束

从这一条决议开始,后续任务必须遵守:

  1. M1 crate 设计时,oss-servicellm-serviceauth-service 固定属于 Axum/application 侧。
  2. M2 ~ M6 设计 reducer 时,只写状态变更,不直接发外部请求。
  3. 若确实需要异步副作用,也必须由 Axum worker 或应用层作业执行,再把结果回写 SpacetimeDB。