v0.2.0:42 — revert implicit Patron→Pro expansion from :41

The only affected license was the operator's own pre-launch
self-license under an earlier entitlement scheme. New Patron licenses
issued from the corrected master-Keysat policy carry the right
entitlements in their signed payload. The implicit expansion was
paying ongoing complexity (magic-slug behavior, hardcoded list
divergence on rename) for a one-shot migration case.

Affected operators: re-issue + Activate Keysat license. The new key
overwrites /data/keysat-license.txt and self_tier picks up live
without a restart.
This commit is contained in:
Grant
2026-05-12 12:27:18 -05:00
parent a3662de6d8
commit 17d5df72d3
2 changed files with 4 additions and 26 deletions
+1 -25
View File
@@ -90,36 +90,12 @@ impl TierInfo {
/// to be fixed.
pub async fn current(state: &AppState) -> TierInfo {
let tier = state.self_tier.read().await;
let mut entitlements = match &*tier {
let entitlements = match &*tier {
Tier::Licensed { entitlements, .. } => entitlements.clone(),
Tier::Unlicensed { .. } => Vec::new(),
};
drop(tier);
// Patron implies Pro by design (see module docstring: "Patron: same
// feature surface as Pro, plus a `patron` entitlement..."). Without
// this expansion, every downstream `tier.has(<pro-entitlement>)`
// check requires the Patron POLICY on the master Keysat to
// redundantly list every Pro entitlement. That's brittle: a single
// missing slug on the policy (e.g. operator forgets
// `zaprite_payments`) breaks Pro-equivalence for every Patron
// customer. Treating `patron` as a strict superset of Pro at the
// resolution layer means policy authors can list `patron` alone
// and have everything Pro grants flow through automatically.
if entitlements.iter().any(|e| e == "patron") {
for implied in [
"unlimited_products",
"unlimited_policies",
"unlimited_codes",
"recurring_billing",
"zaprite_payments",
] {
if !entitlements.iter().any(|e| e == implied) {
entitlements.push(implied.to_string());
}
}
}
let label: &'static str;
let display_name: &'static str;
if entitlements.iter().any(|e| e == "patron") {