Merge branch 'master' into codex/game-rating-review
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m30s
Project CI / Backend tests (pull_request) Successful in 5m11s
Project CI / Native shell tests (pull_request) Successful in 6m6s
Project CI / Frontend tests (pull_request) Successful in 2m9s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 10m23s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m45s
Project CI / Repository checks (pull_request) Successful in 2m15s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m56s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 58s

This commit is contained in:
2026-10-01 14:32:09 +08:00
4 changed files with 83 additions and 8 deletions
@@ -2129,6 +2129,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 决策:主站与图片画板统一复用公共泥点资产入口,收起态展示总额与充值,展开态只展示不限时泥点、每日免费泥点和使用详情;充值中心 BFF 继续统一下发总额、三桶余额、限时到期时间、每日免费基础重置额及下次重置时间,前端不得自行相减推算,但会员周期限时泥点仅用于存量兼容和后端结算,当前版本不在前台展示。钱包明细每次展开都重新读取充值中心 BFF,打开期间实时总额变化时继续补读;图片画板的生成扣费或退款完成后同时刷新总额与充值中心拆分。充值中心读请求必须使用 revision 门禁,支付创建、到账确认等权威响应写入时使旧读失效,避免旧响应覆盖新的每日免费 / 不限时明细。默认泥点商品收敛为 `60 / ¥6`、`180 + 90 / ¥18`、`300 + 150 / ¥30`、`680 + 340 / ¥68` 四档,`60` 档无赠送,后三档按现有 `user_id + product_id` 独立资格规则首次购买加赠 `50%`。当前版本关闭会员购买页签、会员商品和购买 / 升级入口。
- 2026-07-17 追加:主站、图片画板与 AI 游戏创作独立 App 的泥点账单统一复用 `packages/shared/src/components/PlatformProfileWalletLedgerModal`。共享组件只依赖 `ProfileWalletLedgerResponse`,承接来源 label、金额正负号、UTC 日期、余额兜底和 loading / empty / error 展示;`/api/profile/wallet-ledger` 请求、鉴权、打开状态与重试生命周期继续由各宿主持有,不把账户事实或后端副作用下沉到共享 UI。
- 2026-09-07 追加:资产扣费在既有钱包流水 metadata 中记录服务端确定的 `assetKind`,`GET /api/profile/wallet-ledger` 只把白名单类型映射为可选用户文案 `reason`,不暴露原始 metadata、资源 ID、任务 ID 或未知内部枚举。共享账单组件优先展示非空 `reason`;历史、未知和空 metadata 继续按 `sourceType` 回退为“资产操作消耗”,不得由客户端猜测业务类型。
- 2026-10-01 追加:账单不计入实际变动为 0 的条目,规则落在 SpacetimeDB 侧而不是展示层。写入侧只在余额真的变化时落账:每日免费 / 会员周期换期按 `resolve_expiring_points_wallet_transition` 先算出“换期后余额 + 实际变动”,变动为 0(含到期额度等于发放额度、余额不足以扣回到期额度、额度与发放都为 0)时只更新余额状态、不写 `profile_wallet_ledger`;通用结算入口 `apply_profile_wallet_signed_delta` 在 0 变动时同样直接返回当前余额。读取侧 `list_profile_wallet_ledger_entries` 在按余额结算链排序之后、截断 50 条上限之前剔除 `amount_delta == 0` 的存量行,因此历史遗留的 0 流水也立即从账单消失,且不占用列表上限、不改变其余条目的先后与 `balance_after` 语义。此前 `update_profile_wallet_balance_for_expiring_points` 只判断“到期额度与发放额度都为 0”,判的是入参而不是实际余额变动,所以余额不变的换期流水仍会落账并显示成 0。
- 影响范围:`profile_recharge_product_config` 默认商品、充值中心 read model、共享前后端契约、主站与图片画板泥点资产入口、充值弹窗、后台充值商品默认值。
- 验证方式:充值与统一入口定向前端测试、`npm run typecheck`、充值商品定向 Rust 测试、`cargo check -p spacetime-module -p spacetime-client -p api-server --manifest-path server-rs/Cargo.toml`、`npm run check:encoding`、`git diff --check`。
- 关联文档:`docs/【项目基线】当前产品与工程约束-2026-05-15.md`、`docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md`。
@@ -838,8 +838,9 @@ Responses 的终态载荷既是工具调用的恢复源,也是正文的恢复
### `profile_wallet_ledger`
- Rust 结构体:`ProfileWalletLedger`
- 源码:`server-rs/crates/spacetime-module/src/runtime/profile.rs`
- 源码:`server-rs/crates/spacetime-module/src/runtime/active/profile.rs`
- 说明:账号钱包流水表。`created_at` 表示钱包事务实际结算时间,列表先按当前余额反向校验 `balance_after - amount_delta` 的结算链,再以该时间倒序兜底,避免支付回调或退款重放延迟时出现余额顺序倒置;支付平台确认时间继续保存在充值订单 `paid_at`。`metadata_json` 为可选 JSON 对象字符串,旧行缺失时读取层按 `{}` 归一;外部生成扣费 / 退款写入 `externalGenerationJobId`,使退款记录可以追溯到对应 `external_generation_job`。
- 实际变动为 0 的条目不进账单:写入侧只在余额真的变化时落账,每日免费 / 会员周期换期先按 `previous_balance - expired_points + granted_points`(饱和运算)算出实际变动,变动为 0 时只更新余额状态、不写本表;通用结算入口 `apply_profile_wallet_signed_delta` 在 `amount_delta == 0` 时同样不落账。读取侧 `list_profile_wallet_ledger_entries` 在结算链排序之后、截断 50 条上限之前剔除 `amount_delta == 0` 的存量行,因此历史遗留的 0 变动流水不会出现在 `GET /api/profile/wallet-ledger`,也不占用列表上限。该规则只影响展示与落账,不改变幂等 ledger、余额结算、消费投影和退款语义。
### `profile_wallet_consumption_total`