Skip to main content

bctx_cloud_core/client/
upgrade.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
4#[serde(rename_all = "lowercase")]
5pub enum Tier {
6    Free,
7    Beacon,
8    Studio,
9    Enterprise,
10}
11
12impl Tier {
13    pub fn parse_tier(s: &str) -> Self {
14        match s {
15            "beacon" => Tier::Beacon,
16            "studio" => Tier::Studio,
17            "enterprise" => Tier::Enterprise,
18            _ => Tier::Free,
19        }
20    }
21
22    pub fn vault_fact_limit(&self) -> Option<usize> {
23        match self {
24            Tier::Free => Some(500),
25            Tier::Beacon => Some(10_000),
26            Tier::Studio | Tier::Enterprise => None,
27        }
28    }
29
30    pub fn cloud_token_quota(&self) -> Option<u64> {
31        match self {
32            Tier::Free => None,
33            Tier::Beacon => Some(100_000),
34            Tier::Studio => Some(1_000_000),
35            Tier::Enterprise => None,
36        }
37    }
38
39    pub fn cloud_sync_enabled(&self) -> bool {
40        matches!(self, Tier::Beacon | Tier::Studio | Tier::Enterprise)
41    }
42
43    pub fn team_vault_enabled(&self) -> bool {
44        matches!(self, Tier::Studio | Tier::Enterprise)
45    }
46
47    pub fn upgrade_url(&self) -> &'static str {
48        "https://betterctx.com/upgrade"
49    }
50
51    /// Customer-facing tier name. Enterprise is a contact-sales tier shown as
52    /// "Let's Talk" rather than a self-serve plan name.
53    pub fn display_name(&self) -> &'static str {
54        match self {
55            Tier::Free => "Free",
56            Tier::Beacon => "Beacon+",
57            Tier::Studio => "Studio",
58            Tier::Enterprise => "Let's Talk",
59        }
60    }
61}
62
63/// Check whether the current tier allows an action and return an upgrade prompt if not.
64pub fn gate(tier: &Tier, required: &Tier, feature: &str) -> Result<(), String> {
65    if tier >= required {
66        Ok(())
67    } else {
68        Err(format!(
69            "{feature} requires the {} tier. Upgrade at {}",
70            required.display_name(),
71            tier.upgrade_url()
72        ))
73    }
74}