Appearance
ADR-0006: AI 开放接口用静态令牌,不新增应用/微服务
- 日期:2026-07-21 状态:✅ 生效
背景(什么问题)
需要让 AI(内建助手、外部 AI、未来第三方系统)调用整个 SaaS 的大量接口来"操控系统",覆盖 user/merchant/channel/platform 各角色、vem/user/finance 等各服务。诉求是尽量少改动、且现有及未来接口都能被 AI 调。
决策(怎么定的)
- 不新增微服务、不新增账户类型。AI 令牌本质是"一个绑定真实账户、权限被裁剪的长效 Token"。
- 在集中式 token 解析点加一个前缀分支:令牌
hsk_{keyId}_{secret},在TokenServiceImpl.getToken()(hiapi-cloud-public 受保护模块,唯一 1 处)识别hsk_前缀 → 委托IApiKeyResolver解析成标准Token。因为所有服务解析 token 最终都汇聚到这一个方法,改这一处 = 全服务零改动生效。 - 两类凭证(同一张
hiapi_ai_api_key表,type区分):ASSISTANT(四角色一键授权、用户不见明文,给平台内建 AI 助手)/EXTERNAL(merchant/channel/platform 手动生成明文 key,给外部 AI)。 - 接口开放走注解白名单:
@OpenApi(scope=...)标在允许 AI 调的接口上;强校验拦截器只对loginType=api_key生效,无@OpenApi或 scope 不匹配 → 403;普通登录 token 完全不受影响。 - 能力清单自描述:每个服务自动暴露
/open-api/manifest,列出本服务对当前凭证开放的接口——运行时真源,不手工维护。
理由(为什么,否掉了哪些备选)
- 全平台鉴权链路本就统一集中(
HiapiTokenFilter → getToken → Token → SecurityContext → TokenGet),顺着它下钩子成本最低、爆炸半径最小。 - 否掉"改 fast-frame 的 SecurityApiService + 新增 feign 解析端点":那样要重建并重发全部服务,爆炸半径远大于只重建 public 保护模块。
- 否掉"签名式(appId+sign)或新建应用实体":AI 场景要的是最简单的
Authorization: Bearer <静态key>;签名式是给未来第三方外部系统对接用的另一层(过滤器级验签),与本方案共用地基但不在此范围。 - 否掉"表驱动的每路径权限绑定":现系统服务端从未做每路径权限码,只需开放一小撮接口给 AI,注解式(权限码跟着接口走、默认拒绝)比全量梳理路径入表更省、更不易漂移。
- Scope MVP 复用账户现有
authority码(方案 A),签发时校验为账户权限子集;阶段 2 再升级为语义化 scope 目录(vem:device:read)。
影响(约束了什么,谁要遵守)
- 想把某接口开放给 AI/开放平台 → 在该 Controller 方法(或类)上贴
@OpenApi(scope=..., name=..., desc=...);不贴 = 开放凭证默认调不到(白名单制)。见AI 开放接口对接指南。 - 失败取向 fail-closed:凭证解析/校验异常一律拒绝(与授权保护那套 fail-open 灰度相反)。
- JPA 实体/仓库 遵守 ADR-0002:
AiApiKey实体/JPA 放启动期模块,受保护模块只放钩子。 - 多账户 Controller 遵守 ADR-0005:用组合(
AiApiKeyManage)+ 每角色一个@RestController,不用中间继承。 - 改了 fast-frame(注解/拦截器/审计)→ 全部服务重建重部署才生效;public 另需重建上报保护模块(
report-public-module)。 - 未来"第三方外部系统对接"是本方案的治理超集(加接入方注册表 + 按租户授权 + 验签过滤器),复用同一 Token 产物与
@OpenApi目录。