spec.md 15 KB

Forge AI 中枢受控业务动作

status: done created: 2026-07-12 complexity: 🔴复杂 parent-stage: Forge AI 中枢阶段 2.1 — 受控写入

1. 背景与目标

mcp-user-delegation-identity 已归档,MCP 每个请求都能建立可信 USER/SERVICE 双身份,并实时计算 Token scope、客户端 grant、用户权限、租户和当前组织交集。当前 MCP 仍只发布 capability.ping,不能安全发现或执行业务写动作。

本变更交付阶段 2.1 的最小可用闭环:把低代码应用中已经发布的、显式允许 AI 调用的业务动作发布为 BUSINESS_ACTION 能力,通过固定元工具 capability.searchcapability.describecapability.invoke 动态发现和调用。写入必须经过发布快照、授权、字段白名单、幂等和 MCP elicitation 人工确认,不能退化为任意 CRUD、任意 Mapper、任意 SQL、任意 URL 或任意代码执行。

2. 成功标准

  • MCP 仍为单 /mcp Streamable HTTP;固定发布 capability.ping/search/describe/invoke,不动态创建顶层业务 Tool;
  • capability.search/describe 只返回当前 client grant、当前用户权限、tenant/activeOrg 同时允许的已发布业务动作;
  • 业务动作只从 ai_business_object_design_version.publish_status=PUBLISHED 的不可变快照解析,禁止读取已变更草稿作为执行定义;
  • 当前阶段只允许 UPDATE_FIELDCREATE_RECORD 及其安全组合;拒绝 START_FLOWSEND_MESSAGEDOMAIN_ACTION、外部 HTTP/URL、脚本和任意 SQL;
  • 能力版本策略和 grant 实时生效;撤销 client、grant、用户权限或组织成员关系后下一请求立即失败;
  • 输入字段必须同时属于能力版本 policy_snapshot.allowedFields、grant field_policy.allowedFields 和目标发布模型字段;additionalProperties=false
  • capability.invoke 强制 16~128 位幂等键;相同键与相同请求返回已有结果,相同键与不同请求指纹拒绝;
  • MEDIUM/ACTION 必须由支持 MCP elicitation 的客户端在同一次调用中返回 ACCEPTDECLINE/CANCEL 或客户端不支持 elicitation 时不产生业务副作用;
  • 执行身份沿用 A,ORM create_by/update_by/create_dept、业务动作日志和 Capability 调用审计记录 A/client/serviceUser/tenant/org;
  • 返回结构化结果和稳定错误码,不返回 SQL、异常堆栈、Token、Header、完整业务敏感数据或原始请求;
  • Identity、MCP、Control Plane、Generator、Secure Actions 和 Admin 聚合回归通过,不调用真实大模型。

3. 范围

3.1 包含

  • 新增 forge-plugin-capability-secure-actions 组合模块;
  • MCP Tool contributor 扩展点和四个固定 Tool 聚合;
  • 业务动作能力专用发布 API,自动生成 Schema、策略快照和 source binding;
  • 发布动作快照解析、安全步骤验证、字段白名单验证;
  • 授权目录查询、describe 和 invoke;
  • MCP elicitation R2 确认;
  • 业务动作幂等指纹加固;
  • Capability 双身份审计与业务动作执行日志关联;
  • Flyway 权限资源和必要索引/字段迁移;
  • TDD、模块测试和聚合验证。

3.2 明确不做

  • 不开放任意表 CRUD、任意 Mapper、任意 SQL、任意 HTTP、任意文件或任意代码执行;
  • 不实现 Flowable start/approve/reject,留给 forge-ai-hub-flow-actions
  • 不发送站内信、短信、邮件或三方消息;
  • 不开放 DOMAIN_ACTION、库存数量台账等领域副作用;
  • 不实现 R3 高风险审批、加密快照或异步人工审批;
  • 不新增复杂前端工作台;本阶段只增加必要管理 API;
  • 不接 Nacos MCP Registry/Admin、AgentScope 或 Agent Runtime;
  • 不使用旧 SSE、STATELESS、stdio 或 ASYNC MCP Server;
  • 不引入 Spring Authorization Server 或 Sa-Token OAuth2;
  • 不调用真实模型。

4. 架构

/mcp Streamable HTTP
  -> fdu Bearer + ExecutionIdentity
  -> fixed tools: capability.search / describe / invoke
  -> SecureActionCatalogService
       -> ai_capability + version + grant(控制面)
       -> published BusinessObjectDesignVersion(发布快照)
       -> action permission + tenant/org
  -> SecureActionPolicy(版本白名单 ∩ grant 白名单 ∩ 发布模型字段)
  -> MCP elicitation ACCEPT
  -> BusinessActionExecutionService.executePublished(...)
  -> ai_business_action_execution_log + ai_capability_invocation_log

forge-plugin-mcp 只增加协议级 McpToolContributor 聚合扩展点,不依赖 Generator 或控制面。Secure Actions 模块负责把 MCP、控制面、Identity 和 Generator 组合起来;Generator 不反向依赖 Capability,避免循环依赖。

5. 能力契约

5.1 业务动作 source binding

  • source_type=BUSINESS_ACTION
  • source_key={suiteCode}/{objectCode}/{actionCode},每段只允许 [A-Za-z0-9_-]
  • source_version={publishVersion}
  • behavior=ACTION
  • risk_level=MEDIUM
  • visibility=DISCOVERABLE
  • policy_snapshot 至少保存 allowedFieldsrequiredFieldsallowedStepTypesconfirmationMode=MCP_ELICITATIONpublishedObjectVersion
  • 输入 Schema 只包含 recordIdidempotencyKeyarguments,其中 arguments.properties 由字段白名单生成且 additionalProperties=false

5.2 固定元工具

Tool 行为 注解
capability.search 查询当前调用方可发现动作,limit 1~50 readOnly=true, destructive=false, idempotent=true
capability.describe 返回已授权版本、输入/输出 Schema、风险和确认要求 readOnly=true, destructive=false, idempotent=true
capability.invoke 校验并执行一个已授权动作 readOnly=false, destructive=true, idempotent=true

工具结果同时提供文本 JSON 和 structuredContent。业务错误作为 Tool result isError=true 返回;协议级认证仍由 HTTP 401/403/503 处理。

6. 安全与业务规则

  1. capability.invoke 只接受能力编码、可选版本、记录 ID、幂等键和 arguments;suite/object/action、tenant/user/org/client 只能从服务端 source binding 与可信身份获得;
  2. 只允许 USER Token 执行业务动作。SERVICE Token 在本阶段可 search/describe,但 invoke 返回 USER_DELEGATION_REQUIRED
  3. 发布和调用时都递归校验动作步骤,只允许 UPDATE_FIELDCREATE_RECORD;嵌套/未知步骤失败关闭;
  4. grant 创建 ACTION 能力时必须存在非空字段策略,且只能缩小版本白名单;
  5. R2 确认摘要包含动作名称、对象、记录 ID、字段名和请求指纹,不在服务日志中记录字段值;
  6. elicitation 的 ACCEPT 只对当前同步调用有效,不签发可重放确认 Token;
  7. 幂等唯一域保持 tenant/object/record/action/idempotencyKey;服务额外比较 canonical request SHA-256,不同请求不能复用已有成功结果;
  8. 发布快照版本、能力版本和 grant resolvedVersion 必须一致;草稿变更不影响已发布动作;
  9. 任意 DB/Redis/目录故障返回稳定不可用错误,不伪装成无权限或参数错误;
  10. 审计不保存 arguments、elicitation 内容、Token、Header 或原始异常消息。

7. 数据变更

新增 V1.0.23__add_secure_business_action_capabilities.sql

  • 增加受控业务动作发布和调用权限资源;
  • 为业务动作执行日志补充 capability_request_id/client_id/service_user_id/actor_type,便于双日志关联;
  • 字段按数据库规范具备防重复迁移;
  • 不插入真实 capability、client、grant、Token 或业务动作数据;
  • 不修改已执行的 V1.0.21/V1.0.22。

8. HARD-GATE

  • 未经过发布快照、grant、用户动作权限、字段交集、幂等和 elicitation ACCEPT 的请求不能产生写副作用;
  • SERVICE Token、HIGH 风险、流程、消息、领域动作、未知步骤全部失败关闭;
  • 相同幂等键不同请求必须拒绝;
  • 认证/授权/确认/执行异常后 ExecutionIdentity、TenantContext 和 MDC 无泄漏;
  • MCP 仍只有 /mcp Streamable HTTP;
  • 任一硬闸门失败时不得进入 forge-ai-hub-flow-actions

9. 回滚

  • forge.capability.secure-actions.enabled=false 关闭三个元工具和业务动作发布 API,保留 ping 与身份底座;
  • 已发布 capability/grant 可在控制面停用/撤销;
  • 新增审计字段保留,不自动删除;
  • 回滚不得恢复任意 CRUD Tool、裸 Header 身份、长期 fcp 直连或旧 SSE。

10. 确认记录

  • 确认时间:2026-07-12;
  • 确认方式:用户要求归档 mcp-user-delegation-identity 并开始新阶段开发;
  • 批准范围:阶段 2.1 受控业务动作,不包含流程办理、消息和 R3 高风险审批;
  • 执行方式:Proposal 后直接进入 Apply,禁止 commit/push。

11. Review 结论

review-date: 2026-07-12 conclusion: NEEDS_FIX

11.1 Spec Compliance

已满足:单 /mcp Streamable HTTP、固定元工具、USER 委托身份、发布快照、ACTION/MEDIUM、MCP elicitation、幂等请求摘要、结构化结果、禁用旧 SSE/SAS/Sa-Token OAuth2 及 V1.0.23 静态迁移约束均已落地。

存在六个 Spec 不合规项:

  1. R1 / P0 — grant 字段交集没有进入实际输入 Schema。 SecureActionCatalogService 计算了能力版本与 grant 的 allowedFields 交集,但 SecureActionDescriptor.inputSchema 仍直接使用能力版本原始 Schema;SecureActionMcpHandler 只用该原始 Schema 校验 arguments,没有再按交集检查字段。因此被 grant 排除、但仍存在于版本 Schema 的字段仍可进入业务动作执行,违反 §2、§6.4 和 HARD-GATE。
  2. R2 / P0 — resolved capability version 与 source binding 混用。 SecureActionCatalogMapper.xmlai_capability_version v 选择授权版本和策略,却从 ai_capability c 返回当前 source_key/source_version。能力升级或重绑定后,PINNED grant 会混用“旧版本 Schema/策略 + 当前动作 binding”;版本号不同时异常失效,版本号碰巧相同时可能执行错误动作,违反 §6.8。
  3. R3 / P0 — 动作步骤没有递归失败关闭。 SecureActionStepValidator 只检查 actionConfig.steps 的顶层 stepType,没有递归检查 stepList、嵌套 stepschildSteps 或步骤配置中的未知步骤,违反 §6.3 和 HARD-GATE。
  4. R4 / P1 — 目录/DB 故障没有稳定映射为不可用。 目录数据解析异常被包装为 BusinessException 后映射为 INVALID_ARGUMENT,普通 Mapper/数据库异常映射为 EXECUTION_FAILED;两者都不能表达目录/授权/审计基础设施不可用,且前者会把平台故障伪装成调用参数错误,违反 §6.9。
  5. R5 / P1 — Capability 审计失败被吞并仍返回业务成功。 业务动作已提交后才写 Capability 调用审计,审计异常只记录 warn,调用仍返回成功,因此不能保证成功标准要求的 A/client/serviceUser/tenant/org 双日志审计闭环。
  6. R6 / P1 — elicitation 展示的“请求指纹”没有绑定请求内容。 当前短哈希仅由 requestId + idempotencyKey 生成,不包含 capability/version/recordId/arguments,不能作为 §6.5 所要求的请求指纹。

11.2 Review Gate

  • Spec Compliance 结论为 FAIL;按两阶段 Review 规则,不进入 Code Quality Review;
  • 当前状态为 reviewed_with_findings,不得归档或进入 Flow Actions;
  • 下一步执行 /fix forge-ai-hub-secure-actions,优先顺序固定为 R1 → R2 → R3 → R4/R5 → R6;
  • Fix 后必须为每项补充 Red/Green 证据,并增量复跑 Secure Actions、Generator、Control Plane、Identity、MCP 和 Admin 聚合。

12. Fix 结果

fix-date: 2026-07-12 conclusion: FIXED_PENDING_REVIEW

  1. R1 已修复。 目录把能力版本 Schema 的 arguments.properties/required 裁剪到版本策略与 grant 策略交集;invoke 同时显式拒绝交集之外的字段,指定发布模型仍作为第三道校验。
  2. R2 已修复。 目录 SQL 从 resolved ai_capability_version 读取 source_key/source_version/risk_level,并要求 capability/version 同时满足 BUSINESS_ACTION/ACTION/MEDIUM/DISCOVERABLE,PINNED/FOLLOW_MAJOR 不再混用主表当前 binding。
  3. R3 已修复。 发布和调用共用递归容器扫描;顶层兼容 steps/stepList,任意 childSteps、嵌套 steps/stepList、未知或禁用步骤全部失败关闭。
  4. R4 已修复。 新增安全基础设施异常,目录查询、授权查询、目录数据和审计存储分别稳定映射为 CATALOG_UNAVAILABLEAUTHORIZATION_UNAVAILABLEAUDIT_UNAVAILABLE,日志只记录 requestId、错误码和异常类型。
  5. R5 已修复。 elicitation ACCEPT 后、业务写入前必须先按 requestId 与可信双身份写入 EXECUTION_PENDING 审计;最终结果只能按相同身份更新。预留失败不进入执行,最终审计失败返回 AUDIT_UNAVAILABLE 并保留待完成记录,幂等重试可补齐最终状态。
  6. R6 已修复。 elicitation 指纹改为 capabilityCode/version/recordId/idempotencyKey/arguments 的递归排序 canonical JSON SHA-256 短摘要;键顺序不影响摘要,请求内容变化必然改变摘要。

Fix 验证:Secure Actions 27/27、Control Plane 27/27、Generator 专项 7/7、MCP 16/16、Identity 35/35、Admin 40/40 聚合通过;Mapper XML 和静态安全扫描通过。当前状态为 fixed_pending_review,等待再次 Review,复审通过前不归档或进入 Flow Actions。

13. 修复后复审与归档结论

review-date: 2026-07-12 conclusion: PASS

13.1 Spec Compliance

  • R1:运行时 arguments Schema 与显式字段校验均使用能力版本、grant 和发布模型字段交集,PASS;
  • R2:授权版本的 source binding、Schema、policy、风险和可见性统一来自 resolved ai_capability_version,PASS;
  • R3:发布和调用共用步骤校验器,顶层与嵌套 steps/stepList/childSteps、未知和禁用步骤均失败关闭,PASS;
  • R4:目录、授权和审计故障稳定返回 CATALOG_UNAVAILABLEAUTHORIZATION_UNAVAILABLEAUDIT_UNAVAILABLE,PASS;
  • R5:elicitation 后、业务写入前先预留 Capability 审计,最终状态按完整可信身份条件更新,PASS;
  • R6:elicitation 指纹绑定 capability/version/recordId/idempotencyKey/arguments 的 canonical SHA-256,PASS;
  • /mcp Streamable HTTP、USER 委托身份、发布快照、幂等和禁用旧传输/认证依赖边界保持,PASS。

13.2 Code Quality

  • 未发现 Critical、Important 或阻塞归档的 Minor 问题;
  • SQL 位于 Mapper XML,目录分页为稳定 keyset,异常日志不记录参数值和原始异常消息;
  • 审计、幂等、发布快照和执行身份均保持失败关闭,模块依赖方向未形成循环依赖。

13.3 验证与归档

  • 2026-07-12 14:30 复跑 Secure Actions:27/27 PASS;
  • SecureActionCatalogMapper.xml 解析、V1.0.23 Flyway placeholder 扫描和相关 git diff --check PASS;
  • 复用 Fix 阶段 Control Plane 27/27、Generator 7/7、MCP 16/16、Identity 35/35、Admin 40/40 成功基线;
  • 真实 MySQL Flyway、真实外部 MCP elicitation 客户端和真实模型调用仍按条件跳过,不冒充 PASS;
  • HARD-GATE 全部通过,允许归档并进入 forge-ai-hub-flow-actions