release: FL 2.0 候选(C01 记账边界+P2-2 认领协议+D10 变量契约+D11 资格终审+D09 激活代次+T01/T03/T04/T05)
按《FL最终代码审计与上线阻断清单》194 项已审计工作树形成候选,基座 = origin/main 11e0778。
- 源码/测试/资源:沿用已审计工作树内容(96 项相对远端为新增或更新),含未跟踪实现
CallbackFactStore、CallbackSourcePolicy、VariableContract、FormalApplyCommandService、
FlowActorContextGate 等;C01 续验夹具修正一并入内。
- CI:保留远端 11e0778 的门禁强化(CI_SOURCE_SHA 核对、容器回收验证、空 schema 反向门禁、
main ref 才推镜像);ci/flow-test-schema.sql 按当前实体重新生成(14→20 表,补 6 新表与
6 新列,回调日志复合唯一键 uk_flw_log_event_reg),workflow 表数断言同步 14→20。
- 依据:docs/tasks/evidence/FL-final-audit-20261027(194 项哈希/版本核对)。
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package com.yunhai.flowcenter.callback;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yunhai.flowcenter.entity.FlwCallbackReg;
|
||||
import com.yunhai.flowcenter.entity.FlwInstance;
|
||||
import com.yunhai.flowcenter.repository.FlwInstanceRepository;
|
||||
import com.yunhai.flowcenter.service.FlowSourcePrincipalResolver;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/** Same SELF predicate for live fanout, fact recovery, retries and manual re-delivery. */
|
||||
@Component @RequiredArgsConstructor
|
||||
public class CallbackSourcePolicy {
|
||||
private final FlowSourcePrincipalResolver resolver;
|
||||
private final FlwInstanceRepository instances;
|
||||
private final ObjectMapper mapper;
|
||||
public boolean matches(FlwCallbackReg reg, FlwInstance instance) {
|
||||
if (instance.getSourcePrincipalId() == null) {
|
||||
return true; // Legacy callback migration is explicit; formal facts always use UUID SELF.
|
||||
}
|
||||
if (!instance.getSourcePrincipalId().equals(reg.getSourcePrincipalId())) return false;
|
||||
// Recheck the credential mapping: a reused appKey cannot receive its predecessor's facts.
|
||||
return instance.getSourcePrincipalId().equals(resolver.resolve(reg.getAppKey()).id);
|
||||
}
|
||||
public boolean permits(FlwCallbackReg reg, com.yunhai.flowcenter.entity.FlwCallbackLog delivery) {
|
||||
if (!permits(reg, delivery.getInstanceId(), delivery.getPayloadJson())) return false;
|
||||
FlwInstance instance = instances.findById(delivery.getInstanceId()).orElseThrow(IllegalStateException::new);
|
||||
if (instance.getSourcePrincipalId() == null) return true;
|
||||
try {
|
||||
JsonNode body = mapper.readTree(delivery.getPayloadJson());
|
||||
return java.util.Objects.equals(delivery.getEventId(), body.path("eventId").asText())
|
||||
&& java.util.Objects.equals(delivery.getEvent(), body.path("event").asText())
|
||||
&& java.util.Objects.equals(delivery.getBizType(), body.path("bizType").asText())
|
||||
&& java.util.Objects.equals(delivery.getBizId(), body.path("bizId").asText());
|
||||
} catch (Exception e) { return false; }
|
||||
}
|
||||
public boolean permits(FlwCallbackReg reg, Long instanceId, String payload) {
|
||||
FlwInstance instance = instances.findById(instanceId).orElse(null);
|
||||
if (instance == null || !matches(reg, instance)) return false;
|
||||
if (instance.getSourcePrincipalId() == null) return true;
|
||||
try {
|
||||
JsonNode body = mapper.readTree(payload);
|
||||
JsonNode data = body.path("data");
|
||||
return instance.getSourcePrincipalId().equals(body.path("sourcePrincipalId").asText())
|
||||
&& instance.getApplyRound().equals(body.path("applyRound").asInt())
|
||||
&& instance.getSourcePrincipalId().equals(data.path("sourcePrincipalId").asText())
|
||||
&& instance.getApplyRequestToken().equals(data.path("requestId").asText())
|
||||
&& instance.getApplyPayloadHash().equals(data.path("canonicalHash").asText())
|
||||
&& instance.getDefVersion().equals(data.path("defVersion").asInt())
|
||||
&& instance.getApplyRound().equals(data.path("applyRound").asInt())
|
||||
&& instance.getId().equals(body.path("instanceId").asLong())
|
||||
&& instance.getSchId().equals(body.path("schId").asLong())
|
||||
&& instance.getBizType().equals(body.path("bizType").asText())
|
||||
&& instance.getBizId().equals(body.path("bizId").asText());
|
||||
} catch (Exception e) { return false; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user