补齐runtime story到STDB的兼容桥

This commit is contained in:
2026-04-20 11:22:37 +00:00
parent 00edcfe121
commit 9d27284a64
14 changed files with 478 additions and 9 deletions

View File

@@ -13,6 +13,7 @@
- [STDB_AUTH_TAIL_PHASE2_TOKEN_SLOT_SPLIT_2026-04-20.md](./STDB_AUTH_TAIL_PHASE2_TOKEN_SLOT_SPLIT_2026-04-20.md):将 STDB token 与旧 HTTP Bearer token 拆成独立存储槽。
- [RUNTIME_STORY_TO_STDB_PHASE1_TRANSPORT_ABSTRACTION_2026-04-20.md](./RUNTIME_STORY_TO_STDB_PHASE1_TRANSPORT_ABSTRACTION_2026-04-20.md):把 `runtimeStoryService` 改成可替换 transport为后续 STDB provider 接入预留稳定边界。
- [RUNTIME_STORY_TO_STDB_PHASE2_CONTRACT_DESIGN_2026-04-20.md](./RUNTIME_STORY_TO_STDB_PHASE2_CONTRACT_DESIGN_2026-04-20.md):梳理 runtime story 从 Express 迁到 STDB 所需的聚合 view、procedure、mapper 与前端 provider 设计。
- [RUNTIME_STORY_TO_STDB_PHASE2A_COMPAT_BRIDGE_2026-04-20.md](./RUNTIME_STORY_TO_STDB_PHASE2A_COMPAT_BRIDGE_2026-04-20.md):确认 runtime story 当前 STDB/Express 快照真源分裂,并补一层只改 story 边界的 STDB 兼容桥。
- [TASK_AUTO_COMMIT_WORKFLOW_2026-04-20.md](./TASK_AUTO_COMMIT_WORKFLOW_2026-04-20.md):任务完成后按文件边界自动提交的脚本与协作约定。
- [NODE_DEV_STARTUP_HOTFIX_2026-04-20.md](./NODE_DEV_STARTUP_HOTFIX_2026-04-20.md)`npm run dev` 启动失败的热修记录、根因与验证结果。
- [NODE_SERVER_KNOWLEDGE_GRAPH_2026-04-08.md](./NODE_SERVER_KNOWLEDGE_GRAPH_2026-04-08.md):当前 Node 运行时后端的技术栈、入口、鉴权、存储与接口知识图谱。

View File

@@ -0,0 +1,136 @@
# Runtime Story 向 STDB 迁移 Phase 2A兼容桥2026-04-20
## 1. 本轮目标
这轮不是直接把 `runtime story` 全量改成 SpacetimeDB provider而是先补一层最小兼容桥解决当前仓库里已经实际出现的两类断裂
1. `runtime story` 前置快照写入已经走 STDB
2. `/api/runtime/story/*` 仍然从 `server-node` 的旧 `RuntimeRepository` 读取 Postgres 快照
3. 前端认证主链路已经切到 STDB旧 HTTP Bearer token 不再保证可持续刷新
因此本轮目标是:
1. 保持 `runtimeStoryCoordinator` 和上层页面契约不变
2. 保持 `server-node/src/modules/story/storyActionService.ts` 现有规则实现不重写
3. 只在 `runtime story` 边界补齐:
- 前端请求可携带 STDB token
- `server-node` 的 story route 可直接使用 STDB token 解析身份
- `server-node` 的 story route 可直接从 STDB 读写 snapshot
## 2. 当前问题确认
### 2.1 快照真源已经分裂
当前前端 [`src/hooks/story/runtimeStoryCoordinator.ts`](/home/Genarrative/src/hooks/story/runtimeStoryCoordinator.ts) 在读取或执行 runtime story 之前,会先调用:
1. [`putSaveSnapshot`](/home/Genarrative/src/services/storageService.ts)
2. 该调用实际走 STDB `saveSnapshot` procedure
但旧的 `/api/runtime/story/*` 仍然走:
1. [`storyActionRoutes.ts`](/home/Genarrative/server-node/src/modules/story/storyActionRoutes.ts)
2. [`storyActionService.ts`](/home/Genarrative/server-node/src/modules/story/storyActionService.ts)
3. [`RuntimeRepository.getSnapshot()`](/home/Genarrative/server-node/src/repositories/runtimeRepository.ts)
也就是:
1. 写快照在 STDB
2. 读快照在 Postgres
这已经不是“未来可能出现”的风险,而是当前迁移阶段的真实断链。
### 2.2 旧 HTTP token 不再是可靠前提
当前前端认证主链路已经切到:
1. [`src/services/authService.ts`](/home/Genarrative/src/services/authService.ts)
2. [`src/spacetime/client.ts`](/home/Genarrative/src/spacetime/client.ts)
也就是说:
1. 页面登录、恢复会话、匿名建连主要依赖 STDB token
2. 旧 HTTP access token 仅剩兼容用途
3. `/api/auth/refresh` 也不再保证始终存在有效 refresh cookie
因此继续假设 `/api/runtime/story/*` 一定能依赖旧 JWT Bearer是不稳的。
## 3. 本轮兼容桥方案
### 3.1 前端
[`runtimeStoryService.ts`](/home/Genarrative/src/services/runtimeStoryService.ts) 继续保留 HTTP transport但在请求 `/api/runtime/story/*` 时:
1. 优先携带现有 HTTP access token
2. 若不存在 HTTP access token则回退携带 STDB token
3. 新增专用 header明确这是一条 runtime story 的 STDB 兼容认证链路
这样上层调用不变,但 `server-node` 侧已经能识别 STDB token。
### 3.2 后端鉴权
`server-node``/api/runtime/story/*` 单独补一层兼容认证:
1. 先尝试旧 JWT Bearer
2. 若 Bearer 不是 JWT 或 JWT 校验失败,则尝试按 STDB token 建连解析身份
3. 解析成功后,把 `request.userId` 设为 STDB account id
注意:
1. 这不是把所有 `server-node` 路由都改成 STDB 认证
2. 只对 runtime story 这条仍未迁完的兼容链路生效
### 3.3 快照读写
`storyActionService` 现有规则仍保持不变,但其读取与写回的 `runtimeRepository` 改为支持 STDB snapshot 的兼容仓储。
优先级:
1. runtime story 若通过 STDB token 认证进入
2. 则快照直接从 STDB `my_snapshot` / `save_snapshot` / `delete_snapshot` 读取和写回
3. 旧 JWT 路径继续维持原来的 Postgres 仓储行为
这样可以最小化改动:
1. 不重写 story rule
2. 不要求 runtime story 前端立刻切成 STDB provider
3. 先让“当前真实主快照”恢复一致
## 4. 为什么不选其他方案
### 4.1 不恢复前端双写到 Postgres
不选原因:
1. 会把已经迁到 STDB 的快照主链路重新拉回双写状态
2. 会继续制造写时漂移和清理成本
3. 与 express -> stdb 迁移方向相反
### 4.2 不把所有 `/api/runtime/story/*` 立刻删掉
不选原因:
1. 现有 `storyActionService.ts` 承接了大量 battle / npc / inventory / quest 规则
2. 一次性重写成 STDB procedure 风险过高
3. 当前更紧急的是先修复“已断开的运行时快照来源”
## 5. 本轮边界
本轮只做:
1. runtime story 的 STDB token 兼容认证
2. runtime story 的 STDB snapshot 兼容读写
3. 保持现有前端 coordinator / response contract 不变
本轮不做:
1. 新的 STDB runtime story table / procedure / view 正式 contract
2. `runtimeStoryService` 切为真正的 STDB transport
3. 删除 `/api/runtime/story/*`
## 6. 下一步
Phase 2A 稳定后,再继续:
1.`get state``resolve action` 的正式 contract 收到 STDB
2. 在前端接入真正的 STDB transport
3. 删除 `/api/runtime/story/*` 这层兼容桥