Skip to main content

lean_ctx/core/billing/
metering.rs

1//! Usage-based metering — OSS stub (ADR-023).
2//!
3//! The full metering implementation (commercial enforcement, settlement
4//! authority checks) lives in `lean-ctx-enterprise/commercial-core`.
5//! This stub preserves the public API surface so OSS code compiles.
6
7use serde::{Deserialize, Serialize};
8
9use crate::core::savings_ledger::{RoiReport, roi_report};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub struct Usage {
13    pub schema_version: u32,
14    pub period: String,
15    pub created_at: String,
16    pub agent_id: String,
17    pub metered_events: usize,
18    pub net_saved_tokens: u64,
19    pub saved_usd: f64,
20    pub last_entry_hash: String,
21    pub chain_valid: bool,
22    pub signed: bool,
23}
24
25impl Usage {
26    pub const SCHEMA_VERSION: u32 = 1;
27
28    #[must_use]
29    pub fn from_roi(roi: &RoiReport) -> Self {
30        Self {
31            schema_version: Self::SCHEMA_VERSION,
32            period: roi.period.clone(),
33            created_at: roi.created_at.clone(),
34            agent_id: roi.agent_id.clone(),
35            metered_events: roi.total_events,
36            net_saved_tokens: roi.net_saved_tokens,
37            saved_usd: roi.saved_usd,
38            last_entry_hash: roi.last_entry_hash.clone(),
39            chain_valid: roi.chain_valid,
40            signed: roi.signed,
41        }
42    }
43
44    #[must_use]
45    pub fn is_billable(&self) -> bool {
46        self.chain_valid && self.signed
47    }
48
49    #[must_use]
50    pub fn source_integrity_verified(&self) -> bool {
51        self.chain_valid && self.signed
52    }
53
54    #[must_use]
55    pub fn headline(&self) -> String {
56        format!(
57            "Usage[{}]: {} events, {} net tokens, ${:.4} (OSS — metering stub)",
58            self.period, self.metered_events, self.net_saved_tokens, self.saved_usd,
59        )
60    }
61}
62
63#[must_use]
64pub fn metered_usage(agent_id: &str) -> Usage {
65    Usage::from_roi(&roi_report(agent_id))
66}