# 审批业务行为契约 ## 通用完成标准 每个审批能力的完成证据同时包括真实页面或受控机器入口、真实后端 API、权限和对象授权、状态校验、正式持久化、审计追踪以及失败零副作用。验收以完整业务链路的真实状态变化为准。 ## 身份与权限 - 候选用户、角色和部门必须从正式身份目录解析,并验证存在、启用和去重。 - 服务端认证身份和对象授权共同限定用户 ID、流程发起人及数据范围,客户端字段只承担业务筛选作用。 - 五个职责角色为 `workflow_admin`、`workflow_designer`、`workflow_starter`、`workflow_approver`、`workflow_auditor`。 - 管理员权限、设计权限、发起权限、办理权限和审计只读权限必须保持职责分离。 ## 流程状态与动作 | 动作 | 核心约束 | | --- | --- | | 发起 | 使用最新激活定义或明确版本,校验部署表单快照、身份、变量和附件绑定 | | 认领/取消认领 | 当前用户必须属于有效候选范围;重复或过期任务返回稳定冲突结果 | | 完成 | 校验 assignee、delegation、任务表单和附件,提交后核对下一活动任务 | | 委派/委派办结/转办 | 目标用户必须有效,owner、assignee、意见和审计必须保持一致 | | 退回 | 目标固定为可信历史中的首审批节点;受控会签/或签按唯一正式来源轮次整组退回,连续受控节点需逐轮对账 | | 重提 | 发起人从唯一待修改任务提交;普通首审批原任务恢复办理配置,受控首审批从自身权威来源重建,后续节点自然重放 | | 驳回 | 以整实例原子终止表达 `rejected`,写后核验活动兄弟任务为零并保持已有终态优先 | | 撤回 | 操作人必须真实办理过前驱,且直接后继仍处于可逆状态 | | 取消 | 仅发起人对运行中的本人实例执行,并保存明确原因 | | 终止 | 仅管理员执行,终态优先于 Flowable 自然完成事件 | | 挂起/激活 | 写命令受状态约束;具备对象权限的参与者仍可按规则只读查看 | | 已结束实例删除 | 仅管理员对满足引用和保留策略的终态实例执行 | 非法状态、过期 `taskId`、重复提交和执行树漂移返回稳定的业务冲突结果,运行态、历史、业务表、附件和审计按同一事务整体回滚。 ## 任务生命周期重构冻结矩阵 本节是任务生命周期内部职责替换的正式验收合同。内部服务直接替换原集中实现,Controller、DTO、权限标识、HTTP 状态及以下八个公开命令/查询继续保持同一调用方可观察行为。 | Lifecycle 方法 | 冻结的业务语义 | | --- | --- | | `cancelProcess` | 仅既有授权主体可取消允许取消的完整流程树;继续沿用原因、终态、附件、通知、审计及回滚语义 | | `isProcessRevocable` | 投影真实撤回前置条件;继续沿用对象缺失、权限、后继已办理和高风险 BPMN 的分类 | | `revokeProcess` | 仅原真实办理人可撤回仍待办理的安全直接后继;继续沿用锁后核验、迁移、审计和写后对账顺序 | | `completeTask` | 继续沿用办理人、委派、表单、附件、抄送、下一办理人、多实例 revision 和循环控制语义 | | `rejectTask` | 既有权限和状态校验后原子终止完整实例树,并写后核验兄弟任务为零、审计完整 | | `returnTask` | 普通任务只返回安全首审批节点;受控 ALL/ANY 由任一真实办理人整组退回并生成唯一发起人待修改任务 | | `resubmitApplication` | 仅原发起人可重提;统一从可信历史首审批继续,来源轮次只承担审计关闭作用,后续 ALL/ANY 自然重放 | | `isTaskReturnAllowed` | 对满足正式退回全部前置条件的当前任务返回 `true`,并在只读事务中完成计算 | 普通串行退回的冻结写入顺序为:审计 comment → 迁移标记 → Flowable 状态迁移 → 冻结办理配置 → 写入申请人局部变量 → 清除候选人/候选组/owner → 同步流程变量与 business status 为 `returned` → 独占指派发起人 → 持久化抄送 → 写后核验 → 稳定任务通知 → 清除迁移标记。普通重提的冻结写入顺序为:附件绑定 → 表单变量和提交快照 → 审计 comment → 迁移标记 → 清除退回局部变量 → 恢复办理配置 → 同步双状态为 `running` → 写后核验 → 稳定任务通知 → 清除迁移标记。 受控 ALL/ANY 整组退回的冻结写入顺序为:冻结抄送计划 → 审计 comment → 迁移标记/Coordinator 协议 → 撤销来源任务通知 → Flowable 整组迁移 → 关闭来源任务 SLA → 冻结首审批任务办理配置并建立唯一发起人退回态 → `ACTIVE→RETURNED` 来源轮次 CAS → 持久化抄送 → 轮次、执行树、双状态及 Coordinator 写后对账 → 稳定任务通知 → 清除迁移标记。受控来源重提的冻结写入顺序为:附件绑定 → 表单变量和提交快照 → 审计 comment → 迁移标记 → 撤销待修改任务通知 → `RETURNED→REOPENED` 来源轮次 CAS → 同步双状态为 `running`。普通首审批保持当前 task/execution 并恢复冻结办理配置;受控首审批再开启 Coordinator、取消临时根、按该节点权威来源建新根和 revision 0 正式轮次。两类路径均清除后续受控节点的先前运行状态,使其自然进入时各自重新初始化。最后完成 SLA、轮次/成员/计数对账、稳定通知并清除迁移标记。 任一步失败都由同一事务回滚 Flowable、轮次 CAS、附件、SLA、抄送、通知和审计。成员顺序、ALL/ANY 模式、目标多实例节点和 revision 来自服务端实时事实与冻结轮次快照;缺失、重复、漂移、成员不一致或 CAS 冲突返回稳定冲突。Flowable 引擎独占维护 `nrOfInstances`、`nrOfActiveInstances`、`nrOfCompletedInstances` 三个计数。 ## 多实例与复杂执行树 - 多实例成员由服务端身份解析器生成并保存不可变成员快照。 - 动态加签和减签必须使用 revision/CAS 或等效并发保护,并对真实 execution、活动任务和审计结果写后核对。 - ALL 会签只有全部有效成员完成后才能离开节点;ANY 或签由首个有效完成原子取消其余 sibling。 - 受控动态多实例在办理人、同根活动任务、唯一 `ACTIVE` 轮次、成员顺序、ALL/ANY、revision、计数和执行作用域全部一致时允许整组退回;其余状态隐藏页面入口,直接 API 返回冲突且零副作用。 - 整组退回必须一次撤销来源同根全部活动任务,只创建一个发起人待修改任务,并以 CAS 将来源轮次从 `ACTIVE` 改为 `RETURNED`;退回后必须保留首审批任务的办理配置快照,重提再将来源轮次 CAS 为 `REOPENED`。 - 安全主流程允许“普通 → ALL → ANY”和“普通 → ALL → ALL → ANY”等连续平台受控同步多实例路径。每个受控节点的最近正式轮次、部署模式和流程变量逐项对账;静态多实例、CallActivity、服务活动、并行/包容网关、边界事件、循环、损坏引用、跨作用域和超预算图返回稳定冲突。 - 首审批是普通任务时,重提恢复当前首审批任务,来源轮次完成审计关闭;首审批本身是受控多实例时,待修改任务位于临时单成员根并保持临时身份,重提从该首节点权威成员来源建立正式新轮。后续受控节点在自然重新进入时建立各自新轮。 - 受控迁移标记绑定轮次、根 execution、activity、来源任务和操作人,并在 Flowable 命令结束时删除;根取消监听器只接受该精确协议。 - `${multiInstanceHandler.getUserIds(execution)}` 和 `${userTaskListener}` 解析到固定白名单 Bean,表达式执行范围限定在这两个受控入口。 ## 表单、附件与快照 - 详情中的申请表单、本节点办理表单和历史节点表单是三个独立语义:`processFormList` 唯一 `taskId=null` 的正式开始提交快照是申请表单,其他项才是历史;`currentTaskForm` 在普通办理态只表示当前 UserTask 表单,在退回态才表示绑定当前任务的可编辑开始表单投影。 - 节点具有部署表单时显示本节点页签;存在可证明的开始提交快照时显示申请值,缺少快照时页面默认流程图并明确显示缺失。多个开始快照或退回投影身份冲突时返回数据异常。 - 表单模板可编辑,部署时固化到 Flowable 业务制品子部署的 `approvaplat/forms-v1.json`;已部署流程持续读取该冻结快照。 - 内嵌 BPMN 表单与正式模板使用统一快照结构,并保存明确 `source_type`。 - 发起和办理都按部署快照校验字段、类型、必填、长度、选项和附件引用。 - 临时附件只有所有者可以删除;绑定后按流程对象授权读取。容量检查先锁全局配额行,再锁用户配额行。 - 业务删除先留下正式生命周期记录,物理清理失败进入持久化重试并保持可观察状态。 ## 扩展、连接器、DMN 与运行事件 - BPMN 扩展目录和版本统一经过服务端已安装处理器白名单;部署时将不可变执行快照和校验和保存到 `approvaplat/extensions-v1.json`。 - 建模用户从目录选择登记的固定 Delegate;发布门禁只接受目录 Java 实现、已登记 `delegateExpression` 和结构化字段配置。 - HTTP 连接器访问登记端点;请求通过 Flowable async Job 执行,并发送由 `processInstanceId + executionId + elementId + payloadSha256` 生成的稳定 `Idempotency-Key`。 - SQL 连接器使用登记数据源和 AST 校验模板。外库查询允许至少一次重试;外库写接受绑定系统 `idempotencyKey`、由真实业务唯一键保护且重复键分支为空操作的幂等 INSERT。 - HTTP/SQL 失败保留在 Flowable 原生 Job、Timer Job 和 Dead Letter Job;逐次结果进入脱敏结构化日志与 Micrometer 指标,Flowable Job 表作为唯一调用状态台账。 - DMN 部署必须通过 XML 安全校验,并在流程部署时将引用快照固化到 `approvaplat/dmn-v1.json`。 - Message、Signal 和 ReceiveTask 运行事件使用独立集成 Token;数据库保存前缀、哈希、限流状态和完整调用审计,Token 正文只在签发时交付。 ## 边界定时器、审批 SLA 与升级 - 审批 SLA 运行能力由正式 SLA 规则、业务日历、通知策略、升级路径和真实异步执行器共同实现,并完整覆盖状态变更、持久化、审计和补偿。 - SLA 规则绑定流程定义版本和活动/边界事件快照,保存计时起点、截止时间、日历、时区、暂停策略、提醒节点、催办次数、升级目标和幂等键;已部署版本持续读取冻结规则。 - 截止时间按服务端业务日历计算,明确工作日、节假日、工作时段、跨时区和节假日覆盖规则;服务端结果是最终判定。 - 实例、任务或流程被挂起、撤回、终止、驳回或进入补偿状态时,SLA 计时按规则暂停、取消或转入补偿;恢复时从正式持久化的剩余时长和日历游标继续,并通过幂等键保持单一计时器。 - 受控整组退回或重提撤销任务时,原 SLA 使用既有 `COMPLETED` 表达“计时已关闭”;不可变 `COMPLETE` 审计中的固定受控撤销详情负责区分正常业务完成,并在 Flowable 状态迁移后按精确原任务集合收口,保持与正常完成一致的锁序。 - 提醒、自动催办和升级由异步执行器以持久化租约/CAS 或等效幂等机制触发。同一 SLA 节点在并发轮询、节点重启和重试下最多产生一次业务动作;通知失败进入可重试状态,成功投递后写入“已通知”终态。 - 自动动作在服务端执行并验证流程对象权限、候选范围、租户/部门数据范围和当前状态;服务端解析结果限定接收人、升级人和任务范围。 - 每次判定、暂停/恢复、提醒、催办、升级、通知重试、回滚和人工处理都写入审计,记录规则版本、截止时间、执行器、幂等键、前后状态和失败原因;审计字段白名单覆盖业务标识与脱敏原因。 - 通知、任务更新、升级路由或 Flowable 命令失败时,业务状态和审计按事务边界回滚或进入明确的持久化补偿队列;页面只展示已经由任务、数据库和 Flowable 共同确认的升级状态。 ## 错误与审计 - 参数校验失败、认证缺失、权限不足、对象超出访问范围、非法状态和内部失败必须具有稳定且可测试的响应语义。 - 失败请求完成零成功写入核验,Flowable、`wf_*`、附件文件和操作日志保持原业务状态。 - 审批意见、操作者、目标对象、前后状态和必要的幂等标识保持可追踪;日志和报告使用字段白名单与脱敏规则保存业务证据。