execution-log.md 12 KB

执行日志 — MCP 用户委托身份

change: mcp-user-delegation-identity status: done created: 2026-07-12

1. 时间线

时间 阶段 事件 结论
2026-07-12 Archive 归档 forge-ai-hub-control-plane 状态 done,验证证据与跳过项完整保留
2026-07-12 Direction 用户要求开始阶段 2 用户委托身份作为受控写入/流程前置硬闸门
2026-07-12 Research 读取工程 LoginUser、SessionHelper、Sa-Token、ORM 审计和 MCP Filter 当前只能证明服务账号,显式执行身份上下文尚不存在
2026-07-12 Official Spec 读取 MCP 2025-06-18 Authorization/Transport 用户委托必须采用 OAuth 2.1 + PKCE + RFC 9728/8414 + resource audience
2026-07-12 Finding 完整 Auth 拦截链仍匹配 /mcp 机器 Filter 通过后可能被 StpUtil 二次拒绝,列为 Apply P0
2026-07-12 Proposal 创建阶段 2.0 四份文档 仅文档,不写业务代码,不开放写/流程能力
2026-07-12 Apply 用户执行 /apply mcp-user-delegation-identity 进入实现,仍不开放业务写与流程动作
2026-07-12 HARD-GATE 反编译检查 Sa-Token OAuth2 1.38.0 缺 PKCE/resource/PUBLIC Client,拒绝采用
2026-07-12 HARD-GATE 探索 临时引入 Spring Authorization Server 1.5.6 运行公开 API 能力测试 Reactor 28/28 SUCCESS,仅作为探索证据,随后按用户要求完整撤回
2026-07-12 Direction 用户明确禁止 spring-security-oauth2-authorization-server Identity POM 与测试立即移除该依赖,重新打开实现 HARD-GATE
2026-07-12 HARD-GATE 核验 Sa-Token OAuth2 1.45.0 仍缺 PKCE/resource,authorization code 内置 handler 仍依赖 client_secret,不采用

2. 已确认决策

  • 阶段 2 分切片实施;用户委托身份属于阶段 2,但作为第一个独立可验收变更;
  • 采用 MCP 官方 OAuth 授权边界,不信任身份 Header,不把普通 Forge Token 透传给 MCP;
  • 长期机器 Secret 只用于换短期 SERVICE Token,不直接访问 MCP;
  • A 使用 authorization code + PKCE 获取 USER Token;
  • Token audience 固定为 canonical /mcp resource,每次 HTTP 请求重新验证;
  • 通过协议无关显式上下文桥接 SessionHelper/ORM/日志,默认登录链保持不变;
  • 本变更不实现任何业务副作用,HARD-GATE 通过后再建设 secure actions/flow actions。
  • OAuth 实现采用边界受限的 Forge OAuth 2.1 Profile;Spring Authorization Server 与 Sa-Token OAuth2 均不进入运行依赖。

3. Proposal 验证

检查 结果
上一变更归档目录与四份文档 PASS
MCP 官方 Authorization/Transport 内容读取 PASS,规范版本 2025-06-18
当前 LoginUser/SessionHelper/ORM/OperationLog 调用链检查 PASS,已定位上下文桥接点
当前 MCP/Auth 拦截链检查 发现 P0,已进入 Spec/Tasks/Test Spec
下一 Flyway 版本 V1.0.22
业务代码/数据库/服务变更 无;Proposal 阶段未执行

4. Apply HARD-GATE 探索记录

执行命令:

cd forge-server
JAVA_HOME=/opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home \
PATH=/opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home/bin:$PATH \
mvn -Penable-tests \
  -pl forge-framework/forge-plugin-parent/forge-plugin-capability-identity \
  -am test
阶段 结果
临时 Red 未引入 SAS 依赖时探索性测试 testCompile 失败,缺少 OAuth2/SAS 类型
临时 Green 2026-07-12 08:47:35 +08:00 完成;Identity 1/1、MCP 13/13、Control Plane 20/20,Reactor 28/28 SUCCESS
撤回 用户禁止该依赖后已删除 Identity POM 依赖和 AuthorizationFrameworkCapabilityTest,临时 Green 不作为最终选型

5. 当前状态

OAuth/MCP Apply 已完成,等待 Review。运行时不包含 SAS/Sa-Token OAuth2;/mcp 已切换为短期 fdu_ Token,长期 fcp_ 仅用于机密客户端换 Token。

6. Apply 实现记录

  • 创建 forge-plugin-capability-identity 并接入 plugin parent、BOM 和 Admin;
  • 创建 V1.0.22,新增 redirect URI、access token 表及客户端 OAuth 字段;
  • 实现 RFC 8414/9728 metadata、authorization code + PKCE S256、client credentials、resource、revoke;
  • 实现 256-bit 不透明短期 Token、HMAC 持久化、实时用户/组织/客户端校验和立即失效;
  • 实现显式执行身份、租户/MDC/异步恢复、OperationLog/ORM 取值和 Capability 双身份审计落库;
  • /mcp 只接受 Header Bearer fdu_,拒绝 fcp_、query/cookie Token 与非白名单 Origin;
  • 创建简洁授权页并对 OAuth 参数、Token、code、verifier 和 state 做前端审计脱敏;
  • 收尾删除已失效且仍引用旧长期 fcp_ Resolver 的 Admin 测试文件。

7. Apply 验证记录

执行时间:2026-07-12 09:34–09:41 +08:00。

命令/检查 结果
Identity mvn -Penable-tests -f .../forge-plugin-capability-identity/pom.xml test PASS,18/18
Capability mvn -Penable-tests -f .../forge-plugin-capability/pom.xml test PASS,13/13
MCP mvn -Penable-tests -f .../forge-plugin-mcp/pom.xml test PASS,13/13
Control Plane mvn -Penable-tests -f .../forge-plugin-capability-control-plane/pom.xml test PASS,20/20
Admin mvn -pl forge-admin-server -am package -DskipTests PASS,39/39 modules
Admin 单模块启用测试生命周期 首次因本地仓库缺 Forge 模块 POM 失败;执行 reactor install 后 PASS,无测试编译残留
Identity dependency tree + 全 POM + Admin JAR 扫描 PASS,无 spring-security-oauth2-authorization-server、无 sa-token-oauth2
Mapper xmllint、V1.0.22、placeholder、tenant 0、物理 DELETE、git diff --check PASS
目标 ESLint PASS,无输出
Node 20.19.0 pnpm build PASS;仅既有组件命名、CSS 注释和 chunk 警告

未调用真实模型。未启动任何需要清理的长期服务进程。

8. 条件跳过与 Review 入口

  • 未对真实 MySQL 执行 Flyway,避免污染用户现有库;
  • 未使用真实 Redis 验证 20 路并发 code 兑换,当前自动化只证明使用 HMAC key 和 Lua GET+DEL;
  • 未启动 Admin/浏览器执行真实登录授权闭环;
  • 未把 Mock/模块协议测试冒充上述真实环境验证;
  • 下一步应执行 /review mcp-user-delegation-identity,优先审查 OAuth 错误契约、撤销边界、完整 Auth 拦截链与上下文泄漏,再决定是否进入 secure actions。

9. Review 执行记录

执行时间:2026-07-12 10:19 +08:00。

9.1 两阶段审查

  • Spec Compliance:发现 R1 完整身份链证据缺口、R2 client grant/用户权限交集未接线,均为 P0 阻断;
  • Code Quality / Security:发现 R3 PUBLIC/USER 主动撤销缺失、R4 当前组织未前置一致性校验、R5 平台异常静默降级为客户端错误;另记录 R6 参数/issuer/留存/SYNC 加固项;
  • SAS 约束:继续满足,源码 POM、dependency tree 和隔离测试均无 spring-security-oauth2-authorization-server,也无 sa-token-oauth2
  • MCP transport:继续只使用单 /mcp Streamable HTTP,未发现旧 SSE/STATELESS/stdio 回退。

9.2 增量验证证据

Identity: Tests run 18, Failures 0, Errors 0, Skipped 0
MCP:      Tests run 13, Failures 0, Errors 0, Skipped 0
dependency:tree: BUILD SUCCESS,无目标依赖输出
git diff --check / xmllint / Flyway 静态扫描: PASS

首次静态命令在 forge-server 工作目录下误加 forge-server/ 前缀导致路径不存在;随后使用正确相对路径复跑并通过。该次命令错误不计入产品失败。

9.3 结论

Review 状态为 NEEDS_FIX。不归档、不进入 secure actions;下一步执行 /fix mcp-user-delegation-identity,按 R1 → R2 → R3/R4 → R5 → R6 修复并增量验证。

10. Fix 执行记录

执行时间:2026-07-12 10:28–10:59 +08:00。

10.1 实现

  • R1:新增真实 fdu_ 聚合链 MockMvc 测试,装配 Resolver、Filter、Lifecycle、SaTokenConfig、Streamable HTTP SDK、Capability Registry 与实际审计 Observer;
  • R2:新增 Identity 组合层治理 Policy,实时组合 Token scope、控制面 grant、当前 LoginUser.permissions 和 tenant/activeOrg;
  • R3/R4:新增当前用户 USER Token 撤销接口;授权预览/确认在 code 签发前校验当前组织;
  • R5:OAuth 与 MCP 分离 4xx、403、401、503,日志只记录安全元数据并保留基础设施异常堆栈;
  • R6:参数长度、issuer query、SYNC-only、LoginUser 防御性快照、last_used_at 节流、Token 30 天留存清理。

10.2 验证证据

命令/检查 结果
Identity mvn -Penable-tests test PASS,最终复跑 34 tests(R1–R6 全部覆盖)
Capability mvn -Penable-tests test PASS,13/13
MCP mvn -Penable-tests test PASS,14/14;新增 ASYNC 失败关闭
Control Plane mvn -Penable-tests test PASS,20/20
AI mvn -Penable-tests test PASS,84/84;未调用真实模型
Admin mvn -pl forge-admin-server -am package -DskipTests PASS,39/39 modules
Identity dependency tree + Admin JAR 扫描 PASS,无 spring-security-oauth2-authorization-server、无 sa-token-oauth2
Mapper xmllint / Flyway placeholder / tenant 0 / git diff --check PASS
目标 ESLint PASS,无输出
Node 20.19.0 pnpm build PASS,✓ built in 1m 18s;仅既有组件命名、CSS 注释和 chunk 警告

首次使用 reactor -Penable-tests -am test 时,既有 forge-starter-datascope 无测试引擎导致生命周期失败,目标模块尚未执行;随后先 -am install -DskipTests 安装当前 reactor 产物,再按 Identity/MCP/Capability/Control Plane/AI 目标模块分别启用测试并全部通过。该环境命令问题未伪装为产品通过。

10.3 条件跳过与清理

  • 真实 MySQL Flyway、真实 Redis 20 路并发和真实浏览器 OAuth 全闭环继续跳过,原因与 Review 前一致;
  • 本轮未调用真实大模型;AI 84 项均使用 mock/stub;
  • 未启动长期服务,无 PID 需要清理;
  • 状态更新为 fixed_pending_review,下一步再次 /review mcp-user-delegation-identity,当前不归档、不进入 secure actions。

11. Mapper 重复加载构建残留修复

执行时间:2026-07-12 11:15–11:17 +08:00。

  • 启动异常:AiCapabilityClientMapper.BaseColumns 已存在,MyBatis 拒绝重复注册同一 namespace 的 SQL fragment;
  • 根因:AiCapabilityClientMapper.xml 已迁移到 forge-plugin-capability-control-plane,但旧 forge-plugin-capability/target/classes 及其已安装到 ~/.m2 的 JAR 仍残留迁移前资源;classpath*:mapper/**/*Mapper.xml 因而同时加载新旧两份 XML;
  • 处理:使用 JDK 17 执行 mvn clean install -pl forge-admin-server -am -DskipTests,清理 reactor 构建目录并覆盖本地 Maven 仓库;
  • 结果:39/39 reactor modules SUCCESS;源码、target/classes、模块 JAR 和本地 Maven JAR 四层检查均确认 Mapper 只存在于 control-plane 模块;
  • 本轮没有修改 Mapper 源码、namespace 或业务逻辑,没有启动服务、执行 Flyway 或调用真实模型。应用需使用本次重新安装的依赖重启。

12. 最终复审与归档

执行时间:2026-07-12 11:54–11:56 +08:00。

  • 实际代码复核:权限交集、fdu Bearer、Origin、错误分类、上下文清理、SYNC/STREAMABLE 启动闸门符合 Spec;
  • Identity:34 tests,0 failures,0 errors;
  • MCP:14 tests,0 failures,0 errors;
  • 静态扫描:无 spring-security-oauth2-authorization-server、无 sa-token-oauth2,无旧 SSE/STATELESS/stdio/ASYNC 配置;
  • 最终结论:Spec Compliance PASS,Code Quality / Security PASS,状态更新为 done
  • 归档路径:code-copilot/changes/archive/2026-07-12-mcp-user-delegation-identity/
  • 本轮未启动长期服务、未执行真实 Flyway/Redis/浏览器 E2E、未调用真实大模型。