g1t/services/billing/src/margin.rs

2,093 lines98,306 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1//! What g1t earns on each thing it sells, measured against what
2//! Cloudflare actually charged for it.
3//!
4//! Once a day, after `costs` has read Cloudflare's bill, the reconciler
5//! puts three figures side by side for every day and each of g1t's
6//! products (a "bucket": sandboxes, deployments, git, repository storage,
7//! …):
8//!
9//! 1. **What Cloudflare charged**: the day's cost lines `cost_map` gives
10//! the bucket.
11//! 2. **What g1t's meters recorded**: the cost on the ledger's entries for
12//! it (the price book's cost at the time) and, where a mapping names
13//! one, g1t's own count of the same units (git operations).
14//! 3. **What customers were charged**: the entries' value at price, before
15//! the plan's included usage, a trial or a pool paid part of it; and of
16//! that, what workspaces paid. Month-end meters (git, storage, scans,
17//! embeddings, the actions cache) come from daily snapshots of what they
18//! had come to (`pending_days`). The plan's price is the `platform`
19//! bucket's: the plan pays for running g1t.
20//!
21//! From those: margin per product (value against cost) and for all of g1t
22//! (money in against every cost); drift (counts or costs that disagree past
23//! a mapping's threshold, and leaks: cost with no revenue, or a Cloudflare
24//! meter no one mapped); each workspace's cost, Cloudflare's figure shared
25//! out by each workspace's own meters; and price proposals when a unit's
26//! real cost has moved (`pricing`). Alerts go to staff by email and as a
27//! banner in sudo. See docs/BILLING_OPERATIONS.md.
28
29use std::collections::{BTreeMap, BTreeSet};
30
31use g1t_contracts::billing::*;
32use g1t_contracts::{FailureCode, Outcome, new_id};
33use g1t_contracts::time::rfc3339;
34use g1t_kit::now_ms;
35use serde::{Deserialize, Serialize};
36use worker::wasm_bindgen::JsValue;
37use worker::{Env, Result};
38
39use crate::Billing;
40use crate::costs::{self, ARTIFACTS_OPERATIONS, DAY_MS, Rule, SOURCE_ARTIFACTS, SOURCE_BILLABLE, UNMAPPED};
41
42/// Buckets that are the cost of running g1t, paid by the plan rather than
43/// sold by the unit: never a leak for having no revenue of their own.
44pub(crate) const OVERHEAD: [&str; 1] = ["platform"];
45/// Buckets Cloudflare does not bill: their cost is g1t's own figure.
46pub(crate) const NOT_CLOUDFLARE: [&str; 1] = ["models"];
47/// The days drift is judged over.
48const DRIFT_DAYS: u64 = 7;
49/// The days a workspace's cost is set against its revenue.
50const ANOMALY_DAYS: u64 = 30;
51/// The days a unit's cost is measured over.
52const MEASURE_DAYS: u64 = 30;
53/// Fewer of g1t's units than this say nothing about cost per unit.
54const MIN_UNITS: f64 = 1_000.0;
55/// An open alert is emailed again after this long.
56const REMIND_MS: u64 = 7 * DAY_MS;
57
58// ---------------------------------------------------------------------
59// The arithmetic, apart from the database so it can be tested.
60// ---------------------------------------------------------------------
61
62/// One of g1t's products on one day.
63#[derive(Clone, Debug, Default, PartialEq)]
64pub(crate) struct ProductDay {
65 pub day: String,
66 pub bucket: String,
67 /// What Cloudflare charged g1t, in millionths of a dollar.
68 pub cf_cost_micros: i64,
69 /// What g1t's meters recorded it cost (the price book's cost).
70 pub own_cost_micros: i64,
71 /// What customers were charged for it at price, before what paid.
72 pub value_micros: i64,
73 /// Of that, what workspaces paid themselves.
74 pub cash_micros: i64,
75 /// Units Cloudflare counted and units g1t counted, where a mapping
76 /// says they are the same units.
77 pub cf_quantity: f64,
78 pub own_quantity: f64,
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it79 /// Of `cost()`, what went on usage g1t gave away (the workspaces'
80 /// `WorkspaceDay::given`, added up).
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running81 pub given: Given,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily82}
83
84impl ProductDay {
85 /// What it cost: Cloudflare's figure where Cloudflare bills it, else
86 /// g1t's own (models are billed by their providers, through the gateway).
87 pub fn cost(&self) -> i64 {
88 if NOT_CLOUDFLARE.contains(&self.bucket.as_str()) { self.own_cost_micros } else { self.cf_cost_micros }
89 }
90}
91
92/// A line of Cloudflare's bill, as stored.
93#[derive(Clone, Debug, Deserialize)]
94pub(crate) struct LineRow {
95 pub day: String,
96 pub source: String,
97 pub product: String,
98 pub meter: String,
99 pub quantity: f64,
100 pub cost_usd: f64,
101}
102
103/// A count of g1t's own, as stored.
104#[derive(Clone, Debug, Deserialize)]
105pub(crate) struct OwnRow {
106 pub day: String,
107 pub meter: String,
108 pub workspace: String,
109 pub quantity: f64,
110}
111
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running112/// What g1t gave away, by why: its own comped workspaces, free use (a
113/// free period, free allowances, overruns g1t covered), the trial, and the
Merge branch 'worktree-agent-a633ac0f7f66d419d'114/// open-source pool, and discounts on an account's terms (what they took
115/// below cost plus the margin, `ledger.discount_micros`). The Team plan's
116/// included usage is paid for by the plan's price, so it is sold, not given.
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running117#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
118pub(crate) struct Given {
119 pub comped: i64,
120 pub free: i64,
121 pub trial: i64,
122 pub pool: i64,
Merge branch 'worktree-agent-a633ac0f7f66d419d'123 pub discount: i64,
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running124}
125
126impl Given {
127 pub fn total(&self) -> i64 {
Merge branch 'worktree-agent-a633ac0f7f66d419d'128 self.comped + self.free + self.trial + self.pool + self.discount
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running129 }
130
131 fn add(&mut self, other: &Given) {
132 self.comped += other.comped;
133 self.free += other.free;
134 self.trial += other.trial;
135 self.pool += other.pool;
Merge branch 'worktree-agent-a633ac0f7f66d419d'136 self.discount += other.discount;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running137 }
138
139 /// The same shares of `cost` as these are of `value`, at most all of it.
140 fn of(&self, cost: i64, value: i64) -> Given {
141 let total = self.total();
142 if value <= 0 || cost <= 0 || total <= 0 {
143 return Given::default();
144 }
145 let given = cost as i128 * total.min(value) as i128 / value as i128;
146 let part = |x: i64| (given * x.max(0) as i128 / total as i128) as i64;
Merge branch 'worktree-agent-a633ac0f7f66d419d'147 Given {
148 comped: part(self.comped),
149 free: part(self.free),
150 trial: part(self.trial),
151 pool: part(self.pool),
152 discount: part(self.discount),
153 }
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running154 }
155}
156
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily157/// What a workspace was charged for one key on one day.
158#[derive(Clone, Debug, Default, PartialEq)]
159pub(crate) struct UsageRow {
160 pub day: String,
161 pub workspace: String,
162 /// A ledger task (or `builds`), a month-end source, or `plan`.
163 pub key: String,
164 pub value: i64,
165 pub cash: i64,
166 pub cost: i64,
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it167 /// Of `value`, what g1t gave away: all of it for g1t's own (comped)
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running168 /// workspaces and in a free period, else what the trial and the pool
169 /// paid and the overruns g1t covered.
170 pub given: Given,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily171}
172
173/// One workspace's share of a product's cost on one day.
174#[derive(Clone, Debug, PartialEq)]
175pub(crate) struct WorkspaceDay {
176 pub day: String,
177 pub workspace: String,
178 pub bucket: String,
179 pub cost: i64,
Margin alerts measure what is sold, and say dollars when a percentage would mislead180 /// What the workspace paid in cash.
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily181 pub revenue: i64,
Margin alerts measure what is sold, and say dollars when a percentage would mislead182 /// What its usage was priced at, whoever paid for it.
183 pub value: i64,
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running184 /// Of `cost`, the part g1t gave away: all of it for a comped workspace
185 /// or one with nothing priced that day (free use), else the cost times
186 /// the shares of its usage that day that g1t paid for.
187 pub given: Given,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily188}
189
190fn micros(dollars: f64) -> i64 {
191 (dollars * 1_000_000.0).round() as i64
192}
193
194/// Puts the day's bill, g1t's counts and what customers were charged side
195/// by side, a row per day and bucket, and shares each bucket's cost out
196/// to workspaces.
197pub(crate) fn fold(
198 rules: &[Rule],
199 revenue_map: &BTreeMap<String, String>,
200 lines: &[LineRow],
201 own: &[OwnRow],
202 usage: &[UsageRow],
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running203 internal: &BTreeSet<String>,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily204) -> (Vec<ProductDay>, Vec<WorkspaceDay>) {
205 let mut days: BTreeMap<(String, String), ProductDay> = BTreeMap::new();
206 let entry = |day: &str, bucket: &str| -> ProductDay {
207 ProductDay { day: day.to_owned(), bucket: bucket.to_owned(), ..ProductDay::default() }
208 };
209 // Which of g1t's own meters count each bucket's units.
210 let mut own_meters: BTreeMap<&str, BTreeSet<&str>> = BTreeMap::new();
211 for rule in rules {
212 if let Some(meter) = &rule.own_meter {
213 own_meters.entry(rule.bucket.as_str()).or_default().insert(meter.as_str());
214 }
215 }
216 let mut events: BTreeMap<(String, String), f64> = BTreeMap::new();
217 for line in lines {
218 let rule = costs::classify(rules, &line.product, &line.meter);
219 let bucket = rule.map_or(UNMAPPED, |r| r.bucket.as_str());
220 let key = (line.day.clone(), bucket.to_owned());
221 if line.source == SOURCE_ARTIFACTS {
222 // What Artifacts counted: operations only, and only where the
223 // bill does not count them itself.
224 if ARTIFACTS_OPERATIONS.contains(&line.meter.as_str()) {
225 *events.entry(key).or_default() += line.quantity;
226 }
227 continue;
228 }
229 let row = days.entry(key.clone()).or_insert_with(|| entry(&key.0, &key.1));
230 row.cf_cost_micros += micros(line.cost_usd);
231 if line.source == SOURCE_BILLABLE && rule.is_some_and(|r| r.own_meter.is_some()) {
232 row.cf_quantity += line.quantity;
233 }
234 }
235 for (key, quantity) in events {
236 let row = days.entry(key.clone()).or_insert_with(|| entry(&key.0, &key.1));
237 if row.cf_quantity == 0.0 {
238 row.cf_quantity = quantity;
239 }
240 }
241 // g1t's own counts of the same units, by bucket and by workspace.
242 let mut own_by: BTreeMap<(String, String), Vec<(String, f64)>> = BTreeMap::new();
243 // Cloudflare's own count by workspace, where it gives one
244 // (`cloudflare_<bucket>`): the best way to share its cost.
245 let mut cf_by: BTreeMap<(String, String), Vec<(String, f64)>> = BTreeMap::new();
246 for count in own {
247 if let Some(bucket) = count.meter.strip_prefix("cloudflare_") {
248 cf_by.entry((count.day.clone(), bucket.to_owned())).or_default().push((count.workspace.clone(), count.quantity));
249 continue;
250 }
251 for (bucket, meters) in &own_meters {
252 if meters.contains(count.meter.as_str()) {
253 let key = (count.day.clone(), (*bucket).to_owned());
254 days.entry(key.clone()).or_insert_with(|| entry(&key.0, &key.1)).own_quantity += count.quantity;
255 own_by.entry(key).or_default().push((count.workspace.clone(), count.quantity));
256 }
257 }
258 }
259 // What customers were charged.
260 let bucket_of = |key: &str| revenue_map.get(key).cloned().unwrap_or_else(|| "models".to_owned());
261 let mut value_by: BTreeMap<(String, String), Vec<(String, f64)>> = BTreeMap::new();
262 let mut cost_by: BTreeMap<(String, String), Vec<(String, f64)>> = BTreeMap::new();
263 let mut revenue: BTreeMap<(String, String, String), i64> = BTreeMap::new();
Margin alerts measure what is sold, and say dollars when a percentage would mislead264 let mut valued: BTreeMap<(String, String, String), i64> = BTreeMap::new();
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily265 let mut active: BTreeMap<String, Vec<(String, f64)>> = BTreeMap::new();
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running266 let mut gave: BTreeMap<(String, String), (Given, i64)> = BTreeMap::new();
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily267 for u in usage {
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it268 let g = gave.entry((u.day.clone(), u.workspace.clone())).or_default();
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running269 g.0.add(&u.given);
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it270 g.1 += u.value;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily271 let bucket = bucket_of(&u.key);
272 let key = (u.day.clone(), bucket.clone());
273 let row = days.entry(key.clone()).or_insert_with(|| entry(&key.0, &key.1));
274 row.own_cost_micros += u.cost;
275 row.value_micros += u.value;
276 row.cash_micros += u.cash;
277 value_by.entry(key.clone()).or_default().push((u.workspace.clone(), u.value as f64));
278 cost_by.entry(key).or_default().push((u.workspace.clone(), u.cost as f64));
Margin alerts measure what is sold, and say dollars when a percentage would mislead279 *revenue.entry((u.day.clone(), u.workspace.clone(), bucket.clone())).or_default() += u.cash;
280 *valued.entry((u.day.clone(), u.workspace.clone(), bucket)).or_default() += u.value;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily281 active.entry(u.day.clone()).or_default().push((u.workspace.clone(), u.value.max(u.cost) as f64));
282 }
283 // Each bucket's cost shared out: by Cloudflare's own count per
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running284 // workspace, else by g1t's own count of its units, else by what its
285 // usage cost (so free use carries its own cost), else by what it was
286 // charged; running g1t, and what no one mapped, by each workspace's
287 // share of all usage that day.
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily288 let mut shares: BTreeMap<(String, String, String), i64> = BTreeMap::new();
289 for ((day, bucket), row) in &days {
290 let key = (day.clone(), bucket.clone());
291 let weigh = |m: &BTreeMap<(String, String), Vec<(String, f64)>>| m.get(&key).filter(|w| w.iter().any(|(_, v)| *v > 0.0)).cloned();
292 let weights = if OVERHEAD.contains(&bucket.as_str()) || bucket == UNMAPPED {
293 active.get(day).cloned()
294 } else {
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running295 weigh(&cf_by).or_else(|| weigh(&own_by)).or_else(|| weigh(&cost_by)).or_else(|| weigh(&value_by)).or_else(|| active.get(day).cloned())
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily296 };
297 for (workspace, micros) in attribute(row.cost(), &weights.unwrap_or_default()) {
298 *shares.entry((day.clone(), workspace, bucket.clone())).or_default() += micros;
299 }
300 }
301 let keys: BTreeSet<(String, String, String)> = shares.keys().chain(revenue.keys()).cloned().collect();
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it302 let workspaces: Vec<WorkspaceDay> = keys
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily303 .into_iter()
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it304 .map(|(day, workspace, bucket)| {
305 let cost = shares.get(&(day.clone(), workspace.clone(), bucket.clone())).copied().unwrap_or(0);
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running306 // The day's shares given away apply to every bucket, so a
307 // comped workspace's part of running g1t is given too. A
308 // workspace with nothing priced that day used g1t for free.
309 let given = if internal.contains(&workspace) {
310 Given { comped: cost, ..Given::default() }
311 } else {
312 match gave.get(&(day.clone(), workspace.clone())) {
313 Some((given, value)) if *value > 0 => given.of(cost, *value),
314 _ => Given { free: cost.max(0), ..Given::default() },
315 }
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it316 };
317 WorkspaceDay {
318 cost,
319 revenue: revenue.get(&(day.clone(), workspace.clone(), bucket.clone())).copied().unwrap_or(0),
320 value: valued.get(&(day.clone(), workspace.clone(), bucket.clone())).copied().unwrap_or(0),
321 given,
322 day,
323 workspace,
324 bucket,
325 }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily326 })
327 .collect();
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it328 for w in &workspaces {
329 if let Some(row) = days.get_mut(&(w.day.clone(), w.bucket.clone())) {
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running330 row.given.add(&w.given);
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it331 }
332 }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily333 (days.into_values().collect(), workspaces)
334}
335
336/// A month-end source's day, from the snapshots of what it had come to:
337/// each day's figure less the day before's in the same month (the first
338/// day of a month, or the first snapshot, is its own).
339pub(crate) fn pending_deltas(snapshots: &[(String, String, String, i64, i64)]) -> Vec<UsageRow> {
340 // (day, workspace, source, cost, charge), any order.
341 let mut sorted = snapshots.to_vec();
342 sorted.sort_by(|a, b| (&a.1, &a.2, &a.0).cmp(&(&b.1, &b.2, &b.0)));
343 let mut out = Vec::new();
344 let mut previous: Option<&(String, String, String, i64, i64)> = None;
345 for snap in &sorted {
346 let (day, workspace, source, cost, charge) = snap;
347 let (before_cost, before_charge) = match previous {
348 Some(p) if p.1 == *workspace && p.2 == *source && p.0[..7] == day[..7] => (p.3, p.4),
349 _ => (0, 0),
350 };
351 let (cost, charge) = ((cost - before_cost).max(0), (charge - before_charge).max(0));
352 if cost > 0 || charge > 0 {
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running353 out.push(UsageRow { day: day.clone(), workspace: workspace.clone(), key: source.clone(), value: charge, cash: charge, cost, given: Given::default() });
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily354 }
355 previous = Some(snap);
356 }
357 out
358}
359
360/// Margin as a share of what was charged, in percent; None when nothing was.
361pub(crate) fn margin_percent(revenue_micros: i64, cost_micros: i64) -> Option<f64> {
362 (revenue_micros > 0).then(|| (revenue_micros - cost_micros) as f64 * 100.0 / revenue_micros as f64)
363}
364
365/// How far `ours` is from `theirs`, in percent of theirs; None when theirs
366/// is nothing.
367pub(crate) fn delta_percent(ours: f64, theirs: f64) -> Option<f64> {
368 (theirs > 0.0).then(|| (ours - theirs) * 100.0 / theirs)
369}
370
371#[derive(Clone, Copy, Debug, PartialEq, Eq)]
372pub(crate) enum DriftKind {
373 /// g1t counted a different number of units than Cloudflare did.
374 Count,
375 /// What Cloudflare charged differs from what the price book says the
376 /// same usage cost.
377 Cost,
378 /// Cloudflare charged for something nothing charges customers for.
379 Leak,
Merge branch 'worktree-agent-a633ac0f7f66d419d'380 /// Model usage AI Gateway put no price on: its cost is not what the
381 /// provider bills, so neither the ledger nor the gateway total has it.
382 Unpriced,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily383}
384
385impl DriftKind {
386 pub fn as_str(self) -> &'static str {
387 match self {
388 DriftKind::Count => "count",
389 DriftKind::Cost => "cost",
390 DriftKind::Leak => "leak",
Merge branch 'worktree-agent-a633ac0f7f66d419d'391 DriftKind::Unpriced => "unpriced",
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily392 }
393 }
394}
395
396#[derive(Clone, Debug, PartialEq)]
397pub(crate) struct Drift {
398 pub bucket: String,
399 pub kind: DriftKind,
400 pub ours: f64,
401 pub cloudflare: f64,
402 pub delta_percent: Option<f64>,
403}
404
405/// Drift over a window for one bucket: counts more than `threshold`
406/// percent apart, a bill that far from the price book's cost of the same
407/// usage, and cost with nothing charged for it. Under `min_cost_micros`
408/// in all, cost says nothing.
409pub(crate) fn drifts(bucket: &str, days: &[ProductDay], threshold: f64, counted: bool, min_cost_micros: i64) -> Vec<Drift> {
410 let overhead = OVERHEAD.contains(&bucket);
411 let sum = |f: &dyn Fn(&ProductDay) -> f64| days.iter().map(f).sum::<f64>();
412 let cf_cost = sum(&|d| d.cf_cost_micros as f64);
413 let own_cost = sum(&|d| d.own_cost_micros as f64);
414 let value = sum(&|d| d.value_micros as f64);
Costs: counts are compared with Cloudflare's from the day g1t started counting, so days before a meter existed are not drift415 // Counts are compared from the first day g1t counted: before its meter
416 // was deployed there is only Cloudflare's side. A meter that never
417 // counted anything is compared over every day, so it still shows.
418 let first_counted = days.iter().filter(|d| d.own_quantity > 0.0).map(|d| d.day.as_str()).min();
419 let compared = |d: &&ProductDay| first_counted.is_none_or(|from| d.day.as_str() >= from);
420 let (cf_quantity, own_quantity) = days.iter().filter(compared).fold((0.0, 0.0), |(cf, own), d| (cf + d.cf_quantity, own + d.own_quantity));
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily421 let mut out = Vec::new();
422 if counted && cf_quantity > 0.0 {
423 let delta = delta_percent(own_quantity, cf_quantity);
424 if delta.is_some_and(|d| d.abs() > threshold) {
425 out.push(Drift { bucket: bucket.into(), kind: DriftKind::Count, ours: own_quantity, cloudflare: cf_quantity, delta_percent: delta });
426 }
427 }
428 let enough = cf_cost.max(own_cost) >= min_cost_micros as f64;
Merge branch 'worktree-agent-a633ac0f7f66d419d'429 // Models: what AI Gateway priced g1t's own provider traffic at (its
430 // lines, as "Cloudflare's" side) against the ledger's model cost. Only
431 // once the gateway has been read; then the ledger having none of it is
432 // drift too (traffic no run was charged for).
433 let models = NOT_CLOUDFLARE.contains(&bucket) && cf_cost > 0.0;
434 if enough && !overhead && cf_cost > 0.0 && (own_cost > 0.0 || models) {
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily435 let delta = delta_percent(own_cost, cf_cost);
436 if delta.is_some_and(|d| d.abs() > threshold) {
437 out.push(Drift { bucket: bucket.into(), kind: DriftKind::Cost, ours: own_cost, cloudflare: cf_cost, delta_percent: delta });
438 }
439 }
440 if !overhead && cf_cost >= min_cost_micros as f64 && value <= 0.0 {
441 out.push(Drift { bucket: bucket.into(), kind: DriftKind::Leak, ours: value, cloudflare: cf_cost, delta_percent: None });
442 }
443 out
444}
445
Merge branch 'worktree-agent-a633ac0f7f66d419d'446/// What can make AI Gateway's cost differ from what the providers bill,
447/// said for staff: cache tokens (priced by the gateway at its own rates for
448/// them, which may lag the provider's), requests Cloudflare billed itself,
449/// models it has no price for, and runs settled short.
450fn caveat_notes(c: &costs::GatewayCaveats) -> Vec<String> {
451 let mut notes = Vec::new();
452 if c.cache_read_tokens > 0.0 || c.cache_write_tokens > 0.0 {
453 notes.push(format!(
454 "{} prompt-cache read and {} cache write tokens went through it: check its cost against the provider's invoice, since cache reads are billed far below input and writes above it",
455 crate::features::thousands(c.cache_read_tokens.round() as u64),
456 crate::features::thousands(c.cache_write_tokens.round() as u64)
457 ));
458 }
459 if c.wholesale_usd > 0.0 {
460 notes.push(format!(
461 "{} of it Cloudflare billed itself (unified billing): that part is on Cloudflare's bill, not a provider's",
462 dollars(micros(c.wholesale_usd))
463 ));
464 }
465 if !c.unpriced.is_empty() {
466 notes.push(format!("it has no price for {} (tokens used, $0)", c.unpriced.join(", ")));
467 }
468 if c.short_runs > 0 {
469 notes.push(format!("{} runs were settled at no less than the sandbox reported because the gateway could not price all of them", c.short_runs));
470 }
471 notes
472}
473
474/// The models drift's detail: the gateway's total against the ledger's.
475pub(crate) fn models_detail(drift: &Drift, caveats: &costs::GatewayCaveats) -> String {
476 let lower = drift.ours < drift.cloudflare;
477 let mut detail = format!(
478 "Models: AI Gateway priced g1t's own provider traffic at {} over the last {DRIFT_DAYS} days; the ledger's model cost for the same days is {} ({:+.1}%). {}",
479 dollars(drift.cloudflare as i64),
480 dollars(drift.ours as i64),
481 drift.delta_percent.unwrap_or(0.0),
482 if lower {
483 "Model calls g1t paid for were not charged: runs not yet settled, runs with no session, or calls with no run (the ledger catches up as runs settle; a gap that stays is a leak)."
484 } else {
485 "The ledger counts more than the gateway priced: runs that went to a provider without the gateway, or sandbox reports the gateway could not correct."
486 }
487 );
488 let notes = caveat_notes(caveats);
489 if !notes.is_empty() {
490 detail.push_str(" The gateway's cost may be off: ");
491 detail.push_str(&notes.join("; "));
492 detail.push('.');
493 }
494 detail
495}
496
497/// The unpriced drift's detail.
498pub(crate) fn unpriced_detail(caveats: &costs::GatewayCaveats) -> String {
499 format!(
500 "Models: AI Gateway's cost is not all of what the providers bill over the last {DRIFT_DAYS} days: {}. Runs on a model with no gateway price are charged no less than the sandbox reported; add the model's price to the gateway (or route away from it) so it is charged at cost.",
501 caveat_notes(&costs::GatewayCaveats { cache_read_tokens: 0.0, cache_write_tokens: 0.0, wholesale_usd: 0.0, ..caveats.clone() }).join("; ")
502 )
503}
504
505/// Model usage AI Gateway could not price over the window, as drift on
506/// the models bucket: models with tokens and no cost, or runs settled
507/// short. None when there is none.
508pub(crate) fn unpriced_drift(caveats: &costs::GatewayCaveats) -> Option<(Drift, String)> {
509 if caveats.unpriced.is_empty() && caveats.short_runs == 0 {
510 return None;
511 }
512 let drift = Drift {
513 bucket: NOT_CLOUDFLARE[0].into(),
514 kind: DriftKind::Unpriced,
515 ours: f64::from(caveats.short_runs),
516 cloudflare: caveats.unpriced.len() as f64,
517 delta_percent: None,
518 };
519 Some((drift, unpriced_detail(caveats)))
520}
521
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily522/// When the last `days` in a row (each with enough cost to say something)
523/// were all under the floor: the first of them and the worst margin.
524/// Each item is a day's (day, revenue, cost).
525pub(crate) fn breach(series: &[(String, i64, i64)], floor_percent: f64, days: usize, min_cost_micros: i64) -> Option<(String, f64)> {
526 if days == 0 || series.len() < days {
527 return None;
528 }
529 let tail = &series[series.len() - days..];
530 let mut worst = f64::INFINITY;
531 for (_, revenue, cost) in tail {
532 if *cost < min_cost_micros {
533 return None;
534 }
535 let margin = margin_percent(*revenue, *cost).unwrap_or(-100.0);
536 if margin >= floor_percent {
537 return None;
538 }
539 worst = worst.min(margin);
540 }
541 Some((tail[0].0.clone(), worst))
542}
543
544/// `total` shared out in proportion to `weights`, in whole millionths that
545/// add up to it exactly (largest remainder first). Nothing to share, or no
546/// weight, shares nothing.
547pub(crate) fn attribute(total: i64, weights: &[(String, f64)]) -> Vec<(String, i64)> {
548 let mut merged: BTreeMap<String, f64> = BTreeMap::new();
549 for (key, w) in weights {
550 *merged.entry(key.clone()).or_default() += w.max(0.0);
551 }
552 let sum: f64 = merged.values().sum();
553 if total <= 0 || sum <= 0.0 {
554 return Vec::new();
555 }
556 let mut shares: Vec<(String, i64, f64)> = merged
557 .into_iter()
558 .map(|(key, w)| {
559 let exact = total as f64 * w / sum;
560 (key, exact.floor() as i64, exact - exact.floor())
561 })
562 .collect();
563 let mut left = total - shares.iter().map(|s| s.1).sum::<i64>();
564 let mut order: Vec<usize> = (0..shares.len()).collect();
565 order.sort_by(|a, b| shares[*b].2.total_cmp(&shares[*a].2).then(shares[*a].0.cmp(&shares[*b].0)));
566 for index in order {
567 if left <= 0 {
568 break;
569 }
570 shares[index].1 += 1;
571 left -= 1;
572 }
573 shares.into_iter().filter(|s| s.1 > 0).map(|(key, micros, _)| (key, micros)).collect()
574}
575
576/// Workspaces that cost g1t more than `factor` times what they paid, with
577/// at least `floor_micros` of cost: each (workspace, cost, revenue), the
578/// biggest gap first.
Models' margin read -14%: usage nothing paid for is valued at price, not $0579/// What a day's usage was worth at price. g1t's own workspaces are valued
580/// at price. So is usage nothing paid for, neither charged nor drawn from
581/// the plan, a trial, a pool or a gift (a free period): it was given away at
582/// its price, not sold for nothing. Anything paid keeps what it was paid, so
583/// a discount still shows as one.
584pub(crate) fn usage_value(internal: bool, cost: i64, paid: i64, margin_percent: u32) -> i64 {
585 if internal || (paid == 0 && cost > 0) {
586 return crate::credits::with_margin(cost, margin_percent);
587 }
588 paid
589}
590
Margin alerts measure what is sold, and say dollars when a percentage would mislead591/// What the overall alert says: the money as money, and a percentage only
592/// while there is enough coming in for one to mean something (a few cents
593/// against dollars of cost reads as -8000%).
594pub(crate) fn overall_detail(took: i64, spent: i64, days: usize, floor: f64, worst: f64) -> String {
595 if took < 1_000_000 * days as i64 {
596 return format!(
597 "All of g1t, comped workspaces left out: took in {} against {} of Cloudflare's bill over {days} days.",
598 dollars(took),
599 dollars(spent)
600 );
601 }
602 format!("All of g1t, comped workspaces left out: money in against Cloudflare's bill under {floor:.0}% for {days} days running, as low as {worst:.1}%.")
603}
604
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily605pub(crate) fn anomalies(rows: &[(String, i64, i64)], factor: f64, floor_micros: i64) -> Vec<(String, i64, i64)> {
606 let mut out: Vec<(String, i64, i64)> = rows
607 .iter()
608 .filter(|(_, cost, revenue)| *cost >= floor_micros && *cost as f64 > *revenue as f64 * factor)
609 .cloned()
610 .collect();
611 out.sort_by(|a, b| (b.1 - b.2).cmp(&(a.1 - a.2)).then(a.0.cmp(&b.0)));
612 out
613}
614
615/// Cloudflare's marginal rate for one of its units: the median over the
616/// charged days of cost over quantity, in dollars. None while the included
617/// amounts still cover it. Each item is a day's (quantity, cost).
618pub(crate) fn billed_rate(days: &[(f64, f64)]) -> Option<f64> {
619 let mut rates: Vec<f64> = days.iter().filter(|(q, c)| *q > 0.0 && *c > 0.0).map(|(q, c)| c / q).collect();
620 if rates.is_empty() {
621 return None;
622 }
623 rates.sort_by(f64::total_cmp);
624 Some(rates[rates.len() / 2])
625}
626
627/// What one of g1t's units costs, from Cloudflare's rate per its own unit
628/// and how many of Cloudflare's units each of g1t's took: if Cloudflare
629/// counts three operations for every git operation g1t counts, a git
630/// operation costs three of Cloudflare's. None without enough of g1t's
631/// units to say.
632pub(crate) fn derived_unit_cost(rate_per_cf_unit: f64, cf_units: f64, own_units: f64) -> Option<f64> {
633 (own_units >= MIN_UNITS && cf_units > 0.0 && rate_per_cf_unit > 0.0).then(|| rate_per_cf_unit * cf_units / own_units)
634}
635
636/// How many units a price is per: `1,000 operations` → 1,000, `million
637/// requests` → 1,000,000, `second` → 1.
638pub(crate) fn unit_size(unit: &str) -> f64 {
639 let first = unit.split_whitespace().next().unwrap_or_default().replace(',', "");
640 match first.as_str() {
641 "million" => 1_000_000.0,
642 "thousand" => 1_000.0,
643 n => n.parse().unwrap_or(1.0),
644 }
645}
646
647fn day_before(day: &str, days: u64) -> String {
648 let ms = g1t_contracts::time::parse_rfc3339(&format!("{day}T00:00:00Z")).unwrap_or(0);
649 rfc3339(ms.saturating_sub(days * DAY_MS))[..10].to_owned()
650}
651
652/// Dollars to the cent from a dollar up, finer below: `$17.02`, `$0.063`.
653fn dollars(micros: i64) -> String {
654 if micros.abs() >= 1_000_000 {
655 let cents = (micros as f64 / 10_000.0).round() as i64;
656 format!("{}${}.{:02}", if cents < 0 { "-" } else { "" }, cents.abs() / 100, cents.abs() % 100)
657 } else {
658 crate::features::dollars(micros)
659 }
660}
661
662/// The days a plan payment is spread over.
663const PLAN_DAYS: u64 = 30;
664
665/// `micros` paid on `day` spread evenly over `days` days from it, in
666/// whole micros that add up to it (the first days take the remainder).
667pub(crate) fn spread(day: &str, micros: i64, days: u64) -> Vec<(String, i64)> {
668 if micros <= 0 || days == 0 {
669 return Vec::new();
670 }
671 let start = g1t_contracts::time::parse_rfc3339(&format!("{}T00:00:00Z", &day[..10.min(day.len())])).unwrap_or(0);
672 let each = micros / days as i64;
673 let rest = micros % days as i64;
674 (0..days)
675 .map(|n| (rfc3339(start + n * DAY_MS)[..10].to_owned(), each + i64::from((n as i64) < rest)))
676 .collect()
677}
678
679// ---------------------------------------------------------------------
680// The daily run, and what sudo reads.
681// ---------------------------------------------------------------------
682
683#[derive(Serialize)]
684struct Mail<'a> {
685 to: &'a str,
686 from: &'a str,
687 subject: &'a str,
688 text: String,
689 html: String,
690}
691
692fn escape(text: &str) -> String {
693 text.replace('&', "&amp;").replace('<', "&lt;").replace('>', "&gt;").replace('"', "&quot;")
694}
695
696/// Emails staff through Cloudflare Email Sending, the `EMAIL` binding.
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays697pub(crate) async fn email_staff(env: &Env, to: &str, subject: &str, lines: &[String]) -> Result<()> {
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily698 let link = "https://sudo.g1t.sh/costs";
699 let text = format!("{}\n\nCosts & margin: {link}\n\nSent by g1t-billing's margin guard (COSTS_ALERT_EMAIL).\n", lines.join("\n\n"));
700 let mut html = String::from("<div style=\"font-family:system-ui,sans-serif;max-width:560px;margin:0 auto;padding:24px 16px;color:#16150f\">");
701 for line in lines {
702 html.push_str(&format!("<p style=\"font-size:15px;line-height:1.6\">{}</p>", escape(line)));
703 }
704 html.push_str(&format!(
705 "<p><a href=\"{link}\">Open Costs &amp; margin in sudo</a></p><p style=\"font-size:13px;color:#6e6a5e\">Sent by g1t-billing's margin guard (COSTS_ALERT_EMAIL).</p></div>"
706 ));
707 let mail = Mail { to, from: "g1t <noreply@g1t.sh>", subject, text, html };
708 let binding = g1t_kit::js::binding(env, "EMAIL")?;
709 g1t_kit::js::call(&binding, "send", &[g1t_kit::js::to_js(&mail)?]).await?;
710 Ok(())
711}
712
713#[derive(Deserialize)]
714struct AlertRow {
715 id: String,
716 kind: String,
717 subject: String,
718 detail: String,
719 since: String,
720 opened_at: String,
721 emailed_at: Option<String>,
722}
723
724impl From<AlertRow> for MarginAlert {
725 fn from(r: AlertRow) -> Self {
726 MarginAlert { id: r.id, kind: r.kind, subject: r.subject, detail: r.detail, since: r.since, opened_at: r.opened_at, emailed_at: r.emailed_at }
727 }
728}
729
730#[derive(Deserialize)]
731struct MarginRow {
732 day: String,
733 bucket: String,
734 cf_cost_micros: i64,
735 own_cost_micros: i64,
736 value_micros: i64,
737 cash_micros: i64,
738 cf_quantity: f64,
739 own_quantity: f64,
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it740 #[serde(default)]
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running741 given_comped_micros: Option<i64>,
742 #[serde(default)]
743 given_free_micros: Option<i64>,
744 #[serde(default)]
745 given_trial_micros: Option<i64>,
746 #[serde(default)]
747 given_pool_micros: Option<i64>,
Merge branch 'worktree-agent-a633ac0f7f66d419d'748 #[serde(default)]
749 given_discount_micros: Option<i64>,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily750}
751
752impl From<MarginRow> for ProductDay {
753 fn from(r: MarginRow) -> Self {
754 ProductDay {
755 day: r.day,
756 bucket: r.bucket,
757 cf_cost_micros: r.cf_cost_micros,
758 own_cost_micros: r.own_cost_micros,
759 value_micros: r.value_micros,
760 cash_micros: r.cash_micros,
761 cf_quantity: r.cf_quantity,
762 own_quantity: r.own_quantity,
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running763 given: Given {
764 comped: r.given_comped_micros.unwrap_or(0),
765 free: r.given_free_micros.unwrap_or(0),
766 trial: r.given_trial_micros.unwrap_or(0),
767 pool: r.given_pool_micros.unwrap_or(0),
Merge branch 'worktree-agent-a633ac0f7f66d419d'768 discount: r.given_discount_micros.unwrap_or(0),
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running769 },
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily770 }
771 }
772}
773
774impl Billing {
775 /// The day's work: read Cloudflare's bill and g1t's own counts,
776 /// reconcile, look for drift, measure unit costs, apply prices whose
777 /// day has come, and raise or clear alerts.
778 pub(crate) async fn costs_daily(&self, env: &Env, keeper: &crate::keeper::Keeper) -> Result<CostsRun> {
779 let mut run = CostsRun::default();
780 let (since, until) = match self.read_cloudflare(keeper, &mut run.problems).await? {
781 Some((since, until, lines)) => {
782 run.lines = lines;
783 (since, until)
784 }
785 // Without the bill, still reconcile what g1t knows itself, over
786 // the same days the bill would be read for.
787 None => {
788 #[derive(Deserialize)]
789 struct Last {
790 day: Option<String>,
791 }
792 let last = self.db.prepare("SELECT MAX(day) AS day FROM margin_days").first::<Last>(None).await?.and_then(|l| l.day);
793 costs::window(last.as_deref(), now_ms())
794 }
795 };
Costs: Cloudflare's subscriptions read from Cloudflare each day, the estimate only until then; sudo's costs split into Costs & margin and Bill & pricing796 // Not a problem for the run: the last read, or the estimate, stays.
797 if keeper.can_read_bill()
798 && let Err(error) = self.read_subscriptions(keeper).await
799 {
800 worker::console_error!("Cloudflare's subscriptions were not read: {error}");
801 }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily802 if let Err(error) = self.count_own(&since, &until).await {
803 run.problems.push(format!("g1t's own counts could not be read: {error}"));
804 }
805 self.snapshot_pending(&until).await?;
Models' margin read -14%: usage nothing paid for is valued at price, not $0806 // Reconciled over the whole window sudo shows, not only the days the
807 // bill was read for: it reads only what is already kept, so a change
808 // in how a day is valued reaches every day shown at the next run.
809 let window = day_before(&until, costs::BACKFILL_DAYS - 1);
810 let reconcile_from = if window < since { window } else { since.clone() };
811 run.days = self.reconcile_range(&reconcile_from, &until).await?;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily812 let drift = self.find_drift(&until).await?;
813 run.proposals = self.measure_units(&until).await?;
814 self.apply_due_versions().await?;
815 run.alerts = self.raise_alerts(env, &until, &drift).await?;
816 if let Some(identity) = &self.identity
817 && let Err(error) = self.tell_owners_of_rises(identity).await
818 {
819 run.problems.push(format!("owners could not be told of a price rise: {error}"));
820 }
821 for problem in &run.problems {
822 worker::console_warn!("costs: {problem}");
823 }
824 Ok(run)
825 }
826
827 /// What each month-end source had come to by the end of `day`.
828 async fn snapshot_pending(&self, day: &str) -> Result<()> {
829 self.db
830 .prepare(
831 "INSERT INTO pending_days (day, workspace, source, cost_micros, charge_micros)
832 SELECT ?1, workspace, source, COALESCE(cost_micros, 0), COALESCE(charge_micros, 0) FROM pending_usage WHERE month = ?2
833 ON CONFLICT (day, workspace, source) DO UPDATE SET cost_micros = excluded.cost_micros, charge_micros = excluded.charge_micros",
834 )
835 .bind(&[day.into(), day[..7].into()])?
836 .run()
837 .await?;
838 Ok(())
839 }
840
841 /// What customers were charged on the days, by workspace and key.
842 async fn usage_rows(&self, since: &str, until: &str) -> Result<Vec<UsageRow>> {
843 #[derive(Deserialize)]
844 struct Row {
845 day: String,
846 workspace: String,
847 key: String,
848 internal: i64,
849 own_provider: i64,
850 cash: Option<i64>,
851 drawn: Option<i64>,
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running852 trial: Option<i64>,
853 oss: Option<i64>,
854 covered: Option<i64>,
Merge branch 'worktree-agent-a633ac0f7f66d419d'855 discount: Option<i64>,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily856 cost: Option<i64>,
857 }
858 let charged_here = crate::storage::CHARGED_HERE.iter().map(|s| format!("'{s}'")).collect::<Vec<_>>().join(", ");
859 let end = format!("{until}T23:59:59.999Z");
860 let rows = self
861 .db
862 .prepare(format!(
863 "SELECT substr(created_at, 1, 10) AS day, workspace,
864 CASE WHEN task = 'deployments' AND reference LIKE 'deploy/%' THEN 'builds' ELSE COALESCE(task, 'other') END AS key,
865 CASE WHEN workspace IN ({internal}) THEN 1 ELSE 0 END AS internal,
866 CASE WHEN billed_to = 'workspace' THEN 1 ELSE 0 END AS own_provider,
867 -SUM(amount_micros) AS cash,
868 SUM(COALESCE(credit_micros, 0) + COALESCE(trial_micros, 0) + COALESCE(oss_micros, 0) + COALESCE(given_micros, 0)) AS drawn,
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running869 SUM(COALESCE(trial_micros, 0)) AS trial,
870 SUM(COALESCE(oss_micros, 0)) AS oss,
871 SUM(COALESCE(given_micros, 0)) AS covered,
Merge branch 'worktree-agent-a633ac0f7f66d419d'872 SUM(COALESCE(discount_micros, 0)) AS discount,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily873 SUM(COALESCE(cost_micros, 0)) AS cost
874 FROM ledger
875 WHERE kind = 'usage' AND created_at >= ?1 AND created_at <= ?2 AND COALESCE(task, '') NOT IN ({charged_here})
876 GROUP BY 1, 2, 3, 4, 5",
877 internal = crate::sales::INTERNAL_SQL
878 ))
879 .bind(&[since.into(), end.as_str().into()])?
880 .all()
881 .await?
882 .results::<Row>()?;
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it883 let mut internal = BTreeSet::new();
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily884 let mut out: Vec<UsageRow> = rows
885 .into_iter()
886 .map(|r| {
887 // A workspace's own model provider was paid there: no cost
888 // to g1t. g1t's own workspaces are valued at price.
889 let cost = if r.own_provider == 1 { 0 } else { r.cost.unwrap_or(0) };
890 let cash = r.cash.unwrap_or(0);
Merge branch 'worktree-agent-a633ac0f7f66d419d'891 // A discount took its part below cost plus the margin: it is
892 // valued at price and that part counted as given, so a
893 // discounted sale never reads as margin lost.
894 let discount = r.discount.unwrap_or(0).max(0);
895 let paid = cash + r.drawn.unwrap_or(0) + discount;
Models' margin read -14%: usage nothing paid for is valued at price, not $0896 let value = usage_value(r.internal == 1, cost, paid, self.margin_percent);
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running897 let given = if r.internal == 1 {
898 Given { comped: value, ..Given::default() }
899 } else if paid == 0 && cost > 0 {
900 Given { free: value, ..Given::default() }
901 } else {
Merge branch 'worktree-agent-a633ac0f7f66d419d'902 Given { free: r.covered.unwrap_or(0), trial: r.trial.unwrap_or(0), pool: r.oss.unwrap_or(0), comped: 0, discount }
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running903 };
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it904 if r.internal == 1 {
905 internal.insert(r.workspace.clone());
906 }
907 UsageRow { day: r.day, workspace: r.workspace, key: r.key, value, cash, cost, given }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily908 })
909 .collect();
910 // Month-end sources, from their daily snapshots.
911 #[derive(Deserialize)]
912 struct Snap {
913 day: String,
914 workspace: String,
915 source: String,
916 cost_micros: i64,
917 charge_micros: i64,
918 }
919 let snaps = self
920 .db
921 .prepare("SELECT day, workspace, source, cost_micros, charge_micros FROM pending_days WHERE day >= ?1 AND day <= ?2")
922 .bind(&[day_before(since, 1).into(), until.into()])?
923 .all()
924 .await?
925 .results::<Snap>()?
926 .into_iter()
927 .filter(|s| crate::storage::CHARGED_HERE.contains(&s.source.as_str()) || s.source == "domains")
928 .map(|s| (s.day, s.workspace, s.source, s.cost_micros, s.charge_micros))
929 .collect::<Vec<_>>();
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it930 out.extend(pending_deltas(&snaps).into_iter().filter(|u| u.day.as_str() >= since).map(|mut u| {
931 if internal.contains(&u.workspace) {
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running932 u.given = Given { comped: u.value, ..Given::default() };
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it933 }
934 u
935 }));
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily936 // The plan's price, spread over the 30 days it pays for, so a month's
937 // payment does not read as one very good day and 29 bad ones.
938 #[derive(Deserialize)]
939 struct Plan {
940 day: String,
941 workspace: String,
942 micros: Option<i64>,
943 }
944 let plans = self
945 .db
946 .prepare(
947 "SELECT substr(paid_at, 1, 10) AS day, workspace, SUM(amount_micros) AS micros FROM plan_payments
948 WHERE paid_at >= ?1 AND paid_at <= ?2 GROUP BY 1, 2",
949 )
950 .bind(&[day_before(since, PLAN_DAYS - 1).into(), end.as_str().into()])?
951 .all()
952 .await?
953 .results::<Plan>()?;
954 for p in plans {
955 for (day, micros) in spread(&p.day, p.micros.unwrap_or(0), PLAN_DAYS) {
956 if day.as_str() >= since && day.as_str() <= until {
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running957 out.push(UsageRow { day, workspace: p.workspace.clone(), key: "plan".into(), value: micros, cash: micros, cost: 0, given: Given::default() });
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily958 }
959 }
960 }
961 Ok(out)
962 }
963
964 /// Reconciles the days and writes `margin_days` and `workspace_costs`.
965 async fn reconcile_range(&self, since: &str, until: &str) -> Result<u32> {
966 let rules = self.rules().await?;
967 #[derive(Deserialize)]
968 struct Map {
969 key: String,
970 bucket: String,
971 }
972 let revenue_map: BTreeMap<String, String> = self
973 .db
974 .prepare("SELECT key, bucket FROM revenue_map")
975 .all()
976 .await?
977 .results::<Map>()?
978 .into_iter()
979 .map(|m| (m.key, m.bucket))
980 .collect();
981 let lines = self
982 .db
983 .prepare("SELECT day, source, product, meter, quantity, cost_usd FROM cost_lines WHERE day >= ?1 AND day <= ?2")
984 .bind(&[since.into(), until.into()])?
985 .all()
986 .await?
987 .results::<LineRow>()?;
988 let own = self
989 .db
990 .prepare("SELECT day, meter, workspace, quantity FROM own_counts WHERE day >= ?1 AND day <= ?2")
991 .bind(&[since.into(), until.into()])?
992 .all()
993 .await?
994 .results::<OwnRow>()?;
995 let usage = self.usage_rows(since, until).await?;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running996 #[derive(Deserialize)]
997 struct Internal {
998 workspace: String,
999 }
1000 let internal: BTreeSet<String> = self
1001 .db
1002 .prepare(format!("WITH i(workspace) AS ({}) SELECT DISTINCT workspace FROM i", crate::sales::INTERNAL_SQL))
1003 .all()
1004 .await?
1005 .results::<Internal>()?
1006 .into_iter()
1007 .map(|i| i.workspace)
1008 .collect();
1009 let (days, workspaces) = fold(&rules, &revenue_map, &lines, &own, &usage, &internal);
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1010 let now = rfc3339(now_ms());
1011 self.db
1012 .batch(vec![
1013 self.db.prepare("DELETE FROM margin_days WHERE day >= ?1 AND day <= ?2").bind(&[since.into(), until.into()])?,
1014 self.db.prepare("DELETE FROM workspace_costs WHERE day >= ?1 AND day <= ?2").bind(&[since.into(), until.into()])?,
1015 ])
1016 .await?;
1017 for chunk in days.chunks(50) {
1018 let mut statements = Vec::with_capacity(chunk.len());
1019 for d in chunk {
1020 statements.push(
1021 self.db
1022 .prepare(
Merge branch 'worktree-agent-a633ac0f7f66d419d'1023 "INSERT OR REPLACE INTO margin_days (day, bucket, cf_cost_micros, own_cost_micros, value_micros, cash_micros, cf_quantity, own_quantity, given_micros, given_comped_micros, given_free_micros, given_trial_micros, given_pool_micros, given_discount_micros, computed_at)
1024 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1025 )
1026 .bind(&[
1027 d.day.as_str().into(),
1028 d.bucket.as_str().into(),
1029 (d.cf_cost_micros as f64).into(),
1030 (d.own_cost_micros as f64).into(),
1031 (d.value_micros as f64).into(),
1032 (d.cash_micros as f64).into(),
1033 d.cf_quantity.into(),
1034 d.own_quantity.into(),
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1035 (d.given.total() as f64).into(),
1036 (d.given.comped as f64).into(),
1037 (d.given.free as f64).into(),
1038 (d.given.trial as f64).into(),
1039 (d.given.pool as f64).into(),
Merge branch 'worktree-agent-a633ac0f7f66d419d'1040 (d.given.discount as f64).into(),
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1041 now.as_str().into(),
1042 ])?,
1043 );
1044 }
1045 self.db.batch(statements).await?;
1046 }
1047 for chunk in workspaces.chunks(50) {
1048 let mut statements = Vec::with_capacity(chunk.len());
1049 for w in chunk {
1050 statements.push(
1051 self.db
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1052 .prepare("INSERT OR REPLACE INTO workspace_costs (day, workspace, bucket, cost_micros, revenue_micros, value_micros, given_micros) VALUES (?, ?, ?, ?, ?, ?, ?)")
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1053 .bind(&[
1054 w.day.as_str().into(),
1055 w.workspace.as_str().into(),
1056 w.bucket.as_str().into(),
1057 (w.cost as f64).into(),
1058 (w.revenue as f64).into(),
Margin alerts measure what is sold, and say dollars when a percentage would mislead1059 (w.value as f64).into(),
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1060 (w.given.total() as f64).into(),
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1061 ])?,
1062 );
1063 }
1064 self.db.batch(statements).await?;
1065 }
1066 Ok(costs::days_between(since, until).len() as u32)
1067 }
1068
1069 async fn margin_days(&self, since: &str, until: &str) -> Result<Vec<ProductDay>> {
1070 Ok(self
1071 .db
1072 .prepare("SELECT * FROM margin_days WHERE day >= ?1 AND day <= ?2 ORDER BY day, bucket")
1073 .bind(&[since.into(), until.into()])?
1074 .all()
1075 .await?
1076 .results::<MarginRow>()?
1077 .into_iter()
1078 .map(ProductDay::from)
1079 .collect())
1080 }
1081
Merge branch 'worktree-agent-a633ac0f7f66d419d'1082 /// What AI Gateway's lines over the days, and the runs settled in them,
1083 /// say about whether its cost is what the providers bill.
1084 async fn gateway_caveats(&self, since: &str, until: &str) -> Result<costs::GatewayCaveats> {
1085 #[derive(Deserialize)]
1086 struct Line {
1087 meter: String,
1088 quantity: f64,
1089 cost_usd: f64,
1090 }
1091 let lines: Vec<(String, f64, f64)> = self
1092 .db
1093 .prepare("SELECT meter, quantity, cost_usd FROM cost_lines WHERE source = ?1 AND day >= ?2 AND day <= ?3")
1094 .bind(&[costs::SOURCE_GATEWAY.into(), since.into(), until.into()])?
1095 .all()
1096 .await?
1097 .results::<Line>()?
1098 .into_iter()
1099 .map(|l| (l.meter, l.quantity, l.cost_usd))
1100 .collect();
1101 let mut caveats = costs::gateway_caveats(&lines);
1102 #[derive(Deserialize)]
1103 struct Short {
1104 n: Option<f64>,
1105 }
1106 caveats.short_runs = self
1107 .db
1108 .prepare("SELECT COUNT(*) AS n FROM runs WHERE gateway_note IS NOT NULL AND settled_at >= ?1 AND settled_at <= ?2")
1109 .bind(&[since.into(), format!("{until}T23:59:59.999Z").into()])?
1110 .first::<Short>(None)
1111 .await?
1112 .and_then(|s| s.n)
1113 .unwrap_or(0.0) as u32;
1114 Ok(caveats)
1115 }
1116
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1117 /// Drift over the last week, written to `cost_drift` (replacing the
1118 /// last run's), with unmapped Cloudflare meters as leaks.
1119 async fn find_drift(&self, until: &str) -> Result<Vec<(Drift, String)>> {
1120 let since = day_before(until, DRIFT_DAYS - 1);
1121 let settings = self.cost_settings().await?;
1122 let rules = self.rules().await?;
1123 let days = self.margin_days(&since, until).await?;
1124 let mut by: BTreeMap<String, Vec<ProductDay>> = BTreeMap::new();
1125 for d in days {
1126 by.entry(d.bucket.clone()).or_default().push(d);
1127 }
Merge branch 'worktree-agent-a633ac0f7f66d419d'1128 let caveats = self.gateway_caveats(&since, until).await?;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1129 let mut found = Vec::new();
Merge branch 'worktree-agent-a633ac0f7f66d419d'1130 if let Some(drift) = unpriced_drift(&caveats) {
1131 found.push(drift);
1132 }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1133 for (bucket, days) in &by {
1134 let bucket_rules: Vec<&Rule> = rules.iter().filter(|r| &r.bucket == bucket).collect();
1135 let threshold = bucket_rules.iter().map(|r| r.drift_percent).fold(f64::INFINITY, f64::min);
1136 let threshold = if threshold.is_finite() { threshold } else { 10.0 };
1137 let counted = bucket_rules.iter().any(|r| r.own_meter.is_some());
1138 for drift in drifts(bucket, days, threshold, counted, settings.min_daily_cost_micros) {
1139 let title = costs::bucket_title(bucket);
1140 let detail = match drift.kind {
Merge branch 'worktree-agent-a633ac0f7f66d419d'1141 DriftKind::Cost if NOT_CLOUDFLARE.contains(&bucket.as_str()) => models_detail(&drift, &caveats),
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1142 DriftKind::Count => format!(
One operation mapping, owned by repos; billing reads it instead of keeping its own1143 "{title}: g1t counted {}, Cloudflare {} over the last {DRIFT_DAYS} days ({:+.1}%). Customers are charged for what g1t counts; check what Cloudflare counts as a unit and change the repos service's operation_mapping (set_operation_mapping).",
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1144 crate::features::thousands(drift.ours.max(0.0).round() as u64),
1145 crate::features::thousands(drift.cloudflare.max(0.0).round() as u64),
1146 drift.delta_percent.unwrap_or(0.0)
1147 ),
1148 DriftKind::Cost => format!(
1149 "{title}: Cloudflare charged {} over the last {DRIFT_DAYS} days; the price book's cost of the same usage is {} ({:+.1}%). A price may be stale: see the proposals.",
1150 dollars(drift.cloudflare as i64),
1151 dollars(drift.ours as i64),
1152 drift.delta_percent.unwrap_or(0.0)
1153 ),
1154 DriftKind::Leak if bucket == UNMAPPED => {
1155 format!("Cloudflare charged {} for meters no mapping claims. Map them on Costs & margin.", dollars(drift.cloudflare as i64))
1156 }
Merge branch 'worktree-agent-a633ac0f7f66d419d'1157 DriftKind::Leak if NOT_CLOUDFLARE.contains(&bucket.as_str()) => format!(
1158 "{title}: AI Gateway priced g1t's own provider traffic at {} over the last {DRIFT_DAYS} days and the ledger has no model charge for it, not even a comped or free one: model calls with no billing run behind them (a run started without a ticket, or something else using g1t's gateway).",
1159 dollars(drift.cloudflare as i64)
1160 ),
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1161 DriftKind::Leak => format!(
1162 "{title}: Cloudflare charged {} over the last {DRIFT_DAYS} days and customers were charged nothing for it.",
1163 dollars(drift.cloudflare as i64)
1164 ),
Merge branch 'worktree-agent-a633ac0f7f66d419d'1165 // Raised from the gateway's lines, not per bucket.
1166 DriftKind::Unpriced => unpriced_detail(&caveats),
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1167 };
1168 found.push((drift, detail));
1169 }
1170 }
1171 let now = rfc3339(now_ms());
1172 let mut statements = vec![self.db.prepare("DELETE FROM cost_drift")];
1173 for (drift, detail) in &found {
1174 statements.push(
1175 self.db
1176 .prepare("INSERT OR REPLACE INTO cost_drift (bucket, kind, ours, cloudflare, delta_percent, detail, found_at) VALUES (?, ?, ?, ?, ?, ?, ?)")
1177 .bind(&[
1178 drift.bucket.as_str().into(),
1179 drift.kind.as_str().into(),
1180 drift.ours.into(),
1181 drift.cloudflare.into(),
1182 drift.delta_percent.map_or(JsValue::NULL, JsValue::from),
1183 detail.as_str().into(),
1184 now.as_str().into(),
1185 ])?,
1186 );
1187 }
1188 self.db.batch(statements).await?;
1189 Ok(found)
1190 }
1191
1192 /// Unit costs from the bill for mappings that scale to g1t's own count
1193 /// (git operations), proposed to the price book.
1194 async fn measure_units(&self, until: &str) -> Result<u32> {
1195 #[derive(Deserialize)]
1196 struct Scaled {
1197 product: String,
1198 meter: String,
1199 price_meter: String,
1200 own_meter: String,
1201 unit: Option<String>,
1202 }
1203 let scaled = self
1204 .db
1205 .prepare(
1206 "SELECT m.product, m.meter, m.price_meter, m.own_meter, p.unit FROM cost_map m LEFT JOIN prices p ON p.meter = m.price_meter
1207 WHERE m.scale_to_own = 1 AND m.price_meter IS NOT NULL AND m.own_meter IS NOT NULL",
1208 )
1209 .all()
1210 .await?
1211 .results::<Scaled>()?;
1212 let since = day_before(until, MEASURE_DAYS - 1);
1213 let rules = self.rules().await?;
1214 let mut proposed = 0;
1215 for s in scaled {
1216 #[derive(Deserialize)]
1217 struct Day {
1218 product: String,
1219 meter: String,
1220 quantity: f64,
1221 cost_usd: f64,
1222 }
1223 let lines = self
1224 .db
1225 .prepare("SELECT product, meter, quantity, cost_usd FROM cost_lines WHERE source = ?1 AND product = ?2 AND day >= ?3 AND day <= ?4")
1226 .bind(&[SOURCE_BILLABLE.into(), s.product.as_str().into(), since.as_str().into(), until.into()])?
1227 .all()
1228 .await?
1229 .results::<Day>()?;
1230 // Only the lines this very mapping claims.
1231 let mine: Vec<(f64, f64)> = lines
1232 .iter()
1233 .filter(|l| costs::classify(&rules, &l.product, &l.meter).is_some_and(|r| r.product == s.product && r.meter == s.meter))
1234 .map(|l| (l.quantity, l.cost_usd))
1235 .collect();
1236 let Some(rate) = billed_rate(&mine) else { continue };
1237 let cf_units: f64 = mine.iter().map(|(q, _)| q).sum();
1238 #[derive(Deserialize)]
1239 struct Own {
1240 total: Option<f64>,
1241 }
1242 let own_units = self
1243 .db
1244 .prepare("SELECT SUM(quantity) AS total FROM own_counts WHERE meter = ?1 AND day >= ?2 AND day <= ?3")
1245 .bind(&[s.own_meter.as_str().into(), since.as_str().into(), until.into()])?
1246 .first::<Own>(None)
1247 .await?
1248 .and_then(|o| o.total)
1249 .unwrap_or(0.0);
1250 let Some(per_unit) = derived_unit_cost(rate, cf_units, own_units) else { continue };
1251 let size = unit_size(s.unit.as_deref().unwrap_or("1"));
1252 let measured = per_unit * size * 1_000_000.0;
1253 let reason = format!(
1254 "Cloudflare billed ${:.4} per 1,000 of its units and counted {:.2} of them for each one g1t counted over the last {MEASURE_DAYS} days ({} against {})",
1255 rate * 1000.0,
1256 cf_units / own_units,
1257 crate::features::thousands(cf_units.round() as u64),
1258 crate::features::thousands(own_units.round() as u64)
1259 );
1260 if self.propose(&s.price_meter, measured, &reason, "reconciler").await?.is_some() {
1261 proposed += 1;
1262 }
1263 }
1264 Ok(proposed)
1265 }
1266
1267 /// Opens, updates and closes margin alerts, and emails staff about new
1268 /// ones (and open ones each week).
1269 async fn raise_alerts(&self, env: &Env, until: &str, drift: &[(Drift, String)]) -> Result<u32> {
1270 let settings = self.cost_settings().await?;
1271 let since = day_before(until, u64::from(settings.alert_days.max(1)) - 1);
1272 let days = self.margin_days(&since, until).await?;
1273 let mut conditions: Vec<(String, String, String, String)> = Vec::new();
1274 // Each product under the floor.
1275 let mut by: BTreeMap<String, Vec<(String, i64, i64)>> = BTreeMap::new();
1276 let mut all: BTreeMap<String, (i64, i64)> = BTreeMap::new();
1277 for d in &days {
1278 let overall = all.entry(d.day.clone()).or_default();
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1279 // What g1t gave away (comped workspaces, free periods, the
1280 // trial and the pools) is a budget it chose to spend, watched on
1281 // its own (budget.rs): not part of whether what is sold pays.
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1282 overall.0 += d.cash_micros;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1283 overall.1 += (d.cost() - d.given.total()).max(0);
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1284 if !OVERHEAD.contains(&d.bucket.as_str()) && d.bucket != UNMAPPED {
1285 by.entry(d.bucket.clone()).or_default().push((d.day.clone(), d.value_micros, d.cost()));
1286 }
1287 }
1288 let floor = settings.margin_floor_percent;
1289 let n = settings.alert_days as usize;
1290 for (bucket, series) in &by {
1291 if let Some((from, worst)) = breach(series, floor, n, settings.min_daily_cost_micros) {
1292 conditions.push((
1293 "margin".into(),
1294 bucket.clone(),
1295 format!("{}: margin under {floor:.0}% for {n} days running, as low as {worst:.1}%.", costs::bucket_title(bucket)),
1296 from,
1297 ));
Margin alerts measure what is sold, and say dollars when a percentage would mislead1298 }
1299 }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1300 let series: Vec<(String, i64, i64)> = all.into_iter().map(|(day, (revenue, cost))| (day, revenue, cost)).collect();
1301 if let Some((from, worst)) = breach(&series, floor, n, settings.min_daily_cost_micros) {
Margin alerts measure what is sold, and say dollars when a percentage would mislead1302 let tail = &series[series.len().saturating_sub(n)..];
1303 let (took, spent) = tail.iter().fold((0i64, 0i64), |(r, c), (_, revenue, cost)| (r + revenue, c + cost));
1304 conditions.push(("overall".into(), "g1t".into(), overall_detail(took, spent, n, floor, worst), from));
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1305 }
1306 for (d, detail) in drift {
1307 let kind = if d.kind == DriftKind::Leak { "leak" } else { "drift" };
1308 conditions.push((kind.into(), format!("{}:{}", d.bucket, d.kind.as_str()), detail.clone(), until.to_owned()));
1309 }
1310 // Workspaces costing more than they pay.
1311 for (workspace, cost, revenue) in self.workspace_anomalies(until, &settings).await? {
1312 conditions.push((
1313 "workspace".into(),
1314 workspace.clone(),
Margin alerts measure what is sold, and say dollars when a percentage would mislead1315 format!(
1316 "{workspace} cost g1t {} on Cloudflare over {ANOMALY_DAYS} days, and its usage was priced at {}: its prices are below cost.",
1317 dollars(cost),
1318 dollars(revenue)
1319 ),
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1320 day_before(until, ANOMALY_DAYS - 1),
1321 ));
1322 }
1323
1324 let open = self
1325 .db
1326 .prepare("SELECT * FROM margin_alerts WHERE resolved_at IS NULL")
1327 .all()
1328 .await?
1329 .results::<AlertRow>()?;
1330 let now = now_ms();
1331 let stamp = rfc3339(now);
1332 let mut to_email: Vec<String> = Vec::new();
1333 let mut kept: BTreeSet<String> = BTreeSet::new();
1334 for (kind, subject, detail, from) in &conditions {
1335 match open.iter().find(|a| &a.kind == kind && &a.subject == subject) {
1336 Some(alert) => {
1337 kept.insert(alert.id.clone());
1338 self.db
1339 .prepare("UPDATE margin_alerts SET detail = ? WHERE id = ?")
1340 .bind(&[detail.as_str().into(), alert.id.as_str().into()])?
1341 .run()
1342 .await?;
1343 let stale = alert
1344 .emailed_at
1345 .as_deref()
1346 .and_then(g1t_contracts::time::parse_rfc3339)
1347 .is_none_or(|at| now.saturating_sub(at) >= REMIND_MS);
1348 if stale && kind != "workspace" {
1349 to_email.push(format!("Still open: {detail}"));
1350 kept.insert(format!("email:{}", alert.id));
1351 }
1352 }
1353 None => {
1354 let id = new_id("mal", now);
1355 self.db
1356 .prepare("INSERT INTO margin_alerts (id, kind, subject, detail, since, opened_at) VALUES (?, ?, ?, ?, ?, ?)")
1357 .bind(&[id.as_str().into(), kind.as_str().into(), subject.as_str().into(), detail.as_str().into(), from.as_str().into(), stamp.as_str().into()])?
1358 .run()
1359 .await?;
1360 kept.insert(id.clone());
Margin alerts measure what is sold, and say dollars when a percentage would mislead1361 // A workspace's is for Reach out, not the inbox.
1362 if kind != "workspace" {
1363 to_email.push(detail.clone());
1364 }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1365 kept.insert(format!("email:{id}"));
1366 }
1367 }
1368 }
1369 for alert in &open {
1370 if !kept.contains(&alert.id) {
1371 self.db
1372 .prepare("UPDATE margin_alerts SET resolved_at = ? WHERE id = ?")
1373 .bind(&[stamp.as_str().into(), alert.id.as_str().into()])?
1374 .run()
1375 .await?;
1376 }
1377 }
1378 let to = env.var("COSTS_ALERT_EMAIL").map(|v| v.to_string()).unwrap_or_default();
1379 if !to_email.is_empty() && !to.trim().is_empty() {
1380 let subject = format!("[g1t costs] {} margin alert{}", to_email.len(), if to_email.len() == 1 { "" } else { "s" });
1381 match email_staff(env, to.trim(), &subject, &to_email).await {
1382 Ok(()) => {
1383 for marker in kept.iter().filter_map(|k| k.strip_prefix("email:")) {
1384 self.db
1385 .prepare("UPDATE margin_alerts SET emailed_at = ? WHERE id = ?")
1386 .bind(&[stamp.as_str().into(), marker.into()])?
1387 .run()
1388 .await?;
1389 }
1390 }
1391 Err(error) => worker::console_error!("could not email the margin alerts: {error}"),
1392 }
1393 }
1394 Ok(conditions.len() as u32)
1395 }
1396
1397 /// Workspaces costing g1t more than they pay over 30 days, not g1t's own.
Margin alerts measure what is sold, and say dollars when a percentage would mislead1398 /// Each day's cost shared out to comped workspaces.
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1399 async fn workspace_anomalies(&self, until: &str, settings: &CostSettings) -> Result<Vec<(String, i64, i64)>> {
1400 #[derive(Deserialize)]
1401 struct Row {
1402 workspace: String,
1403 cost: Option<i64>,
1404 revenue: Option<i64>,
1405 }
1406 let rows = self
1407 .db
1408 .prepare(format!(
Margin alerts measure what is sold, and say dollars when a percentage would mislead1409 // Against what its usage was priced at, not the cash it
1410 // paid: a trial or a gift paying for usage is not a price
1411 // below cost.
The workspace cost alert compares only days that carry their value, not the days before it was kept1412 // Days from before value_micros was kept have none: only days
1413 // since the first one that does are compared.
Margin alerts measure what is sold, and say dollars when a percentage would mislead1414 "SELECT workspace, SUM(cost_micros) AS cost, SUM(value_micros) AS revenue FROM workspace_costs
The workspace cost alert compares only days that carry their value, not the days before it was kept1415 WHERE day >= ?1 AND day <= ?2 AND workspace NOT IN ({})
1416 AND day >= (SELECT MIN(day) FROM workspace_costs WHERE value_micros > 0)
1417 GROUP BY workspace",
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1418 crate::sales::INTERNAL_SQL
1419 ))
1420 .bind(&[day_before(until, ANOMALY_DAYS - 1).into(), until.into()])?
1421 .all()
1422 .await?
1423 .results::<Row>()?;
1424 let rows: Vec<(String, i64, i64)> = rows.into_iter().map(|r| (r.workspace, r.cost.unwrap_or(0), r.revenue.unwrap_or(0))).collect();
1425 Ok(anomalies(&rows, settings.anomaly_factor, settings.anomaly_floor_micros))
1426 }
1427
1428 /// For Reach out: workspaces with an open cost-over-revenue alert,
1429 /// each with its detail and cost.
1430 pub(crate) async fn costing_more_than_they_pay(&self) -> Result<Vec<(String, String, i64)>> {
1431 let alerts = self
1432 .db
1433 .prepare("SELECT * FROM margin_alerts WHERE resolved_at IS NULL AND kind = 'workspace' ORDER BY opened_at DESC LIMIT 50")
1434 .all()
1435 .await?
1436 .results::<AlertRow>()?;
1437 let mut out = Vec::new();
1438 for alert in alerts {
1439 #[derive(Deserialize)]
1440 struct Cost {
1441 cost: Option<i64>,
1442 }
1443 let cost = self
1444 .db
1445 .prepare("SELECT SUM(cost_micros) AS cost FROM workspace_costs WHERE workspace = ? AND day >= ?")
1446 .bind(&[alert.subject.as_str().into(), alert.since.as_str().into()])?
1447 .first::<Cost>(None)
1448 .await?
1449 .and_then(|c| c.cost)
1450 .unwrap_or(0);
1451 out.push((alert.subject, alert.detail, cost));
1452 }
1453 Ok(out)
1454 }
1455
1456 /// `admin_cost_alerts`: what sudo's banner says.
1457 pub(crate) async fn admin_cost_alerts(&self, _: AdminCostAlertsArgs) -> Result<Vec<MarginAlert>> {
1458 Ok(self
1459 .db
1460 .prepare("SELECT * FROM margin_alerts WHERE resolved_at IS NULL ORDER BY opened_at DESC LIMIT 50")
1461 .all()
1462 .await?
1463 .results::<AlertRow>()?
1464 .into_iter()
1465 .map(MarginAlert::from)
1466 .collect())
1467 }
1468
1469 /// `admin_run_costs`: the daily run, now.
1470 pub(crate) async fn admin_run_costs(&self, env: &Env, a: AdminRunCostsArgs) -> Result<Outcome<CostsRun>> {
1471 let keeper = crate::keeper::Keeper::from_env(env);
1472 let run = self.costs_daily(env, &keeper).await?;
1473 if !a.by.is_empty() {
1474 self.audit(
1475 "costs",
1476 "costs_run",
1477 &format!("{} lines, {} days, {} proposals, {} alerts", run.lines, run.days, run.proposals, run.alerts),
1478 &a.by,
1479 )
1480 .await?;
1481 }
1482 Ok(Outcome::Ok(run))
1483 }
1484
1485 /// `admin_set_cost_mapping`.
1486 pub(crate) async fn admin_set_cost_mapping(&self, a: AdminSetCostMappingArgs) -> Result<Outcome<CostMapping>> {
1487 let product = costs::slug(&a.product);
1488 let meter = if a.meter.trim() == "*" { "*".to_owned() } else { costs::slug(&a.meter) };
1489 if product.is_empty() || meter.is_empty() {
1490 return Ok(Outcome::fail(FailureCode::Invalid, "Name Cloudflare's product and a meter (or * for all of it)."));
1491 }
1492 let now = rfc3339(now_ms());
1493 if a.remove {
1494 self.db
1495 .prepare("DELETE FROM cost_map WHERE product = ? AND meter = ?")
1496 .bind(&[product.as_str().into(), meter.as_str().into()])?
1497 .run()
1498 .await?;
1499 self.audit("costs", "cost_mapping_removed", &format!("{product}/{meter}"), &a.by).await?;
1500 return Ok(Outcome::Ok(CostMapping {
1501 product,
1502 meter,
1503 bucket: String::new(),
1504 price_meter: None,
1505 own_meter: None,
1506 scale_to_own: false,
1507 drift_percent: 0.0,
1508 note: String::new(),
1509 updated_at: now,
1510 updated_by: a.by,
1511 }));
1512 }
1513 let bucket = costs::slug(&a.bucket);
1514 if bucket.is_empty() {
1515 return Ok(Outcome::fail(FailureCode::Invalid, "Say which of g1t's products it is a cost of."));
1516 }
1517 let clean = |v: Option<String>| v.map(|v| v.trim().to_owned()).filter(|v| !v.is_empty());
1518 let (price_meter, own_meter) = (clean(a.price_meter), clean(a.own_meter));
1519 let drift = a.drift_percent.filter(|d| d.is_finite() && *d > 0.0).unwrap_or(10.0);
1520 self.db
1521 .prepare(
1522 "INSERT INTO cost_map (product, meter, bucket, price_meter, own_meter, scale_to_own, drift_percent, note, updated_at, updated_by)
1523 VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)
1524 ON CONFLICT (product, meter) DO UPDATE SET bucket = ?3, price_meter = ?4, own_meter = ?5, scale_to_own = ?6,
1525 drift_percent = ?7, note = ?8, updated_at = ?9, updated_by = ?10",
1526 )
1527 .bind(&[
1528 product.as_str().into(),
1529 meter.as_str().into(),
1530 bucket.as_str().into(),
1531 crate::optional(price_meter.as_deref()),
1532 crate::optional(own_meter.as_deref()),
1533 i32::from(a.scale_to_own).into(),
1534 drift.into(),
1535 a.note.trim().into(),
1536 now.as_str().into(),
1537 a.by.as_str().into(),
1538 ])?
1539 .run()
1540 .await?;
1541 self.audit("costs", "cost_mapping", &format!("{product}/{meter} → {bucket}"), &a.by).await?;
1542 Ok(Outcome::Ok(CostMapping {
1543 product,
1544 meter,
1545 bucket,
1546 price_meter,
1547 own_meter,
1548 scale_to_own: a.scale_to_own,
1549 drift_percent: drift,
1550 note: a.note.trim().to_owned(),
1551 updated_at: now,
1552 updated_by: a.by,
1553 }))
1554 }
1555
1556 /// `admin_costs`: the Costs & margin page.
1557 pub(crate) async fn admin_costs(&self, a: AdminCostsArgs, configured: bool) -> Result<CostsReport> {
1558 let until = rfc3339(now_ms())[..10].to_owned();
1559 let span = u64::from(a.days.unwrap_or(30).clamp(7, 90));
1560 let since = day_before(&until, span - 1);
1561 let days = self.margin_days(&since, &until).await?;
1562 let rules = self.rules().await?;
1563
1564 let mut products: BTreeMap<String, ProductMargin> = BTreeMap::new();
1565 let mut overall = OverallMargin::default();
1566 for d in &days {
1567 let p = products.entry(d.bucket.clone()).or_insert_with(|| ProductMargin {
1568 bucket: d.bucket.clone(),
1569 title: costs::bucket_title(&d.bucket),
1570 cost_source: if NOT_CLOUDFLARE.contains(&d.bucket.as_str()) { "ledger" } else { "cloudflare" }.into(),
1571 overhead: OVERHEAD.contains(&d.bucket.as_str()),
1572 ..ProductMargin::default()
1573 });
1574 p.cf_cost_micros += d.cf_cost_micros;
1575 p.own_cost_micros += d.own_cost_micros;
1576 p.value_micros += d.value_micros;
1577 p.cost_micros += d.cost();
1578 overall.cost_micros += d.cost();
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1579 overall.given_micros += d.given.total();
1580 if NOT_CLOUDFLARE.contains(&d.bucket.as_str()) {
1581 overall.models_cost_micros += d.cost();
1582 } else {
1583 overall.cloudflare_cost_micros += d.cost();
1584 }
1585 overall.given_comped_micros += d.given.comped;
1586 overall.given_free_micros += d.given.free;
1587 overall.given_trial_micros += d.given.trial;
1588 overall.given_pool_micros += d.given.pool;
Merge branch 'worktree-agent-a633ac0f7f66d419d'1589 overall.given_discount_micros += d.given.discount;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1590 let sold = (d.cost() - d.given.total()).max(0);
1591 if OVERHEAD.contains(&d.bucket.as_str()) {
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1592 overall.plans_micros += d.cash_micros;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1593 overall.running_cost_micros += sold;
1594 } else if d.bucket == UNMAPPED {
1595 overall.usage_micros += d.cash_micros;
1596 overall.unmapped_cost_micros += sold;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1597 } else {
1598 overall.usage_micros += d.cash_micros;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1599 overall.usage_cost_micros += sold;
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1600 }
1601 }
1602 for p in products.values_mut() {
1603 p.margin_micros = p.value_micros - p.cost_micros;
1604 p.margin_percent = margin_percent(p.value_micros, p.cost_micros);
1605 }
1606 let revenue = overall.usage_micros + overall.plans_micros;
1607 overall.margin_micros = revenue - overall.cost_micros;
1608 overall.margin_percent = margin_percent(revenue, overall.cost_micros);
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1609 let sold = (overall.cost_micros - overall.given_micros).max(0);
1610 overall.sold_margin_micros = revenue - sold;
1611 overall.sold_margin_percent = margin_percent(revenue, sold);
Costs: the plan's included usage counts as paid for the usage it covered, out of what plans leave for running g1t; the run button shows it is running with CSS alone (sudo ships no JavaScript)1612 // The plan's included usage was paid for by the plan's price: it is
1613 // money in for the usage it covered, and out of what the plans
1614 // leave for running g1t.
1615 #[derive(Deserialize)]
1616 struct Included {
1617 micros: Option<i64>,
1618 }
1619 overall.included_micros = self
1620 .db
1621 .prepare(format!(
1622 "SELECT SUM(COALESCE(credit_micros, 0)) AS micros FROM ledger
1623 WHERE kind = 'usage' AND created_at >= ?1 AND created_at <= ?2 AND workspace NOT IN ({})",
1624 crate::sales::INTERNAL_SQL
1625 ))
1626 .bind(&[since.as_str().into(), format!("{until}T23:59:59.999Z").into()])?
1627 .first::<Included>(None)
1628 .await?
1629 .and_then(|r| r.micros)
1630 .unwrap_or(0);
1631 let usage_in = overall.usage_micros + overall.included_micros;
1632 overall.usage_margin_micros = usage_in - overall.usage_cost_micros;
1633 overall.usage_margin_percent = margin_percent(usage_in, overall.usage_cost_micros);
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1634 let mut products: Vec<ProductMargin> = products.into_values().collect();
1635 products.sort_by_key(|p| std::cmp::Reverse(p.cost_micros.max(p.value_micros)));
1636
1637 #[derive(Deserialize)]
1638 struct DriftRow {
1639 bucket: String,
1640 kind: String,
1641 ours: f64,
1642 cloudflare: f64,
1643 delta_percent: Option<f64>,
1644 detail: String,
1645 found_at: String,
1646 }
1647 let drift = self
1648 .db
1649 .prepare("SELECT * FROM cost_drift ORDER BY kind, bucket")
1650 .all()
1651 .await?
1652 .results::<DriftRow>()?
1653 .into_iter()
1654 .map(|r| CostDrift {
1655 title: costs::bucket_title(&r.bucket),
1656 bucket: r.bucket,
1657 kind: r.kind,
1658 ours: r.ours,
1659 cloudflare: r.cloudflare,
1660 delta_percent: r.delta_percent,
1661 detail: r.detail,
1662 found_at: r.found_at,
1663 })
1664 .collect();
1665
1666 #[derive(Deserialize)]
1667 struct Top {
1668 workspace: String,
1669 cost: Option<i64>,
1670 revenue: Option<i64>,
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1671 given: Option<i64>,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1672 internal: i64,
1673 }
1674 let top_workspaces = self
1675 .db
1676 .prepare(format!(
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1677 "SELECT workspace, SUM(cost_micros) AS cost, SUM(revenue_micros) AS revenue, SUM(given_micros) AS given,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1678 CASE WHEN workspace IN ({}) THEN 1 ELSE 0 END AS internal
1679 FROM workspace_costs WHERE day >= ?1 AND day <= ?2 GROUP BY workspace ORDER BY cost DESC LIMIT 15",
1680 crate::sales::INTERNAL_SQL
1681 ))
1682 .bind(&[since.as_str().into(), until.as_str().into()])?
1683 .all()
1684 .await?
1685 .results::<Top>()?
1686 .into_iter()
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1687 .map(|t| WorkspaceCost { workspace: t.workspace, cost_micros: t.cost.unwrap_or(0), revenue_micros: t.revenue.unwrap_or(0), given_micros: t.given.unwrap_or(0), internal: t.internal == 1 })
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1688 .collect();
1689
1690 #[derive(Deserialize)]
1691 struct Summary {
1692 source: String,
1693 product: String,
1694 meter: String,
1695 raw_name: String,
1696 unit: String,
1697 quantity: f64,
1698 cost_usd: f64,
1699 }
1700 let lines = self
1701 .db
1702 .prepare(
1703 "SELECT source, product, meter, MAX(raw_name) AS raw_name, MAX(unit) AS unit, SUM(quantity) AS quantity, SUM(cost_usd) AS cost_usd
1704 FROM cost_lines WHERE day >= ?1 AND day <= ?2 GROUP BY source, product, meter ORDER BY cost_usd DESC, product, meter LIMIT 200",
1705 )
1706 .bind(&[since.as_str().into(), until.as_str().into()])?
1707 .all()
1708 .await?
1709 .results::<Summary>()?
1710 .into_iter()
1711 .map(|l| CostLineSummary {
1712 bucket: costs::classify(&rules, &l.product, &l.meter).map(|r| r.bucket.clone()),
1713 product: l.product,
1714 meter: l.meter,
1715 raw_name: l.raw_name,
1716 unit: l.unit,
1717 source: l.source,
1718 quantity: l.quantity,
1719 cost_micros: micros(l.cost_usd),
1720 })
1721 .collect();
1722
1723 #[derive(Deserialize)]
1724 struct MapRow {
1725 product: String,
1726 meter: String,
1727 bucket: String,
1728 price_meter: Option<String>,
1729 own_meter: Option<String>,
1730 scale_to_own: i64,
1731 drift_percent: f64,
1732 note: String,
1733 updated_at: String,
1734 updated_by: String,
1735 }
1736 let mappings = self
1737 .db
1738 .prepare("SELECT * FROM cost_map ORDER BY product, meter")
1739 .all()
1740 .await?
1741 .results::<MapRow>()?
1742 .into_iter()
1743 .map(|m| CostMapping {
1744 product: m.product,
1745 meter: m.meter,
1746 bucket: m.bucket,
1747 price_meter: m.price_meter,
1748 own_meter: m.own_meter,
1749 scale_to_own: m.scale_to_own == 1,
1750 drift_percent: m.drift_percent,
1751 note: m.note,
1752 updated_at: m.updated_at,
1753 updated_by: m.updated_by,
1754 })
1755 .collect();
1756
1757 #[derive(Deserialize)]
1758 struct Fetched {
1759 at: Option<String>,
1760 }
1761 let fetched_at = self.db.prepare("SELECT MAX(fetched_at) AS at FROM cost_lines").first::<Fetched>(None).await?.and_then(|f| f.at);
1762
1763 Ok(CostsReport {
1764 configured,
1765 fetched_at,
1766 days: days
1767 .iter()
1768 .map(|d| CostDay {
1769 day: d.day.clone(),
1770 bucket: d.bucket.clone(),
1771 cf_cost_micros: d.cf_cost_micros,
1772 own_cost_micros: d.own_cost_micros,
1773 value_micros: d.value_micros,
1774 cash_micros: d.cash_micros,
1775 })
1776 .collect(),
1777 since,
1778 until,
1779 products,
1780 overall,
1781 drift,
1782 alerts: self.admin_cost_alerts(AdminCostAlertsArgs {}).await?,
1783 proposals: self.proposals().await?,
1784 versions: self.versions().await?,
1785 top_workspaces,
1786 lines,
1787 mappings,
1788 settings: self.cost_settings().await?,
Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays1789 caps: self.spend_caps().await?,
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1790 })
1791 }
1792}
1793
1794#[cfg(test)]
1795mod tests {
1796 use super::*;
1797
Margin alerts measure what is sold, and say dollars when a percentage would mislead1798 #[test]
Models' margin read -14%: usage nothing paid for is valued at price, not $01799 fn usage_nothing_paid_for_is_valued_at_price_and_paid_usage_at_what_was_paid() {
1800 // A free period: charged nothing, drawn from nothing.
1801 assert_eq!(usage_value(false, 1_000_000, 0, 20), 1_200_000);
1802 // Charged, or drawn from a trial: what was paid.
1803 assert_eq!(usage_value(false, 1_000_000, 1_200_000, 20), 1_200_000);
1804 assert_eq!(usage_value(false, 1_000_000, 900_000, 20), 900_000);
1805 // g1t's own: at price.
1806 assert_eq!(usage_value(true, 1_000_000, 0, 20), 1_200_000);
1807 // No cost, nothing paid: nothing.
1808 assert_eq!(usage_value(false, 0, 0, 20), 0);
1809 }
1810
1811 #[test]
Margin alerts measure what is sold, and say dollars when a percentage would mislead1812 fn the_overall_alert_says_dollars_while_little_comes_in() {
1813 let small = overall_detail(90_000, 7_500_000, 3, 10.0, -8239.7);
1814 assert!(small.contains("took in $0.09 against $7.50"), "{small}");
1815 assert!(!small.contains('%'), "{small}");
1816 let real = overall_detail(30_000_000, 40_000_000, 3, 10.0, -33.3);
1817 assert!(real.contains("as low as -33.3%"), "{real}");
1818 }
1819
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1820 fn rule(product: &str, meter: &str, bucket: &str, own: Option<&str>) -> Rule {
1821 Rule { product: product.into(), meter: meter.into(), bucket: bucket.into(), price_meter: None, own_meter: own.map(Into::into), drift_percent: 10.0 }
1822 }
1823
1824 fn rules() -> Vec<Rule> {
1825 vec![
1826 rule("containers", "*", "sandboxes", None),
1827 rule("workers", "*", "platform", None),
1828 rule("artifacts", "*", "git", Some("git_operations")),
1829 rule("artifacts", "events_", "git", Some("git_operations")),
1830 ]
1831 }
1832
1833 fn revenue_map() -> BTreeMap<String, String> {
1834 [("sandbox", "sandboxes"), ("git", "git"), ("plan", "platform")].iter().map(|(k, v)| (k.to_string(), v.to_string())).collect()
1835 }
1836
1837 fn line(day: &str, source: &str, product: &str, meter: &str, quantity: f64, cost: f64) -> LineRow {
1838 LineRow { day: day.into(), source: source.into(), product: product.into(), meter: meter.into(), quantity, cost_usd: cost }
1839 }
1840
1841 fn usage(day: &str, workspace: &str, key: &str, value: i64, cash: i64, cost: i64) -> UsageRow {
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1842 UsageRow { day: day.into(), workspace: workspace.into(), key: key.into(), value, cash, cost, given: Given::default() }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1843 }
1844
1845 #[test]
1846 fn a_day_puts_the_bill_g1ts_counts_and_charges_side_by_side() {
1847 let lines = vec![
1848 line("2026-10-15", SOURCE_BILLABLE, "containers", "container_memory", 1000.0, 2.00),
1849 line("2026-10-15", SOURCE_BILLABLE, "artifacts", "artifacts_operations", 30_000.0, 3.00),
1850 // Artifacts' own events: not used while the bill has a count.
1851 line("2026-10-15", SOURCE_ARTIFACTS, "artifacts", "events_pull", 29_000.0, 0.0),
1852 line("2026-10-15", SOURCE_BILLABLE, "workers", "workers_cpu_ms", 1.0, 0.50),
1853 line("2026-10-15", SOURCE_BILLABLE, "browser_rendering", "browser_hours", 2.0, 0.25),
1854 ];
1855 let own = vec![
1856 OwnRow { day: "2026-10-15".into(), meter: "git_operations".into(), workspace: "acme".into(), quantity: 7_500.0 },
1857 OwnRow { day: "2026-10-15".into(), meter: "git_operations".into(), workspace: "beta".into(), quantity: 2_500.0 },
1858 ];
1859 let usage = vec![
1860 usage("2026-10-15", "acme", "sandbox", 2_400_000, 1_000_000, 2_000_000),
1861 usage("2026-10-15", "beta", "sandbox", 1_200_000, 1_200_000, 1_000_000),
1862 usage("2026-10-15", "acme", "git", 600_000, 600_000, 500_000),
1863 usage("2026-10-15", "acme", "implement", 120_000, 120_000, 100_000),
1864 usage("2026-10-15", "beta", "plan", 20_000_000, 20_000_000, 0),
1865 ];
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1866 let (days, workspaces) = fold(&rules(), &revenue_map(), &lines, &own, &usage, &BTreeSet::new());
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1867 let get = |bucket: &str| days.iter().find(|d| d.bucket == bucket).unwrap();
1868 let sandboxes = get("sandboxes");
1869 assert_eq!((sandboxes.cf_cost_micros, sandboxes.own_cost_micros, sandboxes.value_micros, sandboxes.cash_micros), (2_000_000, 3_000_000, 3_600_000, 2_200_000));
1870 let git = get("git");
1871 assert_eq!(git.cf_cost_micros, 3_000_000);
1872 assert_eq!((git.cf_quantity, git.own_quantity), (30_000.0, 10_000.0));
1873 assert_eq!(get("platform").value_micros, 20_000_000);
1874 // Not mapped: a leak until someone maps it.
1875 assert_eq!(get(UNMAPPED).cf_cost_micros, 250_000);
1876 // Models: no Cloudflare line, their cost is g1t's own.
1877 assert_eq!(get("models").cost(), 100_000);
1878 // Git's cost shared by g1t's own counts (Cloudflare gave none per
1879 // workspace here): three quarters to acme.
1880 let share = |ws: &str, bucket: &str| workspaces.iter().find(|w| w.workspace == ws && w.bucket == bucket).map(|w| (w.cost, w.revenue));
1881 assert_eq!(share("acme", "git"), Some((2_250_000, 600_000)));
1882 assert_eq!(share("beta", "git"), Some((750_000, 0)));
1883 // Every bucket's cost is shared out exactly.
1884 for d in &days {
1885 let shared: i64 = workspaces.iter().filter(|w| w.bucket == d.bucket).map(|w| w.cost).sum();
1886 assert_eq!(shared, d.cost(), "{}", d.bucket);
1887 }
1888 }
1889
1890 #[test]
1891 fn artifacts_events_count_when_the_bill_does_not() {
1892 let lines = vec![
1893 line("2026-10-05", SOURCE_ARTIFACTS, "artifacts", "events_pull", 120.0, 0.0),
1894 line("2026-10-05", SOURCE_ARTIFACTS, "artifacts", "events_push", 30.0, 0.0),
1895 line("2026-10-05", SOURCE_ARTIFACTS, "artifacts", "events_ratelimited", 9.0, 0.0),
1896 ];
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1897 let (days, _) = fold(&rules(), &revenue_map(), &lines, &[], &[], &BTreeSet::new());
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1898 assert_eq!(days[0].cf_quantity, 150.0);
1899 assert_eq!(days[0].cf_cost_micros, 0);
1900 }
1901
1902 #[test]
1903 fn month_end_meters_are_told_by_the_day_from_snapshots() {
1904 let snap = |day: &str, cost: i64, charge: i64| (day.to_string(), "acme".to_string(), "git".to_string(), cost, charge);
1905 let rows = pending_deltas(&[snap("2026-10-30", 100, 120), snap("2026-10-31", 250, 300), snap("2026-11-01", 40, 48), snap("2026-11-02", 40, 48)]);
1906 assert_eq!(
1907 rows.iter().map(|r| (r.day.as_str(), r.cost, r.value)).collect::<Vec<_>>(),
1908 vec![("2026-10-30", 100, 120), ("2026-10-31", 150, 180), ("2026-11-01", 40, 48)]
1909 );
1910 }
1911
1912 #[test]
1913 fn a_plan_payment_is_spread_over_the_month_it_pays_for() {
1914 let days = spread("2026-10-01T00:00:00.000Z", 20_000_000, 30);
1915 assert_eq!(days.len(), 30);
1916 assert_eq!(days[0], ("2026-10-01".to_string(), 666_667));
1917 assert_eq!(days[29], ("2026-10-30".to_string(), 666_666));
1918 assert_eq!(days.iter().map(|d| d.1).sum::<i64>(), 20_000_000);
1919 assert!(spread("2026-10-01", 0, 30).is_empty());
1920 assert_eq!(dollars(17_024_000), "$17.02");
1921 assert_eq!(dollars(-27_668_620), "-$27.67");
1922 assert_eq!(dollars(63_000), "$0.063");
1923 }
1924
1925 #[test]
1926 fn margins_and_deltas() {
1927 assert_eq!(margin_percent(1_200_000, 1_000_000).map(|m| (m * 100.0).round() / 100.0), Some(16.67));
1928 assert_eq!(margin_percent(0, 5), None);
1929 assert_eq!(delta_percent(110.0, 100.0), Some(10.0));
1930 assert_eq!(delta_percent(1.0, 0.0), None);
1931 }
1932
1933 fn day(bucket: &str, cf: i64, own: i64, value: i64, cfq: f64, ownq: f64) -> ProductDay {
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1934 ProductDay { day: "2026-10-15".into(), bucket: bucket.into(), cf_cost_micros: cf, own_cost_micros: own, value_micros: value, cash_micros: value, cf_quantity: cfq, own_quantity: ownq, given: Given::default() }
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1935 }
1936
1937 #[test]
1938 fn counts_more_than_the_threshold_apart_are_drift() {
1939 // Cloudflare counted 30,000 operations where g1t counted 10,000:
1940 // binding reads, perhaps. -66.7%.
1941 let drift = drifts("git", &[day("git", 3_000_000, 1_500_000, 1_800_000, 30_000.0, 10_000.0)], 10.0, true, 100_000);
1942 assert_eq!(drift.iter().map(|d| d.kind).collect::<Vec<_>>(), vec![DriftKind::Count, DriftKind::Cost]);
1943 assert!((drift[0].delta_percent.unwrap() + 66.666).abs() < 0.01);
1944 // 9% apart: within 10%.
1945 assert!(drifts("git", &[day("git", 1_000_000, 1_000_000, 1_200_000, 10_000.0, 10_900.0)], 10.0, true, 100_000).is_empty());
1946 // Uncounted products have no count drift.
1947 assert!(drifts("sandboxes", &[day("sandboxes", 1_000_000, 1_050_000, 1_200_000, 5.0, 0.0)], 10.0, false, 100_000).is_empty());
1948 }
1949
1950 #[test]
1951 fn cost_with_no_revenue_is_a_leak_but_not_for_running_g1t() {
1952 let leak = drifts("actions_cache", &[day("actions_cache", 400_000, 0, 0, 0.0, 0.0)], 10.0, false, 100_000);
1953 assert_eq!(leak.len(), 1);
1954 assert_eq!(leak[0].kind, DriftKind::Leak);
1955 assert!(drifts("platform", &[day("platform", 5_000_000, 0, 0, 0.0, 0.0)], 10.0, false, 100_000).is_empty());
1956 // Pennies say nothing.
1957 assert!(drifts("actions_cache", &[day("actions_cache", 50_000, 0, 0, 0.0, 0.0)], 10.0, false, 100_000).is_empty());
1958 assert!(drifts(UNMAPPED, &[day(UNMAPPED, 250_000, 0, 0, 0.0, 0.0)], 10.0, false, 100_000)[0].kind == DriftKind::Leak);
1959 }
1960
1961 #[test]
1962 fn a_margin_alert_needs_n_days_in_a_row_under_the_floor() {
1963 let s = |d: &str, revenue: i64, cost: i64| (d.to_string(), revenue, cost);
1964 // 5%, 0%, -20%: three days under 10%.
1965 let series = vec![s("10-13", 1_200_000, 1_000_000), s("10-14", 1_050_000, 1_000_000), s("10-15", 1_000_000, 1_000_000), s("10-16", 1_000_000, 1_200_000)];
1966 let (from, worst) = breach(&series, 10.0, 3, 100_000).unwrap();
1967 assert_eq!(from, "10-14");
1968 assert!((worst + 20.0).abs() < 1e-9);
1969 // A good day in the window clears it.
1970 let mended = vec![s("10-14", 1_050_000, 1_000_000), s("10-15", 1_300_000, 1_000_000), s("10-16", 1_000_000, 1_200_000)];
1971 assert!(breach(&mended, 10.0, 3, 100_000).is_none());
1972 // Cost with no revenue at all is the worst margin there is.
1973 assert_eq!(breach(&[s("10-16", 0, 500_000)], 10.0, 1, 100_000).unwrap().1, -100.0);
1974 // Too little cost to judge.
1975 assert!(breach(&[s("10-16", 0, 5_000)], 10.0, 1, 100_000).is_none());
1976 assert!(breach(&series, 10.0, 9, 100_000).is_none());
1977 }
1978
1979 #[test]
1980 fn shared_costs_add_up_to_the_bill() {
1981 let w = |k: &str, v: f64| (k.to_string(), v);
1982 assert_eq!(attribute(100, &[w("a", 1.0), w("b", 1.0), w("c", 1.0)]), vec![("a".into(), 34), ("b".into(), 33), ("c".into(), 33)]);
1983 assert_eq!(attribute(10, &[w("a", 3.0), w("b", 1.0), w("a", 0.0)]), vec![("a".into(), 8), ("b".into(), 2)]);
1984 assert!(attribute(10, &[w("a", 0.0)]).is_empty());
1985 assert!(attribute(0, &[w("a", 1.0)]).is_empty());
1986 }
1987
1988 #[test]
Costs: counts are compared with Cloudflare's from the day g1t started counting, so days before a meter existed are not drift1989 fn counts_are_compared_from_the_day_g1t_started_counting() {
1990 let on = |day: &str, cf: f64, own: f64| ProductDay { day: day.into(), bucket: "git".into(), cf_quantity: cf, own_quantity: own, ..ProductDay::default() };
1991 // Five days of Cloudflare's count before g1t's meter, then two that match.
1992 let days = vec![on("2026-10-01", 500.0, 0.0), on("2026-10-05", 300.0, 0.0), on("2026-10-06", 210.0, 231.0), on("2026-10-07", 450.0, 458.0)];
1993 assert!(drifts("git", &days, 10.0, true, 0).iter().all(|d| d.kind != DriftKind::Count));
1994 // A real gap on the days both counted still shows.
1995 let days = vec![on("2026-10-01", 500.0, 0.0), on("2026-10-06", 400.0, 231.0), on("2026-10-07", 600.0, 300.0)];
1996 let found = drifts("git", &days, 10.0, true, 0);
1997 let count = found.iter().find(|d| d.kind == DriftKind::Count).unwrap();
1998 assert_eq!((count.ours, count.cloudflare), (531.0, 1000.0));
1999 // A meter that never counted is compared over every day.
2000 let days = vec![on("2026-10-06", 400.0, 0.0)];
2001 assert!(drifts("git", &days, 10.0, true, 0).iter().any(|d| d.kind == DriftKind::Count));
2002 }
2003
2004 #[test]
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it2005 fn what_g1t_gives_away_is_kept_apart_from_what_it_sells() {
2006 let map = BTreeMap::new();
2007 // A comped workspace (all of it given), one in its trial (half paid
2008 // by the trial) and one paying in cash, all on models.
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running2009 let comped = usage("2026-10-15", "flagon", "agent", 1_200_000, 0, 1_000_000);
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it2010 let mut trial = usage("2026-10-15", "acme", "agent", 1_200_000, 600_000, 1_000_000);
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running2011 trial.given = Given { trial: 600_000, ..Given::default() };
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it2012 let paying = usage("2026-10-15", "beta", "agent", 1_200_000, 1_200_000, 1_000_000);
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running2013 // Nothing priced that day: free use.
2014 let free = usage("2026-10-15", "gamma", "agent", 0, 0, 1_000_000);
2015 let internal = BTreeSet::from(["flagon".to_string()]);
2016 let (days, workspaces) = fold(&[], &map, &[], &[], &[comped, trial, paying, free], &internal);
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it2017 let models = days.iter().find(|d| d.bucket == "models").unwrap();
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running2018 assert_eq!(models.cost(), 4_000_000);
Merge branch 'worktree-agent-a633ac0f7f66d419d'2019 assert_eq!(models.given, Given { comped: 1_000_000, free: 1_000_000, trial: 500_000, pool: 0, discount: 0 });
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running2020 let given = |w: &str| workspaces.iter().find(|x| x.workspace == w).unwrap().given.total();
2021 assert_eq!((given("flagon"), given("acme"), given("beta"), given("gamma")), (1_000_000, 500_000, 0, 1_000_000));
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it2022 }
2023
2024 #[test]
Merge branch 'worktree-agent-a633ac0f7f66d419d'2025 fn a_discounted_sale_keeps_its_margin_and_counts_the_discount_as_given() {
2026 // $1 of model cost at 20%, sold to an account with 30% off: charged
2027 // $0.84, and $0.36 below cost plus the margin given (as usage_rows
2028 // reads the ledger: value at price, the discount part given).
2029 let mut sale = usage("2026-10-15", "acme", "agent", 1_200_000, 840_000, 1_000_000);
2030 sale.given = Given { discount: 360_000, ..Given::default() };
2031 let (days, _) = fold(&[], &BTreeMap::new(), &[], &[], &[sale], &BTreeSet::new());
2032 let models = days.iter().find(|d| d.bucket == "models").unwrap();
2033 assert_eq!(models.value_micros, 1_200_000);
2034 assert_eq!(models.given, Given { discount: 300_000, ..Given::default() });
2035 // What was sold (cost less given) still makes the margin.
2036 let sold = models.cost() - models.given.total();
2037 assert_eq!(margin_percent(models.cash_micros, sold).map(|m| m.round()), Some(17.0));
2038 }
2039
2040 #[test]
2041 fn the_gateways_total_against_the_ledgers_model_cost_is_drift() {
2042 // The gateway priced $5 of g1t's own traffic; the ledger has $3.
2043 let short = drifts("models", &[day("models", 5_000_000, 3_000_000, 3_600_000, 0.0, 0.0)], 10.0, false, 100_000);
2044 assert_eq!(short.iter().map(|d| d.kind).collect::<Vec<_>>(), vec![DriftKind::Cost]);
2045 assert!((short[0].delta_percent.unwrap() + 40.0).abs() < 1e-9);
2046 // Gateway traffic with nothing on the ledger at all: cost drift and a leak.
2047 let none = drifts("models", &[day("models", 2_000_000, 0, 0, 0.0, 0.0)], 10.0, false, 100_000);
2048 assert_eq!(none.iter().map(|d| d.kind).collect::<Vec<_>>(), vec![DriftKind::Cost, DriftKind::Leak]);
2049 // Within the threshold, or before the gateway was ever read: nothing.
2050 assert!(drifts("models", &[day("models", 1_050_000, 1_000_000, 1_200_000, 0.0, 0.0)], 10.0, false, 100_000).is_empty());
2051 assert!(drifts("models", &[day("models", 0, 1_000_000, 1_200_000, 0.0, 0.0)], 10.0, false, 100_000).is_empty());
2052 // The detail says which way and why it may be off.
2053 let caveats = costs::GatewayCaveats { cache_read_tokens: 3_000_000.0, unpriced: vec!["anthropic_claude_new_1".into()], ..Default::default() };
2054 let detail = models_detail(&short[0], &caveats);
2055 assert!(detail.contains("$5.00") && detail.contains("$3.00") && detail.contains("were not charged"), "{detail}");
2056 assert!(detail.contains("3,000,000 prompt-cache read") && detail.contains("no price for anthropic_claude_new_1"), "{detail}");
2057 }
2058
2059 #[test]
2060 fn model_usage_the_gateway_cannot_price_is_drift_even_when_the_totals_agree() {
2061 assert!(unpriced_drift(&costs::GatewayCaveats::default()).is_none());
2062 // Cache tokens alone are a note on the cost drift, not drift.
2063 assert!(unpriced_drift(&costs::GatewayCaveats { cache_write_tokens: 10.0, ..Default::default() }).is_none());
2064 let (drift, detail) = unpriced_drift(&costs::GatewayCaveats { unpriced: vec!["anthropic_claude_new_1".into()], short_runs: 2, ..Default::default() }).unwrap();
2065 assert_eq!((drift.bucket.as_str(), drift.kind.as_str()), ("models", "unpriced"));
2066 assert!(detail.contains("no price for anthropic_claude_new_1") && detail.contains("2 runs were settled"), "{detail}");
2067 }
2068
2069 #[test]
Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily2070 fn a_workspace_that_costs_more_than_it_pays_is_flagged() {
2071 let rows = vec![("acme".to_string(), 5_000_000, 1_000_000), ("beta".to_string(), 900_000, 0), ("gamma".to_string(), 2_000_000, 3_000_000)];
2072 let found = anomalies(&rows, 1.0, 1_000_000);
2073 assert_eq!(found, vec![("acme".to_string(), 5_000_000, 1_000_000)]);
2074 // At twice its revenue as the threshold, $5 against $3 is fine.
2075 assert!(anomalies(&[("acme".to_string(), 5_000_000, 3_000_000)], 2.0, 1_000_000).is_empty());
2076 }
2077
2078 #[test]
2079 fn a_git_operation_costs_what_cloudflare_counts_for_it() {
2080 // $0.15 per 1,000 of Cloudflare's operations, on the charged days.
2081 let rate = billed_rate(&[(10_000.0, 0.0), (20_000.0, 3.0), (30_000.0, 4.5), (5_000.0, 0.75)]).unwrap();
2082 assert!((rate - 0.000_15).abs() < 1e-12);
2083 // Cloudflare counted 3 for every 1 g1t did: binding reads count.
2084 let per_op = derived_unit_cost(rate, 300_000.0, 100_000.0).unwrap();
2085 let per_thousand_micros = per_op * unit_size("1,000 operations") * 1e6;
2086 assert!((per_thousand_micros - 450_000.0).abs() < 1e-6, "{per_thousand_micros}");
2087 // Too few of g1t's units to say.
2088 assert!(derived_unit_cost(rate, 3_000.0, 500.0).is_none());
2089 assert!(billed_rate(&[(10_000.0, 0.0)]).is_none());
2090 assert_eq!(unit_size("million requests"), 1e6);
2091 assert_eq!(unit_size("second"), 1.0);
2092 }
2093}

This file's history is long; its oldest lines are credited to the oldest commit read.