P2 Foundry
API 与 SDK:把本体能力开放给机器
Foundry 的 API/SDK 层让报表系统、CI 流水线、外部机器调用方用标准 REST + 稳定凭证接入本体、查询、动作等全部能力:OpenAPI 3.0.3 文档(122 路径 / 189 操作)+ lfk_ API Key(库中只存 SHA256 哈希)。三语言 SDK 与独立 API 网关尚未实现——边界如实讲。本主题 4 个故事覆盖"开 Key、看文档、机器调用、边界确认"。
平台管理员
开发工程师
数据工程师
API Key
OpenAPI
机器调用
共 4 个故事
能 / 不能速览
✅ 这个主题能做
- OpenAPI 3.0.3 文档:GET /api/docs(spec JSON)+ /api/docs/ui(Swagger UI 或离线清单)
- API Key 全生命周期:创建(一次性明文)/列表/撤销/删除/公开验证
- 用
Authorization: Bearer lfk_... 直接调受保护端点,无需另配认证
- 统一响应
{code:0,data},错误 {code,error},机器好解析
⛔ 这个主题做不了
- Python / JS / Go 三语言 SDK 未实现,只能手写 REST
- 独立 API 网关(限流 / 版本路由 / 请求日志 / 负载均衡)未实现
- OpenAPI 是手写快照,新增路由不更新 spec 不会报错(易漂移)
- API Key 的 scopes 只存不用,不按 scope 限制端点访问
适用角色
本主题面向三个角色:
- 平台管理员:创建 / 撤销 API Key,掌握凭证生命周期。
- 开发工程师:读 OpenAPI 文档、用 lfk_ Key 集成报表系统 / CI 流水线。
- 数据工程师:把对象查询、动作执行开放给下游系统消费。
能力速览(能做什么)
OpenAPI 3.0.3
手写 spec 覆盖 16+ 模块(122 路径 / 189 操作),统一响应 schema,双认证 scheme 声明。
开发者门户
/api/docs/ui 提供 Swagger UI(CDN 加载),无网时降级为静态路径 / 方法清单。
API Key 体系
lfk_ 前缀 + SHA256 哈希存储,明文只在创建时返回一次;撤销保留记录、删除物理删。
认证分流
Bearer 以 lfk_ 开头走 API Key 认证,否则回退 JWT——机器调用方零额外适配。
前端管理页
/foundry/api-keys 页面:创建、列表(不显示明文)、撤销、删除、验证 Demo。
调整指南(怎么调整)
- 想给系统开凭证:/foundry/api-keys 创建 Key,创建响应里的一次性明文立即保存,丢了只能撤销重建。
- 想接报表:看 /api/docs/ui 找接口,用
Bearer lfk_... 调受保护端点。
- 想验证 Key:GET /api/v1/api-keys/verify?key=... 返回绑定的 user_id 与 scopes。
- 想停用凭证:撤销(软删保留记录)而不是删除,出问题可追溯。
- 想拿 SDK:暂无官方 SDK,直接手写 REST + 统一响应解析即可。
做得好的场景
API/SDK 层让"机器消费本体能力"这件事开箱即用,特别适合以下场景:
- 报表系统定时拉数:一个 lfk_ Key + 只读查询端点,报表每天自动更新。
- CI/CD 验证契约:流水线用 Key 调 /api/docs 对拍接口,改动即校验。
- 凭证可控可撤:离职 / 泄露一键撤销,库中无明文,泄露面小。
- 跨产品接入:AIP / Swift 与第三方用同一套 REST 契约消费语义层。
限制与不足
以下是明确的边界,使用前先知道:
- 无三语言 SDK:Python / JS / Go SDK 均未实现,接入靠手写 REST。
- 无独立网关:限流(429 + Retry-After)、版本路由、请求日志、负载均衡未做。
- spec 手写易漂移:新增后端路由不更新 buildPaths 不会报错,契约以实际行为为准。
- scopes 不强制:创建时填的 scopes 只存不用,不按 scope 限制端点(scope 闸门已就绪、默认不挂载);Key 是绑定用户的能力代理——按绑定用户 DB 角色判权的端点能力=创建者全集,走 AuthorizeUser 的数据面/动作路径则因空角色注入默认拒绝。接入建议绑定最小权限账号。
场景故事
故事 1
给报表系统开一把 Key:明文只给一次,库里只有哈希
场景:凭证生命周期
角色:平台管理员
耗时:约 3 分钟
- 背景
- 运营的日报系统要每天凌晨自动从 Foundry 拉订单数据。平台管理员打开 /foundry/api-keys 页面,为报表系统创建一把 API Key(name="日报系统"),并记下创建响应里的一次性明文。
- 传统做法对比
- 以前要么把管理员密码给报表系统(权限过大、还耦合登录态),要么共用账号(无法区分调用方);现在一把 lfk_ Key 绑定专属用户,可独立撤销,库里只存 SHA256 哈希,即使库被拖走也拿不到明文。
- 角色
- 平台管理员(创建 / 保管 Key);日报系统(消费方)。
- 操作步骤
-
- 登录 /foundry/api-keys 页,点创建 Key
- 填 name="日报系统"(可选 scopes 如 ontology:read)
- 复制创建响应里的一次性明文,立即保存
- 把 lfk_ 明文交给日报系统配置
- 系统响应
- POST /api/v1/api-keys 返回 HTTP 201:
{
"code": 0,
"data": {
"api_key": "lfk_7Gx3mQp9vLz4Kd2RtY8WnB5HcJ1SaE6",
"key": { "id": 3, "name": "日报系统", "key_prefix": "lfk_",
"user_id": "admin", "scopes": ["ontology:read"], "is_active": true }
}
}
再次 GET /api/v1/api-keys 列表,返回的记录不含明文(库中只有 key_hash)。
- 结果洞察
- 明文仅在此一次返回(handler 注释:"请立即保存"),落库只存 HashKey(plain) 的 SHA256 十六进制;key_hash 带唯一索引防碰撞覆盖;撤销走软删(is_active=false)保留记录,删除才物理删。
- 调整建议
- 给每台机器 / 每个系统单独开 Key,泄一个撤一个;Key 名字写清楚用途;定期在列表页检查 last_used_at 清理闲置 Key。
- 动手试一试
- 页面路径:/foundry/api-keys → 创建。输入内容:name=日报系统。预期结果:data.api_key 以 lfk_ 开头;列表页看不到明文;verify 接口可验证。
- 限制提示
- 明文只返回一次,丢失只能撤销重建;scopes 目前只存不强制(闸门已就绪、默认不挂载);Key 能力=绑定用户(按 DB 角色判权的端点),走 AuthorizeUser 的数据面/动作路径因空角色注入默认拒绝——接入建议绑定最小权限账号。
故事 2
开发按 OpenAPI 文档接入:122 条路径 / 189 个操作一次看清
场景:开发者门户
角色:开发工程师
耗时:约 5 分钟
- 背景
- 开发工程师小唐要写一个脚本批量读取指标目录。他不翻代码,直接打开 GET /api/docs 拿到 OpenAPI 3.0.3 spec,或用浏览器打开 /api/docs/ui 开发者门户页,看接口路径、参数与统一响应结构。
- 传统做法对比
- 以前接口文档靠"找后端同事问",权限参数全靠猜,改一个字段要来回对齐半天;现在 spec 一次给全:路径、方法、参数、统一 code=0 响应,机器可读,还能直接生成客户端。
- 角色
- 开发工程师(读文档 + 写调用脚本);后端(维护 buildPaths)。
- 操作步骤
-
- GET http://127.0.0.1:18081/api/docs 拉 spec JSON
- 或浏览器打开 /api/docs/ui 看交互页(网络可用时加载 Swagger UI)
- 定位 /metrics/catalog 等目标接口,确认方法与参数
- 按统一响应结构写解析代码
- 系统响应
- GET /api/docs 返回:
{
"openapi": "3.0.3",
"info": { "title": "LightFoundry API", "version": "1.0.0" },
"servers": [ { "url": "/api/v1" } ],
"components": { "securitySchemes": {
"bearerAuth": { "type": "http", "scheme": "bearer" },
"apiKeyAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "lfk_..." } } },
"paths": { "/metrics/catalog": { "get": { ... } }, ... }
}
spec 覆盖 auth / ontology / metrics / pipelines / lineage / quality / charts / dashboards / governance / ml / apps / workflows / audit / security / api-keys 等 16+ 模块。
- 结果洞察
- 统一响应 schema(SuccessResponse/ErrorResponse)是机器解析的天然锚点;资源类端点由 crudWithID 一键生成 GET/POST + GET/PUT/DELETE,规律性强。offline 环境 /api/docs/ui 有静态路径清单兜底。
- 调整建议
- 用 spec 生成类型定义 / 客户端桩代码,减少手写;接入前先对拍 spec 与真实响应;发现 spec 与实现不一致时反馈后端更新 buildPaths。
- 动手试一试
- 输入:GET http://127.0.0.1:18081/api/docs。预期结果:openapi=3.0.3、paths 非空(≥122 条路径)、securitySchemes 含 bearerAuth 与 apiKeyAuth。/api/docs/ui 页面标题含"LightFoundry API 文档"。
- 限制提示
- OpenAPI 为手写快照,新增路由不更新 spec 不会报错,可能与实际行为漂移;Swagger UI 交互页依赖 CDN,离线时只有静态清单。
故事 3
机器调用:Bearer lfk_ 一把 Key 打通对象查询
场景:机器调用
角色:开发工程师
耗时:约 4 分钟
- 背景
- 日报系统拿到 lfk_ Key 后,每天凌晨调用对象语义查询拉订单数据。开发小唐先用 GET /api-keys/verify 验证 Key 有效性,再用
Authorization: Bearer lfk_... 调 /ontology/objects/:id/query。
- 传统做法对比
- 以前机器调用要维护 JWT 登录态、处理 Token 过期刷新,多一套流程;现在 lfk_ Key 直接放进 Bearer 头,authMiddleware 按前缀自动分流到 API Key 认证,机器调用零额外适配。
- 角色
- 开发工程师(写定时拉数脚本);认证中间件(按 lfk_ 前缀分流)。
- 操作步骤
-
- GET /api/v1/api-keys/verify?key=lfk_... 验证有效
- 构造查询请求体(对象类型 id + filters)
- 带 Authorization: Bearer lfk_... 调用 /ontology/objects/:id/query
- 按统一响应解析 rows 并入库
- 系统响应
- 验证返回:
GET /api/v1/api-keys/verify?key=lfk_7Gx3...
{ "code": 0, "data": { "user_id": "admin", "scopes": ["ontology:read"], "valid": true } }
带 Key 调用对象查询返回:POST /ontology/objects/2/query
{ "code": 0, "data": { "columns": ["order_id","amount","status"],
"rows": [[1, 995.0, "shipped"], [3, 1990.0, "shipped"]] } }
中间件把 user_id 注入为 Key 绑定的用户,username="apikey"。
- 结果洞察
- 一次配置、反复调用:ValidateKey 校验前缀 + 哈希 + is_active + 未过期,并更新 last_used_at(失败不阻断);查询走语义层真实数据源,行级/属性级安全照常生效。
- 调整建议
- 脚本里把 Key 放环境变量别硬编码;调用失败先 verify 看是否被撤销 / 过期;给不同系统开不同 Key 便于定位调用方。
- 动手试一试
- 输入内容:curl 带 Authorization: Bearer lfk_... 调 GET /api/v1/ontology/objects。预期结果:HTTP 200,currentUserID 为 Key 绑定用户。传错误前缀 / 已撤销 / 已过期 Key 分别返回 401。
- 限制提示
- API Key 调用不单独标记审计(机器调用与人工操作难以区分);Key 撤销只对后续 Bearer 调用生效,已签发的 JWT 不受影响;scopes 不按资源过滤。
故事 4
开发想要 SDK:现在只能手写 REST,边界先讲清楚
场景:边界确认
角色:开发工程师 + 平台管理员
耗时:约 3 分钟
- 背景
- 集成项目会上,开发小唐问"有没有 Python / JS / Go 的 SDK 可以 pip install / npm install?"平台管理员查了一下 Foundry 的实现范围,如实回答:目前没有官方 SDK,只有手写 OpenAPI 文档 + lfk_ API Key,接入靠直接写 REST 调用。
- 传统做法对比
- 以前很多平台文档把 SDK 画在路线图里,集成方默认"应该有",结果对接时才发现要手搓;这次先把边界讲清楚:没有 SDK 就用统一响应 + spec 自己封装,避免集成方踩坑。
- 角色
- 开发工程师(确认接入方式);平台管理员(确认能力边界)。
- 操作步骤
-
- 确认仓库中无 lightfoundry-sdk 等包(pip / npm / go get 均无)
- 评估手写 REST 的接入成本(统一响应 + spec 可生成客户端桩)
- 评估限流 / 网关需求(当前无 429 限流,需自建防护)
- 记录边界到集成方案里,后续 SDK 落地再升级
- 系统响应
- 仓库内确认:
action/products/foundry/ 下仅有 server / apikey 等 Go 包,无独立 SDK 目录;OpenAPI spec 中也没有 SDK 下载 / 试用控制台端点。接入现有能力:# 手写调用示例(Python 风格)
headers = {"Authorization": "Bearer " + API_KEY}
resp = requests.post(
"http://127.0.0.1:18081/api/v1/ontology/objects/2/query",
json={...}, headers=headers)
data = resp.json()["data"] # 统一 code=0 结构
- 结果洞察
- 边界一旦确认,接入方案就不会悬空:统一响应
{code:0,data} 让手写解析成本很低;OpenAPI spec 可以生成客户端桩代码,等于"半自动 SDK";无网关意味着调用方自己处理重试与流量,这在集成方案里要写清楚。
- 调整建议
- 把"无 SDK / 无网关"写进集成文档的已知限制;后续迭代按 v1 规划补 Python / JS SDK;如果调用量大,先在前端加一层网关或自建限流。
- 动手试一试
- 输入内容:在 /api/docs 里挑一个只读接口,用 lfk_ Key 手写一个调用脚本。预期结果:解析 data 字段即可拿到数据。三语言 SDK、独立 API 网关、Webhook/GraphQL 均为规划中。
- 限制提示
- SDK(Python / JS / Go)未实现,接入只能手写 REST;无限流 / 版本路由 / 请求日志;API Key scopes 不强制;OpenAPI 手写快照可能与实现漂移。
常见问题
创建 API Key 后明文丢了怎么办?
明文只在创建时返回一次,丢失后无法找回;在 /foundry/api-keys 里撤销并重建一把新 Key 即可(哈希存储保证平台侧也无法恢复明文)。
API Key 的 scopes 会限制访问吗?
暂不限制。scopes 目前只存储与返回(如 verify 接口能查到),authMiddleware 不按 scope 过滤端点访问(scope 闸门已就绪、默认不挂载);Key 是绑定用户的能力代理——按绑定用户 DB 角色判权的端点能力=创建者全集,走 AuthorizeUser 的数据面/动作路径则因空角色注入默认拒绝。接入建议绑定最小权限账号。
OpenAPI 文档和真实接口会不一致吗?
有可能。spec 是手写快照(buildPaths),新增后端路由不更新 spec 不会报错;接入以实际行为为准,发现不一致请反馈后端同步 buildPaths。
离线环境能用 /api/docs/ui 吗?
能看静态清单。Swagger UI 走 CDN,无网络时交互文档不可用,但页面内嵌的路径 / 方法清单表可离线查看。
有官方 SDK 吗?
目前没有。Python / JS / Go 三语言 SDK 均未实现,接入靠手写 REST;OpenAPI spec 可生成客户端桩代码降低成本。独立 API 网关(限流 / 版本路由)也在规划中。
主题小结
一句话:Foundry 用 OpenAPI 文档 + lfk_ API Key 把本体能力开放给机器:密钥创建即一次性、库里只有哈希、Bearer 头零适配。记住三件事:没有官方 SDK、spec 是手写快照、scopes 不强制——接入方案按"手写 REST + 自建防护"来规划。