变更目录:
code-copilot/changes/unified-capability-open-platform/依据:code-copilot/rules/automated-testing-standard.md(增量优先、证据优先) 创建:2026-07-31(本变更首个测试轮次,无历史 test-spec 可复用)
将 Forge Capability 底座通过 REST 开放网关 POST /openapi/v1/capabilities/{capabilityCode}/invoke 开放给外部机器客户端。涉及:
forge-starter-openapi-security(防重放/限流/幂等通用组件)、forge-plugin-capability-identity(客户端凭据与签名认证)、forge-plugin-capability-open-gateway(网关认证 + 九步编排)V1.0.74__capability_open_gateway.sql(表/字典/菜单/权限)+ V1.0.75__add_capability_registration_dict.sql(流程动作字典)+ V1.0.76__add_capability_external_user_delegation.sql(客户端主体模式与外部身份映射)forge-admin-ui/src/api/ai/capability.js + views/ai/capability/{catalog,client,grant,invocation}.vue + 能力注册弹窗| 编号 | 验证项 | 方式 | 命令/位置 |
|---|---|---|---|
| P0-1 | OpenApiReplayGuard 单测:appId 缺失 401 / 时间戳超窗 401 / nonce 格式非法 401 / nonce 重复 401 / Redis 不可用与异常失败关闭 503 / 正常放行 | JUnit5 + Mockito | forge-starter-openapi-security → OpenApiReplayGuardTest |
| P0-2 | CapabilityInvokeOrchestrator 单测:scope 缺失 FORBIDDEN / 授权目录不可用 INTERNAL_ERROR 503 / ACTOR_TYPE_NOT_ALLOWED / 权限缺失 FORBIDDEN / RATE_LIMITED 429 / 写操作缺 Idempotency-Key SCHEMA_INVALID / 幂等命中 idempotentHit / payload 非法顶层字段 SCHEMA_INVALID / READ_ONLY 跳过幂等 / 写路径成功 SUCCESS | JUnit5 + Mockito | forge-plugin-capability-open-gateway → CapabilityInvokeOrchestratorTest |
| P0-3 | Admin 聚合生产打包 | JAVA_HOME=... mvn -Penable-tests -pl forge-admin-server -am package -Dforge.tests.skip=true(forge-server 根) |
47 个 Reactor 模块成功 |
| P0-4 | 本变更 Flyway 脚本静态检查(无占位符) | rg -n '\$\{[^}]+\}' forge-server/db/migration/V1.0.7{4,5,6}__*.sql |
应无输出;全目录存在 V1.0.72 历史占位符,不能作为本变更失败依据 |
| P0-5 | 前端构建 | nvm use v20.19.0 && NODE_OPTIONS=--max-old-space-size=8192 pnpm build(forge-admin-ui) |
构建成功 |
| P0-6 | 前端 Lint(API、4 页面、注册组件) | pnpm exec eslint src/api/ai/capability.js src/views/ai/capability/*.vue src/views/ai/capability/components/*.vue |
零错误 |
| P0-7 | 控制面授权候选项、客户端凭据和 ACTION/FLOW 授权策略 | JUnit5 + Mockito,4 个目标测试类 | 23 条通过 |
| P0-8 | 流程能力注册来源校验 | FlowActionSourceServiceTest + FlowActionCapabilityPublisherTest |
5 条通过 |
| P0-9 | 签名 AppId 稳定性与网关认证 | OpenGatewayAuthenticatorTest |
2 条通过;数值 clientId 同时作为 OAuth client_id 与签名 AppId |
| 编号 | 验证项 | 方式 | 前置条件 |
|---|---|---|---|
| P1-1 | 端到端:启动 admin 服务 → Flyway V1.0.74 迁移成功 | 启动日志 + forge_schema_history |
本地 MySQL/Redis 可用 |
| P1-2 | 端到端:创建客户端 → 授权能力 → HMAC 签名 curl 调用 /openapi/v1/capabilities/{code}/invoke 走通 8 错误码契约 |
curl | 本地 MySQL/Redis 可用 + 存在已发布能力 |
| P1-3 | 控制台 4 页面(能力目录/机器客户端/能力授权/调用日志)人工走查 | 浏览器 | 前后端均启动 |
JAVA_HOME=/opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Homemvn test,仅跑本变更两个模块的单测执行证据统一记录到同目录 execution-log.md。
client_id 和签名 X-Forge-App-Id,OAuth 密钥轮换不再改变签名身份标识。enabled 条件,默认关闭外部网关时路由也被移除。FlowActionAutoConfigurationTest 验证开关关闭时保留来源/发布 Bean,不装配执行日志与流程执行适配器;开启时执行 Bean 正常装配。SecureActionAutoConfigurationTest 验证开关关闭时保留业务动作发布 Bean,不装配 MCP 目录/Handler/工具贡献者;开启时运行时 Bean 正常装配。@ConditionalOnProperty,前端 404 显示明确的 Admin 更新/重启提示。git diff --check。GET /ai/capability/flow-action/registration-source,预期从 404 变为成功数据或可解释的业务校验错误。CapabilityClientServiceTest 覆盖 USER_DELEGATION 不需要 serviceUserId/activeOrgId、拒绝 SIGNATURE,以及 SERVICE/HYBRID 仍强制绑定。invalid_grant,禁止任意选取第一条。/oauth2/userinfo 身份返回。CapabilityAccessTokenServiceTest 与流程动作测试覆盖 USER 身份 serviceUserId 可空,SERVICE 身份仍强制服务账号。crypto.properties 不含 Pepper 时,在文件锁内原子补齐并保留既有 Crypto 密钥。application.yml 空占位符不得覆盖持久化值。forge.crypto.bootstrap.enabled 时不生成文件或 Pepper,Capability 既有启动校验继续失败关闭。