Skip to main content

lean_ctx/core/billing/
mod.rs

1//! Commercial-plane billing substrate (`billing-plane-v1`, EPIC 13.6).
2//!
3//! Turns the existing plan-upgrade flow into **real plans + entitlements** plus
4//! **usage-based metering** derived from the signed savings ledger (EPIC 12.20)
5//! — without touching the local experience.
6//!
7//! ## Two halves, one invariant
8//!
9//! * [`plans`](crate::core::billing::plans) — the plan catalog and their
10//!   [`Entitlements`](crate::core::billing::Entitlements). Commercial, additive.
11//!   [`entitlement_allows`](crate::core::billing::entitlement_allows) expresses
12//!   the **Local-Free Invariant**: every local-always-on capability is allowed
13//!   on every plan, including [`Plan::Free`](crate::core::billing::Plan::Free).
14//!   No local feature is ever gated.
15//! * [`metering`](crate::core::billing::metering) —
16//!   [`Usage`](crate::core::billing::Usage) derived read-only from the
17//!   privacy-preserving, Ed25519-signed ledger aggregate. Only signed + intact
18//!   chains are billable.
19//!
20//! Crucially, this module computes and *describes* commercial state; it never
21//! enforces anything against the local plane. Enforcement (checkout, plan
22//! gating) lives on the hosted control plane, which is the only place an
23//! account/plan is consulted. The local engine has **no entitlement checks** —
24//! asserted by `tests/local_free_invariant.rs`.
25
26pub mod metering;
27pub mod plans;
28
29pub use metering::{metered_usage, Usage};
30pub use plans::{entitlement_allows, min_plan_for, Entitlements, Plan};
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35    use crate::core::server_capabilities::{LOCAL_ALWAYS_ON_FEATURES, LOCAL_OPTIONAL_FEATURES};
36
37    #[test]
38    fn no_local_feature_is_gated_by_any_plan() {
39        // The whole point: local capabilities (always-on *and* compile-optional)
40        // are never restricted by a commercial plan.
41        for plan in Plan::all() {
42            for feature in LOCAL_ALWAYS_ON_FEATURES
43                .iter()
44                .chain(LOCAL_OPTIONAL_FEATURES.iter())
45            {
46                assert!(
47                    entitlement_allows(*plan, feature),
48                    "local feature '{feature}' gated on plan {plan:?}"
49                );
50            }
51        }
52    }
53
54    #[test]
55    fn commercial_entitlements_exist_only_above_free() {
56        // Self-hosting (team_server/cloud_server) stays free; the real commercial
57        // gates are the hosted/governance entitlement keys. Free grants none of
58        // them; higher plans add them. This keeps the plan ladder honest.
59        assert!(!entitlement_allows(Plan::Free, "sso_scim"));
60        assert!(entitlement_allows(Plan::Enterprise, "sso_scim"));
61        assert!(entitlement_allows(Plan::Team, "private_registry"));
62        assert!(!entitlement_allows(Plan::Free, "private_registry"));
63    }
64}