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::{Usage, metered_usage};
30pub use plans::{Entitlements, Plan, entitlement_allows, min_plan_for};
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}