fix(msg): 消息 jump_app 换源 apply 调用方 app_code 快照,替代 bizType 冒充
build / build-push (push) Successful in 49s

P1/P2 联合修复(消息归属 + jump_app 值域污染):
- FlwInstance 新增 apply_app_key/apply_app_code 双列快照(自动 DDL)
- apply 从验签上下文(yh.app.auth)取调用方身份,by-key 一次换得 app_code
  (域间边界只在 apply 转换一次;查无/不可达降级 null,不阻断 apply)
- UserMsgNotifier 两处 jumpApp 改源 applyAppCode——bizType 是消息分类
  不是路由键;降级空时接收方按发送方回落(现状行为)
- FlowDefAdminService.save appKey 必填化(2026-10-12 拍板):新建必须
  显式传;升版本/直改可继承源行,源行为空必须补填(存量 19 条 NULL 随编辑收敛)
- 单测:SaveTest 新增必填拦截 3 用例、BizUrlTest 换源断言+降级用例(19 绿)
- E2E(8085+UserBase):100617->apply_app_code=notice 正向落库、
  100018(app_code NULL)->降级成功、错签名 401,三断言全过
This commit is contained in:
chenxing
2026-10-12 10:44:07 +08:00
parent d687ba7d56
commit b4856a480d
10 changed files with 160 additions and 30 deletions
@@ -73,11 +73,13 @@ public class UserMsgNotifier {
String content = "「" + safe(instance.getBizTitle()) + "」等待您审批"
+ (task.getNodeName() == null ? "" : "(" + task.getNodeName() + ")");
// 跳转路径:办件自带 bizUrl(业务方详情页,改造后为裸相对路径)优先——应用内审批免跳
// 流程中心,页面归属=业务方(jumpApp=instance.bizType,接收方按它查基址拼绝对地址);
// 未传 bizUrl 回落流程中心办理页 /task/{taskId},页面属自己(jumpApp 留空按 bizType 回落)
// 流程中心,页面归属=apply 调用方(jumpApp=instance.applyAppCode,apply 时由验签身份
// 按_by-key 换得的 app_code,接收方按它查基址拼绝对地址);applyAppCode 空(老数据/
// UserBase 不可达)或未传 bizUrl 回落流程中心页(/task/{taskId}、/instance/{id}),
// 页面属自己(jumpApp 留空按发送方回落)。bizType 是消息分类,不是路由键,不再冒充。
boolean useBizUrl = instance.getBizUrl() != null && !instance.getBizUrl().trim().isEmpty();
String jumpPath = useBizUrl ? instance.getBizUrl() : "/task/" + task.getId();
String jumpApp = useBizUrl ? instance.getBizType() : null;
String jumpApp = useBizUrl ? instance.getApplyAppCode() : null;
userMsgClient.sendUserMsg(instance.getSchId().intValue(),
Collections.singletonList(task.getAssigneeId()), 2,
"flow.task", String.valueOf(instance.getId()), title, content,
@@ -143,10 +145,11 @@ public class UserMsgNotifier {
String content = "「" + bizTitle + "」抄送给您"
+ (nodeName == null || String.valueOf(nodeName).isEmpty()
? "" : "(" + nodeName + ")");
// 跳转与任务到达同策略:bizUrl(业务方详情页,页面归属=业务方)优先,空回落办件详情(属自己)
// 跳转与任务到达同策略:bizUrl(业务方详情页,页面归属=apply 调用方 applyAppCode)优先,
// 空回落办件详情(属自己)
boolean useBizUrl = instance.getBizUrl() != null && !instance.getBizUrl().trim().isEmpty();
String jumpPath = useBizUrl ? instance.getBizUrl() : "/instance/" + instance.getId();
String jumpApp = useBizUrl ? instance.getBizType() : null;
String jumpApp = useBizUrl ? instance.getApplyAppCode() : null;
userMsgClient.sendUserMsg(instance.getSchId().intValue(),
Collections.singletonList((Integer) ccUserId), 1,
"flow.cc", String.valueOf(instance.getId()),