Skip to content

feat(payments,mcp): 押金运营安全网——unforfeit 补救通道 + 批量没收告警(#545) - #661

Merged
sundevilyang merged 1 commit into
developfrom
feat/545-deposit-safety-net
Sep 16, 2026
Merged

sundevilyang merged 1 commit into
developfrom
feat/545-deposit-safety-net

Conversation

@sundevilyang

Copy link
Copy Markdown
Contributor

#545 押金运营安全网:unforfeit 补救通道 + 批量没收告警

A. unforfeit(错没收的人工救济)

落点 内容
域 action payments/order.ex update :unforfeit:CAS forfeited → refundingclaim 单点,与 retry_refund 同形)+ after_action 入队 PaymentRefundWorker(与 refund 同链,查单幂等不重复退)+ LogAdminAction :order_unforfeitfrom_status/reason/amount_cents 进 metadata)
权限 域 policy 仅 PlatformAdmin(刻意不并入 refund 的 OwnerOrAdmin 组:没收是平台裁决,推翻须同权)
MCP mcp/tools/unforfeit_order.ex(新) meta: platform_admin(Wrapper 族)+ 两段确认(摘要带金额/渠道/理由);reason 1–500 字工具层前置校验;非 forfeited 快速失败不建 pending

原 issue 里低优先级的「迟到核销补偿」被本通道覆盖:错没收 → 人工核实 → unforfeit → 原路全退(无需补录 attendance)。

B. 批量没收告警(双口径)

口径 实现 消费面
事件口径 本拍单场没收 ≥ 5 笔 → Logger.error("BATCH ALERT …")(event uuid 文本化,可直接拷贝查询) ops 日志通道
状态口径 Finding 规16 :deposit_forfeit_batch_alert(该场 forfeited 计数 ≥5,HAVING 下推)走 apply_rule/3 刷新语义unforfeit 降到阈值下自动删除(自愈) /admin/reconciliation 页天然可见,零前端工作
不阻塞 sync_batch_alert_findings 自带 rescue:Finding 段落 raise 只落 error,不把已提交的结算拍拖进 Oban 重试

阈值 @batch_alert_threshold = 5 硬编码(101 场规模,Finding moduledoc 规16 同步口径)。

验证

  • mix precommit2389/2389 passed(终态);
  • 变异验证:删掉 alert_batch_forfeits + sync_batch_alert_findings 两处调用 → Finding 用例红(22/23)→ 恢复 23/23 绿;
  • 行为矩阵:5 笔没收 → Finding(detail 计数/金额/阈值)+ 双口径 error 日志;4 笔 → 零噪音;5 笔告警 → unforfeit 2 笔 → 下一拍 Finding 自动删除(自愈闭环钉住);unforfeit 的权限/状态/审计均有断言(Owner → Forbidden;paid 单 → order_already_processed);MCP 非 platform admin(含工作台 Owner)→ forbidden 不建 pending;
  • 契约守卫按设计拦截:全量首跑 4 失败 = 工具面计数(82→83)+ 确认流名单 + 豁免名单(38→39)——守卫有效,名单同步演进后全绿。

check 自检

  • check 期间修掉:告警日志里 inspect(event_id) 输出 binary 字节串不可读 → 改 uuid 文本化(兼容 worker 内两条 SQL 的不同返回形态,注释已说明);
  • 已验证SDL 零扰动unforfeit 刻意不注册 GraphQL mutation,MCP-only 入口 → schema.graphql 无变更);资金回流安全链完整(双层 PlatformAdmin + CAS + 两段确认 + 必填 reason + 审计);
  • advisory 记录:Finding 全局表断言按 target_id 收窄(既有沙箱纪律,新测试已遵守)。

非目标

不给 web 加订单/退款页面(运营是 agent-first,避免第二套入口);不改 refund/retry_refund 的既有权限组;不引入告警通道(Findings + Logger 已足够,且不阻塞结算主链)。

@sundevilyang
sundevilyang merged commit 0212426 into develop Sep 16, 2026
7 checks passed
@sundevilyang
sundevilyang deleted the feat/545-deposit-safety-net branch September 16, 2026 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant