业务故事站
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 限制端点;API Key 注入空角色,写路径动作默认拒绝。

场景故事

故事 1 给报表系统开一把 Key:明文只给一次,库里只有哈希
背景
运营的日报系统要每天凌晨自动从 Foundry 拉订单数据。平台管理员打开 /foundry/api-keys 页面,为报表系统创建一把 API Key(name="日报系统"),并记下创建响应里的一次性明文。
传统做法对比
以前要么把管理员密码给报表系统(权限过大、还耦合登录态),要么共用账号(无法区分调用方);现在一把 lfk_ Key 绑定专属用户,可独立撤销,库里只存 SHA256 哈希,即使库被拖走也拿不到明文。
角色
平台管理员(创建 / 保管 Key);日报系统(消费方)。
操作步骤
  1. 登录 /foundry/api-keys 页,点创建 Key
  2. 填 name="日报系统"(可选 scopes 如 ontology:read)
  3. 复制创建响应里的一次性明文,立即保存
  4. 把 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 目前只存不强制;API Key 认证注入空角色,写路径 Action 默认拒绝,只适合只读/演示。
故事 2 开发按 OpenAPI 文档接入:122 条路径 / 189 个操作一次看清
背景
开发工程师小唐要写一个脚本批量读取指标目录。他不翻代码,直接打开 GET /api/docs 拿到 OpenAPI 3.0.3 spec,或用浏览器打开 /api/docs/ui 开发者门户页,看接口路径、参数与统一响应结构。
传统做法对比
以前接口文档靠"找后端同事问",权限参数全靠猜,改一个字段要来回对齐半天;现在 spec 一次给全:路径、方法、参数、统一 code=0 响应,机器可读,还能直接生成客户端。
角色
开发工程师(读文档 + 写调用脚本);后端(维护 buildPaths)。
操作步骤
  1. GET http://127.0.0.1:18081/api/docs 拉 spec JSON
  2. 或浏览器打开 /api/docs/ui 看交互页(网络可用时加载 Swagger UI)
  3. 定位 /metrics/catalog 等目标接口,确认方法与参数
  4. 按统一响应结构写解析代码
系统响应
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 打通对象查询
背景
日报系统拿到 lfk_ Key 后,每天凌晨调用对象语义查询拉订单数据。开发小唐先用 GET /api-keys/verify 验证 Key 有效性,再用 Authorization: Bearer lfk_... 调 /ontology/objects/:id/query。
传统做法对比
以前机器调用要维护 JWT 登录态、处理 Token 过期刷新,多一套流程;现在 lfk_ Key 直接放进 Bearer 头,authMiddleware 按前缀自动分流到 API Key 认证,机器调用零额外适配。
角色
开发工程师(写定时拉数脚本);认证中间件(按 lfk_ 前缀分流)。
操作步骤
  1. GET /api/v1/api-keys/verify?key=lfk_... 验证有效
  2. 构造查询请求体(对象类型 id + filters)
  3. 带 Authorization: Bearer lfk_... 调用 /ontology/objects/:id/query
  4. 按统一响应解析 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,边界先讲清楚
背景
集成项目会上,开发小唐问"有没有 Python / JS / Go 的 SDK 可以 pip install / npm install?"平台管理员查了一下 Foundry 的实现范围,如实回答:目前没有官方 SDK,只有手写 OpenAPI 文档 + lfk_ API Key,接入靠直接写 REST 调用。
传统做法对比
以前很多平台文档把 SDK 画在路线图里,集成方默认"应该有",结果对接时才发现要手搓;这次先把边界讲清楚:没有 SDK 就用统一响应 + spec 自己封装,避免集成方踩坑。
角色
开发工程师(确认接入方式);平台管理员(确认能力边界)。
操作步骤
  1. 确认仓库中无 lightfoundry-sdk 等包(pip / npm / go get 均无)
  2. 评估手写 REST 的接入成本(统一响应 + spec 可生成客户端桩)
  3. 评估限流 / 网关需求(当前无 429 限流,需自建防护)
  4. 记录边界到集成方案里,后续 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 过滤端点访问;且 API Key 注入空角色,写路径动作默认拒绝,只适合只读/演示。

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 + 自建防护"来规划。