修复泥点消耗刷新不及时 #138

Merged
kdletters merged 48 commits from fix/one-mud-point-store into master 2026-08-08 10:25:02 +08:00
Member

refactor:

  • 主站复用game agent的zustand store

fix:

  • 修复旧请求覆盖问题

  • 修复账号切换问题

  • 主站原本已经每 4 秒轮询 external generation 任务状态, 在这里补充触发余额刷新的时机

refactor: - 主站复用game agent的zustand store fix: - 修复旧请求覆盖问题 - 修复账号切换问题 - 主站原本已经每 4 秒轮询 external generation 任务状态, 在这里补充触发余额刷新的时机
k88936 self-assigned this 2026-08-05 17:01:01 +08:00
k88936 added this to the 美术画布 project 2026-08-05 17:01:01 +08:00
k88936 added 1 commit 2026-08-05 17:01:01 +08:00
统一主站与AI游戏创作钱包状态
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 3m2s
Project CI / Native shell tests (pull_request) Failing after 5m29s
3a4a8e2029
新增共享泥点钱包 Store 并合并并发刷新
  按账号 owner 隔离快照并屏蔽切换期间的旧余额
  中止并脱离旧账号请求以保障新账号立即刷新
  统一主站、图片编辑器和 AI Game Creator 钱包数据源
  补充账号切换、悬挂请求和焦点刷新回归测试
  同步更新项目基线与共享决策记录
k88936 added 12 commits 2026-08-05 19:25:36 +08:00
提取泥点余额格式化函数,移除统计卡中的嵌套三元表达式。
通过现有请求选项透传 AbortSignal,确保共享钱包切换账号时可以中止旧请求。

新增充值中心信号透传回归测试并纳入 Vitest。
将可见性与焦点事件合并到同一零延迟刷新任务,避免前台切换产生连续请求。

卸载时清理待执行定时器,并补充双事件回归测试。
共享泥点明细暂不可用时继续使用充值中心响应中的兼容总额与明细。

补充充值弹窗余额兜底回归测试。
使用控制器账号生命周期和账单请求 revision 校验响应,不再耦合钱包 Store owner 初始化。

确保当前账号的最新账单请求总能正确结束加载状态。
奖励码与邀请码兑换记录发起账号和账号生命周期 revision,忽略切换账号后的成功、失败与收尾回调。

账号切换时同步结束兑换提交态,并补充两类兑换回归测试。
为 AI Game Creator 钱包本地弹窗状态绑定账号 owner,并与共享钱包 owner 一起同步控制可见性。

账号切换时立即隐藏旧账单、充值与支付数据,并补充回归测试。
为 AI Game Creator 账单读取使用独立 lifecycle token,并在账号切换时失效旧请求。

补充充值弹窗变化期间账单仍可正常收尾的回归测试。
使用同时处理成功与失败的 Promise 回调清理活动请求,避免 finally 派生拒绝无人观察。
在应用外部钱包快照前统一 trim owner ID,保持与 owner 绑定入口相同的边界规则。

补充带前后空白的同账号快照回归测试。
记录请求取消、前台事件合并、账号异步隔离与兼容余额兜底规则。

明确 AI Game Creator 账单与充值使用独立 lifecycle。
修复主站外部生成任务泥点刷新时机
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Frontend tests (pull_request) Successful in 2m56s
Project CI / Native shell tests (pull_request) Failing after 5m48s
1f3d3f1aa1
复用主站任务轮询推动共享钱包余额收敛
覆盖运行中扣费与失败退款后的余额刷新
支持其他项目任务驱动账号级钱包更新
补充主站外部生成任务回归测试
同步更新项目基线与共享决策记录
k88936 changed title from WIP: 统一主站与AI游戏创作钱包状态 to WIP: 修复泥点消耗刷新不及时 2026-08-05 20:05:29 +08:00
k88936 marked the pull request as ready for review 2026-08-05 20:13:40 +08:00
kdletters requested changes 2026-08-05 20:58:15 +08:00
kdletters left a comment
Member

发现 4 个需要修复的问题:

  1. 旧充值中心快照可覆盖并取消更新的钱包刷新,仍会导致余额长期不收敛。
  2. 充值异步链路没有完整绑定账号生命周期,切换账号后旧请求仍可写入订单、UI 与认证副作用。
  3. 首次任务列表瞬时失败后,钱包轮询不会启动。
  4. 兼容充值响应缺少 mudPointBalance 时,空账单会伪显示 0 泥点。

另外请修复当前 4 个 Prettier 失败文件,并整理 581323b4、658ebef5 两个空提交正文。修复后请基于新 head 重新跑四组 CI 并请求复审。

发现 4 个需要修复的问题: 1. 旧充值中心快照可覆盖并取消更新的钱包刷新,仍会导致余额长期不收敛。 2. 充值异步链路没有完整绑定账号生命周期,切换账号后旧请求仍可写入订单、UI 与认证副作用。 3. 首次任务列表瞬时失败后,钱包轮询不会启动。 4. 兼容充值响应缺少 mudPointBalance 时,空账单会伪显示 0 泥点。 另外请修复当前 4 个 Prettier 失败文件,并整理 581323b4、658ebef5 两个空提交正文。修复后请基于新 head 重新跑四组 CI 并请求复审。
@@ -0,0 +72,4 @@
return;
}
invalidateActiveRefresh();
Member

这里把 settledRefreshVersion 直接推进到当前最新版本,同时上一步中止 active refresh。loadRechargeCenter() 的普通 GET 快照可能早于之后发生的生成扣费或失败退款;它晚返回时会覆盖余额并吞掉终态刷新。我已复现:应用旧快照 80 后,即使被中止的刷新随后返回 100,Store 最终仍停在 80。请给快照绑定请求发起时的版本和 owner,只结算不晚于它的 invalidation,或让普通读统一走 Store,不能取消更晚的刷新。

这里把 `settledRefreshVersion` 直接推进到当前最新版本,同时上一步中止 active refresh。`loadRechargeCenter()` 的普通 GET 快照可能早于之后发生的生成扣费或失败退款;它晚返回时会覆盖余额并吞掉终态刷新。我已复现:应用旧快照 80 后,即使被中止的刷新随后返回 100,Store 最终仍停在 80。请给快照绑定请求发起时的版本和 owner,只结算不晚于它的 invalidation,或让普通读统一走 Store,不能取消更晚的刷新。
k88936 marked this conversation as resolved
@@ -419,3 +434,3 @@
useEffect(() => {
if (!activeExternalTaskIds.length) {
if (!walletActiveExternalTaskKey) {
Member

walletActiveExternalTaskKey 初始为空时这里直接不启动轮询;首轮 Promise.all 任一列表请求失败只会清空任务,没有重试或已知 active ID。这样页面打开时的一次瞬时失败,就会令后续预扣和终态退款都没有钱包通知。请让 bootstrap 失败也有有界重试,或让轮询启动不依赖首次成功取得任务 ID。

`walletActiveExternalTaskKey` 初始为空时这里直接不启动轮询;首轮 `Promise.all` 任一列表请求失败只会清空任务,没有重试或已知 active ID。这样页面打开时的一次瞬时失败,就会令后续预扣和终态退款都没有钱包通知。请让 bootstrap 失败也有有界重试,或让轮询启动不依赖首次成功取得任务 ID。
k88936 marked this conversation as resolved
@@ -342,3 +373,1 @@
profileCenter.rechargeCenter?.mudPointBalance?.totalPoints ??
profileCenter.rechargeCenter?.walletBalance ??
null;
const balance = mudPointBalance?.totalPoints ?? null;
Member

这里移除了 rechargeCenter.walletBalance 的兼容兜底,但账单 modal 仍传入 fallbackBalance={balance ?? 0}。当响应只有 legacy walletBalance = 37、没有 mudPointBalance 时,充值弹窗显示 37,空账单却显示 0。请保留 owner 匹配的 legacy fallback,或显式展示不可用,不能伪造 0。

这里移除了 `rechargeCenter.walletBalance` 的兼容兜底,但账单 modal 仍传入 `fallbackBalance={balance ?? 0}`。当响应只有 legacy `walletBalance = 37`、没有 `mudPointBalance` 时,充值弹窗显示 37,空账单却显示 0。请保留 owner 匹配的 legacy fallback,或显式展示不可用,不能伪造 0。
k88936 marked this conversation as resolved
@@ -641,3 +736,3 @@
if (paymentChannel === WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_CHANNEL) {
pendingWechatRechargeOrderIdRef.current = response.order.orderId;
applyRechargeCenter(response.center);
if (!applyRechargeCenter(response.center, true)) {
Member

owner 检查发生在 pendingWechatRechargeOrderIdRef.current = response.order.orderId 之后,而且后续 catch/finally 也没有校验账号 revision。A 切换到 B 后,A 的延迟响应仍可覆盖或清空 B 的 pending order、二维码和提交状态;特殊错误路径还可能通过 clearStoredAccessToken() 清掉 B 的登录。请把一次充值从下单到确认的所有 ref、state 和认证副作用绑定同一个 owner + lifecycle revision,并在每次副作用前校验。

owner 检查发生在 `pendingWechatRechargeOrderIdRef.current = response.order.orderId` 之后,而且后续 `catch/finally` 也没有校验账号 revision。A 切换到 B 后,A 的延迟响应仍可覆盖或清空 B 的 pending order、二维码和提交状态;特殊错误路径还可能通过 `clearStoredAccessToken()` 清掉 B 的登录。请把一次充值从下单到确认的所有 ref、state 和认证副作用绑定同一个 owner + lifecycle revision,并在每次副作用前校验。
k88936 marked this conversation as resolved
kdletters requested changes 2026-08-06 14:13:38 +08:00
kdletters left a comment
Member

复审后,上一轮 4 个功能问题已有对应修复,但仍有两个当前 head 的阻断:

  1. 微信充值确认的延迟重试没有绑定账号生命周期。切换账号后旧订单仍会带新账号 token 发出确认请求,401 路径可能影响新账号登录。
  2. 任务列表 bootstrap 重试在 Promise.all 一侧失败时未取消同轮另一条请求,重试和卸载后会遗留悬挂网络请求。

请补齐 AbortSignal / 生命周期门禁及回归测试后重新请求复审。另请处理剩余 Prettier 失败文件与空提交正文。

复审后,上一轮 4 个功能问题已有对应修复,但仍有两个当前 head 的阻断: 1. 微信充值确认的延迟重试没有绑定账号生命周期。切换账号后旧订单仍会带新账号 token 发出确认请求,401 路径可能影响新账号登录。 2. 任务列表 bootstrap 重试在 Promise.all 一侧失败时未取消同轮另一条请求,重试和卸载后会遗留悬挂网络请求。 请补齐 AbortSignal / 生命周期门禁及回归测试后重新请求复审。另请处理剩余 Prettier 失败文件与空提交正文。
@@ -383,0 +407,4 @@
),
);
})
.catch(() => {
Member

Promise.all 任一分支先失败时会进入 retry,但没有 abort 同一轮 controller;另一个列表请求若一直 pending,下一轮会覆盖 controller 引用,卸载时只能 abort 最新请求。请在安排 retry 前中止当前 attempt,或保存并清理全部 attempt controller;补“一侧 reject、另一侧 pending、重试后卸载”的测试,确保不会留下悬挂请求。

Promise.all 任一分支先失败时会进入 retry,但没有 abort 同一轮 controller;另一个列表请求若一直 pending,下一轮会覆盖 controller 引用,卸载时只能 abort 最新请求。请在安排 retry 前中止当前 attempt,或保存并清理全部 attempt controller;补“一侧 reject、另一侧 pending、重试后卸载”的测试,确保不会留下悬挂请求。
k88936 marked this conversation as resolved
@@ -212,5 +212,5 @@
await waitWechatPayConfirmDelay(delayMs);
latestResponse = await confirmWechatPlatformProfileRechargeOrder(orderId);
if (isWechatRechargeOrderTerminalForConfirmation(latestResponse.order)) {
return latestResponse;
Member

这两个确认 helper 的每一次重试都在等待后直接调用 confirm API,没有 AbortSignal 或账号 revision 检查。A 的第一次确认返回 pending 后切换到 B,800ms 后这里仍会用当前全局 token 发 A 的第二次确认请求;apiClient 每次请求都即时读取 token,401 还可能 refresh/清掉 B 的登录。请让整个确认链持有 owner 生命周期的 AbortController,在每次 delay、confirm 和 watch 前检查/传递 signal,并在账号切换时中止;补 fake-timer 用例证明切换后不会产生第二个确认请求。

这两个确认 helper 的每一次重试都在等待后直接调用 confirm API,没有 AbortSignal 或账号 revision 检查。A 的第一次确认返回 pending 后切换到 B,800ms 后这里仍会用当前全局 token 发 A 的第二次确认请求;apiClient 每次请求都即时读取 token,401 还可能 refresh/清掉 B 的登录。请让整个确认链持有 owner 生命周期的 AbortController,在每次 delay、confirm 和 watch 前检查/传递 signal,并在账号切换时中止;补 fake-timer 用例证明切换后不会产生第二个确认请求。
k88936 marked this conversation as resolved
k88936 added 14 commits 2026-08-06 15:23:45 +08:00
合并资源卡依赖关系主线,保留钱包单一生命周期系列修改。
修正钱包生命周期分支的 lint 问题。
为钱包快照绑定请求发起时的 owner 生命周期与 invalidation 版本
拒绝过期普通 GET 快照覆盖余额或中止更新刷新
同步主站与 AI Game Creator 调用方及竞态回归测试
更新账户与充值基线约束
合并远端主线,保留钱包快照竞态修复。
为任务列表 bootstrap 增加一秒、两秒和四秒的有界退避重试
瞬时失败时保留已有任务并在恢复 active ID 后启动钱包轮询
覆盖重试恢复与重试耗尽边界
同步更新账户钱包轮询基线
在钱包 owner 匹配时保留充值中心 legacy walletBalance
共享泥点明细仍优先于兼容展示余额
覆盖仅返回旧版余额时空账单显示 37 泥点
同步更新账户余额兼容边界
为下单到确认和 watch 全链路绑定 owner 与账号生命周期版本
pending、confirming、二维码和提交状态仅由所属充值链更新
在 catch、finally、成功回调及清 token 前拒绝旧账号副作用
覆盖旧下单、旧确认和特殊错误不影响新账号
同步更新充值生命周期基线
绑定 snapshot 至 owner lifecycle。
合并游戏创作条件任务图主线,保留账户充值链修复。
合并画布素材导出主线,保留钱包与充值修复。
在任一 bootstrap 分支失败时中止当前轮全部请求。

补充失败分支悬挂、重试后卸载的 AbortSignal 回归测试。
为充值订单绑定 owner、账号 revision 与同一 AbortController。

在延迟确认、确认请求和 SSE watch 前后校验生命周期并透传 signal。

账号切换和卸载先中止旧链,再清理订单状态与支付回调。

补充 fake timer 回归并记录并发异步生命周期约束。
按 Prettier 统一钱包、平台入口和画布相关分支文件格式。

补齐共享决策文档缺失的 Markdown 段落间距。
收紧充值确认延迟信号约束
Project CI / Repository checks (pull_request) Failing after 8s
Project CI / Backend tests (pull_request) Failing after 9s
Project CI / Frontend tests (pull_request) Successful in 3m12s
Project CI / Native shell tests (pull_request) Has been cancelled
532df4d231
要求所有微信充值确认延迟显式传入 AbortSignal。

移除可选 signal 分支,防止后续调用绕过订单生命周期取消。
k88936 force-pushed fix/one-mud-point-store from 3cf10af96f to 532df4d231 2026-08-06 15:23:45 +08:00 Compare
Author
Member

处理空提交正文。

处理空提交正文。
k88936 added 1 commit 2026-08-06 16:13:00 +08:00
合并主分支
Project CI / Repository checks (pull_request) Successful in 1m46s
Project CI / Frontend tests (pull_request) Successful in 4m19s
Project CI / Native shell tests (pull_request) Successful in 12m22s
Project CI / Backend tests (pull_request) Successful in 3m46s
0397866d84
追加文档, 无冲突
k88936 force-pushed fix/one-mud-point-store from 82826efa20 to 0397866d84 2026-08-06 16:13:00 +08:00 Compare
kdletters reviewed 2026-08-06 16:53:50 +08:00
kdletters left a comment
Member

复审确认 review 132 的两条功能阻断已经修复,支付确认链与任务 bootstrap 请求都具备对应取消和回归测试。

当前仍需处理:

  1. decision-log.md 的既有 Seedance 数量约束被格式化为 0~~9 / 0~~3,改变了 Markdown 语义。
  2. Changed-file Prettier 仍在 ImageCanvasStageView.tsxusePlatformProfileCenterController.ts 失败。

定向 116 项测试和四组 CI 当前全绿,提交正文也已补齐;修复上述内容后请重新请求复审。

复审确认 review 132 的两条功能阻断已经修复,支付确认链与任务 bootstrap 请求都具备对应取消和回归测试。 当前仍需处理: 1. `decision-log.md` 的既有 Seedance 数量约束被格式化为 `0~~9 / 0~~3`,改变了 Markdown 语义。 2. Changed-file Prettier 仍在 `ImageCanvasStageView.tsx`、`usePlatformProfileCenterController.ts` 失败。 定向 116 项测试和四组 CI 当前全绿,提交正文也已补齐;修复上述内容后请重新请求复审。
@@ -1229,3 +1231,3 @@
- 背景:`/editor/canvas` 生成视频需要严格对齐火山 Seedance 2.0 多模态参考输入;参考视频若继续走 Base64 / `data:video` 会超过请求体并被上游拒绝,参考音频单独输入和非 Seedance 模型携带参考字段也会违反文档契约。
- 决策:仅 `seedance2.0-fast` / `seedance2.0` 可提交参考图片、参考视频、参考音频;图片 0~9、视频 0~3、音频 0~3,音频必须搭配图片或视频。参考视频只能提交公网 URL、`asset://` 或画板资源 `objectKey`,禁止 `data:video/*`;视频 / 音频上传先走 OSS 直传和 asset*object confirm,前端保存 signed URL 预览但提交优先 `objectKey`,后端统一重新签名给 Ark。Ark body 按 `image_url` / `video_url` / `audio_url` + `reference*\*`role 构造,并显式发送`generate_audio:false`
- 决策:仅 `seedance2.0-fast` / `seedance2.0` 可提交参考图片、参考视频、参考音频;图片 0~~9、视频 0~~3、音频 0~3,音频必须搭配图片或视频。参考视频只能提交公网 URL、`asset://` 或画板资源 `objectKey`,禁止 `data:video/*`;视频 / 音频上传先走 OSS 直传和 asset*object confirm,前端保存 signed URL 预览但提交优先 `objectKey`,后端统一重新签名给 Ark。Ark body 按 `image_url` / `video_url` / `audio_url` + `reference*\*`role 构造,并显式发送`generate_audio:false`
Member

这里原本的权威约束是“图片 09、视频 03、音频 0~3”,当前被格式化成 0~~9 / 0~~3,Markdown 会把中间内容解释成删除线,导致共享决策与 RAG 读取到错误数量范围。这属于钱包变更范围外的语义损坏。请恢复原约束,建议把三个范围分别写成行内代码(例如 0~90~3)以避免 Prettier 再次改写。

这里原本的权威约束是“图片 0~9、视频 0~3、音频 0~3”,当前被格式化成 `0~~9 / 0~~3`,Markdown 会把中间内容解释成删除线,导致共享决策与 RAG 读取到错误数量范围。这属于钱包变更范围外的语义损坏。请恢复原约束,建议把三个范围分别写成行内代码(例如 `0~9`、`0~3`)以避免 Prettier 再次改写。
k88936 marked this conversation as resolved
k88936 added 2 commits 2026-08-06 17:07:38 +08:00
将图片、视频和音频参考数量范围恢复为原权威值。

使用行内代码保护波浪号范围,避免 Prettier 改写为 Markdown 删除线。
合并主分支
Project CI / Repository checks (pull_request) Successful in 1m2s
Project CI / Frontend tests (pull_request) Successful in 3m39s
Project CI / Backend tests (pull_request) Successful in 4m4s
Project CI / Native shell tests (pull_request) Successful in 14m1s
6d1c871fc4
解决简单冲突
k88936 added 1 commit 2026-08-06 17:25:36 +08:00
修复前端格式
Project CI / Repository checks (pull_request) Successful in 54s
Project CI / Frontend tests (pull_request) Successful in 4m1s
Project CI / Backend tests (pull_request) Successful in 4m35s
Project CI / Native shell tests (pull_request) Successful in 17m9s
d063580c0a
使用 package-lock 锁定的 Prettier 3.3.3 格式化图片画布与充值 controller。

修正布尔表达式缩进、复合否定条件和充值结果联合类型换行。
kdletters requested changes 2026-08-06 20:46:02 +08:00
kdletters left a comment
Member

复审确认旧 review 中的钱包并发、账号生命周期和任务轮询问题均已修复。当前 head 仍有 1 个 P2 阻断:兼容响应只有 walletBalance、没有 mudPointBalance 时,个人中心统计卡与图片编辑器顶部会丢失可用的 legacy 总额。

请把 owner 匹配的 legacy 总额传给这两个总额展示入口;明细仍应保持为空,避免伪造分桶数据,并补齐两处回归测试。修复后请基于新 head 请求复审。

复审确认旧 review 中的钱包并发、账号生命周期和任务轮询问题均已修复。当前 head 仍有 1 个 P2 阻断:兼容响应只有 `walletBalance`、没有 `mudPointBalance` 时,个人中心统计卡与图片编辑器顶部会丢失可用的 legacy 总额。 请把 owner 匹配的 legacy 总额传给这两个总额展示入口;明细仍应保持为空,避免伪造分桶数据,并补齐两处回归测试。修复后请基于新 head 请求复审。
@@ -544,3 +563,1 @@
? formatDashboardCount(dashboard.walletBalance)
: '暂不可用'
}
value={formatWalletBalance(
Member

[P2] 这里把个人中心统计卡只绑定到 mudPointBalance;图片编辑器也在 ImageCanvasEditorView.tsx 中只用 mudPointBalance?.totalPoints。复现兼容响应 { walletBalance: 37 }(无 mudPointBalance)时,PlatformEntryActiveFlowShell 已经算出 owner 匹配的 legacyWalletBalance,充值弹窗和空账单能显示 37,但传到这里仍是 null,因此个人中心显示“暂不可用”,图片编辑器顶部也不显示余额。请把同一 legacy 总额传给这两个只展示总额的入口,同时让明细继续保持 null,不要伪造分桶数据;补两处 legacy 回归测试。

[P2] 这里把个人中心统计卡只绑定到 `mudPointBalance`;图片编辑器也在 `ImageCanvasEditorView.tsx` 中只用 `mudPointBalance?.totalPoints`。复现兼容响应 `{ walletBalance: 37 }`(无 `mudPointBalance`)时,`PlatformEntryActiveFlowShell` 已经算出 owner 匹配的 `legacyWalletBalance`,充值弹窗和空账单能显示 37,但传到这里仍是 `null`,因此个人中心显示“暂不可用”,图片编辑器顶部也不显示余额。请把同一 legacy 总额传给这两个只展示总额的入口,同时让明细继续保持 `null`,不要伪造分桶数据;补两处 legacy 回归测试。
k88936 marked this conversation as resolved
k88936 force-pushed fix/one-mud-point-store from 226c3f9c32 to 8405aa3af1 2026-08-07 13:33:34 +08:00 Compare
k88936 requested review from kdletters 2026-08-07 14:42:04 +08:00
Member

当前仍有一个账号隔离相关的阻塞问题:充值下单、邀请码兑换和奖励码兑换这三条写请求没有绑定账号生命周期的 AbortSignal。现有 owner/revision 门禁只能阻止旧请求回调覆盖 UI,不能取消已经发出的服务端副作用;同时 PLATFORM_PROFILE_WRITE_RETRY 会自动重试 POST,fetchWithApiAuth 每轮重试又会重新读取当前 Token。这样 A 账号发起请求后切换到 B,如果请求进入 401、503 或网络重试,旧操作可能改用 B 的凭证创建订单或兑换代码。

建议给这三条写请求绑定账号生命周期 AbortController,在切号和卸载时中止请求,并补充测试,证明 signal 已中止后不会继续 retry。

另外,旧 GET 覆盖刷新、任务 bootstrap 失败后仍轮询、legacy 余额伪造这几项已修复。当前格式门禁仍有 5 个文件未通过 Prettier 3.3.3;提交 7ecb883057 的标题为英文且正文为空,也不符合仓库提交规范。

当前仍有一个账号隔离相关的阻塞问题:充值下单、邀请码兑换和奖励码兑换这三条写请求没有绑定账号生命周期的 AbortSignal。现有 owner/revision 门禁只能阻止旧请求回调覆盖 UI,不能取消已经发出的服务端副作用;同时 PLATFORM_PROFILE_WRITE_RETRY 会自动重试 POST,fetchWithApiAuth 每轮重试又会重新读取当前 Token。这样 A 账号发起请求后切换到 B,如果请求进入 401、503 或网络重试,旧操作可能改用 B 的凭证创建订单或兑换代码。 建议给这三条写请求绑定账号生命周期 AbortController,在切号和卸载时中止请求,并补充测试,证明 signal 已中止后不会继续 retry。 另外,旧 GET 覆盖刷新、任务 bootstrap 失败后仍轮询、legacy 余额伪造这几项已修复。当前格式门禁仍有 5 个文件未通过 Prettier 3.3.3;提交 7ecb883057 的标题为英文且正文为空,也不符合仓库提交规范。
k88936 removed review request for kdletters 2026-08-07 15:54:05 +08:00
k88936 requested review from kdletters 2026-08-07 15:56:06 +08:00
kdletters requested changes 2026-08-07 18:16:26 +08:00
kdletters left a comment
Member

当前 head 仍有 1 个 P1 账号隔离阻断:业务 AbortSignal 只中止对共享 refresh Promise 的等待,不能取消底层 /api/auth/refresh,而 refreshAccessToken 完成后仍会无条件发布 token。A 的写请求收到 401 并开始 refresh 后切到 B,A 的调用链虽然不会重放 POST,但旧 refresh 晚到仍会覆盖 B 的 token;我用当前实现确定性复现得到 fetchCalls=2storedToken=late-account-a-token。后续 B 页面请求因此可能携带 A 的凭证。

请给 token 发布绑定账号/auth generation 或等价 CAS,确保旧 refresh 不能覆盖新账号状态,也不能让 B 加入 A 的共享 refresh Promise;补齐相应回归测试。旧 GET 快照、任务 bootstrap 轮询、legacy 余额及业务 POST 重放问题已确认修复。

另外,提交 7ecb883057 仍是英文标题且正文为空,请按仓库提交规范整理。

当前 head 仍有 1 个 P1 账号隔离阻断:业务 AbortSignal 只中止对共享 refresh Promise 的等待,不能取消底层 `/api/auth/refresh`,而 `refreshAccessToken` 完成后仍会无条件发布 token。A 的写请求收到 401 并开始 refresh 后切到 B,A 的调用链虽然不会重放 POST,但旧 refresh 晚到仍会覆盖 B 的 token;我用当前实现确定性复现得到 `fetchCalls=2`、`storedToken=late-account-a-token`。后续 B 页面请求因此可能携带 A 的凭证。 请给 token 发布绑定账号/auth generation 或等价 CAS,确保旧 refresh 不能覆盖新账号状态,也不能让 B 加入 A 的共享 refresh Promise;补齐相应回归测试。旧 GET 快照、任务 bootstrap 轮询、legacy 余额及业务 POST 重放问题已确认修复。 另外,提交 `7ecb883057` 仍是英文标题且正文为空,请按仓库提交规范整理。
@@ -665,0 +740,4 @@
await refreshResponse.promise;
await Promise.resolve();
expect(fetchMock).toHaveBeenCalledTimes(2);
Member

这里仅断言中止后没有第三次业务 POST,却没有验证晚到 refresh 不会改写新账号 token。当前时序中先写入 account-b-token、再 abort、最后 resolve late-refresh-token,底层共享 refreshAccessToken 仍会在 apiClient.ts 无条件调用 setStoredAccessToken,实测最终 token 变成旧账号返回值。请先为 refresh/token 发布增加 auth generation 或 CAS,再在此等待 refresh 完整收束并断言 token 仍为 account-b-token;同时覆盖 B 不复用 A 的共享 refresh Promise。

这里仅断言中止后没有第三次业务 POST,却没有验证晚到 refresh 不会改写新账号 token。当前时序中先写入 `account-b-token`、再 abort、最后 resolve `late-refresh-token`,底层共享 `refreshAccessToken` 仍会在 `apiClient.ts` 无条件调用 `setStoredAccessToken`,实测最终 token 变成旧账号返回值。请先为 refresh/token 发布增加 auth generation 或 CAS,再在此等待 refresh 完整收束并断言 token 仍为 `account-b-token`;同时覆盖 B 不复用 A 的共享 refresh Promise。
k88936 marked this conversation as resolved
k88936 added 13 commits 2026-08-07 19:15:14 +08:00
同步主分支的背景音乐生成路径优化及相关工程变更
保留本分支的钱包、账号状态与个人中心修复
活动精选图片换签断言使用局部有界等待

等待 manifest 失效监听注册后再验证实时重投影

补充异步测试超时与监听时序的项目记忆
向个人中心和图片画板传递 owner 匹配的 legacy 总额

保持钱包分桶与账单明细为空避免伪造数据

补充个人中心和图片画板回归测试及契约文档
隔离账号切换后的充值响应并中止失效支付监听

防止乱序钱包快照回滚并保留旧版总额兜底

清理任务重试耗尽后的陈旧状态并补充回归测试

稳定测试夹具、用户错误提示与首帧加载状态

同步单一钱包 Store 的长期决策记录
将主站唯一钱包 lifecycle 上移到 AuthGate 根认证边界

在账号切换、StrictMode 重放和根卸载时统一清空钱包 Store

移除平台子壳的重复 owner 声明并补充测试边界

新增 mount、focus、unmount 与 StrictMode 回归测试

同步钱包 lifecycle 长期决策与 Vitest 收集范围
同步主分支的 Chat 生成预算字段兼容逻辑

更新大模型平台实现、测试脚本与背景音乐提示词辅助

补充相关架构文档、决策记录与排障经验
更新旧版钱包总额场景的用户可见错误断言

补充内部充值响应错误不外显的回归断言
修复 legacy 余额回退与编辑器加载态
保留任务列表局部成功结果并持续钱包轮询
隔离邀请码异步状态并防止重复下单
补齐支付响应快照时序与定向回归测试
同步钱包与支付生命周期文档
说明小程序支付期间切号风险较低
记录未来跨 WebView 恢复所需的账号订单关联校验
移除个人中心控制器中的 TODO 开发标记
为充值下单、邀请码兑换和奖励码兑换绑定账号生命周期中止信号
补充切号、卸载、401 与 503 重试回归测试
按 Prettier 3.3.3 修复分支变更文件格式并更新工程约束
按认证代际与起始令牌隔离共享 refresh 并使用 CAS 发布新令牌
防止旧 refresh 失败清理新账号令牌
补充晚到回包与新账号独立 refresh 回归测试
同步项目基线与共享项目记忆
合并主分支
Project CI / Repository checks (pull_request) Successful in 1m6s
Project CI / Frontend tests (pull_request) Successful in 3m2s
Project CI / Backend tests (pull_request) Successful in 3m40s
Project CI / Native shell tests (pull_request) Failing after 45s
f2df562099
处理合并冲突
k88936 force-pushed fix/one-mud-point-store from 654edcb527 to f2df562099 2026-08-07 19:15:14 +08:00 Compare
k88936 added 1 commit 2026-08-07 19:46:41 +08:00
合并主分支
Project CI / Frontend tests (pull_request) Successful in 3m29s
Project CI / Repository checks (pull_request) Successful in 43s
Project CI / Backend tests (pull_request) Successful in 4m13s
Project CI / Native shell tests (pull_request) Successful in 15m52s
3fc0741d99
处理合并冲突
k88936 requested review from kdletters 2026-08-07 20:10:23 +08:00
k88936 added 1 commit 2026-08-07 21:16:24 +08:00
合并主分支
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
a333742f88
处理合并冲突
kdletters requested changes 2026-08-07 21:20:33 +08:00
kdletters left a comment
Member

当前 head 仍有 1 个合并阻断:src/services/apiClient.ts 未通过仓库锁定的 Prettier 3.3.3。仅有两处 Boolean(...) 续行缩进与格式化输出不一致。请按仓库 Prettier 格式化该文件后重新请求复审。

当前 head 仍有 1 个合并阻断:`src/services/apiClient.ts` 未通过仓库锁定的 Prettier 3.3.3。仅有两处 `Boolean(...)` 续行缩进与格式化输出不一致。请按仓库 Prettier 格式化该文件后重新请求复审。
@@ -785,3 +871,3 @@
let hasAuthHeader = Boolean(
requestHeaders.Authorization?.trim() ||
requestHeaders.authorization?.trim(),
requestHeaders.authorization?.trim(),
Member

这里与下方同类 Boolean(...) 表达式的续行缩进不符合仓库锁定的 Prettier 3.3.3;同文件还有一处同样问题。prettier --check src/services/apiClient.ts 会失败。请运行该文件的 Prettier 格式化并提交结果,避免 CI/本地格式门禁不一致。

这里与下方同类 `Boolean(...)` 表达式的续行缩进不符合仓库锁定的 Prettier 3.3.3;同文件还有一处同样问题。`prettier --check src/services/apiClient.ts` 会失败。请运行该文件的 Prettier 格式化并提交结果,避免 CI/本地格式门禁不一致。
k88936 marked this conversation as resolved
k88936 added 1 commit 2026-08-07 21:35:03 +08:00
修正认证客户端格式
Project CI / Repository checks (pull_request) Successful in 1m4s
Project CI / Frontend tests (pull_request) Successful in 3m6s
Project CI / Backend tests (pull_request) Successful in 3m29s
Project CI / Native shell tests (pull_request) Successful in 14m6s
341b333786
按 Prettier 3.3.3 格式化鉴权头布尔判断续行
k88936 requested review from kdletters 2026-08-07 21:48:01 +08:00
kdletters added 1 commit 2026-08-08 10:24:33 +08:00
Merge branch 'master' into fix/one-mud-point-store
Project CI / Repository checks (pull_request) Successful in 1m20s
Project CI / Frontend tests (pull_request) Successful in 2m58s
Project CI / Backend tests (pull_request) Successful in 4m14s
Project CI / Native shell tests (pull_request) Has been cancelled
554883e258
kdletters merged commit fc0dcb0782 into master 2026-08-08 10:25:02 +08:00
kdletters deleted branch fix/one-mud-point-store 2026-08-08 10:25:02 +08:00
Sign in to join this conversation.