diff --git a/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/application/muse/facade/ProjectionSecurityRuntimePermissionFacade.java b/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/application/muse/facade/ProjectionSecurityRuntimePermissionFacade.java index 6375a801..5d08867d 100644 --- a/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/application/muse/facade/ProjectionSecurityRuntimePermissionFacade.java +++ b/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/application/muse/facade/ProjectionSecurityRuntimePermissionFacade.java @@ -56,8 +56,7 @@ public class ProjectionSecurityRuntimePermissionFacade implements SecurityRuntim requireCompleteRequest(request); Long tenantId = TenantContextHolder.getRequiredTenantId(); MuseToolGrantDO grant = toolGrantMapper.selectRuntimeApprovedGrant(tenantId, request.operationId(), - request.targetType(), request.targetId(), request.targetKey(), request.sourceSnapshotId(), - request.agentId()); + request.targetType(), request.targetId(), request.targetKey(), request.agentId()); if (!isApprovedSecurityProjection(grant)) { // Security projection 不存在或不是 approved/active/security 时,AI runtime 只能拒绝执行。 throw new ServiceException(AI_RUNTIME_PERMISSION_DENIED); @@ -113,7 +112,8 @@ public class ProjectionSecurityRuntimePermissionFacade implements SecurityRuntim requireTextEquals(scope, "operationId", request.operationId()); requireTextEquals(scope, "targetType", request.targetType()); requireMatchingTargetFields(scope, request); - requireTextEquals(scope, "sourceSnapshotId", request.sourceSnapshotId()); + // sourceSnapshotId 是单次执行的运行时证据(随机生成),按设计不参与能力授权命中(详见 MuseToolGrantMapper 注释), + // 仅由 summary() 记入 envelope 作事后审计;requireCompleteRequest 仍要求其非空(执行证据必须存在)。 requireTextEquals(scope, "agentId", String.valueOf(request.agentId())); List> resourceRefs = resourceRefs(scope.get("resourceRefs")); diff --git a/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/dal/mysql/muse/MuseToolGrantMapper.java b/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/dal/mysql/muse/MuseToolGrantMapper.java index 34e481a0..b082c086 100644 --- a/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/dal/mysql/muse/MuseToolGrantMapper.java +++ b/muse-cloud/muse-module-ai/muse-module-ai-server/src/main/java/cn/iocoder/muse/module/ai/dal/mysql/muse/MuseToolGrantMapper.java @@ -27,6 +27,11 @@ public interface MuseToolGrantMapper extends BaseMapperX { *

P1R-4 还没有接入 Security 主流程 RPC,只能消费已落库的 ToolGrant 投影。查询必须固定 * security owner、approved、active 三个条件;scope 必须显式携带本次 runtime 可消费的资源引用,避免 AI * 模块把普通审批号或缺字段投影当成 runtime envelope。

+ * + *

命中按「能力授权」粒度匹配 operationId/targetType/targetId·targetKey/agentId/resourceRefs——均为可预登记的稳定标识。 + * sourceSnapshotId 是单次执行的运行时证据(每次随机 "src-"+UUID 生成),属事后审计字段而非授权条件:若纳入命中, + * 等于要求预登记 grant 预知未来随机值,逻辑无解(任何 AI 执行都永远 fail-closed)。故剥离出命中条件, + * 仅由 runtime envelope summary 记录追溯(见 ProjectionSecurityRuntimePermissionFacade)。

*/ @Select("""