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. Its frozen v1
18//! `is_billable` predicate means source integrity only; it is not settlement
19//! authority.
20//! * [`settlement_evidence`](crate::core::billing::settlement_evidence) — bounded,
21//! payload-free v2 evidence reconciliation.
22//! It never calculates prices, approves customers, decides disputes, or
23//! issues invoices.
24//!
25//! Crucially, this module computes and *describes* commercial state; it never
26//! enforces anything against the local plane. Enforcement (checkout, plan
27//! gating) lives on the hosted control plane, which is the only place an
28//! account/plan is consulted. The local engine has **no entitlement checks** —
29//! asserted by `tests/local_free_invariant.rs`.
30
31pub mod metering;
32pub mod plans;
33pub mod settlement_evidence;
34
35pub use metering::{Usage, metered_usage};
36pub use plans::{Entitlements, Plan, entitlement_allows, min_plan_for};
37pub use settlement_evidence::{
38 SettlementEligibilityV2, SettlementEvidenceManifestV2, reconcile_settlement_evidence_v2,
39};
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44 use crate::core::server_capabilities::{LOCAL_ALWAYS_ON_FEATURES, LOCAL_OPTIONAL_FEATURES};
45
46 #[test]
47 fn no_local_feature_is_gated_by_any_plan() {
48 // The whole point: local capabilities (always-on *and* compile-optional)
49 // are never restricted by a commercial plan.
50 for plan in Plan::all() {
51 for feature in LOCAL_ALWAYS_ON_FEATURES
52 .iter()
53 .chain(LOCAL_OPTIONAL_FEATURES.iter())
54 {
55 assert!(
56 entitlement_allows(*plan, feature),
57 "local feature '{feature}' gated on plan {plan:?}"
58 );
59 }
60 }
61 }
62
63 #[test]
64 fn commercial_entitlements_exist_only_above_free() {
65 // Commercial entitlements (ADR-023: enforcement in lean-ctx-enterprise).
66 // gates are the hosted/governance entitlement keys. Free grants none of
67 // them; higher plans add them. This keeps the plan ladder honest.
68 assert!(!entitlement_allows(Plan::Free, "sso_scim"));
69 assert!(entitlement_allows(Plan::Enterprise, "sso_scim"));
70 assert!(entitlement_allows(Plan::Team, "private_registry"));
71 assert!(!entitlement_allows(Plan::Free, "private_registry"));
72 }
73}