KeelBase AI 写操作在外部系统产生副作用后,可通过 revokePath 撤销——撤销时 KeelBase 会调用 Java 系统的补偿端点(注入委托身份)。 This is the Java-side compensation endpoint that KeelBase calls to undo an AI-created side effect.
位置:本示例是「集成商在 Java 存量系统侧实现的参考」,KeelBase 侧撤销机制已具备(
proxy-revoker.service.ts)。Spring Boot 3.x / Java 17+ 请优先用 keelbase-java-starter 的
KeelBaseCompensationSupport——本页手写的委托验签 + 幂等 + 审计样板已被脚手架封装(文档:仓库docs/compensation.md/docs/compensation.zh-CN.md);本示例仅作 Java 8 / Spring Boot 2 存量系统兜底。
KeelBase 撤销外部副作用时(GET /ai/tool-effects 撤销 / P0-15 本人撤销):
KeelBase
├─ 签发委托 JWT(audience 限定 = 你的系统)
└─ DELETE {baseUrl}{revokePath}{resultId}
headers: Authorization: Bearer <委托 JWT>
revokePath在 ProxyTool 配置(ai_proxy_tools工具项)里指定,支持DELETE /api/customers/{customerId}/followups/{id}这类「方法 + 路径 + 占位」格式{id}占位 → 副作用 resultId(AI 写调用锚点)- 补偿端点需返回 2xx(成功);幂等(重复撤销返回 200 +
idempotent)
// KeelBaseCompensationController.java —— AI 副作用撤销补偿端点(参考实现)
@RestController
@RequestMapping("/api/compensation")
public class KeelBaseCompensationController {
/** 与 KeelBase 共享的委托密钥(DELEGATION_SECRET,验签用) */
private final SecretKey delegationKey =
Keys.hmacShaKeyFor(System.getenv("DELEGATION_SECRET").getBytes(StandardCharsets.UTF_8));
/** 撤销 AI 创建的跟进任务(外部 CRM 场景) */
@DeleteMapping("/followups/{id}")
public ResponseEntity<?> revokeFollowup(
@PathVariable Long id,
@RequestHeader(value = "Authorization", required = false) String auth) {
// 1. 验签委托 JWT(KeelBase 签发,audience 限定;失败 401)
Claims claims = verifyDelegation(auth);
if (claims == null) return unauthorized();
// 2. 幂等:已撤销 / 不存在 → 200 + idempotent:true
Followup f = followupRepo.findById(id).orElse(null);
if (f == null || Boolean.TRUE.equals(f.getCancelled())) {
return ok(Map.of("idempotent", true, "resultId", id));
}
// 3. 撤销(软删 cancelled;如需硬删走事务)
f.setCancelled(true);
followupRepo.save(f);
// 4. 审计(谁 / 何时 / 补偿什么——企业可追溯)
auditLogger.log("compensation", id, claims.getSubject(),
"followup revoked by KeelBase compensation");
return ok(Map.of("idempotent", false, "resultId", id, "status", "revoked"));
}
/** 验签 KeelBase 委托 JWT:HS256 + audience 校验 + 过期校验 */
private Claims verifyDelegation(String bearer) {
if (bearer == null || !bearer.startsWith("Bearer ")) return null;
try {
JwtParser parser = Jwts.parserBuilder().setSigningKey(delegationKey).build();
Claims c = parser.parseClaimsJws(bearer.substring(7)).getBody();
// audience 限定:确保是 KeelBase 本平台签发(可选,按系统约定校验)
if (!"legacy-crm".equals(c.getAudience())) return null;
return c;
} catch (JwtException e) {
return null; // 签名不合法 / 过期
}
}
}| 要点 | 说明 |
|---|---|
| 验签 | 用 DELEGATION_SECRET(与 KeelBase 同密钥)HS256 验签;audience 校验防跨系统 |
| 幂等 | 重复撤销返回 200 + idempotent:true(KeelBase 撤销是幂等操作) |
| 软删/硬删 | 建议软删(cancelled 标记)便于追溯;需要物理删除走事务 |
| 审计 | 补偿动作必须记审计(谁 / 何时 / 撤销了什么),与 KeelBase 审计哈希链呼应 |
| 失败语义 | 返回非 2xx → KeelBase 撤销失败并透传原因(proxy-revoker.service.ts) |
- 在 Java 系统实现补偿端点(参考上面示例)
- 在 KeelBase 配置
ai_proxy_tools:写工具加revokePath: "DELETE /api/compensation/followups/{id}" - 配置
DELEGATION_SECRET(KeelBase 与 Java 系统共享,缺省回退 JWT_SECRET,生产应独立配置) - 验证:管理台
AI 工具与副作用→ 撤销该副作用 → 观察 Java 补偿端点被调用 + 状态变为已撤销
- 撤销发起方:
proxy-revoker.service.ts(读 revokePath + 签发委托 JWT + 调补偿端点) - 副作用登记:
ai-tool-side-effect(proxy_call 类型,可见/可审计) - 前端入口:管理台「AI 行为回放 / 工具与副作用」→ 撤销按钮;工作台「AI 执行轨迹」→ 本人撤销