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:
chenxing
2026-10-27 12:05:08 +08:00
parent 11e077867b
commit 500a9a2fcb
99 changed files with 7973 additions and 633 deletions
@@ -109,6 +109,46 @@ public class FlowAdminController {
return appAdminService.stats(adminGuard.requireAdmin(user, null));
}
// ==================== 应用使用授权(T01) ====================
/**
* 使用授权管理面(字段注入:构造被既有单测逐位钉住,同 formCenterCatalogClient 先例)。
* 授权对象是稳定应用主体(UserBase appId),非 appKey 凭据;撤权只拦新发起。
*/
@org.springframework.beans.factory.annotation.Autowired
private com.yunhai.flowcenter.service.FlowUsageGrantAdminService usageGrantAdminService;
/** 某流程线的使用授权清单(含已撤销行,审计可见) */
@GetMapping("/usage-grant/list")
public List<com.yunhai.flowcenter.entity.FlwUsageGrant> usageGrantList(
BoaUser user, @RequestParam("flowGuid") String flowGuid) {
return usageGrantAdminService.listByFlow(adminGuard.requireAdmin(user, null), flowGuid);
}
/** 授予/重申使用授权(appKey 当场解析为 UserBase 稳定主体落库;enforce 开启时校学校开通) */
@PostMapping("/usage-grant/grant")
public com.yunhai.flowcenter.entity.FlwUsageGrant usageGrantGrant(
BoaUser user, @RequestBody Map<String, Object> body) {
Long schId = adminGuard.requireAdmin(user, null);
return usageGrantAdminService.grant(schId,
body.get("flowGuid") == null ? null : String.valueOf(body.get("flowGuid")),
body.get("appKey") == null ? null : String.valueOf(body.get("appKey")),
body.get("remark") == null ? null : String.valueOf(body.get("remark")),
user.getName());
}
/** 撤销使用授权(enabled=0 行保留;只拦新发起,在途与已受理命令不受影响) */
@PostMapping("/usage-grant/revoke")
public com.yunhai.flowcenter.entity.FlwUsageGrant usageGrantRevoke(
BoaUser user, @RequestBody Map<String, Object> body) {
Long schId = adminGuard.requireAdmin(user, null);
return usageGrantAdminService.revoke(schId,
body.get("flowGuid") == null ? null : String.valueOf(body.get("flowGuid")),
body.get("appId") == null ? null : Integer.valueOf(String.valueOf(body.get("appId"))),
body.get("remark") == null ? null : String.valueOf(body.get("remark")),
user.getName());
}
@GetMapping("/def/get")
public FlwDef defGet(BoaUser user, @RequestParam("id") Long id) {
return defAdminService.get(adminGuard.requireAdmin(user, null), id);
@@ -191,6 +231,24 @@ public class FlowAdminController {
return defAdminService.versions(adminGuard.requireAdmin(user, null), flowGuid);
}
// ==================== 线级停发/恢复(T03) ====================
/** 线级停发:整条 flowGuid 停止新发起/预览;在途实例按原版本跑完不受影响 */
@PostMapping("/def/offlineLine")
public int defOfflineLine(BoaUser user, @RequestBody Map<String, Object> body) {
Long schId = adminGuard.requireAdmin(user, null);
return defAdminService.offlineLine(schId,
body.get("flowGuid") == null ? null : String.valueOf(body.get("flowGuid")));
}
/** 线级恢复:只恢复线可用性,不改写任何版本状态或发布内容 */
@PostMapping("/def/enableLine")
public int defEnableLine(BoaUser user, @RequestBody Map<String, Object> body) {
Long schId = adminGuard.requireAdmin(user, null);
return defAdminService.enableLine(schId,
body.get("flowGuid") == null ? null : String.valueOf(body.get("flowGuid")));
}
/** 在途办件数(议题二④):flowGuids 逗号分隔,去重后最多 100;返回 flowGuid → 审批中办件数(无在途也返 0 键) */
@GetMapping("/def/inflight")
public Map<String, Long> defInflight(BoaUser user, @RequestParam("flowGuids") String flowGuids) {
@@ -3,6 +3,7 @@ package com.yunhai.flowcenter.controller.api;
import com.yunhai.flowcenter.entity.FlwInstance;
import com.yunhai.flowcenter.entity.FlwTask;
import com.yunhai.flowcenter.model.FlowModels;
import com.yunhai.flowcenter.model.OapiModels;
import com.yunhai.flowcenter.service.FlowAccessGuard;
import com.yunhai.flowcenter.service.FlowDiagramService;
import com.yunhai.flowcenter.service.FlowInstanceService;
@@ -41,6 +42,22 @@ public class FlowUserController {
private final FlowDiagramService diagramService;
private final com.yunhai.flowcenter.service.DiagramImageService imageService;
/** oapi 预览服务复用(T07 托管选人:候选+版本锚同源,字段注入防构造钉) */
@org.springframework.beans.factory.annotation.Autowired
private com.yunhai.flowcenter.service.OapiFlowService oapiFlowService;
/**
* 发起时指派预览(2026-10-25 T07 托管选人 iframe 数据源,F6 预置件点亮):
* CAS 会话取学校+提交人,复用 oapi applyPreview(含 T03 线级停发守卫)——
* 返回 {flowGuid, defVersion, nodes:[{nodeId,nodeName,countersign,selection,candidates}]}。
* <b>只读预览</b>:不建实例、不建任务、不落任何流程事实;正式提交仍走 apply 终审
* (前端候选不是授权凭据)。
*/
@GetMapping("/apply/preview")
public OapiModels.ApplyPreviewVo applyPreview(BoaUser user, @RequestParam("flowGuid") String flowGuid) {
return oapiFlowService.applyPreview(requireSchId(user), flowGuid, user.getId());
}
/** 我提交的办件 */
@GetMapping("/my")
public BasePageResult<FlowModels.InstanceItem> my(BoaUser user,
@@ -0,0 +1,21 @@
package com.yunhai.flowcenter.controller.oapi;
import com.yunhai.flowcenter.model.FormalApplyModels;
import com.yunhai.flowcenter.service.FormalApplyCommandService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController @RequestMapping("/oapi/flow/commands") @RequiredArgsConstructor
public class FormalApplyCommandController {
private final FormalApplyCommandService commands;
@PostMapping
public FormalApplyModels.Receipt submit(@RequestParam("schId") Long school,
@RequestAttribute("yh.app.auth") String appKey, @RequestBody FormalApplyModels.Request request) {
return commands.submit(school, appKey, request);
}
@GetMapping("/{requestId}")
public FormalApplyModels.Receipt query(@RequestParam("schId") Long school,
@RequestAttribute("yh.app.auth") String appKey, @PathVariable String requestId,
@RequestParam(value="expectedHash", required=false) String expectedHash) {
return commands.query(school, appKey, requestId, expectedHash);
}
}
@@ -208,7 +208,7 @@ public class OapiFlowController {
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size,
@RequestAttribute(value = "yh.app.auth", required = false) String appKey) {
return queryService.pageDone(schId, assigneeId, appKey, page, size);
return queryService.pageDone(schId, assigneeId, com.yunhai.flowcenter.service.FlowOapiSourceScope.currentOr(appKey), page, size);
}
/**
@@ -222,7 +222,7 @@ public class OapiFlowController {
@RequestParam(value = "page", required = false) Integer page,
@RequestParam(value = "size", required = false) Integer size,
@RequestAttribute(value = "yh.app.auth", required = false) String appKey) {
return queryService.pageCc(schId, userId, appKey, page, size);
return queryService.pageCc(schId, userId, com.yunhai.flowcenter.service.FlowOapiSourceScope.currentOr(appKey), page, size);
}
/** 办件分页(oapi):bizType/status 可选过滤 */