v0.3.0 — entitlements catalog in PublicPoliciesResponse

Mirrors keysat 0014 + TS SDK 0.3.0. PublicPoliciesProduct gains
entitlements_catalog: Vec<EntitlementDef> 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.
This commit is contained in:
Keysat
2026-05-10 07:58:58 -05:00
parent 5dd301cd69
commit a0d3f47192
4 changed files with 29 additions and 4 deletions
Generated
+1 -1
View File
@@ -511,7 +511,7 @@ dependencies = [
[[package]] [[package]]
name = "keysat-licensing-client" name = "keysat-licensing-client"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"data-encoding", "data-encoding",
"ed25519-dalek", "ed25519-dalek",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "keysat-licensing-client" name = "keysat-licensing-client"
version = "0.2.0" version = "0.3.0"
edition = "2021" edition = "2021"
rust-version = "1.75" rust-version = "1.75"
description = "Client library for Keysat. Verifies signed license keys offline and wraps the HTTP API for purchase and revocation checks." description = "Client library for Keysat. Verifies signed license keys offline and wraps the HTTP API for purchase and revocation checks."
+3 -2
View File
@@ -47,6 +47,7 @@ pub use verify::{Verifier, VerifyOk};
#[cfg(feature = "online")] #[cfg(feature = "online")]
pub use online::{ pub use online::{
Client, MachineResponse, PollResponse, PublicPoliciesProduct, PublicPoliciesResponse, Client, EntitlementDef, MachineResponse, PollResponse, PublicPoliciesProduct,
PublicPolicy, PurchaseSession, StartPurchaseOptions, ValidateRequest, ValidateResponse, PublicPoliciesResponse, PublicPolicy, PurchaseSession, StartPurchaseOptions,
ValidateRequest, ValidateResponse,
}; };
+24
View File
@@ -427,6 +427,24 @@ fn default_one() -> i64 {
1 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. /// Product-level fields included in the public-policies response.
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct PublicPoliciesProduct { pub struct PublicPoliciesProduct {
@@ -440,6 +458,12 @@ pub struct PublicPoliciesProduct {
/// Product's base price in sats. Tiers may override via /// Product's base price in sats. Tiers may override via
/// [`PublicPolicy::price_sats`]. /// [`PublicPolicy::price_sats`].
pub base_price_sats: i64, 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<EntitlementDef>,
} }
/// Response from `/v1/products/<slug>/policies`. /// Response from `/v1/products/<slug>/policies`.