5.0 KiB
5.0 KiB
资产对象业务实体绑定 reducer 设计
日期:2026-04-21
1. 文档目的
这份文档用于冻结 M6 中“对象绑定业务实体 reducer”的首版落地方案。
当前已经完成:
- 浏览器可通过
PostObject把文件直传到私有 OSS。 POST /api/assets/objects/confirm已能确认对象存在。asset_object已按bucket + object_key写入 SpacetimeDB。
下一步要补上的最小闭环是:
- 已确认的
asset_object能绑定到某个业务实体。 - 绑定关系由 SpacetimeDB 持久化。
- Axum 提供最小 HTTP facade,避免前端直接拼 SpacetimeDB reducer 参数。
2. 当前阶段不直接创建强业务表的原因
当前先落通用 asset_entity_binding,不直接创建 character_visual_asset / scene_image_asset / sprite_sheet_asset。
原因固定如下:
- 角色、场景、精灵等强业务表的完整字段还没有冻结。
- 当前最紧急的工程闭环是“确认后的对象能被实体引用”,不是完整发布模型。
- 通用绑定表可以先承接旧接口迁移中的
entityId + slot关系,后续再由强业务表逐步替换或派生。
3. 表设计
首版新增 private table:
asset_entity_binding
字段如下:
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
binding_id |
String |
是 | 主键,固定 assetbind_ 前缀。 |
asset_object_id |
String |
是 | 被绑定的 asset_object.asset_object_id。 |
entity_kind |
String |
是 | 业务实体类型,例如 character、scene、profile。 |
entity_id |
String |
是 | 业务实体 ID。 |
slot |
String |
是 | 实体上的资产槽位,例如 primary_visual、cover、sprite_sheet。 |
asset_kind |
String |
是 | 资产类型,例如 character_visual。 |
owner_user_id |
Option<String> |
否 | 归属用户,当前仅作为服务端传入的记录字段。 |
profile_id |
Option<String> |
否 | 归属 profile。 |
created_at |
Timestamp |
是 | 首次绑定时间。 |
updated_at |
Timestamp |
是 | 最近绑定更新时间。 |
索引如下:
entity_kind + entity_id + slot用于按实体槽位查当前绑定。asset_object_id用于按对象反查被哪些业务实体引用。
4. 幂等规则
绑定写入按以下规则执行:
asset_object_id必须已存在于asset_object。entity_kind + entity_id + slot作为首版幂等定位键。- 同一实体槽位重复绑定时,不新增第二行。
- 重复绑定会复用原
binding_id与created_at,更新asset_object_id / asset_kind / owner_user_id / profile_id / updated_at。 - 不同槽位可以绑定同一个
asset_object_id。
5. reducer / procedure 设计
SpacetimeDB 新增:
bind_asset_object_to_entityreducer,只返回Result<(), String>,供后续模块内部复用。bind_asset_object_to_entity_and_returnprocedure,面向 Axum 同步接口返回最终绑定快照。
procedure 返回结构采用:
okrecorderror_message
与 asset_object 确认 procedure 保持一致,便于 spacetime-client 做统一错误映射。
6. Axum HTTP facade
首版新增接口:
POST /api/assets/objects/bind
请求体:
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
assetObjectId |
String |
是 | 已确认对象 ID。 |
entityKind |
String |
是 | 业务实体类型。 |
entityId |
String |
是 | 业务实体 ID。 |
slot |
String |
是 | 资产槽位。 |
assetKind |
String |
是 | 资产类型。 |
ownerUserId |
String |
否 | 当前阶段由后端调用方显式传入。 |
profileId |
String |
否 | 当前阶段由后端调用方显式传入。 |
响应体核心字段:
bindingIdassetObjectIdentityKindentityIdslotassetKindownerUserIdprofileIdcreatedAtupdatedAt
7. 当前阶段安全边界
当前接口是 Axum facade,不是前端直接调用 SpacetimeDB reducer 的最终权限模型。
约束如下:
- 当前不把长期 OSS AK/SK 下发给客户端。
- 当前不让客户端直接写 private table。
owner_user_id当前只作为记录字段,不作为可信授权依据。- 后续接入 SpacetimeDB 身份透传后,绑定 reducer 的授权必须改为基于可信身份,不信任客户端传入的用户 ID。
8. 完成定义
首版完成条件:
module-assets提供绑定输入、快照、结果结构与字段校验。spacetime-module新增asset_entity_binding表与绑定 reducer/procedure。spacetime-client生成最新 Rust bindings 并封装绑定 procedure。api-server暴露POST /api/assets/objects/bind。- 本地测试覆盖字段错误与 “asset_object 不存在不能绑定”。
9. 一句话结论
当前阶段先用通用 asset_entity_binding 把已确认 OSS 对象绑定到业务实体槽位,强业务资产表等字段稳定后再继续拆分。