v0.2.0:41 — Patron implies Pro; BTCPay Connect back to one-click authorize
Patron entitlement now expands to the full Pro surface (unlimited_products / _policies / _codes, recurring_billing, zaprite_payments) in tier::current(). Existing Patron customers get the implied entitlements without re-issuing. BTCPay Connect: replace the four-field paste form (Base URL + API key + Store id + Webhook secret) with the original one-click button that fetches an authorize URL from /v1/admin/btcpay/connect, opens it in a new tab, and polls /v1/admin/btcpay/status until the BTCPay callback finishes. Zaprite path unchanged.
This commit is contained in:
@@ -90,12 +90,36 @@ impl TierInfo {
|
||||
/// to be fixed.
|
||||
pub async fn current(state: &AppState) -> TierInfo {
|
||||
let tier = state.self_tier.read().await;
|
||||
let entitlements = match &*tier {
|
||||
let mut 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") {
|
||||
|
||||
Reference in New Issue
Block a user