Files
Genarrative/docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md
T
2026-06-07 00:42:05 +08:00

63 KiB
Raw Blame History

server-rs 与 SpacetimeDB 数据契约

更新时间:2026-05-15

后端主线

当前后端固定为:

server-rs + Axum + SpacetimeDB

server-node、Express、PostgreSQL、Go 服务端和 maincloud 口径全部为历史残留。新功能不得回到旧接口、旧兼容层或前端临时业务真相。

Rust workspace

server-rs/Cargo.toml 是 workspace 事实源。默认构建成员为 crates/api-server;第三方依赖版本和 workspace 内 crate path 统一放在 [workspace.dependencies]

SpacetimeDB 版本口径:当前 Rust crate spacetimedbspacetimedb-sdkspacetimedb-lib 统一锁定 2.3.0;本地 spacetime CLI / standalone、生成的 spacetime-client bindings 和容器压测镜像也必须与 2.3.0 对齐,避免 BSATN / procedure result 反序列化错配。

当前主要 crate

  • HTTP 服务:api-server
  • 领域模块:module-aimodule-assetsmodule-authmodule-bark-battlemodule-big-fishmodule-combatmodule-creative-agentmodule-custom-worldmodule-inventorymodule-match3dmodule-npcmodule-progressionmodule-puzzlemodule-questmodule-runtimemodule-runtime-itemmodule-runtime-storymodule-square-holemodule-storymodule-visual-novel
  • 平台副作用:platform-agentplatform-authplatform-imageplatform-llmplatform-ossplatform-speech
  • 共享层:shared-contractsshared-kernelshared-logging
  • SpacetimeDBspacetime-clientspacetime-module
  • 测试支撑:tests-support

DDD 边界

  1. module-* 不直接依赖 Axum、SpacetimeDB table/reducer/procedure、reqwest、OSS、LLM、spacetime-clienttokio 或文件系统。
  2. 业务规则、命令校验、领域错误和可纯测逻辑优先沉到 module-*
  3. SpacetimeDB 表结构、reducer、procedure 和持久化 row shape 留在 spacetime-module
  4. 后端访问 SpacetimeDB 必须经 spacetime-client facade。
  5. HTTP 鉴权、BFF 聚合、SSE、外部模型编排、OSS 上传和第三方回调在 api-server
  6. 前端共享 DTO 通过 shared-contractspackages/shared 对齐,不在页面内重新发明旧接口。

验证:

npm run check:server-rs-ddd

spacetime-client mapper 组织

server-rs/crates/spacetime-client/src/mapper.rs 只作为聚合入口,负责声明 src/mapper/ 下的领域子模块并 re-export 原有 record / mapper 能力;不要在该文件继续堆叠大段映射实现。

当前子模块按调用领域拆分:assets.rsauth.rsruntime.rsruntime_profile.rscustom_world.rspuzzle.rsmatch3d.rsjump_hop.rswooden_fish.rssquare_hole.rsvisual_novel.rsbig_fish.rsstory.rsai.rsbark_battle.rscombat.rsinventory.rsnpc.rs,跨领域轻量 helper 和共享 record 统一放在 common.rs。该拆分只改变 spacetime-client 文件组织,不改变 SpacetimeDB schema、生成绑定、procedure result 契约或外部 DTO;后续新增 mapper 时优先落到对应领域子模块,不得重新引入跨层 JSON 字符串兼容结构。

API 路由分组

路由树由 server-rs/crates/api-server/src/app.rs 统一构造。当前主要分组:

  • 健康检查:GET /healthz
  • 后台管理:/admin/api/*,包括登录、概览、HTTP debug、埋点、表查询、创作入口开关、作品可见性、兑换码、邀请码、任务配置和充值商品配置。
  • 认证与账号:/api/auth/*/api/profile/me,包括短信、密码、微信、refresh session、多端会话和登出。
  • 个人中心:/api/profile/*,包括钱包流水、任务、领奖、充值、反馈、邀请、兑换、存档、历史浏览和游玩统计。
  • LLM 与语音:/api/llm/*/api/speech/volcengine/*
  • 资产:/api/assets/*,包括直传票据、STS、对象确认、实体绑定、读签名、读 bytes、历史资产、角色图像/动画和 Hyper3D 代理。
  • 创作入口配置:/api/creation-entry/config,后台 /admin/api/creation-entry/config/admin/api/creation-entry/config/banners
  • 自定义世界 / RPG/api/runtime/custom-world*/api/story/*/api/runtime/chat/*
  • 拼图:/api/runtime/puzzle/*
  • 抓大鹅 Match3D/api/creation/match3d/*/api/runtime/match3d/*
  • 敲木鱼:/api/creation/wooden-fish/*/api/runtime/wooden-fish/*
  • 方洞挑战:/api/creation/square-hole/*/api/runtime/square-hole/*
  • 视觉小说:/api/creation/visual-novel/*/api/runtime/visual-novel/*
  • 大鱼吃小鱼:/api/runtime/big-fish/*
  • 汪汪声浪:/api/runtime/bark-battle/*
  • 儿童向创作:/api/creation/edutainment/*
  • AI task/api/ai/tasks*

需要新增路由时,先确认玩法入口配置和 tracking 分类,不要绕过 app.rs 的统一中间件、鉴权和入口开关。

认证态用户与会话摘要下发口径

  • AuthUserPayload / AuthUser 只保留前端当前会用到的身份与绑定展示字段:idpublicUserCodedisplayNameavatarUrlphoneNumberphoneNumberMaskedloginMethodbindingStatuswechatBoundwechatDisplayNamewechatAccount。账号信息面板展示微信绑定时优先使用 wechatDisplayName;该字段只能来自微信平台 profile、历史已保存的微信身份资料,或小程序原生 input type="nickname" 提交的 displayName,不得用系统账号显示名或“微信旅人”这类假昵称兜底。小程序 /api/auth/wechat/miniprogram-login/api/auth/wechat/bind-phone 可接收 displayName/api/auth/wechat/miniprogram-login 额外返回 created,供小程序壳在快捷登录后判断是否需要补采集微信昵称。jscode2session 无法直接返回微信昵称或个人微信号,只能稳定拿到小程序维度 openid,后端以 wechatAccount 下发可区分的绑定账号标识,前端在缺少真实昵称时展示账号尾号。
  • AuthSessionSummaryPayload / AuthSessionSummary 只保留设备卡片与撤销需要的摘要字段:sessionIdsessionIdssessionCountclientLabelipMaskedisCurrentcreatedAtlastSeenAtexpiresAt
  • 设备诊断信息(例如原始 clientType / clientRuntime / clientPlatform / userAgent / miniProgramAppId / miniProgramEnv / deviceDisplayName)不再默认下发到前端;若未来确需展示,优先单独加窄 DTO,而不是把账号 / 会话快照恢复为全量对象。

api-server 模块化演进规则

api-server 的长期方向是从超大 app.rs 和超大 handler 文件收敛为按能力组织的 HTTP/BFF Module。后续改造必须保持 HTTP route、DTO、error envelope、SpacetimeDB schema、前端行为和计费语义默认不变;任何 contract 或 schema 变化都要先在当前文档中写清影响范围和迁移计划。

路由模块化规则:

  1. 每个能力 Module 只暴露 router(state) -> Router<AppState>,由 app.rs 统一 .merge(...)
  2. app.rs 只保留全局 middleware、TraceLayer、request context、tracking middleware、入口开关和少量顶层 glue。
  3. 能力 Module 可在路由内部用 FromRef<AppState> 派生自己的 Feature State,例如 PuzzleApiState。全局 AppState 仍作为进程组合根、鉴权层和全局中间件状态,但业务 handler 优先只提取对应 Feature State,不直接暴露完整 AppState
  4. Feature State 只暴露该能力实际需要的 facade / adapter / 配置快照;若必须复用仍要求 AppState 的横切 helper(例如计费、外部失败审计或通用 tracking),应通过 Feature State 的窄方法或显式 root_state() 过渡,并在后续继续收窄。
  5. 路由迁移和业务重构分阶段处理;先移动路由装配,再拆 handler 内部实现,再收窄 handler 可见状态。
  6. 大 handler 拆分时优先按 router.rshandlers.rsapplication.rsassets.rsmapper.rserrors.rs 分层。handlers.rs 只做 Axum extract、鉴权和 request/response,业务规则继续下沉到 module-*
  7. 手写 Rust 模块入口统一使用同名 .rs 文件,例如 puzzle.rs + puzzle/*.rsmatch3d.rs + match3d/*.rs;不要再新增 mod.rs 入口。生成的 SpacetimeDB Rust bindings 也由生成脚本同步为 module_bindings.rs + module_bindings/*.rs 布局。

拼图 api-server 内部拆分:

  • server-rs/crates/api-server/src/modules/puzzle.rs 只负责路由装配、鉴权层和参考图 body limit;对外继续引用同一批 handler 名称。
  • server-rs/crates/api-server/src/state.rs 中的 PuzzleApiState 是拼图 HTTP/BFF 的 Feature State,集中暴露 SpacetimeClientPuzzleGalleryCache、OSS client、作者查询所需认证服务、拼图 LLM client 和少量 VectorEngine / Agent 配置快照。拼图 handler 只提取 State<PuzzleApiState>,不得重新改回 State<AppState>
  • server-rs/crates/api-server/src/puzzle.rs 只作为聚合入口,保留共享 import / 常量、内部模块声明和 handler re-export,不继续承载大段实现。
  • server-rs/crates/api-server/src/puzzle/handlers.rs 承接 Axum handler,负责 extract、鉴权上下文、调用 SpacetimeDB facade / 编排 helper,并返回 HTTP/SSE 响应。
  • server-rs/crates/api-server/src/puzzle/draft.rs 承接表单草稿保存、草稿编译、首关命名、UI 背景 prompt、降级 snapshot 和初始资产就绪校验。
  • server-rs/crates/api-server/src/puzzle/generation.rs 承接拼图图片与 UI 背景的生成编排、计费包裹和 reference image 路径选择。
  • server-rs/crates/api-server/src/puzzle/vector_engine.rs 承接 VectorEngine 请求体、HTTP 调用、下载 / base64 解码、OSS 写入、asset object / binding 持久化和上游错误归一。
  • server-rs/crates/api-server/src/puzzle/mappers.rs 承接 SpacetimeDB record 到 shared-contracts DTO 的映射。
  • server-rs/crates/api-server/src/puzzle/tags.rs 保留拼图标签生成、拼图通用错误映射和 SSE helper。

该拆分只改变 api-server 文件组织,不改变 /api/runtime/puzzle/* route、DTO、error envelope、SpacetimeDB schema、公开 gallery cache 语义或计费语义;后续继续细分时也必须先保持行为不变,再单独讨论领域规则下沉。

/api/runtime/puzzle/runs* 当前接受 RuntimePrincipal,可同时识别登录用户 Bearer 和 runtime guest token。推荐页嵌入运行态的正式开局、交换、拖拽、下一关、暂停、道具与排行榜请求,应由前端在登录态下继续携带账号 access token;匿名游客仅在确认为未登录时走 runtime guest token。不要再把拼图 runtime 当成只认普通 Bearer 的纯账号接口。

抓大鹅 Match3D api-server 内部拆分:

  • server-rs/crates/api-server/src/modules/match3d.rs 继续负责路由装配和 body limit;对外 handler 名称保持不变。
  • server-rs/crates/api-server/src/match3d.rs 只作为聚合入口,保留共享 import / 常量 / 内部类型、模块声明和 handler re-export。
  • server-rs/crates/api-server/src/match3d/handlers.rs 承接 Axum handler,负责 extract、鉴权上下文、调用 SpacetimeDB facade / 编排 helper,并返回 HTTP 响应。
  • server-rs/crates/api-server/src/match3d/draft.rs 承接 Agent session、草稿编译、题材 / 难度 / 物品计划和草稿持久化编排。
  • server-rs/crates/api-server/src/match3d/works.rs 承接作品 CRUD、封面 / 背景 / 容器资产生成入口、发布 / Remix / 点赞 / 游玩记录和作品级 helper。
  • server-rs/crates/api-server/src/match3d/item_assets.rs 承接物品生成批次编排、append / replace / delete / sort / merge、计费外层和草稿素材映射;sheet prompt、绿幕 / 近白底透明化、切图和切片持久化复用 generated_asset_sheets 通用模块。
  • server-rs/crates/api-server/src/match3d/vector_engine_gemini.rs 仅保留历史 VectorEngine Gemini 物品 sheet helper;当前草稿物品 spritesheet 以关卡整图为参考走 gpt-image-2 编辑链路,提示词、绿幕透明化和 OSS 持久化由 item_assets.rs / works.rs 约束。
  • server-rs/crates/api-server/src/match3d/runtime.rs 保留运行态轻量归一 helpermappers.rs / tags.rs / tests.rs 分别承接 DTO 映射、标签 / 通用错误 helper 和原有单测。

该拆分只改变 api-server 文件组织,不改变 /api/creation/match3d/*/api/runtime/match3d/* route、DTO、error envelope、SpacetimeDB schema、公开 gallery cache 语义、VectorEngine / OSS 副作用边界或计费语义;后续继续细分时也必须先保持行为不变,再单独讨论领域规则下沉到 module-match3d

生成资产 Adapter 规则:

  1. 稳定单图链路可收敛到 api-server 内部生成资产 Adapterprovider 生成、下载/base64 解码、MIME/extension 归一、OSS private upload、HEAD、asset object confirm、entity binding。
  2. Adapter 输入应显式包含 provider、prompt、reference images、OSS prefix/path/file name、asset kind、entity kind/id、slot、owner/profile/source job、metadata 和可选透明背景后处理。
  3. Adapter 输出应保留 legacy public path、object key、asset object id、MIME、extension、task id 和实际 prompt。
  4. Adapter 不负责扣费、退款或钱包读取;计费仍由调用方显式包裹。
  5. 图片 provider 协议不再放在玩法模块里实现。VectorEngine gpt-image-2 创建 / 编辑协议、URL / base64 图片解析、远端图片下载、请求超时 / 上游状态 / 响应解析 / 缺图 / 下载失败的结构化日志统一在 server-rs/crates/platform-image/src/vector_engine/;其中 client.rs 只保留 provider 调用编排,transport.rs 负责 HTTP client 与 reqwest 错误归一,request.rs 负责请求体和路径,payload.rs 负责响应 JSON 字段提取,response.rs 负责响应状态分流和图片结果归一。api-server 只负责配置校验、玩法 prompt 编排、OSS / asset object / binding 持久化、计费和外部 API 失败审计落库。
  6. OSS 平台适配日志统一在 server-rs/crates/platform-oss 输出,覆盖 sign_post_objectsign_get_object_urlhead_objectput_object。日志字段固定使用 provideroperationbucketendpointobject_key / key_prefixaccesscontent_typecontent_lengthstatusstatus_classerror_kindelapsed_ms,只记录对象定位和排障信息;不得输出 AccessKey、policy、signature、Authorization header 或完整 signed URL。
  7. Puzzle、Match3D、音频、GLB、视频等复杂媒体可以复用 OSS + asset object + binding 的底层持久化能力,但玩法专属处理规则留在各自编排层,不塞进公共接口。
  8. 拼图入口页与结果页新增关卡的本地参考图不走浏览器直传 OSS,前端读取为 Data URL 后随创作 action 提交,并在读取前限制 6MB、显示“图片≤6MB”。api-server 必须对 Data URL 实际字节数再次校验;历史图片才提交 referenceImageAssetObjectId(s),后端校验 asset_object 的 bucket、kind、图片 MIME、大小和 owner 后签发只读 URL 给 VectorEngine 读取。
  9. 系列素材图集实现真相源在 server-rs/crates/platform-image/src/generated_asset_sheets/:调用方必须传入 grid_size 作为 n*nn,可选传入物品名称 prompt 模板和特殊设定 prompt;模块负责 sheet prompt 组装、按 n*n 切片、透明化、PNG 输出、OSS private upload 请求构造和 sheet / item / special prompt 元数据持久化。server-rs/crates/api-server/src/generated_asset_sheets.rs 只保留 AppState / AppError 适配和兼容导出。玩法只负责规划 slot、调用具体生图 provider、计费、失败回写,以及把通用切片结果映射回自己的 DTO / 草稿 / runtime 字段。

SpacetimeDB schema 变更规则

  1. 任何 table、view、reducer、procedure、row shape 或 bindings 变化,都必须同步本文件表 / view 目录和生成绑定;真实 table 变化还必须同步 server-rs/crates/spacetime-module/src/migration.rs,view 属于派生投影,不写入迁移导入导出表清单。
  2. 已有表新增字段必须放在 Rust 表结构体最后,并设置明确 #[default(...)]
  3. 删除字段、改名、重排字段、改类型或修改字段属性前,必须先询问用户并确认迁移计划。
  4. Vec 字段不要直接写无法 const 求值的 default;需要默认空集合时优先使用 Option<Vec<T>>#[default(None::<Vec<T>>)],业务层归一为空数组。
  5. 运行态读表必须按已声明索引访问。只要 table 上存在覆盖查询前缀的 #[index(...)] 或主键 / unique accessor,列表、详情、快照组装和计数都先用对应 accessor .filter(...) / .find(...),再在内存中处理索引无法覆盖的残余条件;不得用 .iter().filter(...) 扫整表替代现成索引。
  6. 面向公开列表的只读投影优先做成 public view / public 读模型表,并由 api-serverspacetime-client 长期订阅后读本地 cache。跨玩法公开作品统一主读模型是 public_work_gallery_entrypublic_work_detail_entry;各玩法既有 *_gallery_card_view / *_gallery_view / custom_world_gallery_entry 保留为 source view 和兼容路径。短期不把作品列表整体交给浏览器前端直接订阅;不要让 HTTP 列表接口每次请求都调用 procedure 重新组装全量列表。需要请求时间窗口的轻量统计可订阅 public_work_play_daily_stat 后在 api-server 本地聚合,需要写入副作用的详情、点赞、游玩记录仍走玩法 procedure / reducer。前端不得直接订阅 puzzle_work_profilecustom_world_profile 等领域源表,也不得自己做 join、聚合或权限逻辑。首屏、排序、字段归一、权限降级和 HTTP fallback 由 api-server BFF 维持。
  7. 多列索引按 SpacetimeDB 绑定生成的元组参数直接传入,例如 .filter((source_type, profile_id, played_day));前缀查询只传前缀元组,例如 .filter((scope_kind, scope_id.as_str()))。不要为了绕过类型问题退回整表遍历。
  8. procedure result 必须返回 typed snapshot / typed value。spacetime-client mapper 不得再通过 row_json/session_json/work_json/items_json/run_json/event_json/feedback_json: Option<String> 做跨层 JSON 字符串传输,也不得在 mapper 里反序列化旧 *JsonRecord 兼容结构。业务内部持久化字段如 profile_payload_jsonlevels_json 等不属于 procedure result 载荷例外,仍按各自表契约处理。
  9. 修改后运行:
npm run spacetime:generate
npm run check:spacetime-runtime-access
npm run check:spacetime-schema
npm run check:server-rs-ddd

本地联调和人工排障不要使用 spacetime --root-dir。本地数据隔离使用项目脚本或 --data-dir;发布目标显式传 --server / --server-url

账户充值数据契约

  1. profile_recharge_product_config 是泥点和会员商品配置真相源,默认商品只在表为空时由 SpacetimeDB 播种。module-runtime 中的默认商品 helper 只作为空库种子和兼容入口,不再作为运行期业务真相。
  2. 后台通过 /admin/api/profile/recharge-products 读写充值商品配置;字段覆盖 productId、标题、商品类型、金额分、基础泥点、首充赠送泥点、会员天数、徽标、说明、会员层级、启用状态和排序。
  3. 充值中心、下单校验和支付确认入账都读取 profile_recharge_product_config。历史订单保留下单时写入的商品标题、金额、渠道、状态和 provider transaction id,不随配置改动回写。
  4. 泥点首充资格按 user_id + product_id 的历史 paid 订单独立判断。某个档位已支付后,只隐藏该档位的首充赠送;其它未购买档位仍展示和结算首充赠送。
  5. hasPointsRecharged 只保留为账号是否发生过任一泥点充值的兼容字段,不得驱动所有商品展示隐藏或结算金额计算。前端只渲染后端返回的商品快照。
  6. paymentChannel 缺失、未知或和设备不匹配时必须拒绝;真实微信渠道只允许 wechat_mpwechat_h5wechat_native,生产配置不得把真实支付静默降级为 mock
  7. access JWT 只携带最小设备快照 device.client_typedevice.client_runtimedevice.client_platform。充值下单按该快照拦截渠道:小程序只允许 wechat_mp,手机微信内网页只允许 wechat_h5,桌面微信内网页只允许 wechat_native
  8. 所有微信真实渠道都以微信支付通知或服务端查单确认 SUCCESS 为到账事实;小程序、H5 跳转和 Native 二维码返回都不能直接发放泥点或会员。

外部服务与资产

  • LLMGENARRATIVE_LLM_*,创意 Agent 另用 APIMART_BASE_URL / APIMART_API_KEY
  • 图片生成:VectorEngine gpt-image-2 图片 provider 归属 platform-image,密钥只在后端环境变量中;api-server 内的 openai_image_generation.rs 只是兼容调用面和外部失败审计桥接,不再承载 provider 协议实现。实际外部生成运行记录统一落 tracking_eventevent_key = external_generation_runmetadata 记录开始 / 结束时间、耗时、状态、成功标记、失败原因、provider task id 和结果摘要,不再写回过时的 ai_task。APIMart 只保留给创意 Agent gpt-5 Responses 文本 / 多模态链路;DashScope 只按仍在使用的历史能力单独处理,不作为 GPT-image-2 兜底。VectorEngine /v1/images/generations/v1/images/edits 上游 POST 使用 libcurl 发送;reqwest 只保留给参考图 URL 下载和响应中图片 URL 下载。/v1/images/edits 的 multipart 参考图必须作为 libcurl 文件上传 part 发送,字段名为 image,实现上使用 Form::buffer(file_name, bytes) 并设置 Content-Type;不能只用 contents(...).filename(...),否则上游会把请求转码为缺少图片并返回 image is requiredrequest_send 阶段的 curl timeout / connect error 按可重试传输错误处理,最多尝试 5 次,并使用指数退避加短抖动;排障时优先看 attemptmax_attemptsretry_delay_msreference_image_bytes_totalrequest_params,不要把 SendRequest 当成上游业务错误。
  • Match3D 物品 sheet:关卡整图完成后走 VectorEngine /v1/images/edits multipart image,模型为 gpt-image-22K 1:1 输出 10*10 spritesheet;物品 sheet prompt 固定要求纯绿色绿幕背景,后端上传 OSS 前必须把绿幕扣成透明 PNG,并把透明整图写入 itemSpritesheetImageSrc/itemSpritesheetImageObjectKey。后端优先按透明 alpha 连通域从该 sheet 识别真实素材矩形并持久化 20 个物品、每个 5 个形态;识别数量不足时才回退 10*10 固定网格。通用系列素材图集的行列索引按每行 2 个物品计算,必须落在 1..=10,难度只决定运行态加载 3 / 9 / 15 / 20 种。
  • Match3D UI spritesheet 和背景派生图:关卡整图作为参考图并发生成 1K 1:1 UI spritesheet 与 1K 9:16 背景图,模型均为 gpt-image-2。UI spritesheet prompt 固定要求纯绿色绿幕背景,后端上传 OSS 前必须把绿幕扣成透明 PNG;背景图必须合成为全画幅不透明 PNG。
  • Match3D 1:1 容器 UIVectorEngine /v1/images/edits multipart 参考图。该容器参考图是后端生图协议输入,必须通过 include_bytes!api-server 编译进二进制,避免 API 单独发布或运行目录缺少 public/ 时生成失败。
  • 敲木鱼敲击物和背景环境图:VectorEngine /v1/images/edits,模型固定 gpt-image-2。敲击物支持 multipart 多参考图,第一张固定为后端内嵌默认木鱼图,用户上传图只作为新主题参考;prompt 必须要求 1:1 真实透明 alpha PNG 并禁止黑底、白底、棋盘格和任何实底背景。当前敲击物上传 OSS 前不做服务端抠图后处理,避免误伤玉米等主体像素。背景环境图只使用第一步抠图完成后的透明敲击物图作为参考,prompt 必须要求中央主体预留区保持干净,中央 40% 区域禁止出现主题主体、主体局部特写、轮廓影子或重复元素,主题元素只能作为外围氛围,且必须显式声明不继承任何绿色底色、绿幕底色或纯绿色画布。
  • Hyper3D / Rodin:只保留后端安全代理和旧数据兼容;Rodin 提交、状态、下载和响应解析归属 platform-hyper3dapi-server/src/hyper3d_generation.rs 只做路由、配置和错误 envelope 映射;新 Match3D 草稿和批量新增不再生成 GLB。
  • 音频:视觉小说专用音频路由保留;VectorEngine Suno/Vidu provider 协议、任务提交/查询、音频 URL 提取、下载、MIME/extension 归一和 OSS put 请求准备归属 platform-audioapi-server/src/vector_engine_audio_generation.rs 只做路由、配置、计费、asset object confirm、entity binding 和错误 envelope 映射;拼图、抓大鹅和敲木鱼提示词生成音效入口暂时关闭,通用 /api/creation/audio/* 对这些目标返回 410 Gone。敲木鱼创作只接收上传 / 录音音频资产;前端选择或录音阶段只在浏览器本地处理待提交音频,统一限制裁切后最长 1 秒、裁掉前后声音过小片段,并用浏览器端近似响度算法平衡到 -15 LKFS 后做峰值保护。点击生成时才直传 OSS 并确认 asset_object,创作 JSON 只提交轻量 WoodenFishAudioAsset,不得继续上传 Data URL 音频;未提供时由 api-server 写回内置默认木鱼音 /wooden-fish/default-hit-sound.mp3
  • OSS:私有 generated legacy path 进入浏览器前必须通过 /api/assets/read-url 换签;不要裸请求 /generated-*。OSS 签名、读签名、HEAD 和 PUT 的结构化日志由 platform-oss 输出,排查资产写入 / 确认失败时优先按 operationobject_key / key_prefixstatus_classerror_kindelapsed_ms 下钻。
  • 外部 API 失败审计:外部供应商调用未成功时,api-server 必须发送 OTLP 失败事件并写入 tracking_event。VectorEngine 图片 provider 在 platform-image 内输出结构化日志和 PlatformImageFailureAudit,覆盖 request_sendresponse_bodyupstream_statusresponse_parsemissing_imageimage_download 阶段;api-server 只把该 audit 映射成 external_api_call_failurescope_kind = modulescope_id = providermodule_key = external-api。metadata 固定包含 provider、endpoint、operation、failureStage、statusCode、statusClass、timeout、retryable、errorMessage、latencyMs、promptChars、referenceImageCount、imageModel、rawExcerpt,以及在调用方可获得上下文时补充的 userId(触发者)和 profileId(草稿 / 作品 / 场景作用域)。图片生成入口应优先把 owner user id 和 profile id 透传到失败审计,不要只保留 provider 级聚合,否则很难按“谁触发、哪个作品触发”定位问题。入库优先复用 tracking outboxoutbox 不可写或保护阈值拒绝时回退同步写 SpacetimeDB;不得新增前端兜底或在 SpacetimeDB reducer 内做外部 I/O。
  • 外部生成运行记录:所有外部生成编排的完成态统一写入 tracking_eventevent_key = external_generation_runscope_kind = modulescope_id = providermodule_key = external-generation。metadata 固定包含 runIdprovideroperationrequestLabelrequestPayloadstatussuccessfailureReasonproviderRequestIdresultPayloadstartedAtMicroscompletedAtMicrosdurationMs。这类记录只用于运行审计和排障,不再走 ai_task 旧表。

SpacetimeDB 表目录

下列 ### 标题是 schema guard 的机器可读表目录。新增、删除或改名表时必须同步这里。

ai_result_reference

  • Rust 结构体:AiResultReference
  • 源码:server-rs/crates/spacetime-module/src/ai/stages.rs

ai_task

  • Rust 结构体:AiTask
  • 源码:server-rs/crates/spacetime-module/src/ai/tasks.rs

ai_task_event

  • Rust 结构体:AiTaskEvent
  • 源码:server-rs/crates/spacetime-module/src/ai/events.rs

ai_task_stage

  • Rust 结构体:AiTaskStage
  • 源码:server-rs/crates/spacetime-module/src/ai/stages.rs

ai_text_chunk

  • Rust 结构体:AiTextChunk
  • 源码:server-rs/crates/spacetime-module/src/ai/stages.rs

analytics_date_dimension

  • Rust 结构体:AnalyticsDateDimension
  • 源码:server-rs/crates/spacetime-module/src/runtime/analytics_date_dimension.rs

asset_entity_binding

  • Rust 结构体:AssetEntityBinding
  • 源码:server-rs/crates/spacetime-module/src/asset_metadata/bindings.rs

asset_event

  • Rust 结构体:AssetEvent
  • 源码:server-rs/crates/spacetime-module/src/asset_metadata/objects.rs

asset_object

  • Rust 结构体:AssetObject
  • 源码:server-rs/crates/spacetime-module/src/asset_metadata/objects.rs

auth_identity

  • Rust 结构体:AuthIdentity
  • 源码:server-rs/crates/spacetime-module/src/auth/tables.rs

auth_store_projection_meta

  • Rust 结构体:AuthStoreProjectionMeta
  • 源码:server-rs/crates/spacetime-module/src/auth/tables.rs

auth_store_snapshot

  • Rust 结构体:AuthStoreSnapshot
  • 源码:server-rs/crates/spacetime-module/src/auth/tables.rs

认证恢复策略:api-server 启动时只从 SpacetimeDB 正式认证表(user_account / auth_identity / refresh_session)投影恢复进程内认证工作集;auth_store_snapshot 只保留行级快照备查,不再作为启动兜底来源。module-auth 只保留内存工作集和 JSON 导入 / 导出能力,不再写本地持久化文件;auth-store.json / GENARRATIVE_AUTH_STORE_PATH 不再是兼容恢复源,也不得在启动时回写覆盖 auth_identity / user_account。认证创建、登录会话、刷新、退出、改密、重置密码、绑定和资料变更等写操作必须在返回客户端前成功同步 SpacetimeDB 正式认证表;同步失败时接口返回错误,不允许把只存在于当前进程内存的账号或会话当成成功结果。新用户注册奖励、邀请码绑定和登录埋点必须排在认证同步成功之后,避免认证没落库时先写出钱包或邀请关系。若启动恢复阶段 SpacetimeDB 不可连接或超时,api-server 进入依赖不可用模式并对请求返回 503 SERVICE_UNAVAILABLE,直到运维恢复 SpacetimeDB 并重启服务。

auth_store_snapshot 禁止再写单行 snapshot_id = "default" 聚合 JSON。认证同步入口收到 module-auth 整份快照后必须拆成行级记录写入同一张表,当前行键前缀包括:meta/next_user_iduser/<user_id>phone/<phone+user>session/<session_id>session_hash/<hash+session>wechat/<provider_uid+user>union/<union+user>。SpacetimeDB 模块只保留 import_auth_store_snapshot_jsonexport_auth_store_snapshot_from_tables 两个认证快照过程;旧 get_auth_store_snapshotupsert_auth_store_snapshotimport_auth_store_snapshot 兼容入口已删除。导入正式表时只按主键 upsert 本次快照包含的用户、身份和会话,避免过期快照把其他用户整表删除。

导出认证快照时,auth_identityrefresh_session 只能引用仍存在于 user_account 的用户;孤儿手机号 identity、微信 identity、union 索引或 refresh session 必须被过滤,不能恢复成 module-auth 内存态里的 phone_to_user_id 死索引。module-auth 从 JSON 快照恢复时也要二次清理这些孤儿索引,避免历史坏快照导致密码登录提示错误、短信登录又提示手机号已存在。

bark_battle_draft_config

  • Rust 结构体:BarkBattleDraftConfigRow
  • 源码:server-rs/crates/spacetime-module/src/bark_battle/tables.rs

bark_battle_leaderboard_entry

  • Rust 结构体:BarkBattleLeaderboardEntryRow
  • 源码:server-rs/crates/spacetime-module/src/bark_battle/tables.rs

bark_battle_personal_best_projection

  • Rust 结构体:BarkBattlePersonalBestProjectionRow
  • 源码:server-rs/crates/spacetime-module/src/bark_battle/tables.rs

bark_battle_published_config

  • Rust 结构体:BarkBattlePublishedConfigRow
  • 源码:server-rs/crates/spacetime-module/src/bark_battle/tables.rs
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

bark_battle_runtime_run

  • Rust 结构体:BarkBattleRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/bark_battle/tables.rs

bark_battle_score_record

  • Rust 结构体:BarkBattleScoreRecordRow
  • 源码:server-rs/crates/spacetime-module/src/bark_battle/tables.rs

bark_battle_work_stats_projection

  • Rust 结构体:BarkBattleWorkStatsProjectionRow
  • 源码:server-rs/crates/spacetime-module/src/bark_battle/tables.rs

battle_state

  • Rust 结构体:BattleState
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

big_fish_agent_message

  • Rust 结构体:BigFishAgentMessage
  • 源码:server-rs/crates/spacetime-module/src/big_fish/tables.rs

big_fish_asset_slot

  • Rust 结构体:BigFishAssetSlot
  • 源码:server-rs/crates/spacetime-module/src/big_fish/tables.rs

big_fish_creation_session

  • Rust 结构体:BigFishCreationSession
  • 源码:server-rs/crates/spacetime-module/src/big_fish/tables.rs
  • 索引:by_big_fish_session_owner_user_idby_big_fish_session_stage。公开广场 view 使用 by_big_fish_session_stage 读取已发布会话,避免扫整表。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

big_fish_event

  • Rust 结构体:BigFishEvent
  • 源码:server-rs/crates/spacetime-module/src/big_fish/events.rs

big_fish_runtime_run

  • Rust 结构体:BigFishRuntimeRun
  • 源码:server-rs/crates/spacetime-module/src/big_fish/tables.rs
  • Rust viewbig_fish_gallery_view
  • 返回类型:Vec<BigFishWorkSummarySnapshot>
  • 源码:server-rs/crates/spacetime-module/src/big_fish/session.rs
  • 说明:大鱼吃小鱼公开 source 投影,只从 Published creation session 组装公开卡片字段;统一公开列表 / 详情主路径通过 public_work_gallery_entry / public_work_detail_entry 消费该 view 并映射成跨玩法契约。玩法旧 gallery 路径保留兼容 shape;个人作品列表、详情、点赞、游玩记录和 Remix 仍按原有 procedure / reducer 路径处理。

chapter_progression

  • Rust 结构体:ChapterProgression
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

creation_entry_config

  • Rust 结构体:CreationEntryConfig
  • 源码:server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs
  • 字段:config_idstart_titlestart_descriptionstart_idle_badgestart_busy_badgemodal_titlemodal_descriptionupdated_atevent_titleevent_descriptionevent_cover_image_srcevent_prize_pool_mud_pointsevent_starts_at_textevent_ends_at_textevent_banners_json
  • 迁移兼容:旧迁移包缺少活动横幅字段时,由 migration.rs 写入 None / 58000 默认值;旧库缺少 event_banners_json 时写入 None,运行态读取层再按 module-runtime 默认公告数组归一,不覆盖后台已保存配置,也不把旧结构化 eventBanner 升格为前端优先数组。HTTP 响应同时返回 eventBanners 数组和旧 eventBanner 单条兼容字段,前端优先消费数组;后台新配置主格式为 HTML 公告字符串数组或 {title, htmlCode} 对象数组,旧结构化 banner 字段仅保留兼容。默认公告背景和旧结构化默认 coverImageSrc 必须引用 public/ 下真实存在的静态资源,当前为 /creation-type-references/puzzle.webp

creation_entry_type_config

  • Rust 结构体:CreationEntryTypeConfig
  • 源码:server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs
  • 字段:idtitlesubtitlebadgeimage_srcvisibleopensort_orderupdated_atcategory_idcategory_labelcategory_sort_orderunified_creation_spec_json
  • 迁移兼容:旧迁移包缺少入口分类字段或统一创作契约字段时,由 migration.rs 写入 None / 0 / None 默认值;入口分组展示由 module-runtime 和前端展示派生消费,统一创作契约由 module-runtime 解析为 creationTypes[].unifiedCreationSpec,为空时只回退首批 puzzlematch3dwooden-fish 默认 spec。

custom_world_agent_message

  • Rust 结构体:CustomWorldAgentMessage
  • 源码:server-rs/crates/spacetime-module/src/custom_world.rs

custom_world_agent_operation

  • Rust 结构体:CustomWorldAgentOperation
  • 源码:server-rs/crates/spacetime-module/src/custom_world.rs

custom_world_agent_session

  • Rust 结构体:CustomWorldAgentSession
  • 源码:server-rs/crates/spacetime-module/src/custom_world.rs
  • 发布约束:publish_world 的 action payload 不要求携带 settingTextspacetime-module 调用 module-custom-world::resolve_custom_world_publish_setting_text(...),优先从当前 draft_profile_json 草稿真相派生正式 setting_text,避免旧会话 seed_text 为空时在最终 compile / publish 阶段触发 custom_world.setting_text 不能为空

custom_world_draft_card

  • Rust 结构体:CustomWorldDraftCard
  • 源码:server-rs/crates/spacetime-module/src/custom_world.rs

custom_world_gallery_entry

  • Rust 结构体:CustomWorldGalleryEntry
  • 源码:server-rs/crates/spacetime-module/src/custom_world.rs
  • 作用:自定义世界公开 source 读模型。统一公开列表 / 详情主路径通过 public_work_gallery_entry / public_work_detail_entry 消费该投影并映射成跨玩法契约;/api/runtime/custom-world-gallery 保留旧 HTTP shape,并从统一 public cache 映射回旧 DTO。旧 procedure 只用于兼容旧库缺少 gallery 读模型行时的一次性同步兜底。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

custom_world_profile

  • Rust 结构体:CustomWorldProfile
  • 源码:server-rs/crates/spacetime-module/src/custom_world.rs
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

custom_world_session

  • Rust 结构体:CustomWorldSession
  • 源码:server-rs/crates/spacetime-module/src/custom_world.rs

database_migration_import_chunk

  • Rust 结构体:DatabaseMigrationImportChunk
  • 源码:server-rs/crates/spacetime-module/src/migration.rs

database_migration_operator

  • Rust 结构体:DatabaseMigrationOperator
  • 源码:server-rs/crates/spacetime-module/src/migration.rs

inventory_slot

  • Rust 结构体:InventorySlot
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

jump_hop_agent_session

  • Rust 结构体:JumpHopAgentSessionRow
  • 源码:server-rs/crates/spacetime-module/src/jump_hop/tables.rs

jump_hop_event

  • Rust 结构体:JumpHopEventRow
  • 源码:server-rs/crates/spacetime-module/src/jump_hop/tables.rs

jump_hop_leaderboard_entry

  • Rust 结构体:JumpHopLeaderboardEntryRow
  • 源码:server-rs/crates/spacetime-module/src/jump_hop/tables.rs
  • 说明:跳一跳作品维度排行榜 read model,每个 profile_id + player_id 只保留 1 条最佳记录;排序口径为成功跳跃次数降序、游戏时长升序、更新时间升序,草稿试玩不作为公开排行榜语义。

jump_hop_runtime_run

  • Rust 结构体:JumpHopRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/jump_hop/tables.rs
  • 说明:运行记录持久化 runtime_mode,取值为 draft / published;草稿试玩只允许作品所有者启动,不累计公开游玩次数,也不写入公开排行榜。

jump_hop_work_profile

  • Rust 结构体:JumpHopWorkProfileRow
  • 源码:server-rs/crates/spacetime-module/src/jump_hop/tables.rs
  • 说明:作品投影持久化独立 theme_text,用于生成主题和公开卡片主题展示;历史行为空时按 work_title 兜底。back_button_asset_json 保存 image2 单独生成并去绿后的 1:1 左上角返回按钮资产快照;旧迁移数据按 None 兼容,运行态缺失该字段时使用同尺寸 CSS 主题按钮兜底。
  • Rust viewjump_hop_gallery_card_view
  • 返回类型:Vec<JumpHopGalleryCardViewRow>
  • 源码:server-rs/crates/spacetime-module/src/jump_hop.rs
  • 说明:跳一跳公开列表 source 投影,只暴露 publication_status = Published 的作品卡片字段;统一公开列表主路径通过 public_work_gallery_entry 消费该 view 并映射成跨玩法契约。个人作品列表、详情、发布和运行态仍按 procedure 路径处理。
  • Rust viewjump_hop_gallery_view
  • 返回类型:Vec<JumpHopGalleryViewRow>
  • 源码:server-rs/crates/spacetime-module/src/jump_hop.rs
  • 说明:跳一跳公开详情兼容投影,包含作品、路径和素材字段;统一公开详情主路径通过 public_work_detail_entry 消费该 view,只保留平台详情页展示摘要。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

wooden_fish_agent_session

  • Rust 结构体:WoodenFishAgentSessionRow
  • 源码:server-rs/crates/spacetime-module/src/wooden_fish/tables.rs

wooden_fish_event

  • Rust 结构体:WoodenFishEventRow
  • 源码:server-rs/crates/spacetime-module/src/wooden_fish/tables.rs

wooden_fish_runtime_run

  • Rust 结构体:WoodenFishRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/wooden_fish/tables.rs

wooden_fish_work_profile

  • Rust 结构体:WoodenFishWorkProfileRow
  • 源码:server-rs/crates/spacetime-module/src/wooden_fish/tables.rs
  • 说明:敲木鱼作品 profile 真相,包含敲击物图案、背景环境图、主题返回按钮图、敲击音效、飘字配置、发布状态和公开计数;background_asset_json 保存 image2 生成的 9:16 背景环境图资产快照,back_button_asset_json 保存 image2 生成并去绿后的 1:1 返回按钮图资产快照,旧迁移数据按 None 兼容。
  • Rust viewwooden_fish_gallery_card_view
  • 返回类型:Vec<WoodenFishGalleryCardViewRow>
  • 源码:server-rs/crates/spacetime-module/src/wooden_fish.rs
  • 说明:敲木鱼公开列表 source 投影,只暴露 publication_status = published 的作品卡片字段;统一公开列表主路径通过 public_work_gallery_entry 消费该 view 并映射成跨玩法契约。个人作品列表、详情、发布和运行态仍按 procedure 路径处理。
  • Rust viewwooden_fish_gallery_view
  • 返回类型:Vec<WoodenFishGalleryViewRow>
  • 源码:server-rs/crates/spacetime-module/src/wooden_fish.rs
  • 说明:敲木鱼公开详情兼容投影,包含敲击物图案、背景环境图、主题返回按钮图、敲击音效和飘字配置;统一公开详情主路径通过 public_work_detail_entry 消费该 view,只保留平台详情页展示摘要。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

match3d_agent_message

  • Rust 结构体:Match3DAgentMessageRow
  • 源码:server-rs/crates/spacetime-module/src/match3d/tables.rs

match3d_agent_session

  • Rust 结构体:Match3DAgentSessionRow
  • 源码:server-rs/crates/spacetime-module/src/match3d/tables.rs

match3d_runtime_run

  • Rust 结构体:Match3DRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/match3d/tables.rs

match_3_d_work_profile

  • Rust 结构体:Match3DWorkProfileRow
  • Rust accessormatch_3_d_work_profile
  • 源码:server-rs/crates/spacetime-module/src/match3d/tables.rs
  • 兼容说明:dev 现有 SpacetimeDB 元数据中的真实表名 / 索引名为 match_3_d_work_profilematch_3_d_work_profile_*_idx_btree。module 内部 accessor 必须与该 canonical name 对齐,避免 Rust SDK 在 index_id_from_name 初始化二级索引时查找 match3d_work_profile_* 并触发 No such index panic。migration.rs 仍兼容旧迁移包中的 match3d_work_profile 表名补默认字段。
  • Rust viewmatch3d_gallery_view
  • 返回类型:Vec<Match3DGalleryViewRow>
  • 源码:server-rs/crates/spacetime-module/src/match3d.rs
  • 说明:抓大鹅公开 source 投影,只暴露 publication_status = published 的作品卡片字段;统一公开列表 / 详情主路径通过 public_work_gallery_entry / public_work_detail_entry 消费该 view 并映射成跨玩法契约。个人作品列表、详情、发布、点赞、游玩记录和 Remix 仍按原有 procedure / reducer 路径处理。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

npc_state

  • Rust 结构体:NpcState
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

player_progression

  • Rust 结构体:PlayerProgression
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

profile_dashboard_state

  • Rust 结构体:ProfileDashboardState
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_feedback_submission

  • Rust 结构体:ProfileFeedbackSubmission
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_invite_code

  • Rust 结构体:ProfileInviteCode
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_membership

  • Rust 结构体:ProfileMembership
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_recharge_product_config

  • Rust 结构体:ProfileRechargeProductConfig
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs
  • 作用:泥点和会员充值商品配置真相源,供充值中心展示、下单校验、支付确认和后台“充值商品”页维护。

profile_played_world

  • Rust 结构体:ProfilePlayedWorld
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_recharge_order

  • Rust 结构体:ProfileRechargeOrder
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_redeem_code

  • Rust 结构体:ProfileRedeemCode
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_redeem_code_usage

  • Rust 结构体:ProfileRedeemCodeUsage
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_referral_relation

  • Rust 结构体:ProfileReferralRelation
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_save_archive

  • Rust 结构体:ProfileSaveArchive
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_task_config

  • Rust 结构体:ProfileTaskConfig
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_task_progress

  • Rust 结构体:ProfileTaskProgress
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_task_reward_claim

  • Rust 结构体:ProfileTaskRewardClaim
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

profile_wallet_ledger

  • Rust 结构体:ProfileWalletLedger
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

public_work_like

  • Rust 结构体:PublicWorkLike
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

public_work_play_daily_stat

  • Rust 结构体:PublicWorkPlayDailyStat
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs

puzzle_agent_message

  • Rust 结构体:PuzzleAgentMessageRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs

puzzle_agent_session

  • Rust 结构体:PuzzleAgentSessionRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs

puzzle_event

  • Rust 结构体:PuzzleEvent
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs

puzzle_leaderboard_entry

  • Rust 结构体:PuzzleLeaderboardEntryRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs

puzzle_runtime_run

  • Rust 结构体:PuzzleRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs

puzzle_work_profile

  • Rust 结构体:PuzzleWorkProfileRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs

puzzle_clear_agent_session

  • Rust 结构体:PuzzleClearAgentSessionRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle_clear/tables.rs
  • 说明:拼消消创作会话表,保存轻表单草稿、生成状态、已发布 profile 关联和更新时间;只由拼消消 procedure 读写。

puzzle_clear_work_profile

  • Rust 结构体:PuzzleClearWorkProfileRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle_clear/tables.rs
  • 说明:拼消消作品 profile 表,保存中央底图资产、4 张素材工作表切片后合成的最终 atlas、35 个复合图案组、95 个 1x1 卡牌切片、卡背占位图、发布状态、可见性和基础 play count;公开列表 / 详情只通过 read model 消费,不让前端直接订阅源表。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

puzzle_clear_runtime_run

  • Rust 结构体:PuzzleClearRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle_clear/tables.rs
  • 说明:拼消消正式 runtime run 表,保存当前关卡、已消除次数、棋盘 snapshot、开始 / 完成时间和 run 状态;正式胜负、重试、完成、超时和交换结果以后端 procedure 裁决为准。

puzzle_clear_event

  • Rust 结构体:PuzzleClearEventRow
  • 源码:server-rs/crates/spacetime-module/src/puzzle_clear/tables.rs
  • 说明:拼消消基础 runtime 事件表,记录 published run 的开局、关卡完成、全局完成、失败、超时和消除统计来源;首版不做排行榜。
  • Rust viewpuzzle_clear_gallery_view
  • 返回类型:Vec<PuzzleClearGalleryViewRow>
  • 源码:server-rs/crates/spacetime-module/src/puzzle_clear.rs
  • 说明:拼消消公开详情 source 投影,只暴露 publication_status = publishedvisible = true 的作品,包含 atlas、底图、图案组和卡牌切片等详情级字段;统一公开详情主路径通过 public_work_detail_entry 消费该 view,只保留平台详情页展示摘要。
  • Rust viewpuzzle_clear_gallery_card_view
  • 返回类型:Vec<PuzzleClearGalleryCardViewRow>
  • 源码:server-rs/crates/spacetime-module/src/puzzle_clear.rs
  • 说明:拼消消公开列表 source 投影,只暴露平台卡片需要的公开字段;统一公开列表主路径通过 public_work_gallery_entry 消费该 view/api/runtime/puzzle-clear/gallery 保留玩法专属 HTTP shape。
  • Rust viewpuzzle_gallery_view
  • 返回类型:Vec<PuzzleWorkProfile>
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs
  • 说明:拼图广场公开详情 source / 兼容投影,只暴露 publication_status = Published 的作品,但返回完整 PuzzleWorkProfile,包含 levels / anchor_pack 等详情级字段;统一公开详情主路径通过 public_work_detail_entry 消费该 view,只保留平台详情页展示摘要。
  • Rust viewpuzzle_gallery_card_view
  • 返回类型:Vec<PuzzleGalleryCardViewRow>
  • 源码:server-rs/crates/spacetime-module/src/puzzle.rs
  • 说明:拼图公开列表 source 投影,只暴露前端列表卡片需要的公开字段,不携带 levels / anchor_pack 等详情级载荷;统一公开列表主路径通过 public_work_gallery_entry 消费该 view/api/runtime/puzzle/gallery 保留旧 HTTP shape,并从统一 public cache 映射回 PuzzleGalleryResponse

拼图公开列表 HTTP 窗口缓存

  • 接口:GET /api/runtime/puzzle/gallery
  • 响应契约:保留 items 字段兼容旧前端;当前 items 只返回前 10 个完整卡片,新增 previewRefs 返回后 10 个 workId/profileId 引用,并返回 hasMorenextCursortotalCount
  • 缓存策略:api-serverPuzzleGalleryCache 中缓存最终 PuzzleGalleryResponse 的预序列化 data JSON。缓存 miss / 过期时单飞重建,避免并发请求重复排序、映射、DTO 深拷贝和 serde_json::Value 树构造;开启响应 envelope 时只按请求拼接轻量 meta,缓存短 TTL 刷新 recentPlayCount7d,后台 cleanup task 周期清理超过最大空闲窗口的旧响应。OTLP 通过 genarrative.puzzle_gallery.cache.*genarrative.spacetime.read.*genarrative.http.server.response_bodies.in_flightgenarrative.http.server.request_permits.available 区分缓存重建、SpacetimeDB 本地订阅读、响应 body 生命周期和 HTTP 背压状态。
  • 详情路径:公开详情、点赞、游玩记录和 Remix 仍按原有 procedure / reducer 路径处理;前端拿到 previewRefs 后如果需要展开更多内容,应优先使用后续列表窗口能力或详情 cache,不要把自动详情预取变成新的 procedure 热点。

api-server 长期订阅读模型

spacetime-client 建立每个池连接时会等待下列订阅初始同步:

  • SELECT * FROM public_work_gallery_entry
  • SELECT * FROM public_work_detail_entry
  • SELECT * FROM bark_battle_gallery_view
  • SELECT * FROM puzzle_gallery_card_view
  • SELECT * FROM puzzle_clear_gallery_card_view
  • SELECT * FROM jump_hop_gallery_card_view
  • SELECT * FROM wooden_fish_gallery_card_view
  • SELECT * FROM custom_world_gallery_entry
  • SELECT * FROM match_3_d_gallery_view
  • SELECT * FROM square_hole_gallery_view
  • SELECT * FROM visual_novel_gallery_view
  • SELECT * FROM big_fish_gallery_view
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'puzzle'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'jump-hop'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'wooden-fish'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'custom-world'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'match3d'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'square-hole'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'visual-novel'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'big-fish'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'bark-battle'
  • SELECT * FROM public_work_play_daily_stat WHERE source_type = 'puzzle-clear'
  • SELECT * FROM creation_entry_config
  • SELECT * FROM creation_entry_type_config
  • SELECT * FROM asset_object

跨玩法公开作品列表 / 详情主读模型是 public_work_gallery_entrypublic_work_detail_entry。拼图、自定义世界等旧玩法公开列表 HTTP 路由保留原响应 shape,由 BFF mapper 从统一 public cache 映射回当前 DTO;旧 *_gallery_card_view / *_gallery_view / custom_world_gallery_entry 继续作为 source view 和兼容缓存。各玩法的个人作品列表、详情、发布、点赞、游玩记录、Remix 和其它需要鉴权或写入副作用的路径继续走 procedure / reducer;不要为了公开列表性能把这些 owner-specific 或 mutation 语义混进 public view。

GET /api/creation-entry/config 和入口熔断优先从订阅 cache 读取创作入口配置;cache 缺失时使用最近一次成功读取的内存快照,再兜底调用 get_creation_entry_config procedure 完成空库种子或旧库兼容。 入口配置快照包含 start card、类型弹窗、公告位兼容字段和入口类型列表;入口类型列表新增 category_idcategory_labelcategory_sort_order 后,后台 upsert、shared-contractsmodule-runtimespacetime-client binding 必须同步,旧迁移 JSON 通过 migration.rs 默认值兼容。

RPG 创作入口的配置 ID 是 rpg,当前 visible=trueopen=true;历史 custom-world 路由仍是 RPG 的工程域与运行态源类型。入口熔断把 /api/runtime/custom-world*/api/story/*/api/runtime/chat/* 统一映射到 rpg,不要新增平行 airp 路由或用 airp 接管当前文字冒险链路。

结构化创作和 RPG 的 LLM JSON 链路默认不启用 Responses web_search;只有在明确需要联网增强时,才通过 GENARRATIVE_RPG_LLM_WEB_SEARCH_ENABLEDGENARRATIVE_CREATION_AGENT_LLM_WEB_SEARCH_ENABLED 显式打开。否则未开通工具的上游会先吐自然语言再返回 ToolNotOpen,这类失败要按上游工具不可用处理,不要误判成模型返回结果解析失败。

统一公开作品 BFF 路由是 GET /api/public-worksGET /api/public-works/{publicWorkCode},响应契约由 shared-contracts::public_workpackages/shared/src/contracts/publicWork.ts 共同维护。前端首期仍走 BFF HTTP,不直接订阅 SpacetimeDB;后续若允许浏览器直连订阅,也只能订阅 public_work_gallery_entry / public_work_detail_entry 这类稳定公开 read model,不能订阅 puzzle_work_profilecustom_world_profile 等源表后自行拼装列表。设计细节见 docs/technical/【后端架构】统一公开作品ReadModel设计-2026-05-26.md

  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

quest_log

  • Rust 结构体:QuestLog
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

quest_record

  • Rust 结构体:QuestRecord
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

refresh_session

  • Rust 结构体:RefreshSession
  • 源码:server-rs/crates/spacetime-module/src/auth/tables.rs

runtime_setting

  • Rust 结构体:RuntimeSetting
  • 源码:server-rs/crates/spacetime-module/src/runtime/settings.rs

runtime_snapshot

  • Rust 结构体:RuntimeSnapshotRow
  • 源码:server-rs/crates/spacetime-module/src/runtime/snapshots.rs

square_hole_agent_message

  • Rust 结构体:SquareHoleAgentMessageRow
  • 源码:server-rs/crates/spacetime-module/src/square_hole/tables.rs

square_hole_agent_session

  • Rust 结构体:SquareHoleAgentSessionRow
  • 源码:server-rs/crates/spacetime-module/src/square_hole/tables.rs

square_hole_runtime_run

  • Rust 结构体:SquareHoleRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/square_hole/tables.rs

square_hole_work_profile

  • Rust 结构体:SquareHoleWorkProfileRow
  • 源码:server-rs/crates/spacetime-module/src/square_hole/tables.rs
  • Rust viewsquare_hole_gallery_view
  • 返回类型:Vec<SquareHoleGalleryViewRow>
  • 源码:server-rs/crates/spacetime-module/src/square_hole.rs
  • 说明:方洞挑战公开 source 投影,只暴露 publication_status = published 的作品卡片字段;统一公开列表 / 详情主路径通过 public_work_gallery_entry / public_work_detail_entry 消费该 view 并映射成跨玩法契约。个人作品列表、详情、发布、点赞、游玩记录和 Remix 仍按原有 procedure / reducer 路径处理。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。

story_event

  • Rust 结构体:StoryEvent
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

story_session

  • Rust 结构体:StorySession
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

tracking_daily_stat

  • Rust 结构体:TrackingDailyStat
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs
  • 写入:由单条或批量 tracking procedure 在同一事务中随 tracking_event 更新,作为运营查询和个人任务进度的聚合投影。

tracking_event

  • Rust 结构体:TrackingEvent
  • 源码:server-rs/crates/spacetime-module/src/runtime/profile.rs
  • 写入:关键业务埋点同步调用单条 procedure;普通 HTTP route tracking 由 api-server 本机 outbox 批量调用 record_tracking_events_and_return。outbox 到达批量阈值时先封存 active 文件并切新 active,后台 worker 异步 flush sealed 文件,HTTP 请求线程不等待 SpacetimeDB。FLUSH_INTERVAL_MS 只负责兜底封存长时间未满批的 active 文件,MAX_BYTES 只做磁盘保护阈值。event_id 必须稳定且全局唯一,批量重试时用唯一索引做幂等跳过。
  • 外部 API 失败:event_key = external_api_call_failure 使用同一张表落库;它是供应商失败审计事实,不新增 SpacetimeDB 表,查询时按 module_key = 'external-api'scope_kind = module AND scope_id = '<provider>' 过滤。

treasure_record

  • Rust 结构体:TreasureRecord
  • 源码:server-rs/crates/spacetime-module/src/gameplay.rs

user_account

  • Rust 结构体:UserAccount
  • 源码:server-rs/crates/spacetime-module/src/auth/tables.rs

user_browse_history

  • Rust 结构体:UserBrowseHistory
  • 源码:server-rs/crates/spacetime-module/src/runtime/browse_history.rs

visual_novel_agent_message

  • Rust 结构体:VisualNovelAgentMessageRow
  • 源码:server-rs/crates/spacetime-module/src/visual_novel.rs

visual_novel_agent_session

  • Rust 结构体:VisualNovelAgentSessionRow
  • 源码:server-rs/crates/spacetime-module/src/visual_novel.rs

visual_novel_runtime_event

  • Rust 结构体:VisualNovelRuntimeEvent
  • 源码:server-rs/crates/spacetime-module/src/visual_novel.rs

visual_novel_runtime_history_entry

  • Rust 结构体:VisualNovelRuntimeHistoryEntryRow
  • 源码:server-rs/crates/spacetime-module/src/visual_novel.rs

visual_novel_runtime_run

  • Rust 结构体:VisualNovelRuntimeRunRow
  • 源码:server-rs/crates/spacetime-module/src/visual_novel.rs

visual_novel_work_profile

  • Rust 结构体:VisualNovelWorkProfileRow
  • 源码:server-rs/crates/spacetime-module/src/visual_novel.rs
  • Rust viewvisual_novel_gallery_view
  • 返回类型:Vec<VisualNovelGalleryViewRow>
  • 源码:server-rs/crates/spacetime-module/src/visual_novel.rs
  • 说明:视觉小说公开 source 投影,只暴露 publication_status = published 的作品卡片字段,不把完整 draft 暴露给公开列表订阅;统一公开列表 / 详情主路径通过 public_work_gallery_entry / public_work_detail_entry 消费该 view 并映射成跨玩法契约。个人历史、详情、运行态和发布仍按原有 procedure / reducer 路径处理。
  • 字段变更:visible 控制是否进入公开列表 / 详情,默认 true;旧迁移数据由 migration.rs 补默认值。