ai-cortex-sdk
Rust client SDK for the AI Cortex server — PAT 鉴权、设备绑定、软件商店、自动更新(check-update + SSE)、离线许可证(Ed25519 签名)。
Installation
[]
= "0.1"
Quick Start
SDK 用用户 PAT(actx_pat_...)鉴权,PAT 由用户在服务端 web 控制台调 POST /api/access-tokens 创建。
use ;
async
Configuration
let config = new
.with_timeout // 请求超时(秒),默认 30
.with_heartbeat_interval // 心跳间隔(秒);0 = 关闭,默认 60
.without_heartbeat // 或直接关闭心跳
.with_software_public_key; // 钉扎离线许可证公钥
CortexClient::new 会自动启动后台心跳(首次即向服务端绑定当前设备,按该软件许可证的 max_devices 校验上限);Drop 时自动停止心跳。
API Reference
Software Store
| Method | Description |
|---|---|
client.list_software() |
列出所有软件及其最新活动版本 |
client.get_latest_version(software_id) |
取某软件最新版本 |
client.download(version_id) |
取某版本的下载地址(需许可证) |
Auto Update(自动更新)
提供 Pull(主动检查) 与 Push(SSE 订阅) 两种检测方式,互补使用:SSE 做实时通知,Pull 做准确判定 + 断线兜底。两者都需对该 software 持有有效许可证。
| Method | Description |
|---|---|
client.check_update(platform, current_version, channel) |
主动检查更新(Pull),返回 UpdateInfo |
client.open_update_events(software_id, last_event_id) |
打开更新事件 SSE 流(Push),返回 UpdateEventStream |
Pull — check_update
// channel 传 None 默认 "stable"
let info = client.check_update.await?;
// UpdateInfo { has_update, force_update, current_version, target_version: Option<VersionBrief> }
if info.force_update else if info.has_update
Push — open_update_events(SSE 长连接)
服务端发布新版本时通过 GET /api/softwares/sdk-update-events(text/event-stream,PAT 鉴权)主动推送,无需轮询。返回的流配合 futures_util::StreamExt 使用:
use StreamExt;
// software_id 传 None 订阅全部;last_event_id 用于断线重连补播
let mut stream = client.open_update_events.await?;
while let Some = stream.next.await
说明:
- SSE 是长连接,内部用无读超时的 HTTP 客户端(绕过
CortexConfig.timeout的 30s 默认值),靠服务端 15s keepalive 注释帧保活。 - 断线重连时把最后收到的
event.id作为last_event_id传入,服务端补播id > last的事件。 : keepalive/: lagged注释帧由 SDK 内部自动忽略。
Device(设备)
| Method | Description |
|---|---|
device::collect() |
采集当前设备指纹(DeviceIdentity { fingerprint, info }) |
client.list_devices() |
列出当前用户名下绑定的有效设备 |
client.unbind_device(device_id) |
解绑设备(释放名额) |
Error Handling
use SdkError;
match client.check_update.await
Examples
basic.rs— 软件商店浏览 / 下载 / 设备列表auth_check.rs— 校验 PAT 是否有效offline_license.rs— 拉取并验签离线许可证auto_update.rs— 检查更新(Pull)+ 订阅 SSE 事件(Push)
离线许可证
服务端可在 PAT 鉴权下通过 POST /api/offline-licenses/issue 下发一份签名许可证文件,
让客户端在受限网络/断网环境下仍能本地证明自己持有有效授权。文件结构:
payload 是 OfflineLicensePayload 的 snake_case JSON,包含
license_id / user_id / software_id / fingerprint / max_devices / expire_time / issued_at。
签名是对 payload 字符串 UTF-8 字节的 Ed25519 签名。
流程
use ;
// 1. 配置(可选钉扎公钥,增强防替换)
let config = new
.with_software_public_key;
let client = new;
let fp = collect.fingerprint;
// 2. 在线拉取(需联网 + 有效 PAT + 有效软件授权)
let file = client.fetch_offline_license.await?;
// 3. 本地验签:Ed25519 验签 → 解析 payload → 校验 software_id/fingerprint → 校验未过期
let payload = verify_offline_license?;
// 或用 client.verify_offline_license(&file, &fp) 自动带入配置的 software_id 与钉扎公钥
撤销语义与短 TTL
许可证的 expire_time = issued_at + 86400(1 天 TTL)。撤销依赖在线刷新:
许可证本身是自包含签名文件,服务端无法主动吊销已下发的离线文件;通过短 TTL 强制客户端
周期性联网 fetch_offline_license 重新换取。若服务端撤销了用户的软件授权或解绑了该设备指纹,
下一次 fetch 将失败,客户端即失去有效许可证,从而实现“软撤销”。
可选公钥钉扎
默认情况下客户端信任 issue 响应中下发的 public_key(依赖 TLS 保证传输不被篡改)。
对安全敏感场景,可通过 CortexConfig::with_software_public_key(hex) 钉扎一个预期公钥:
设置后 verify_offline_license 会要求下发公钥与之严格相等,否则直接判定为
LicenseFieldMismatch,可防御 TLS 被绕过/中间人替换公钥的攻击。不设置时则退化为信任下发公钥。
校验顺序
verify_offline_license 按以下顺序校验,任一失败立即返回对应 SdkError:
- 公钥钉扎(若提供)——
public_key必须与钉扎值相等 - Ed25519 验签 ——
public_key对payload字节验签 - 解析 payload JSON
- 字段匹配 ——
software_id与fingerprint必须与期望值一致 - 过期校验 ——
expire_time > now
License
MIT(见 LICENSE)。