1. 页面概览

1.1 是什么

API Key 管理页是 LightFoundry 的开发者门户,面向 SDK 与机器到机器(machine-to-machine)调用场景提供长期凭证(区别于 AIP 登录的短期 JWT)。页面允许已登录用户创建、查看、撤销与删除自己的 API Key:创建时填写名称、Scopes 与过期时间,创建成功后一次性展示明文 Keylfk_ 前缀 + 32 位随机串),数据库仅存该 Key 的 SHA256 哈希,关闭提示后任何人均无法再次查看明文。

页面同时提供「我的 API Key」列表,逐条展示 Key 的状态(有效 / 已撤销 / 已过期)、过期时间、最近使用时间与绑定的 scopes;支持两种下线方式——撤销IsActive=false,保留记录供审计)与删除(物理删除,不可恢复)。底部还内置一个「验证 API Key(Demo)」区,输入完整明文 Key 后调用后端公开验证端点,返回该 Key 绑定的 user_idscopes,用于在接入 SDK 之前确认凭证有效性。

从产品定位上看,本页属于「认证与密钥」基础设施(V3-4 阶段交付,对应 TAD-14 §4.4/§5),是外部系统以程序化方式访问 Foundry 本体、语义层与数据能力的入口凭证管理面。

1.2 核心价值

维度说明
长期凭证Key 绑定具体用户,供 CI/CD 流水线、数据导出脚本等无人值守场景使用,不依赖登录会话
哈希存储库中只存 SHA256 哈希(key_hash),库表泄露也无法反推明文
一次性明文明文仅创建响应返回一次,前端提供「复制」按钮并强提示立即保存
细粒度 scopes每个 Key 可声明一组 scope(如 ontology:read,query:execute),随 Key 存储并在验证时返回
生命周期管理过期时间、撤销(保留记录)与删除(物理清除)三种下线方式,兼顾审计与应急
验证闭环内置 verify 端点,SDK / 外部系统调用前可先行校验 Key 有效性与绑定身份

1.3 一句话总结

在 Foundry 里「给机器开一把可控失效的长期钥匙」——创建时一次性拿到明文,库中只存哈希,随时可撤销可删除,并可在接入前用验证 Demo 确认 Key 绑定的用户与 scopes。Key 是绑定用户的「能力代理」:按绑定用户 DB 角色判权的端点,Key 能力=创建者全集;而走 AuthorizeUser 的数据面/动作执行路径会因空角色注入而拒绝。接入建议绑定最小权限账号。

2. 访问入口

2.1 路由与菜单

2.2 认证与权限

2.3 端口与 API 前缀

3. 界面布局

页面纵向分为 5 个板块(从上到下):

┌──────────────────────────────────────────────────────────────┐
│ ① 页头:标题「API Key 管理」+ 副题「开发者门户 · 长期凭证…」    │
│ ② 操作结果提示条(alert,成功绿 / 失败红,可关闭)              │
│ ③ 创建 API Key 卡片(名称 / Scopes / 过期时间 + 两个按钮)      │
│ ④ 一次性明文展示卡片(创建成功后出现,含复制与关闭按钮)         │
│ ⑤ 我的 API Key 列表卡片(表格 + 撤销 / 删除操作列)             │
│ ⑥ 验证 API Key(Demo)卡片(完整 Key 输入 + 验证结果展示)      │
└──────────────────────────────────────────────────────────────┘

各板块职责:

4. 交互元素详解

4.1 创建表单

元素位置含义必填 / 默认值操作效果与触发调用
名称 *创建卡片第 1 列Key 的业务名称(如 CI/CD Pipeline数据导出脚本必填(required空名提交会被前端拦截并提示「请填写 Key 名称」
Scopes创建卡片第 2 列逗号分隔的权限标识(中文逗号亦可),如 ontology:read,query:execute非必填,留空则 scopes 为空数组提交时按 /[,,]/ 拆分、去空格、去空项
过期时间创建卡片第 3 列datetime-local 类型输入,超过该时间 Key 自动失效非必填,留空 = 永不过期提交时转 ISO 字符串;有值则 expires_at 非空
创建 API Key按钮提交创建POST /api/v1/api-keys;成功后展示明文卡片并刷新列表
清空按钮重置表单调用 resetCreateForm() 将三个字段全部置空

创建提交的请求体字段名:name(trim 后)、scopes(数组)、expires_at(ISO 字符串或 null)。

4.2 一次性明文展示卡片

元素含义操作效果
<code> 明文创建响应返回的完整 Key(lfk_ 开头)展示后即不可再查;样式 user-select: all 便于鼠标全选
复制一键复制明文到剪贴板navigator.clipboard.writeText;成功后提示「明文 Key 已复制到剪贴板」,失败降级提示「复制失败,请手动选中复制」
我已保存,关闭关闭明文卡片置空 newPlainKey,卡片消失,此后无法再次查看明文

若后端未返回明文(旧版本后端),前端提示「创建成功,但未返回明文(请检查后端版本)」(alert-warning)。

4.3 我的 API Key 列表

含义说明
IDKey 记录主键数字自增
名称Key 名称粗体展示
前缀key_prefix固定为 lfk_cell-code 样式
Scopes权限标识集合每个 scope 一个 scope-tag 标签;为空显示「全部」
过期时间expires_atformatTime 格式化(T 替换为空格、截取 19 位),空显示 -
最近使用last_used_at验证成功时会更新,空显示 -
状态有效 / 已撤销 / 已过期徽标三态:status-enabled(有效)/ status-disabled(已撤销)/ status-expired(已过期)
创建时间created_at同上格式化
操作撤销 / 删除见下

4.4 撤销与删除

按钮出现条件确认文案操作效果与调用
撤销仅当 k.is_active === true「确定撤销 API Key「{name}」吗?撤销后立即失效(记录保留)。」POST /api/v1/api-keys/:id/revoke;成功提示「API Key「{name}」已撤销」并刷新列表
删除恒显示「确定删除 API Key「{name}」吗?此操作不可恢复。」DELETE /api/v1/api-keys/:id;成功提示「API Key「{name}」已删除」并刷新列表

两个操作均有 window.confirm 二次确认,且操作期间按钮 busy 置灰防重复提交。后端对「不属于当前用户」的 Key 返回 404 类错误(「API Key 不存在或不属于当前用户」)。

4.5 验证 API Key(Demo)

元素含义操作效果
完整 Key 输入框粘贴要验证的完整明文 Keyv-model="verifyKey",placeholder lfk_xxxxxxxx...
验证按钮提交验证空输入时禁用;调 GET /api/v1/api-keys/verify?key=<encodeURIComponent>;成功后 sample-box 展示 user_id 与 scopes 标签,提示「Key 验证通过」

验证端点位于公开路由组(无需 JWT),返回 {user_id, scopes, valid:true};前端仅展示 user_idscopes

5. 后端关联

5.1 API 客户端

5.2 端点表(前缀 /api/v1

方法路径请求体 / 参数鉴权超时用途
POST/api-keys{name, scopes[], expires_at?}JWT30s创建 Key,返回一次性明文
GET/api-keysJWT30s我的 Key 列表
DELETE/api-keys/:idJWT30s物理删除 Key
POST/api-keys/:id/revokeJWT30s撤销 Key(保留记录)
GET/api-keys/verify?key=查询参数 key公开30s验证 Key,返回 user_id + scopes

路由注册位置:foundry/server/server.go setupRouter()——RegisterAPIKeyVerifyRoute(api, s) 挂在公开组 api := r.Group("/api/v1")RegisterAPIKeyRoutes(protected, s) 挂在 protected := api.Group("")(走 authMiddleware)。

5.3 响应结构(JSON 示例)

创建成功(HTTP 201):

{ "code": 0, "data": {
  "api_key": "lfk_aB3dEfGhIjKlMnOpQrStUvWxYz012345",
  "key": { "id": 1, "name": "CI/CD Pipeline", "key_prefix": "lfk_",
           "user_id": "550e8400-...", "scopes": ["ontology:read"],
           "expires_at": null, "last_used_at": null, "is_active": true,
           "created_at": "2026-08-30T08:00:00Z", "updated_at": "..." }
} }

列表(HTTP 200):{ "code": 0, "data": [ { ...同上 key 结构,无 api_key 明文... } ] }

撤销 / 删除:{ "code": 0, "data": { "revoked": true, "id": 1 } } / { "code": 0, "data": { "deleted": true, "id": 1 } }

验证(HTTP 200):{ "code": 0, "data": { "user_id": "...", "scopes": ["ontology:read"], "valid": true } }

错误响应统一为 { "code": "<错误码>", "error": "<描述>" };无效前缀 / 不存在 / 已撤销 / 已过期均返回 401 AUTH_ERROR

5.4 关联模块

后端包 / 文件职责
foundry/server/apikey_handlers.goHTTP handler:创建 / 列表 / 删除 / 撤销 / 验证五端点
foundry/apikey/service.go业务服务:生成、SHA256 哈希、查询、撤销、删除、验证
foundry/apikey/model.goAPIKey 模型,表 api_keyskey_hash 唯一索引)
foundry/apikey/apikey_test.go单元测试(生成 / 验证 / 撤销等)
foundry/server/core_auth_apikey_v4_test.go认证集成测试(Bearer lfk_ 走 API Key 认证)

5.5 关键机制

6. 核心流程详解

6.1 创建 Key 主流程

  1. 在「名称 *」输入业务名(必填),可选填 Scopes(逗号分隔)与过期时间。
  2. 点「创建 API Key」→ 前端校验名称非空 → busy=true → 调 POST /api/v1/api-keys
  3. 后端 CreateKey:校验名称非空、绑定当前用户 → GenerateKey()HashKey() → 落库 → 返回 {api_key 明文, key 记录}
  4. 前端把 data.data.api_key 写入 newPlainKey,展示黄色明文卡片并提示「API Key 创建成功,请立即复制明文(仅展示一次)」,同时 resetCreateForm() 清空表单、fetchKeys() 刷新列表。
  5. 用户点「复制」保存明文,或「我已保存,关闭」收起卡片。关闭后明文不可再查

分支:后端未返回明文时,前端提示「创建成功,但未返回明文(请检查后端版本)」(alert-warning),列表仍刷新。

6.2 撤销流程

  1. 列表中找到目标 Key(须 is_active === true),点「撤销」。
  2. window.confirm 二次确认 → 调 POST /api/v1/api-keys/:id/revoke
  3. 后端 RevokeKey:按 id AND user_id 更新 is_active=false;0 行影响返回「API Key 不存在或不属于当前用户」。
  4. 成功提示「API Key「{name}」已撤销」,fetchKeys() 刷新——状态徽标变为「已撤销」(灰色),操作列不再显示「撤销」按钮(记录保留)。

6.3 删除流程

  1. 点「删除」→ window.confirm 确认「此操作不可恢复」。
  2. DELETE /api/v1/api-keys/:id → 后端物理删除该行。
  3. 成功提示「API Key「{name}」已删除」,刷新后记录消失。删除不可恢复,撤销更安全

6.4 验证流程(Demo 与 SDK 前置校验)

  1. 输入完整明文 Key(lfk_ 开头)→ 点「验证」。
  2. 前端调公开端点 GET /api/v1/api-keys/verify?key=...(无需登录)。
  3. 后端 ValidateKey 校验通过则返回 user_id + scopes + valid:true,同时更新 last_used_at
  4. 前端在 sample-box 展示 user_id 与 scopes 标签,提示「Key 验证通过」。

业务侧(SDK / 外部系统)同样可先调 verify 确认凭证,再以 Authorization: Bearer lfk_... 调业务端点。

7. 权限与安全

8. 常见问题与排错

8.1 创建成功后没有弹出明文

8.2 验证 Demo 返回 401 / 验证失败

8.3 列表加载失败 / 一直转圈

8.4 明文复制失败

8.5 撤销后还想恢复

9. 已知缺陷与边界

项目说明
scope 不强制执行(语义债)scopes 仅存储与返回,authMiddleware 不按 scope 过滤端点访问(apiKeyScopeGate() 闸门已就绪、默认不挂载)。鉴权双路径:请求上下文注入空角色roles=[]),走 AuthorizeUser 的数据面/动作执行路径默认拒绝;按绑定用户 DB 角色判权的端点 Key 能力=创建者全集(admin 绑定的 Key 可写)——接入建议绑定最小权限账号
明文不可恢复明文仅在创建响应返回一次;关闭提示 / 刷新页面后无法再次查看,只能重新创建
撤销不可逆无重新启用接口,撤销后需重建 Key
删除不可恢复物理删除记录,无回收站
验证端点公开GET /api/v1/api-keys/verify 无需登录,可被枚举尝试(仅返回绑定信息,无业务数据泄露,仍建议监控)
单 Key 绑定单用户Key 无法同时代表多用户或多角色;多人共用需每人各建 Key
无轮转 / 自动续期过期时间到期后 Key 即失效,系统不会自动续期或通知