From a0d3f471928e0b1846574708fae331b5fd77c465 Mon Sep 17 00:00:00 2001 From: Keysat Date: Sun, 10 May 2026 07:58:58 -0500 Subject: [PATCH] =?UTF-8?q?v0.3.0=20=E2=80=94=20entitlements=20catalog=20i?= =?UTF-8?q?n=20PublicPoliciesResponse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors keysat 0014 + TS SDK 0.3.0. PublicPoliciesProduct gains entitlements_catalog: Vec with {slug, name, description}. SDK consumers' in-app tier pickers can render display names + tooltip descriptions instead of raw slugs. Empty vec on legacy products without a catalog. No breaking change. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/lib.rs | 5 +++-- src/online.rs | 24 ++++++++++++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d8bdf80..208a71f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -511,7 +511,7 @@ dependencies = [ [[package]] name = "keysat-licensing-client" -version = "0.2.0" +version = "0.3.0" dependencies = [ "data-encoding", "ed25519-dalek", diff --git a/Cargo.toml b/Cargo.toml index cff7d48..668d942 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "keysat-licensing-client" -version = "0.2.0" +version = "0.3.0" edition = "2021" rust-version = "1.75" description = "Client library for Keysat. Verifies signed license keys offline and wraps the HTTP API for purchase and revocation checks." diff --git a/src/lib.rs b/src/lib.rs index c535004..70d56b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,7 @@ pub use verify::{Verifier, VerifyOk}; #[cfg(feature = "online")] pub use online::{ - Client, MachineResponse, PollResponse, PublicPoliciesProduct, PublicPoliciesResponse, - PublicPolicy, PurchaseSession, StartPurchaseOptions, ValidateRequest, ValidateResponse, + Client, EntitlementDef, MachineResponse, PollResponse, PublicPoliciesProduct, + PublicPoliciesResponse, PublicPolicy, PurchaseSession, StartPurchaseOptions, + ValidateRequest, ValidateResponse, }; diff --git a/src/online.rs b/src/online.rs index 6ad9ae1..94d760b 100644 --- a/src/online.rs +++ b/src/online.rs @@ -427,6 +427,24 @@ fn default_one() -> i64 { 1 } +/// One entry in a product's entitlements catalog. Operator declares +/// the closed list once per product; policies pick from this list. +/// Use [`EntitlementDef::name`] as the human-readable label when +/// rendering an in-app tier picker (e.g. "AI summaries" instead of +/// the raw `ai_summaries` slug). +#[derive(Debug, Clone, Deserialize)] +pub struct EntitlementDef { + /// Stable identifier — what the SDK's `has_entitlement(slug)` + /// checks against and what gets baked into the signed payload. + pub slug: String, + /// Operator-set display label. Falls back to slug if empty. + #[serde(default)] + pub name: String, + /// Optional one-sentence tooltip. Empty when unset. + #[serde(default)] + pub description: String, +} + /// Product-level fields included in the public-policies response. #[derive(Debug, Clone, Deserialize)] pub struct PublicPoliciesProduct { @@ -440,6 +458,12 @@ pub struct PublicPoliciesProduct { /// Product's base price in sats. Tiers may override via /// [`PublicPolicy::price_sats`]. pub base_price_sats: i64, + /// Closed list of entitlements this product offers, with display + /// names + descriptions for buyer-facing rendering. Empty vec + /// when the operator hasn't defined a catalog (legacy "free-text" + /// mode). + #[serde(default)] + pub entitlements_catalog: Vec, } /// Response from `/v1/products//policies`.