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 daily | 1 | /** |
| 2 | * Costs & margin: the arithmetic behind the page, apart from the SVG and | |
| 3 | * the Workers runtime so it can be tested under Node. Money is in micros. | |
| 4 | */ | |
| Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays | 5 | import type { CostDay, CostMappingInput, CostSettings, SpendCaps } from "@g1t/contracts"; |
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 6 | |
| Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays | 7 | import { parseDollars, usd } from "./money.ts"; |
| Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily | 8 | |
| 9 | /** Buckets Cloudflare does not bill: their cost is g1t's own figure. */ | |
| 10 | export const NOT_CLOUDFLARE = new Set(["models"]); | |
| 11 | ||
| 12 | /** A day's cost: Cloudflare's bill, or g1t's own figure where Cloudflare does not bill it. */ | |
| 13 | export function dayCost(day: CostDay): number { | |
| 14 | return NOT_CLOUDFLARE.has(day.bucket) ? day.ownCostMicros : day.cfCostMicros; | |
| 15 | } | |
| 16 | ||
| 17 | export type DayFigures = { day: string; revenueMicros: number; costMicros: number }; | |
| 18 | ||
| 19 | /** Every day from `since` to `until`, inclusive (YYYY-MM-DD, UTC). */ | |
| 20 | export function daysBetween(since: string, until: string): string[] { | |
| 21 | const start = Date.parse(`${since}T00:00:00Z`); | |
| 22 | const end = Date.parse(`${until}T00:00:00Z`); | |
| 23 | if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) return []; | |
| 24 | const out: string[] = []; | |
| 25 | for (let at = start; at <= end && out.length < 400; at += 86_400_000) out.push(new Date(at).toISOString().slice(0, 10)); | |
| 26 | return out; | |
| 27 | } | |
| 28 | ||
| 29 | /** | |
| 30 | * A day per day of the range, every day there even with nothing on it. | |
| 31 | * All of g1t: money in (what workspaces paid, the plan too) against every | |
| 32 | * cost. One product: what customers were charged for it at price against | |
| 33 | * what it cost. | |
| 34 | */ | |
| 35 | export function daySeries(days: CostDay[], since: string, until: string, bucket: string | null): DayFigures[] { | |
| 36 | const totals = new Map<string, DayFigures>(daysBetween(since, until).map((day) => [day, { day, revenueMicros: 0, costMicros: 0 }])); | |
| 37 | for (const row of days) { | |
| 38 | if (bucket && row.bucket !== bucket) continue; | |
| 39 | const figures = totals.get(row.day); | |
| 40 | if (!figures) continue; | |
| 41 | figures.revenueMicros += bucket ? row.valueMicros : row.cashMicros; | |
| 42 | figures.costMicros += dayCost(row); | |
| 43 | } | |
| 44 | return [...totals.values()]; | |
| 45 | } | |
| 46 | ||
| 47 | /** Margin as a whole percent of revenue; none when there was none. */ | |
| 48 | export function marginPercent(revenueMicros: number, costMicros: number): number | null { | |
| 49 | return revenueMicros > 0 ? ((revenueMicros - costMicros) / revenueMicros) * 100 : null; | |
| 50 | } | |
| 51 | ||
| 52 | /** `12.3%`, `−4.0%`, or a dash. */ | |
| 53 | export function percentLabel(percent: number | null | undefined, { signed = false }: { signed?: boolean } = {}): string { | |
| 54 | if (percent == null || !Number.isFinite(percent)) return "—"; | |
| 55 | const text = `${Math.abs(percent).toFixed(1)}%`; | |
| 56 | if (percent < 0) return `−${text}`; | |
| 57 | return signed && percent > 0 ? `+${text}` : text; | |
| 58 | } | |
| 59 | ||
| 60 | /** How a margin reads against the floor: under it is danger, close to it a warning. */ | |
| 61 | export function marginTone(percent: number | null | undefined, floor: number): "danger" | "warn" | "mint" | undefined { | |
| 62 | if (percent == null) return undefined; | |
| 63 | if (percent < floor) return "danger"; | |
| 64 | if (percent < floor + 5) return "warn"; | |
| 65 | return "mint"; | |
| 66 | } | |
| 67 | ||
| 68 | /** A count: `1,234` or `1.2M`. */ | |
| 69 | export function countLabel(value: number): string { | |
| 70 | if (!Number.isFinite(value)) return "—"; | |
| 71 | if (Math.abs(value) >= 10_000_000) return `${(value / 1_000_000).toFixed(1)}M`; | |
| 72 | return Math.round(value).toLocaleString("en-US"); | |
| 73 | } | |
| 74 | ||
| 75 | /** What a kind of drift is called. */ | |
| 76 | export function driftLabel(kind: string): string { | |
| 77 | return { count: "Count", cost: "Cost", leak: "Leak" }[kind] ?? kind; | |
| 78 | } | |
| 79 | ||
| 80 | /** A cost per unit in micros, as dollars with as many places as it needs: `$0.000016`, `$0.15`. */ | |
| 81 | export function unitDollars(micros: number): string { | |
| 82 | const dollars = micros / 1_000_000; | |
| 83 | if (dollars === 0) return "$0"; | |
| 84 | if (Math.abs(dollars) >= 1) return `$${dollars.toFixed(2)}`; | |
| 85 | const places = Math.min(10, Math.max(2, 2 - Math.floor(Math.log10(Math.abs(dollars))))); | |
| 86 | return `$${dollars.toFixed(places)}`; | |
| 87 | } | |
| 88 | ||
| 89 | /** The range shown: 7 to 90 days, 30 when not said. */ | |
| 90 | export function parseRange(raw: string | null): number { | |
| 91 | const days = Number(raw); | |
| 92 | return Number.isInteger(days) && days >= 7 && days <= 90 ? days : 30; | |
| 93 | } | |
| 94 | ||
| 95 | /** The product to chart, if it is one the page has. */ | |
| 96 | export function parseBucket(raw: string | null, known: string[]): string | null { | |
| 97 | return raw && known.includes(raw) ? raw : null; | |
| 98 | } | |
| 99 | ||
| 100 | export type Parsed<T> = { ok: true; value: T } | { ok: false; error: string }; | |
| 101 | ||
| 102 | function numberField(form: FormData, name: string): number { | |
| 103 | const raw = String(form.get(name) ?? "").trim(); | |
| 104 | return raw === "" ? Number.NaN : Number(raw); | |
| 105 | } | |
| 106 | ||
| 107 | /** The guardrails from the settings form. */ | |
| 108 | export function parseCostSettings(form: FormData): Parsed<CostSettings> { | |
| 109 | const autoApplyPercent = numberField(form, "autoApplyPercent"); | |
| 110 | const noticeDays = numberField(form, "noticeDays"); | |
| 111 | const marginFloorPercent = numberField(form, "marginFloorPercent"); | |
| 112 | const alertDays = numberField(form, "alertDays"); | |
| 113 | const anomalyFactor = numberField(form, "anomalyFactor"); | |
| 114 | const minDaily = parseDollars(String(form.get("minDailyCost") ?? "")); | |
| 115 | const anomalyFloor = parseDollars(String(form.get("anomalyFloor") ?? "")); | |
| 116 | if (!(autoApplyPercent >= 0 && autoApplyPercent <= 100)) return { ok: false, error: "The guardrail is a percentage from 0 to 100." }; | |
| 117 | if (!(Number.isInteger(noticeDays) && noticeDays >= 0 && noticeDays <= 90)) return { ok: false, error: "Notice is 0 to 90 days." }; | |
| 118 | if (!(marginFloorPercent >= -100 && marginFloorPercent <= 100)) return { ok: false, error: "The margin floor is a percentage." }; | |
| 119 | if (!(Number.isInteger(alertDays) && alertDays >= 1 && alertDays <= 30)) return { ok: false, error: "Alert after 1 to 30 days." }; | |
| 120 | if (!(anomalyFactor > 0 && anomalyFactor <= 100)) return { ok: false, error: "The factor is a positive number." }; | |
| 121 | if (minDaily == null || anomalyFloor == null) return { ok: false, error: "Amounts are dollars to the cent." }; | |
| 122 | return { | |
| 123 | ok: true, | |
| 124 | value: { | |
| 125 | autoApply: form.get("autoApply") === "on", | |
| 126 | autoApplyPercent, | |
| 127 | noticeDays, | |
| 128 | marginFloorPercent, | |
| 129 | alertDays, | |
| 130 | minDailyCostMicros: minDaily, | |
| 131 | anomalyFactor, | |
| 132 | anomalyFloorMicros: anomalyFloor, | |
| 133 | }, | |
| 134 | }; | |
| 135 | } | |
| 136 | ||
| 137 | const NAME = /^(\*|[a-z0-9][a-z0-9_]{0,79})$/; | |
| 138 | ||
| 139 | /** A mapping from the mapping form: Cloudflare's product and meter (or `*`) to one of g1t's products. */ | |
| 140 | export function parseMapping(form: FormData): Parsed<CostMappingInput> { | |
| 141 | const value = (name: string) => String(form.get(name) ?? "").trim(); | |
| 142 | const product = value("product").toLowerCase(); | |
| 143 | const meter = value("meter").toLowerCase() || "*"; | |
| 144 | const remove = form.get("remove") === "1"; | |
| 145 | if (!NAME.test(product) || product === "*") return { ok: false, error: "Cloudflare's product, as the lines table names it." }; | |
| 146 | if (!NAME.test(meter)) return { ok: false, error: "A meter prefix as the lines table names it, or * for all of the product." }; | |
| 147 | if (remove) return { ok: true, value: { product, meter, remove: true } }; | |
| 148 | const bucket = value("bucket").toLowerCase(); | |
| 149 | if (!NAME.test(bucket) || bucket === "*") return { ok: false, error: "Which of g1t's products it is a cost of." }; | |
| 150 | const drift = value("driftPercent"); | |
| 151 | const driftPercent = drift === "" ? null : Number(drift); | |
| 152 | if (driftPercent != null && !(driftPercent > 0 && driftPercent <= 1000)) return { ok: false, error: "Drift is a percentage above zero." }; | |
| 153 | return { | |
| 154 | ok: true, | |
| 155 | value: { | |
| 156 | product, | |
| 157 | meter, | |
| 158 | bucket, | |
| 159 | priceMeter: value("priceMeter") || null, | |
| 160 | ownMeter: value("ownMeter") || null, | |
| 161 | scaleToOwn: form.get("scaleToOwn") === "on", | |
| 162 | driftPercent, | |
| 163 | note: value("note").slice(0, 200), | |
| 164 | }, | |
| 165 | }; | |
| 166 | } | |
| Spend caps: a monthly budget for comped workspaces and a daily breaker on what g1t pays | 167 | |
| 168 | // --- g1t's own spend (billing's budget) --------------------------------------- | |
| 169 | ||
| 170 | /** | |
| 171 | * The red bar on every sudo page: the daily breaker open, or a comped | |
| 172 | * account's monthly budget used up. Null when neither. | |
| 173 | */ | |
| 174 | export function spendBanner(caps: SpendCaps): string | null { | |
| 175 | const parts: string[] = []; | |
| 176 | if (caps.tripped) { | |
| 177 | parts.push( | |
| 178 | `the daily breaker is open (${usd(caps.todayMicros)} of ${usd(caps.dailyCapMicros)} today), so new hosted-model agent runs g1t pays for wait until 00:00 UTC`, | |
| 179 | ); | |
| 180 | } | |
| 181 | for (const budget of caps.comped) { | |
| 182 | if (budget.ceilingMicros > 0 && budget.usedMicros >= budget.ceilingMicros) { | |
| 183 | parts.push(`${budget.name} used its ${usd(budget.ceilingMicros)} monthly budget, so new work on it is refused`); | |
| 184 | } | |
| 185 | } | |
| 186 | if (parts.length === 0) return null; | |
| 187 | const text = parts.join("; and "); | |
| 188 | return `${text.charAt(0).toUpperCase()}${text.slice(1)}.`; | |
| 189 | } | |
| 190 | ||
| 191 | /** What g1t paid this month, by bucket, with the free tier and Cloudflare's subscriptions; and the total. */ | |
| 192 | export function spendRows(caps: SpendCaps): { rows: { key: string; title: string; micros: number; note: string }[]; totalMicros: number } { | |
| 193 | const notes: Record<string, string> = { | |
| 194 | comped: "Work on comped accounts, at cost", | |
| 195 | trial: "Trial credit, at cost", | |
| 196 | oss: "Checks and workflows on public repositories, at cost", | |
| 197 | given: "Free workspaces' overruns past their trial", | |
| 198 | unpaid: "Charged, but no real money yet (test-mode payments)", | |
| 199 | }; | |
| 200 | const rows = caps.monthBuckets.map((b) => ({ key: b.bucket, title: b.title, micros: b.micros, note: notes[b.bucket] ?? "" })); | |
| 201 | rows.push({ key: "free", title: "Free tier", micros: caps.freeTierMicros, note: "Free workspaces' share of git, storage and platform, reconciled through yesterday" }); | |
| 202 | rows.push({ key: "fixed", title: "Cloudflare subscriptions", micros: caps.fixedMonthlyMicros, note: "A month, estimated (CLOUDFLARE_FIXED_MONTHLY_MICROS)" }); | |
| 203 | return { rows, totalMicros: rows.reduce((sum, row) => sum + row.micros, 0) }; | |
| 204 | } | |
| 205 | ||
| 206 | /** How far a cap is used, 0 to 100, for a meter. */ | |
| 207 | export function capPercent(usedMicros: number, capMicros: number): number { | |
| 208 | if (capMicros <= 0) return 0; | |
| 209 | return Math.max(0, Math.min(100, (usedMicros / capMicros) * 100)); | |
| 210 | } |