Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

1,874 linesCodeBlameRaw
1import type { ComputeKind, Reservation } from "./compute";
2import type { PauseLevel } from "./platform";
3import type { User, Viewer } from "./identity";
4import type { RepoPath } from "./repos";
5import type { Result } from "./result";
6
7/** Millionths of a US dollar in one dollar: the unit money is held in. */
8export const MICROS_PER_DOLLAR = 1_000_000;
9
10/** Whether workspaces are charged for agents at all, and with real money. */
11export type BillingStatus = {
12 /**
13 * False when no card processor is configured: nothing is charged, and who
14 * may run agents is decided some other way.
15 */
16 enabled: boolean;
17 /** False while the card processor is in its test mode, where cards are not real. */
18 live: boolean;
19 /**
20 * True while g1t is being built out: runs are recorded with what they
21 * cost, but nothing is charged and no credit is needed. Not forever.
22 */
23 free?: boolean;
24};
25
26/** A workspace's standing. */
27export type BillingAccount = {
28 workspace: string;
29 /**
30 * Credit left, in millionths of a dollar. Can dip below zero by the cost
31 * of the runs that were under way when it ran out.
32 */
33 balanceMicros: number;
34 status: BillingStatus;
35 /** What is added to a run's cost, in percent. */
36 marginPercent: number;
37 /** The card charged near the limit and when a month closes, if one is saved. */
38 card?: { brand: string; last4: string; expMonth: number; expYear: number } | null;
39};
40
41/** One line of a workspace's statement. */
42export type LedgerEntry = {
43 id: string;
44 /** Credit bought with a card, or an agent's run. */
45 kind: "top_up" | "usage";
46 /** Positive for credit added, negative for usage. */
47 amountMicros: number;
48 description: string;
49 /** For usage: the repository and pull request the agent worked on. */
50 repo: string | null;
51 number: number | null;
52 /** For usage: `implement`, `review` or `update`. */
53 task: string | null;
54 /** For usage: the model, by its public name. */
55 model: string | null;
56 /** For usage: who paid the model provider. */
57 billedTo: "g1t" | "workspace";
58 /** For a top-up: the username of whoever paid. */
59 createdBy: string | null;
60 /** RFC 3339. */
61 createdAt: string;
62 /** The workspace the line belongs to, which tells an enterprise's lines apart. */
63 workspace?: string | null;
64 /** For usage: what the plan's included usage paid of it. `amountMicros` is what is left to pay. */
65 creditMicros?: number;
66 /** For usage: what the workspace's trial credit paid of it. */
67 trialMicros?: number;
68 /** For usage: what g1t's open-source pool paid of it. */
69 ossMicros?: number;
70 /** For usage: what g1t covered itself, such as a trial's last run past its credit. */
71 givenMicros?: number;
72 /** For usage: what a complimentary allowance from g1t paid of it. */
73 giftMicros?: number;
74 /** For usage: what the account's discount took off its price. */
75 discountMicros?: number;
76 /** For a credit from g1t, and for what of one expired or was revoked: its kind. */
77 creditKind?: CreditKind;
78};
79
80/**
81 * Why g1t gave a workspace credit. Promotional (a welcome, a referral) and
82 * goodwill (an apology) are given away when spent; a refund gives back
83 * money already paid, and never expires.
84 */
85export type CreditKind = "promotional" | "goodwill" | "refund" | "purchased";
86
87/** One credit g1t gave, with what of it was used: spent before anything paid in advance, the soonest-expiring first. */
88export type CreditGrant = {
89 /** `crd_…`, the grant's ledger reference. */
90 id: string;
91 workspace: string;
92 kind: CreditKind;
93 amountMicros: number;
94 usedMicros: number;
95 /** What can still be spent: nothing once it expired or was revoked. */
96 leftMicros: number;
97 note: string;
98 /** A refund: what it refunds, and the day of it. */
99 refundFor?: string | null;
100 refundDay?: string | null;
101 /** RFC 3339; null never expires. */
102 expiresAt: string | null;
103 createdBy: string;
104 createdAt: string;
105 state: "open" | "used" | "expired" | "revoked";
106 closedAt?: string | null;
107 closedNote?: string | null;
108 closedBy?: string | null;
109 /** What expiring or revoking took off the balance. */
110 closedMicros?: number;
111 /** What it pays for: all usage, or models only (spent first). */
112 scope?: "all" | "models";
113 /** Where it came from. */
114 source?: "staff" | "purchase" | "promo_code" | "upgrade";
115};
116
117/** A workspace's credits from g1t, newest first. */
118export type Credits = { grants: CreditGrant[]; leftMicros: number };
119
120/** One month's credits of one kind: given, spent that month, and taken back unused. */
121export type CreditMonth = {
122 month: string;
123 kind: CreditKind;
124 givenMicros: number;
125 grants: number;
126 usedMicros: number;
127 expiredMicros: number;
128 revokedMicros: number;
129};
130
131/** Every credit g1t gave (at most 200, filtered), the last 12 months by kind, and who gave them. */
132export type AdminCredits = { grants: CreditGrant[]; months: CreditMonth[]; staff: string[] };
133
134/** What a credit from sudo is, past its amount and note. */
135export type CreditOptions = {
136 kind: CreditKind;
137 /** RFC 3339; never for a refund. */
138 expiresAt?: string | null;
139 /** A refund: what it is for, and the day refunded (`YYYY-MM-DD`). */
140 refundFor?: string | null;
141 refundDay?: string | null;
142};
143
144/**
145 * How an account is charged. Standard unless g1t set otherwise in sudo:
146 * custom terms are a discount (0 to 100%), a ceiling, or both. A 100%
147 * discount charges nothing and shows the usage at its price. `comped` is
148 * from before discounts and reads as 100%; billing no longer writes it.
149 */
150export type Terms = {
151 kind: "standard" | "comped" | "custom";
152 discountPercent: number;
153 ceilingMicros: number | null;
154 note: string;
155 until: string | null;
156 setBy: string | null;
157 setAt: string | null;
158};
159
160/**
161 * Who pays: a workspace's own account, or an enterprise's, which pays for
162 * several workspaces with one bill and one limit.
163 */
164export type PayingAccount = {
165 id: string;
166 kind: "workspace" | "enterprise";
167 name: string;
168 terms: Terms;
169 workspaces: string[];
170 /** Where an enterprise's invoices go. */
171 billingEmail?: string | null;
172 /** An enterprise's invoices, newest first. */
173 invoices?: EnterpriseInvoice[];
174 createdAt: string;
175 /** What g1t staff set for the account beyond its terms. */
176 allowances?: Allowances;
177};
178
179/** Set per account by g1t staff in sudo, on top of its terms. */
180export type Allowances = {
181 /** The g1t plan without its monthly price; usage is charged as usual. Comped accounts have it anyway. */
182 plan: boolean;
183 /** Each public repository's monthly cap on g1t's open-source pool; null for the default. */
184 ossRepoMicros: number | null;
185 /** Each workspace's trial credit, outside the monthly pool; null for the default. */
186 trialMicros: number | null;
187 /** Agents at once, in place of the plan's (2 in the first month or on the trial, then 10); null for the default. */
188 maxConcurrentAgents?: number | null;
189 /** Days of audit log its workspaces keep, in place of the plan's (7 free, 90 on the plan), longer or shorter; null for the plan's. */
190 auditRetentionDays?: number | null;
191 /** A hold on new compute, with why; null for none. */
192 hold?: string | null;
193};
194
195// --- Entitlements, and compute started under a reservation ------------------
196//
197// Every service that starts compute asks billing first:
198// 1. `entitlements(workspace)`: what it may do at all, its caps, and whether compute is paused.
199// 2. `reserve(...)`: holds the estimate against what may pay for it, so starts at the same moment
200// cannot overshoot together. Answers who pays first, or refuses with a stable code
201// (`not_paid`, `trial_used`, `limit`, `paused`, `oss_pool_empty`) and a message for the owner.
202// 3. `settle(reservationId, actualMicros)`: releases the hold. The charge goes on the ledger the usual way.
203// A reservation never settled lapses after `RESERVATION_HOURS`.
204
205/** A reservation that is never settled stops holding after this long. */
206export const RESERVATION_HOURS = 3;
207/** What a ceiling reads as when there is none (g1t's own workspaces). */
208export const UNLIMITED_MICROS = 1_000_000_000_000_000;
209
210/** What a workspace pays g1t on, as far as compute is concerned. Mirrors `PlanKind`. */
211export type PlanKind = "free" | "paid" | "internal" | "enterprise" | "complimentary";
212
213// `ComputeKind` (what compute is for), `PaidBy` (who pays first: credit, trial, oss, on_demand) and
214// `Reservation` are in `./compute`, with the gate that calls `reserve` and `settle`.
215
216/** One level reached: 50, 75, 90 or 100 percent. */
217export type UsageAlert = {
218 /** `included` (the plan's included usage), `spend_limit` or `ceiling`. */
219 meter: "included" | "spend_limit" | "ceiling" | string;
220 level: number;
221 usedMicros: number;
222 limitMicros: number;
223 message: string;
224};
225
226/** An hour's spend well above the workspace's usual: new compute waits for an owner. */
227export type Spike = {
228 id: string;
229 /** `open` (waiting), `continued` (keep going) or `stopped`. */
230 status: "open" | "continued" | "stopped" | string;
231 hourMicros: number;
232 averageMicros: number;
233 detectedAt: string;
234 decidedBy?: string | null;
235 decidedAt?: string | null;
236 /** While continued: until when, unless spend doubles again first. */
237 until?: string | null;
238};
239
240/** What a workspace may do now. Mirrors `Entitlements` in `crates/contracts/src/billing.rs`. */
241export type Entitlements = {
242 workspace: string;
243 plan: PlanKind;
244 /** May start sandboxes, models, deployments and semantic search at all: paid, internal, enterprise, or free with trial credit left. */
245 compute: boolean;
246 /** The one-time trial credit left; 0 if none or used. */
247 trialMicrosLeft: number;
248 /** A card check has been done; the trial and the open-source pool need it. */
249 trialVerified: boolean;
250 /** A paid workspace still in its first billing cycle. */
251 firstMonth: boolean;
252 /** 2 in the first month or on the trial, 10 after; staff can override it. */
253 maxConcurrentAgents: number;
254 /** 60 in the first month or on the trial; otherwise the guardrails' own caps. */
255 maxRunMinutes: number;
256 /** g1t's ceiling on usage not yet paid for; `UNLIMITED_MICROS` for g1t's own; 0 for free. */
257 ceilingMicros: number;
258 /** Usage not yet paid for this month, prepayment taken off. */
259 exposureMicros: number;
260 /** Why new compute is paused, for the owner; null when it is not. */
261 paused: string | null;
262 /** g1t staff put a hold on the account: nothing new is set up for it, such as a self-hosted runner. */
263 held?: boolean;
264 /** What open reservations hold now. */
265 heldMicros?: number;
266 /** Paid in advance and not used yet. */
267 prepaidMicros?: number;
268 /** The plan's included usage each month, and what of it is used. */
269 includedMicros?: number;
270 includedUsedMicros?: number;
271 /** How far back the audit log can be read and exported, and what is kept: the plan's days, or what g1t staff set for the account. */
272 auditRetentionDays: number;
273 /** Whether `auditRetentionDays` is what staff set for the account rather than the plan's. */
274 auditRetentionCustom?: boolean;
275 /** Private repository storage free for every workspace: past it, the plan pays and a free workspace's pushes stop. */
276 freePrivateStorageBytes: number;
277 /** The last daily measure of the workspace's private repositories (a lower bound). */
278 privateStorageBytes: number;
279 /** On a paid plan: package storage past the free amounts is charged, never refused. */
280 hasPlan?: boolean;
281 /** Package storage free for every workspace (public, and private): past it a free workspace's pushes are refused. */
282 packagePublicFreeBytes?: number;
283 packagePrivateFreeBytes?: number;
284 /** What g1t's open-source pool paid for the workspace this month. */
285 ossPaidMicros: number;
286 /** Deploy build time this month, every second of it metered. */
287 buildSecondsUsed?: number;
288 /** Git operations this month, and how many are free for every workspace. */
289 gitOperations?: number;
290 gitOperationsIncluded?: number;
291 /** The smallest amount a card is charged when a month closes. */
292 minChargeMicros: number;
293 /** A spend spike waiting for an owner, or decided. */
294 spike?: Spike | null;
295 /** Where usage stands against what is included and the limits, from 50%. */
296 alerts?: UsageAlert[];
297 /** A complimentary enrollment's allowance this month. */
298 complimentary?: ComplimentaryMonth | null;
299};
300
301/** A complimentary allowance this calendar month (UTC). Usage counts at its ordinary price. Mirrors `ComplimentaryMonth`. */
302export type ComplimentaryMonth = {
303 /** `YYYY-MM`. */
304 month: string;
305 allowanceMicros: number;
306 unlimited?: boolean;
307 /** Usage this month the allowance paid for. */
308 usedMicros: number;
309 /** Metered this month and not on the ledger yet (storage, git operations), which the allowance will pay for. */
310 pendingMicros?: number;
311 /** What running work holds against it. */
312 heldMicros?: number;
313 /** What is left after all three: at 0, new work that costs money stops. */
314 remainingMicros: number;
315 /** What g1t covered past the allowance this month: never charged. */
316 overrunMicros?: number;
317 /** RFC 3339: when next month's allowance starts. */
318 resetsAt: string;
319 /** The recurring monthly fee, in cents; 0: waived. */
320 feeCents?: number;
321 /** Past the allowance, usage is charged to the workspace's own card under its limits; otherwise new paid work stops. */
322 chargePastAllowance?: boolean;
323 /** A card is on file to charge past the allowance. */
324 hasCard?: boolean;
325};
326
327/** A complimentary enrollment, as sudo shows it. Mirrors `ComplimentaryStanding`. */
328export type ComplimentaryStanding = {
329 workspace: string;
330 grantId: string;
331 /** `pending` (Stripe not confirmed yet), `active` or `ended`. */
332 status: "pending" | "active" | "ended";
333 allowanceMicros: number;
334 unlimited?: boolean;
335 feeCents?: number;
336 chargePastAllowance?: boolean;
337 live?: boolean;
338 customerId?: string | null;
339 subscriptionId?: string | null;
340 stripeStatus?: string | null;
341 /** A Stripe step still owed, tried again every fifteen minutes. */
342 pendingOp?: "create" | "terms" | "cancel" | "convert" | null;
343 lastError?: string | null;
344 note: string;
345 createdBy: string;
346 createdAt: string;
347 updatedBy: string;
348 updatedAt: string;
349 endedAt?: string | null;
350 endedReason?: "revoked" | "converted" | null;
351 month?: ComplimentaryMonth | null;
352 periods?: ComplimentaryPeriod[];
353 /** Money actually paid to g1t, all time: plan and fee invoices, prepayments, bank transfers. */
354 moneyReceivedMicros?: number;
355 /** Promotional and goodwill credit from g1t, all time: never money. */
356 promotionalCreditMicros?: number;
357 /** Usage complimentary allowances paid for, all time: never money. */
358 giftedMicros?: number;
359};
360
361export type ComplimentaryPeriod = {
362 id: string;
363 startsAt: string;
364 endsAt?: string | null;
365 allowanceMicros: number;
366 unlimited?: boolean;
367 feeCents?: number;
368 chargePastAllowance?: boolean;
369 note: string;
370 createdBy: string;
371};
372
373/** Where an owner's conversion to the plan stands. */
374export type Conversion = {
375 status: "converted" | "needs_card" | "needs_action" | "declined";
376 url?: string | null;
377 message: string;
378};
379
380/** A hold on a start's estimated cost, as billing answers it (`Reservation` in `./compute`, and more). */
381export type ReservationHeld = Reservation & {
382 /** What is held, at cost; may be less than the estimate for a free workspace's last bit of trial. */
383 heldMicros?: number;
384 /** When the hold lapses if never settled. */
385 expiresAt?: string;
386};
387
388/** A request to g1t: a higher limit, or help with usage past what was meant. */
389export type LimitRequest = {
390 id: string;
391 workspace: string;
392 kind: "limit" | "overage" | string;
393 amountMicros: number;
394 reason: string;
395 expectedMonthlyMicros: number;
396 status: "open" | "approved" | "declined" | string;
397 decidedMicros?: number | null;
398 decidedBy?: string | null;
399 /** The answer, as the owner sees it. */
400 answer?: string | null;
401 createdBy: string;
402 createdAt: string;
403 decidedAt?: string | null;
404};
405
406/** What staff see beside a request. */
407export type WorkspaceHistory = {
408 plan: PlanKind | null;
409 months: MonthFigures[];
410 paidClearedMicros: number;
411 payments: number;
412 disputes: number;
413 declines: number;
414 firstSeen: string | null;
415 ceilingMicros: number | null;
416 maxCeilingMicros: number | null;
417 spendLimitMicros: number | null;
418 lastHourMicros: number;
419 averageHourMicros: number;
420 lastDayMicros: number;
421};
422
423export type LimitRequestReview = { request: LimitRequest; history: WorkspaceHistory };
424
425/** What a one-time goodwill credit comes to: the margin on the overage, always, plus its cost up to the cap. */
426export type Goodwill = {
427 overageMicros: number;
428 marginMicros: number;
429 costMicros: number;
430 creditMicros: number;
431 absorbedMicros: number;
432};
433
434/** A workspace whose month went well past its usual, or hit a spike. */
435export type Overage = {
436 workspace: string;
437 plan: PlanKind;
438 typicalMonthMicros: number;
439 thisMonthMicros: number;
440 costMicros: number;
441 marginMicros: number;
442 spike: Spike | null;
443 topEntries: LedgerEntry[];
444 goodwill: Goodwill;
445 goodwillAvailable: boolean;
446 lastGoodwillAt: string | null;
447 request: LimitRequest | null;
448};
449
450/** One workspace's recent pace. */
451export type Velocity = {
452 workspace: string;
453 plan: PlanKind;
454 lastHourMicros: number;
455 averageHourMicros: number;
456 lastDayMicros: number;
457 thisMonthMicros: number;
458 ratio: number;
459 spike: Spike | null;
460 firstSeen: string | null;
461};
462
463/** g1t's capped budgets for free usage this month. */
464export type Pools = {
465 month: string;
466 trialGrantedMicros: number;
467 trialPoolMicros: number;
468 trialGrants: number;
469 ossUsedMicros: number;
470 ossPoolMicros: number;
471 ossRepoMicros: number;
472};
473
474export type AccountSummary = {
475 account: PayingAccount;
476 limit: Limit;
477 chargedMicros: number;
478 costMicros: number;
479 paidMicros: number;
480 /** The same figures for each of the account's workspaces that has any. */
481 byWorkspace: WorkspaceFigures[];
482 /** The last six months, oldest first. */
483 months?: MonthFigures[];
484};
485
486/** One workspace's share of an `AccountSummary`. */
487export type WorkspaceFigures = { workspace: string; chargedMicros: number; costMicros: number; paidMicros: number };
488
489export type StripeStatus = {
490 /** `test` or `live`, from the key; `off` without one. */
491 mode: "test" | "live" | "off" | string;
492 /** Whether `STRIPE_WEBHOOK_SECRET` is set, so events can be checked. */
493 secretSet: boolean;
494 /** The destination at billing's address in Stripe, as Stripe has it. */
495 webhook: { url: string; endpointId: string; status: "enabled" | "disabled" | string; events: string[]; createdAt: string } | null;
496 /** Events billing handles that the destination does not send. */
497 missingEvents: string[];
498 recentEvents: { id: string; kind: string; outcome: string; receivedAt: string }[];
499 error: string | null;
500 /** Stripe Tax for the key's mode: `active`, or `pending` with the settings it still needs. Null when it could not be read. */
501 tax?: { status: "active" | "pending" | string; missingFields: string[] } | null;
502 /** The customer portal configuration billing makes (`metadata[g1t]=billing`). Null until the first portal session makes it. */
503 portal?: { configurationId: string; active: boolean } | null;
504};
505
506/** An enterprise's invoice: one line per workspace, paid on Stripe's page. */
507export type EnterpriseInvoice = {
508 invoiceId: string;
509 hostedUrl: string | null;
510 amountMicros: number;
511 status: "open" | "paid" | "overdue" | "void" | string;
512 period: string;
513 lines: { workspace: string; amountMicros: number }[];
514 createdAt: string;
515};
516
517/** A workspace's invoice: monthly, or when charged near its limit. Itemised, in Stripe's billing page. */
518export type WorkspaceInvoice = {
519 invoiceId: string;
520 workspace: string;
521 reason: "month" | "threshold" | string;
522 period: string;
523 amountMicros: number;
524 status: "paid" | "open" | "failed" | "void" | string;
525 hostedUrl: string | null;
526 pdfUrl: string | null;
527 lines: { description: string; amountMicros: number }[];
528 createdAt: string;
529 /** The card processing fee on top of `amountMicros` (only on invoices from before g1t's prices included it), and the tax Stripe added once known. */
530 feeMicros?: number;
531 taxMicros?: number;
532};
533
534/** A month of the ledger, grouped by day or project, a line per kind of charge. */
535export type Statement = {
536 month: string;
537 months: string[];
538 groups: {
539 key: string;
540 label: string;
541 /** `coveredMicros`: what the plan's included usage, the trial, the open-source pool or g1t paid, not in `chargedMicros`. */
542 /** `priceMicros`: usage at its price; `discountMicros`: what the account's discount took off it. */
543 lines: {
544 kind: string;
545 count: number;
546 chargedMicros: number;
547 costMicros: number;
548 coveredMicros?: number;
549 priceMicros?: number;
550 discountMicros?: number;
551 /** On `Tax` and `Card processing fees` lines: what was paid with payments on top of what reached the balance. Never charged. */
552 passedMicros?: number;
553 /** On a `Runner minutes, <machine>` line: the minutes charged, each job's time rounded up to the minute. */
554 minutes?: number;
555 }[];
556 chargedMicros: number;
557 priceMicros?: number;
558 discountMicros?: number;
559 }[];
560 totals: {
561 chargedMicros: number;
562 paidMicros: number;
563 costMicros: number;
564 entries: number;
565 /** Usage at price, and what the discount took off: charged is the price less the discount and what paid for it. */
566 priceMicros?: number;
567 discountMicros?: number;
568 /** The account's discount now, in percent; absent without one. */
569 discountPercent?: number | null;
570 /** What paid for usage before it was charged, such as "Paid by g1t's open-source pool". */
571 covered?: { source: "included" | "trial" | "oss_pool" | "given" | string; label: string; micros: number }[];
572 /** Owed when the month closed but under the minimum charge: on the next invoice. */
573 carriedMicros?: number;
574 /** Tax and card processing fees paid with the month's payments, on top of `paidMicros`. */
575 taxMicros?: number;
576 cardFeeMicros?: number;
577 };
578};
579
580export type MonthFigures = {
581 month: string;
582 /** Usage charged, after what paid for it first. */
583 chargedMicros: number;
584 /** What usage cost g1t: never a workspace's own model provider. */
585 costMicros: number;
586 paidMicros: number;
587 /** The plan's monthly price, paid. */
588 plansMicros?: number;
589 /** What g1t gave at price (internal use, trials, the open-source pool, goodwill, covered). Not margin. */
590 givenMicros?: number;
591};
592
593/** What g1t gave this month from one source. */
594export type GivenFigures = { source: "internal" | "trial" | "oss_pool" | "goodwill" | "covered" | string; label: string; micros: number; costMicros: number };
595
596/** One internal workspace's use this month, and why it is not charged. */
597export type InternalUse = { workspace: string; reason: string; costMicros: number; entries: number };
598
599export type SignalKind = "at_limit" | "near_ceiling" | "declined" | "growing" | "established" | "first_payment" | "high_spend" | "cost_over_revenue";
600
601/** Why a workspace is worth reaching out to. */
602export type Signal = {
603 workspace: string;
604 kind: SignalKind;
605 detail: string;
606 valueMicros: number;
607 stage: string | null;
608 owner: string | null;
609 nextStep?: string | null;
610 /** When the next step is due, YYYY-MM-DD. */
611 nextAt?: string | null;
612};
613
614/** One invoice g1t has sent, a workspace's or an enterprise's. */
615export type InvoiceSummary = {
616 invoiceId: string;
617 kind: "workspace" | "enterprise";
618 account: string;
619 name: string;
620 reason: string;
621 period: string;
622 amountMicros: number;
623 status: string;
624 hostedUrl: string | null;
625 createdAt: string;
626 paidAt: string | null;
627};
628
629export type SalesStage = "none" | "lead" | "contacted" | "negotiating" | "won" | "lost" | "churn_risk";
630
631export type SalesRecord = {
632 workspace: string;
633 stage: SalesStage | string;
634 owner: string | null;
635 nextStep: string | null;
636 nextAt: string | null;
637 notes: { id: string; text: string; by: string; createdAt: string }[];
638 updatedAt: string | null;
639};
640
641export type Overview = {
642 month: string;
643 months: MonthFigures[];
644 byKind: { kind: string; chargedMicros: number; costMicros: number }[];
645 payingWorkspaces: number;
646 stopped: number;
647 nearCeiling: number;
648 declined: number;
649 openInvoicesMicros: number;
650 followUpsDue: number;
651 /** g1t's capped budgets for free usage, this month. */
652 pools?: Pools | null;
653 /** Usage charged plus the plan's price paid, this month. */
654 revenueMicros?: number;
655 activePlans?: number;
656 planMrrMicros?: number;
657 /** What g1t gave this month, by source, apart from its margin. */
658 given?: GivenFigures[];
659 /**
660 * This month so far by the Costs & margin model, the same figures the
661 * Costs page adds up (Cloudflare's bill included, credits spent among
662 * what was given), through `marginThrough`. Null before the month's
663 * first day is rolled up.
664 */
665 monthMargin?: OverallMargin | null;
666 /** The last day `monthMargin` holds. YYYY-MM-DD. */
667 marginThrough?: string | null;
668 /** g1t's own and Flagon's workspaces: what their use cost, and why they are not charged. */
669 internal?: InternalUse[];
670 openRequests?: number;
671 overages?: number;
672 openSpikes?: number;
673};
674
675/** A customer's Stripe billing page, for staff to send them. */
676export type BillingLink = {
677 /** One-time and short-lived, signed in already. */
678 portalUrl: string;
679 /** The page's sign-in, which does not expire: the customer signs in by email. */
680 loginUrl: string | null;
681 customerEmail: string | null;
682 expiresNote: string;
683};
684
685export type AdminAction = { id: string; account: string; action: string; detail: string; by: string; createdAt: string };
686
687export type AccountDetail = {
688 summary: AccountSummary;
689 workspaces: Limit[];
690 ledger: LedgerEntry[];
691 audit: AdminAction[];
692};
693
694/** Staff-only billing, for sudo.g1t.sh. Every change names who made it. */
695export interface BillingAdminApi {
696 accounts(query?: string): Promise<AccountSummary[]>;
697 account(id: string): Promise<Result<AccountDetail>>;
698 setTerms(id: string, terms: Terms, by: string): Promise<Result<PayingAccount>>;
699 /** Team on or off without charge, and the account's share of the pools. Needs a note. */
700 setAllowances(id: string, allowances: Allowances, note: string, by: string): Promise<Result<PayingAccount>>;
701 /** A workspace's complimentary enrollment, if it ever had one. */
702 complimentary(workspace: string): Promise<ComplimentaryStanding | null>;
703 /**
704 * Enrolls a workspace, or changes its terms from now on (the month's use is kept). Needs a note.
705 * `chargePastAllowance`: past the allowance, its own card is charged (employees, friends); otherwise work stops.
706 */
707 setComplimentary(
708 workspace: string,
709 terms: { allowanceMicros: number; unlimited: boolean; feeCents: number; chargePastAllowance: boolean },
710 note: string,
711 by: string,
712 ): Promise<Result<ComplimentaryStanding>>;
713 /** Ends an enrollment now: back to Free, its Stripe subscription canceled. */
714 endComplimentary(workspace: string, note: string, by: string): Promise<Result<ComplimentaryStanding>>;
715 createEnterprise(name: string, workspaces: string[], by: string): Promise<Result<PayingAccount>>;
716 attach(workspace: string, account: string | null, by: string): Promise<Result<PayingAccount>>;
717 /** Credit for a workspace: promotional, goodwill or a refund; the owners are emailed. */
718 credit(workspace: string, amountMicros: number, note: string, by: string, options?: CreditOptions): Promise<Result<LedgerEntry>>;
719 /** Every credit g1t gave, filtered, with each month's totals by kind. */
720 credits(filter?: { workspace?: string | null; kind?: CreditKind | null; month?: string | null; by?: string | null }): Promise<AdminCredits>;
721 /** What is left of a credit, taken back, with why. */
722 revokeCredit(id: string, note: string, by: string): Promise<Result<CreditGrant>>;
723 /** A test workspace's billing wiped, to start again as a new customer. Only on Stripe's test key; never comped or enterprise. Logged. */
724 resetBilling(workspace: string, confirm: string, note: string, by: string): Promise<Result<BillingReset>>;
725 /**
726 * Test-mode Stripe data made inert before the live key, history kept: one
727 * workspace (any but an enterprise's), or every workspace not comped, not an
728 * enterprise's and not excluded (default syntaqx, flagon-io). Refused on a live key. Logged.
729 */
730 detachTestStripe(args: DetachTestStripeArgs): Promise<Result<TestStripeDetach>>;
731 /** The workspace's Stripe billing page, to send to the customer. Logged. */
732 billingLink(workspace: string, by: string): Promise<Result<BillingLink>>;
733 /** Where billing stands with Stripe; with `setup`, registers the webhook first. */
734 /** Stripe's state for billing; `fix` enables the destination and adds missing events first. */
735 stripe(fix?: boolean, by?: string): Promise<StripeStatus>;
736 /** Where an enterprise's invoices go; makes its Stripe customer. */
737 enterpriseBilling(id: string, email: string, by: string): Promise<Result<PayingAccount>>;
738 /** The enterprise's billing address and tax ID, on its Stripe customer: Stripe Tax works its invoices out from them. */
739 enterpriseAddress(id: string, address: PostalAddress, taxIdType: string | null, taxId: string | null, by: string): Promise<Result<boolean>>;
740 /** Sends an enterprise its invoice now, for what its workspaces owe. */
741 invoiceEnterprise(id: string, by: string): Promise<Result<EnterpriseInvoice>>;
742 /** Exactly these workspaces' accounts, such as one page of the list. */
743 accountsFor(workspaces: string[]): Promise<AccountSummary[]>;
744 /** Every workspace worth reaching out to, most urgent first. */
745 signals(): Promise<Signal[]>;
746 /** The business at a glance. */
747 overview(): Promise<Overview>;
748 /** A workspace's sales record. */
749 sales(workspace: string): Promise<SalesRecord>;
750 setSales(
751 workspace: string,
752 record: { stage: string; owner?: string | null; nextStep?: string | null; nextAt?: string | null },
753 by: string,
754 ): Promise<Result<SalesRecord>>;
755 addNote(workspace: string, text: string, by: string): Promise<Result<SalesRecord>>;
756 /** A workspace's invoices from g1t, for staff. */
757 workspaceInvoices(workspace: string): Promise<WorkspaceInvoice[]>;
758 /** Every invoice g1t has sent, newest first. */
759 allInvoices(filter?: { status?: string; month?: string }): Promise<InvoiceSummary[]>;
760 /** Every change made in sudo and by Stripe, newest first, 100 at a time. */
761 audit(filter?: { by?: string; action?: string; before?: string }): Promise<AdminAction[]>;
762 /** Limit and overage requests, with each workspace's history; `open` by default. */
763 limitRequests(status?: "open" | "approved" | "declined" | "all"): Promise<LimitRequestReview[]>;
764 /** Approve (at the amount asked, or another) or decline; the owner is told in the app and by email. */
765 decideLimitRequest(id: string, decision: "approve" | "decline", amountMicros: number | null, note: string, by: string): Promise<Result<LimitRequest>>;
766 /** The Overages queue. */
767 overages(): Promise<Overage[]>;
768 /** A goodwill credit; no amount is the one-click credit. Larger, or a second in 12 months, needs a reason. `requestKey`, made once per form, makes a double click or a retry one credit. */
769 goodwill(
770 workspace: string,
771 amountMicros: number | null,
772 reason: string,
773 by: string,
774 day?: string | null,
775 requestKey?: string | null,
776 ): Promise<Result<LedgerEntry>>;
777 /** Workspaces spending in the last day, fastest first. */
778 velocity(): Promise<Velocity[]>;
779 /** Money that reached g1t outside the card pages, such as a bank transfer: entered as a payment. */
780 recordPayment(workspace: string, amountMicros: number, reference: string, note: string, by: string): Promise<Result<LedgerEntry>>;
781 /** Costs & margin: Cloudflare's bill against what g1t charged, over the last `days` (7 to 90, 30 by default). */
782 costs(days?: number): Promise<CostsReport>;
783 /** The open margin alerts, for the banner on every page. */
784 costAlerts(): Promise<MarginAlert[]>;
785 /** g1t's own spend against its caps: the daily breaker and comped budgets. */
786 spendCaps(): Promise<SpendCaps>;
787 /** Lets compute start again for the rest of today (UTC) after the daily breaker; needs a note. */
788 liftBreaker(note: string, by: string): Promise<Result<SpendCaps>>;
789 /** Platform pauses, the last hour of platform usage, the month so far and the last day's breaches (billing's platform.rs). */
790 platformGuard(): Promise<PlatformGuard>;
791 /** Pauses or resumes one level across g1t; needs a note, recorded in the audit log. */
792 setPause(level: PauseLevel, paused: boolean, note: string, by: string): Promise<Result<PlatformGuard>>;
793 /** Approve or reject a price proposal; a rejection needs a note. An approved rise waits out the notice period. */
794 decideProposal(id: string, decision: "approve" | "reject", note: string, by: string): Promise<Result<PriceProposal>>;
795 setCostSettings(settings: CostSettings, by: string): Promise<Result<CostSettings>>;
796 setCostMapping(mapping: CostMappingInput, by: string): Promise<Result<CostMapping>>;
797 /** Reads Cloudflare's bill and reconciles now, as the daily run does. */
798 runCosts(by: string): Promise<Result<CostsRun>>;
799}
800
801/** How much a workspace has earned g1t's trust with money. */
802export type Trust = "new" | "paid" | "established" | "reviewed" | "internal";
803
804/**
805 * How far a workspace's unpaid usage has gone this month, and where its
806 * work stops: past `ceilingMicros`, no new sandboxes, builds or app
807 * requests. Usage counts at its cost to g1t or its charge, whichever is
808 * more, so it counts while g1t is free too.
809 */
810export type Limit = {
811 workspace: string;
812 /** The account that pays: the workspace's own (`ws_<slug>`), or its enterprise's. */
813 account: string;
814 accountName: string;
815 trust: Trust;
816 exposureMicros: number;
817 /** The lower of g1t's ceiling and the owner's spend limit; null for g1t's own. */
818 ceilingMicros: number | null;
819 trustCeilingMicros: number | null;
820 spendLimitMicros: number | null;
821 state: "ok" | "warning" | "stopped";
822 message: string | null;
823 /**
824 * Charged this month, which the spend limit is measured against: usage at
825 * price less the discount, included usage, the trial, pools and credit,
826 * with usage metered through the month counted on the same terms. The
827 * same number as the month's `UsageTotals.chargedMicros`.
828 */
829 spentMicros?: number;
830 /** True while the owners have not chosen a limit, so the automatic one applies: $200, or twice last month's spend. */
831 defaultSpendLimit?: boolean;
832 /** The most owners may set their own limit to without asking: the highest ceiling ever, plus what is prepaid. */
833 availableMicros?: number | null;
834 /** How the ceiling grows from here, in a sentence. */
835 growth?: string | null;
836 /** Paid in advance and not used yet; raises what can be used before work stops by as much. */
837 prepaidMicros?: number;
838 /** The highest ceiling the workspace has had. */
839 maxCeilingMicros?: number | null;
840 /** The most owners may raise the limit to themselves, once: twice the highest ceiling. Null once used. */
841 raiseOnceMicros?: number | null;
842 /** When the one-time raise was used. */
843 raisedAt?: string | null;
844 /** A paid workspace's first billing cycle, on the starting ceiling. */
845 firstMonth?: boolean;
846 /** The budget's alerts, in percent of the spend limit: some of 50, 75, 90 and 100. */
847 alertLevels?: number[];
848 /** Whether usage pauses at the spend limit (the default); off, it only alerts. */
849 pauseAtLimit?: boolean;
850 /** An HTTPS address told of each budget alert. */
851 budgetWebhook?: string | null;
852};
853
854/** One metered unit: what it costs g1t and what it is sold at; the price follows the cost. */
855export type Price = {
856 meter:
857 | "sandbox_second"
858 | "build_second"
859 | "app_requests"
860 | "app_cpu"
861 | "app_month"
862 | "custom_domain_month"
863 | "private_storage"
864 | "embedding_tokens"
865 | "scan_cpu"
866 | "scan_rows"
867 | string;
868 title: string;
869 unit: string;
870 costMicros: number;
871 markupPercent: number;
872 priceMicros: number;
873 /** `list`: Cloudflare's published price. `cloudflare`: measured from Cloudflare's bill. */
874 source: "list" | "cloudflare" | string;
875 checkedAt: string | null;
876 updatedAt: string;
877};
878
879export type PriceChange = {
880 meter: string;
881 oldCostMicros: number;
882 newCostMicros: number;
883 markupPercent: number;
884 /** The markup before, when the change was to the markup rather than the cost. */
885 oldMarkupPercent?: number;
886 reason: string;
887 createdAt: string;
888 /** When a change still to come takes effect: a rise is announced before it is charged. */
889 effectiveAt?: string;
890};
891
892export type PriceBook = {
893 prices: Price[];
894 changes: PriceChange[];
895 /** Retired with the models g1t no longer runs; still sent. */
896 modelMarginPercent: number;
897 /** Every plan, as sold now. */
898 plans?: FeaturePlan[];
899 /** What is free, and the capped budgets that pay for it. */
900 free?: FreeTier | null;
901};
902
903/** One kind of meter's usage this month, from `usage_meters`. */
904export type MeterUsage = {
905 /** `agents`, `builds`, `requests`, `domains`, `git_storage` or `search_scans`. */
906 key: string;
907 label: string;
908 /** At price (cost plus 20%, on the account's terms), before what paid for it. */
909 micros: number;
910 /** How much, when it is known: `12 runs`, `41 build minutes`. */
911 quantity?: string | null;
912};
913
914/** What g1t gives without a plan; each is paid for by a capped budget. */
915export type FreeTier = {
916 /** Each new workspace's trial credit, once. */
917 trialWorkspaceMicros: number;
918 /** Trial grants each month, in all; new trials wait when it is spent. */
919 trialMonthlyPoolMicros: number;
920 /** g1t's open-source pool each month, and any one repository's share. */
921 ossPoolMicros: number;
922 ossRepoMicros: number;
923 /** Private repository storage free for every workspace. Past it, the plan pays; a free workspace's pushes stop. */
924 freePrivateStorageBytes: number;
925 /** Days of audit log a free workspace keeps. */
926 auditRetentionDays: number;
927 /** Days of audit log the g1t plan keeps, and g1t's own and enterprise workspaces; longer by arrangement. */
928 planAuditRetentionDays?: number;
929 /** The smallest amount a card is charged when a month closes; less carries over. */
930 minChargeMicros: number;
931 /** Git operations free for every workspace each month. Past it, the plan pays; a free workspace is slowed down. */
932 gitOperationsIncluded?: number;
933 /** A new paid workspace's ceiling in its first month. */
934 paidStartCeilingMicros?: number;
935 /** The most a one-click goodwill credit can cost g1t. */
936 overageForgiveCostMicros?: number;
937};
938
939/**
940 * A workspace's trial credit: one grant per workspace, made the first time
941 * it uses something, out of a pool that resets each calendar month. Mirrors
942 * `Trial` in `crates/contracts/src/billing.rs`.
943 */
944export type Trial = {
945 open: boolean;
946 usedMicros: number;
947 limitMicros: number;
948 /** No longer used: trials do not end on a date. */
949 endsAt: string | null;
950 /** Why it is closed: `off`, `used` (this workspace's grant is spent) or `pool` (this month's are given out). */
951 reason: "off" | "ended" | "used" | "pool" | null;
952 /** Whether the workspace has its grant already. */
953 granted?: boolean;
954 /** With `pool`: when new trials start again, the first of next month. */
955 waitsUntil?: string | null;
956};
957
958/**
959 * What a workspace has: the g1t plan (`plan`), and Security and quality
960 * (`security`), which comes with the plan at no price of its own. Deployments
961 * are part of the plan too; `has_feature` for either answers whether the
962 * workspace has the plan. Mirrors `Feature` in `crates/contracts/src/billing.rs`.
963 */
964export type Feature = "plan" | "deployments" | "security";
965
966/**
967 * What deployments cost g1t, in millionths of a dollar: fallbacks for when
968 * billing's price book cannot be read. Not an allowance: on the plan every
969 * unit is metered from the first, at cost plus 20%, and drawn from the
970 * plan's included usage first. Projects, previews and the apps behind them
971 * are not metered at all. Mirrors `deployment_costs`.
972 */
973export const DEPLOYMENT_COSTS = {
974 microsPerMillionRequests: 300_000,
975 microsPerMillionCpuMs: 20_000,
976 /** One second of a build's sandbox: a fallback; billing charges the price book's `build_second`. */
977 microsPerBuildSecond: 15,
978 /** One custom domain for a month. */
979 microsPerDomainMonth: 100_000,
980 /**
981 * Container apps, at Cloudflare Containers' list prices: a vCPU-second
982 * $0.00002, a GiB-second of memory $0.0000025, a GB-second of disk
983 * $0.00000007, the Durable Object in front of each instance while it
984 * runs (128 MB at $12.50 per million GB-seconds), and a GB of egress
985 * at $0.05, the most Cloudflare charges for one anywhere (Oceania, Korea
986 * and Taiwan; $0.025 in North America and Europe), since g1t cannot
987 * tell where a container's traffic went.
988 */
989 container: {
990 vcpuSecond: 20,
991 memoryGibSecond: 2.5,
992 diskGbSecond: 0.07,
993 instanceSecond: 1.5625,
994 egressGb: 50_000,
995 },
996} as const;
997
998export type FeaturePlan = {
999 feature: Feature;
1000 title: string;
1001 /** Charged every month while the plan is on, in cents, excluding tax: all of it, with no card fee on top. */
1002 monthlyCents: number;
1003 /** What the price includes, one line each. */
1004 includes: string[];
1005 /** How usage past the allowance is charged. */
1006 overage: string;
1007};
1008
1009export type SubscriptionStatus = "active" | "canceling" | "past_due" | "canceled";
1010
1011export type Subscription = {
1012 feature: Feature;
1013 status: SubscriptionStatus;
1014 /** RFC 3339: when the period paid for ends. */
1015 periodEnd: string | null;
1016 startedBy: string;
1017 startedAt: string;
1018};
1019
1020/** A feature as a workspace sees it. */
1021export type FeatureState = {
1022 plan: FeaturePlan;
1023 subscription: Subscription | null;
1024 /** Whether the feature works for the workspace now. */
1025 on: boolean;
1026 /** On without a plan: comped terms, or given by g1t. Nothing to pay or turn off. */
1027 included?: boolean;
1028};
1029
1030export interface BillingApi {
1031 status(): Promise<BillingStatus>;
1032 /** Members of the workspace only. */
1033 account(workspace: string, viewer: Viewer): Promise<Result<BillingAccount>>;
1034 /** Newest first. Members of the workspace only. */
1035 ledger(workspace: string, viewer: Viewer): Promise<Result<LedgerEntry[]>>;
1036 /** Credits from g1t, newest first, with what is left of each. Members only. */
1037 credits(workspace: string, viewer: Viewer): Promise<Result<Credits>>;
1038 /** A month of the ledger, grouped by `day` (default) or `project`. Members only. */
1039 statement(workspace: string, viewer: Viewer, month?: string | null, group?: "day" | "project"): Promise<Result<Statement>>;
1040 /** One statement line's entries, 50 at a time; `before` is the last id seen. */
1041 statementEntries(
1042 workspace: string,
1043 viewer: Viewer,
1044 filter: { month: string; kind: string; day?: string | null; project?: string | null; before?: string | null },
1045 ): Promise<Result<LedgerEntry[]>>;
1046 /** What the workspace's agents cost since `since`, broken down. Members only. */
1047 usage(workspace: string, viewer: Viewer, since: string): Promise<Result<Usage>>;
1048 /**
1049 * Prepays usage ($25 at least) and returns the page to send the person to:
1050 * by card with 3-D Secure, or by bank transfer from $1,000. Owners only.
1051 * The payment's id comes back to `returnUrl` as `session`.
1052 */
1053 checkout(actor: User, workspace: string, amountCents: number, returnUrl: string, method?: "card" | "bank_transfer"): Promise<Result<{ url: string }>>;
1054 /**
1055 * Stripe's hosted billing page for the workspace: card, invoices, billing
1056 * email and address. g1t never handles card numbers. Owners only.
1057 */
1058 billingPortal(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
1059 /** Credits a payment once the processor says it was made. Safe to repeat. */
1060 confirm(workspace: string, viewer: Viewer, session: string): Promise<Result<BillingAccount>>;
1061 /** A workspace's free trial allowance; `exempt` workspaces are open anyway. */
1062 trial(workspace: string, exempt: string[]): Promise<Trial>;
1063 /** Every paid feature and the workspace's plan for each. Members only. */
1064 features(workspace: string, viewer: Viewer): Promise<Result<FeatureState[]>>;
1065 /**
1066 * Starts the card page for a feature's monthly plan. Owners only. The
1067 * page's id comes back to `returnUrl` as `session`.
1068 */
1069 subscribe(actor: User, workspace: string, feature: Feature, returnUrl: string): Promise<Result<{ url: string }>>;
1070 /** Turns the feature on once the plan is paid for. Safe to repeat. */
1071 confirmSubscription(workspace: string, viewer: Viewer, session: string): Promise<Result<FeatureState>>;
1072 /** Ends a plan at the end of its period, or (`resume`) takes that back. Owners only. */
1073 cancelSubscription(actor: User, workspace: string, feature: Feature, resume?: boolean): Promise<Result<FeatureState>>;
1074 /** A complimentary workspace starts the plan on its own subscription; nothing changes until the first payment succeeds. Owners and billing managers. */
1075 convertToPaid(actor: User, workspace: string, returnUrl: string): Promise<Result<Conversion>>;
1076 /** Which of the workspaces are free (on no paid plan); none where payments are not set up. */
1077 freeWorkspaces(workspaces: string[]): Promise<string[]>;
1078 /** Whether a feature works for a workspace now; a failure with the reason when not. */
1079 hasFeature(workspace: string, feature: Feature): Promise<Result<boolean>>;
1080 /**
1081 * Usage past a plan's allowance, charged from credit at cost plus the
1082 * margin, once per `reference`. False if it was charged before.
1083 */
1084 chargeFeature(charge: {
1085 workspace: string;
1086 feature: Feature;
1087 costMicros: number;
1088 description: string;
1089 repo?: string | null;
1090 reference: string;
1091 /** For a build: how long it ran, so the plan's included build time pays for what it can. */
1092 buildSeconds?: number | null;
1093 }): Promise<Result<boolean>>;
1094 /**
1095 * What a source cost g1t so far this month, so the workspace's limit
1096 * counts it now. Replaces the last report. Billing charges `context`
1097 * and `security` itself once the month is over; `deployments` charges
1098 * its own. `context` is search embeddings (services/artifacts) and
1099 * `telemetry` is observability ingest past the free amount
1100 * (services/telemetry), both at cost.
1101 */
1102 notePending(
1103 workspace: string,
1104 source: "deployments" | "domains" | "context" | "security" | "telemetry",
1105 costMicros: number,
1106 /** How much of it, for the Billing page: `1.2 million requests and 3.4 million CPU ms`. */
1107 detail?: string | null,
1108 /**
1109 * The month (`YYYY-MM`, UTC) the total belongs to, read when it was
1110 * worked out. Billing takes this month, or the month before while its
1111 * figure for the source is not charged and the month is not closed.
1112 * Left out: the month the report arrives in.
1113 */
1114 month?: string | null,
1115 ): Promise<boolean>;
1116 /**
1117 * This month's usage, one line per kind of meter, at what it is charged
1118 * before the plan's included usage or a pool paid for it. Members only.
1119 */
1120 usageMeters(workspace: string, viewer: Viewer): Promise<Result<MeterUsage[]>>;
1121 /** What the workspace may do now: its plan, caps, pause, trial, and what the plan gives it. */
1122 entitlements(workspace: string): Promise<Entitlements>;
1123 /**
1124 * Holds a start's estimated cost before the work starts. A failure's code says why not:
1125 * `paused`, `limit`, `not_paid`, `trial_used` or `oss_pool_empty`, with a message for the owner.
1126 */
1127 reserve(reservation: {
1128 workspace: string;
1129 repo: RepoPath;
1130 public: boolean;
1131 kind: ComputeKind;
1132 /** The most the work is expected to cost g1t, before the margin. */
1133 estimateMicros: number;
1134 }): Promise<Result<ReservationHeld>>;
1135 /** Releases a reservation's hold with what the work cost g1t, before the margin. Safe to repeat. */
1136 settle(reservationId: string, actualMicros: number): Promise<Result<boolean>>;
1137 /** Stripe's page to save and verify a card (3-D Secure, never charged). Owners only. */
1138 cardCheck(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
1139 /** Records the card check once Stripe says it passed, and grants the trial if it can. Safe to repeat. */
1140 confirmCardCheck(workspace: string, viewer: Viewer, session: string): Promise<Result<Entitlements>>;
1141 /** An owner asks for a higher limit, or for help with usage past what was meant. */
1142 requestLimit(
1143 actor: User,
1144 workspace: string,
1145 request: { kind: "limit" | "overage"; amountMicros: number; reason: string; expectedMonthlyMicros: number },
1146 ): Promise<Result<LimitRequest>>;
1147 /** The workspace's requests and their answers, newest first. Members only. */
1148 limitRequests(workspace: string, viewer: Viewer): Promise<Result<LimitRequest[]>>;
1149 /** An owner's answer to a spend spike: keep going for 24 hours, or stop. */
1150 confirmSpike(actor: User, workspace: string, keepGoing: boolean): Promise<Result<Entitlements>>;
1151 /** Every metered price and the recent changes. Public. */
1152 prices(): Promise<PriceBook>;
1153 /** A workspace's limit, for its members. */
1154 limit(workspace: string, viewer: Viewer): Promise<Result<Limit>>;
1155 /** The same, for the services that enforce it. */
1156 checkLimit(workspace: string): Promise<Result<Limit>>;
1157 /**
1158 * The owners' own monthly limit, up to what is available; null goes back
1159 * to the default, and `useFullLimit` uses everything available. Owners only.
1160 */
1161 setSpendLimit(
1162 actor: User,
1163 workspace: string,
1164 spendLimitMicros: number | null,
1165 useFullLimit?: boolean,
1166 /** Use the one-time raise: up to twice the highest ceiling, once per workspace. */
1167 raiseOnce?: boolean,
1168 ): Promise<Result<Limit>>;
1169 /** The workspace's invoices from g1t, newest first. Owners and billing managers only. */
1170 invoices(workspace: string, viewer: Viewer): Promise<Result<WorkspaceInvoice[]>>;
1171 /**
1172 * How long a sandbox ran for a workspace, reported when it stops. Its
1173 * cost is recorded and every second is charged, from the first. False if
1174 * `reference` was recorded before.
1175 */
1176 recordSandbox(usage: {
1177 workspace: string;
1178 seconds: number;
1179 description: string;
1180 repo?: string | null;
1181 reference: string;
1182 /** What ran; checks, workflows and the merge queue on public repositories may use the open-source pool. */
1183 kind?: ComputeKind | null;
1184 /** vCPU-seconds used, when the sandbox can tell: the run is priced on its own CPU. */
1185 cpuSeconds?: number | null;
1186 /** The reservation it started under, settled with this cost. */
1187 reservationId?: string | null;
1188 /** It ran on one of the workspace's self-hosted runners: its minutes go on usage at $0. */
1189 selfHosted?: boolean;
1190 /** The machine it ran on, by label (`g1t-4core`); absent, the standard one. */
1191 instance?: string | null;
1192 }): Promise<Result<boolean>>;
1193 /** Usage over a range of days (`YYYY-MM-DD`, both included), at price, by product, meter, project and day. Members only. */
1194 usageReport(
1195 workspace: string,
1196 viewer: Viewer,
1197 range: { from: string; until: string; products?: string[]; projects?: string[] },
1198 ): Promise<Result<UsageReport>>;
1199 /** The monthly budget: the spend limit, its alerts, whether usage pauses at 100%, and a webhook. Owners only. */
1200 setBudget(
1201 actor: User,
1202 workspace: string,
1203 budget: { amountMicros: number | null; alerts: number[]; pauseAtLimit: boolean; webhook: string | null; keepLimit?: boolean },
1204 ): Promise<Result<Limit>>;
1205 /** Invoice details from the Stripe customer, the default payment method, invoices and the next invoice: owners and billing managers. Any other member gets the next invoice only. */
1206 billingDetails(workspace: string, viewer: Viewer): Promise<Result<BillingDetails>>;
1207 /** Saves invoice details on the Stripe customer; absent fields stay, empty clears. Owners only. */
1208 setBillingDetails(actor: User, workspace: string, details: BillingDetailsInput): Promise<Result<BillingDetails>>;
1209 /** The AI providers whose cost reports the workspace reads: never their keys. Members only. */
1210 providerConnections(workspace: string, viewer: Viewer): Promise<Result<ProviderConnection[]>>;
1211 /**
1212 * Saves a provider's admin key after one small report request shows it works, then reads up to 90 days of its
1213 * report. Connecting again replaces the key and the costs read with the old one. Owners only.
1214 */
1215 connectProvider(actor: User, workspace: string, provider: CostProvider, credential: string): Promise<Result<ProviderConnection>>;
1216 /** Deletes the provider's key and every cost read with it. Owners only. True when there was one. */
1217 disconnectProvider(actor: User, workspace: string, provider: CostProvider): Promise<Result<boolean>>;
1218 /** What the connected providers say the organization spent, by day, from `since` (`YYYY-MM-DD`, UTC). Members only. */
1219 providerCosts(workspace: string, viewer: Viewer, since: string): Promise<Result<ProviderCosts>>;
1220}
1221
1222/** One slice of usage: what it was for, what it cost, how many runs. */
1223export type UsageSlice = { key: string; micros: number; runs: number };
1224
1225/** What a workspace's agents cost over a period. */
1226export type Usage = {
1227 since: string;
1228 /** Charged, including g1t's margin. */
1229 spentMicros: number;
1230 /** What g1t's usage came to at price, less what was charged: the plan's included usage, the trial, a pool or a free period paid it. Usage at price is `spentMicros` plus this. */
1231 coveredMicros?: number;
1232 /** What the account's discount took off the price; usage at price is spent + covered + this. */
1233 discountMicros?: number;
1234 /** The account's discount now, in percent; with one, the slices are at price. */
1235 discountPercent?: number | null;
1236 /** Usage at price: spent + covered + discount, from the same ledger lines. The one usage figure every page shows. */
1237 priceMicros?: number;
1238 /** What g1t's model provider charged, before the margin. */
1239 costMicros: number;
1240 /** What runs on the workspace's own provider cost there, estimated. Not charged by g1t. */
1241 providerMicros: number;
1242 /** What the runs used, at cost: g1t's models and the workspace's own provider together. */
1243 usedMicros: number;
1244 /** g1t charges nothing for now; the slices then measure usage at cost. */
1245 free: boolean;
1246 runs: number;
1247 /** Spend per day and task, keyed `YYYY-MM-DD/task`. */
1248 byDay: UsageSlice[];
1249 byTask: UsageSlice[];
1250 byRepo: UsageSlice[];
1251 /** Keyed `namespace/name#number`. */
1252 byPull: UsageSlice[];
1253 byModel: UsageSlice[];
1254 /** Credit bought in the period. */
1255 addedMicros: number;
1256};
1257
1258/** One of g1t's products (a "bucket") on one day. Money in micros. */
1259export type CostDay = { day: string; bucket: string; cfCostMicros: number; ownCostMicros: number; valueMicros: number; cashMicros: number };
1260
1261/** One product over the range: what customers were charged at price against what it cost. */
1262export type ProductMargin = {
1263 bucket: string;
1264 title: string;
1265 /** Cloudflare's bill, or g1t's own figure where Cloudflare does not bill it (`costSource`). */
1266 costMicros: number;
1267 cfCostMicros: number;
1268 ownCostMicros: number;
1269 valueMicros: number;
1270 marginMicros: number;
1271 marginPercent: number | null;
1272 costSource: "cloudflare" | "ledger" | string;
1273 /** Running g1t, paid for by the plan. */
1274 overhead: boolean;
1275};
1276
1277/** All of g1t: money in (usage and the plan) against every cost. */
1278export type OverallMargin = {
1279 usageMicros: number;
1280 plansMicros: number;
1281 costMicros: number;
1282 marginMicros: number;
1283 marginPercent: number | null;
1284 /** Of costMicros, what went on usage g1t gave away on purpose: comped workspaces, free periods, the trial and the open-source pool. */
1285 givenMicros?: number;
1286 /** Money in against costMicros - givenMicros. */
1287 soldMarginMicros?: number;
1288 soldMarginPercent?: number | null;
1289 /** Usage sold: usageMicros against what that usage cost, less what was given. */
1290 usageCostMicros?: number;
1291 usageMarginMicros?: number;
1292 usageMarginPercent?: number | null;
1293 /** Running g1t: plansMicros against the platform's cost, less its given share. */
1294 runningCostMicros?: number;
1295 /** Cost no mapping names, less its given share. */
1296 unmappedCostMicros?: number;
1297 /** givenMicros by why. Free is free periods, free allowances and overruns g1t covered. */
1298 givenCompedMicros?: number;
1299 givenFreeMicros?: number;
1300 givenTrialMicros?: number;
1301 givenPoolMicros?: number;
1302 /** What discounts on an account's terms took below cost plus the margin: given, not margin lost. */
1303 givenDiscountMicros?: number;
1304 /** Credits from g1t spent on usage, by kind: given, never money in. Refunds come off money in instead. */
1305 givenCreditPromotionalMicros?: number;
1306 givenCreditGoodwillMicros?: number;
1307 /** What testing resets wiped that g1t paid for: the usage still happened, so its cost is given, never a leak. */
1308 givenResetMicros?: number;
1309 /** Credits over the range: given (every kind), spent on usage, and refunds' money given back. */
1310 creditsGivenMicros?: number;
1311 creditsUsedMicros?: number;
1312 creditsRefundedMicros?: number;
1313 /** costMicros by who g1t pays: Cloudflare's bill (billed, after included allowances) and model providers (tokens, not on Cloudflare's bill). */
1314 /** What the plan's included usage paid for, at price: money in for usage, paid out of plansMicros. */
1315 includedMicros?: number;
1316 cloudflareCostMicros?: number;
1317 modelsCostMicros?: number;
1318 /** Tax collected with payments over the range, net of refunds: owed to tax authorities, never cash or revenue. */
1319 taxCollectedMicros?: number;
1320 /** Card processing fees passed on with card payments, net of refunds: they pay Stripe's fee, not revenue. */
1321 cardFeesMicros?: number;
1322 /** What workspaces were charged while payments were not live (Stripe's test mode): given, never money in. */
1323 givenUnpaidMicros?: number;
1324 /** Cloudflare's subscriptions over the range: each day's share of the billing cycle it is in. */
1325 subscriptionsMicros?: number;
1326 /** What AI Gateway priced g1t's own provider traffic at over the range, beside the ledger's model cost. */
1327 gatewayCostMicros?: number;
1328};
1329
1330/** A count, cost or leak that does not add up. */
1331export type CostDrift = {
1332 bucket: string;
1333 title: string;
1334 kind: "count" | "cost" | "leak" | string;
1335 ours: number;
1336 cloudflare: number;
1337 deltaPercent: number | null;
1338 detail: string;
1339 foundAt: string;
1340};
1341
1342export type MarginAlert = {
1343 id: string;
1344 kind: "margin" | "overall" | "leak" | "drift" | "workspace" | string;
1345 /** The product, or the workspace. */
1346 subject: string;
1347 detail: string;
1348 since: string;
1349 openedAt: string;
1350 emailedAt: string | null;
1351};
1352
1353/** A change to a price, measured from what Cloudflare charged. */
1354export type PriceProposal = {
1355 id: string;
1356 meter: string;
1357 title: string;
1358 unit: string;
1359 currentCostMicros: number;
1360 proposedCostMicros: number;
1361 changePercent: number;
1362 markupPercent: number;
1363 reason: string;
1364 source: "keeper" | "reconciler" | string;
1365 /** Far off the current cost: look before approving. */
1366 suspect: boolean;
1367 status: "open" | "applied" | "approved" | "rejected" | "superseded" | string;
1368 createdAt: string;
1369 decidedAt: string | null;
1370 decidedBy: string | null;
1371 note: string | null;
1372 effectiveAt: string | null;
1373};
1374
1375/** One version of one meter's price; never changed once written. */
1376export type PriceVersion = {
1377 id: string;
1378 meter: string;
1379 version: number;
1380 costMicros: number;
1381 markupPercent: number;
1382 priceMicros: number;
1383 effectiveAt: string;
1384 reason: string;
1385 createdBy: string;
1386 appliedAt: string | null;
1387 /**
1388 * What `costMicros` is: `cost`, what g1t pays for a unit; `rate`, a price
1389 * g1t sets with no cost behind it (the agent rate), so it is no cost;
1390 * `weight`, a multiplier in millionths, not money. Absent from older
1391 * billing: read as `cost`.
1392 */
1393 basis?: "cost" | "rate" | "weight" | "";
1394};
1395
1396/** `detachTestStripe`'s arguments. `confirm`: the slug, or "detach" for every workspace; not needed for a dry run. */
1397export type DetachTestStripeArgs = {
1398 workspace?: string | null;
1399 exclude?: string[] | null;
1400 dryRun: boolean;
1401 cancelAtStripe?: boolean;
1402 confirm?: string;
1403 by: string;
1404};
1405
1406/** One workspace's detach (snake_case, as billing sends it). */
1407export type WorkspaceDetach = {
1408 workspace: string;
1409 done: boolean;
1410 customer: boolean;
1411 card: string | null;
1412 card_cached: boolean;
1413 subscriptions: number;
1414 card_checks: number;
1415 checkouts: number;
1416 ai_reload: boolean;
1417 autopay_cleared: boolean;
1418 invoices_voided: number;
1419 months_skipped: string[];
1420 credit_grants_closed: number;
1421 credit_closed_micros: number;
1422 payments_reversed_micros: number;
1423 plan_payments_reversed_micros: number;
1424 written_off_micros: number;
1425 balance_before_micros: number;
1426 balance_after_micros: number;
1427 stripe_canceled: number;
1428 stripe_errors: string[];
1429 /** Metered figures of months before this one marked charged without a charge, and what they came to. */
1430 pending_months_marked: number;
1431 pending_marked_micros: number;
1432 /** This month's metered figures kept as the baseline later reports are charged past. */
1433 pending_baselined: number;
1434 pending_baselined_micros: number;
1435 /** This month's draws on the plan's included usage removed. */
1436 plan_credit_cleared_micros: number;
1437 /** What lost test-mode disputes left owed, cleared. */
1438 dispute_owed_cleared_micros: number;
1439 /** Open test-mode disputes closed. */
1440 disputes_closed: number;
1441};
1442
1443/** What `detachTestStripe` changed, or would change. */
1444export type TestStripeDetach = {
1445 dry_run: boolean;
1446 workspaces: WorkspaceDetach[];
1447 skipped: { workspace: string; reason: string }[];
1448 /** Workspaces left for another call (25 a call). */
1449 remaining: number;
1450};
1451
1452/** What `resetBilling` removed. */
1453export type BillingReset = { workspace: string; rows: number; refreshed?: boolean };
1454
1455export type WorkspaceCost = { workspace: string; costMicros: number; revenueMicros: number; givenMicros?: number; internal: boolean };
1456
1457export type CostLineSummary = {
1458 product: string;
1459 meter: string;
1460 rawName: string;
1461 unit: string;
1462 source: string;
1463 quantity: number;
1464 costMicros: number;
1465 /** Absent when no mapping claims it. */
1466 bucket: string | null;
1467};
1468
1469export type CostMapping = {
1470 product: string;
1471 meter: string;
1472 bucket: string;
1473 priceMeter: string | null;
1474 ownMeter: string | null;
1475 scaleToOwn: boolean;
1476 driftPercent: number;
1477 note: string;
1478 updatedAt: string;
1479 updatedBy: string;
1480};
1481
1482export type CostMappingInput = {
1483 product: string;
1484 meter: string;
1485 bucket?: string;
1486 priceMeter?: string | null;
1487 ownMeter?: string | null;
1488 scaleToOwn?: boolean;
1489 driftPercent?: number | null;
1490 note?: string;
1491 remove?: boolean;
1492};
1493
1494export type CostSettings = {
1495 autoApply: boolean;
1496 autoApplyPercent: number;
1497 noticeDays: number;
1498 marginFloorPercent: number;
1499 alertDays: number;
1500 minDailyCostMicros: number;
1501 anomalyFactor: number;
1502 anomalyFloorMicros: number;
1503};
1504
1505export type CostsReport = {
1506 configured: boolean;
1507 fetchedAt: string | null;
1508 since: string;
1509 until: string;
1510 days: CostDay[];
1511 products: ProductMargin[];
1512 overall: OverallMargin;
1513 drift: CostDrift[];
1514 alerts: MarginAlert[];
1515 proposals: PriceProposal[];
1516 versions: PriceVersion[];
1517 topWorkspaces: WorkspaceCost[];
1518 lines: CostLineSummary[];
1519 mappings: CostMapping[];
1520 settings: CostSettings;
1521 /** g1t's own spend against its two caps. */
1522 caps: SpendCaps;
1523 /** Cloudflare's current billing cycle: usage cost so far by meter, and the projection. Absent until the bill is read. */
1524 cycle?: CloudflareCycle | null;
1525 /** The last read of Cloudflare's billable usage: what came back. */
1526 billRead?: BillRead | null;
1527 /** Of the range's cost, what no workspace's usage could carry: running g1t, attributed to no one. */
1528 unattributedMicros?: number;
1529};
1530
1531/** Cloudflare's billing cycle, as its Billable usage page shows it. */
1532export type CloudflareCycle = {
1533 /** First and last days, YYYY-MM-DD, UTC. */
1534 start: string;
1535 end: string;
1536 days: number;
1537 /** Days from its start to today, today included. */
1538 daysElapsed: number;
1539 /** Usage cost so far, after the included allowances. */
1540 usageMicros: number;
1541 /** usageMicros over the days elapsed, times the cycle's days. */
1542 projectedMicros: number;
1543 averageDailyMicros: number;
1544 /** Cloudflare's subscriptions for the cycle (not on the usage bill). */
1545 subscriptionsMicros: number;
1546 meters: CycleMeter[];
1547};
1548
1549/** One of Cloudflare's meters over the cycle so far. */
1550export type CycleMeter = {
1551 product: string;
1552 meter: string;
1553 rawName: string;
1554 unit: string;
1555 quantity: number;
1556 /** What the cycle includes; null without a list price. */
1557 included: number | null;
1558 billableQuantity: number;
1559 costMicros: number;
1560 /** cloudflare: Cloudflare's own cost; list: the list price past the included amount; none: no list price known. */
1561 basis: "cloudflare" | "list" | "none" | string;
1562};
1563
1564/** What the last read of Cloudflare's billable usage got back. */
1565export type BillRead = {
1566 readAt: string;
1567 since: string;
1568 until: string;
1569 rows: number;
1570 pages: number;
1571 consumedRows: number;
1572 pricingOnlyRows: number;
1573 costedRows: number;
1574};
1575
1576/** One level of the platform pause, as sudo shows it. Snake case, as billing sends it. */
1577export type PauseState = {
1578 level: PauseLevel;
1579 paused: boolean;
1580 note: string | null;
1581 set_by: string | null;
1582 set_at: string | null;
1583 /** Set by billing's usage watcher, not a person. */
1584 auto: boolean;
1585};
1586
1587/** One platform metric over an hour or the month so far. */
1588export type PlatformMetric = {
1589 metric: string;
1590 title: string;
1591 value: number;
1592 /** Its hourly threshold (`PLATFORM_HOURLY_*`); 0: none. */
1593 threshold: number;
1594 /** The script, queue, database or namespace that counted most. */
1595 top_name: string | null;
1596 top_value: number | null;
1597};
1598
1599/** A breach billing's usage watcher found. */
1600export type PlatformBreach = {
1601 id: string;
1602 metric: string;
1603 hour: string;
1604 rule: "threshold" | "spike";
1605 value: number;
1606 threshold: number;
1607 severe: boolean;
1608 top_name: string | null;
1609 detail: string;
1610 /** Levels it paused. */
1611 paused: PauseLevel[];
1612 opened_at: string;
1613 emailed_at: string | null;
1614};
1615
1616/** Billing's `admin_platform_guard`: the platform pause and usage watcher
1617 * (docs.g1t.sh/guides/deploy-to-cloudflare/#spend-guardrails). */
1618export type PlatformGuard = {
1619 levels: PauseState[];
1620 /** The last hour read, `YYYY-MM-DDTHH:00:00Z`. */
1621 hour: string | null;
1622 last_hour: PlatformMetric[];
1623 month: string;
1624 month_to_date: PlatformMetric[];
1625 breaches: PlatformBreach[];
1626 /** Whether billing can read Cloudflare's analytics. */
1627 can_read: boolean;
1628 /** `AUTO_PAUSE`: the levels a severe breach may pause. */
1629 auto_pause: PauseLevel[];
1630 /** What the latest run could not see: each query that failed, with its error. */
1631 blind?: { key: string; dataset: string; error: string }[];
1632 /** The latest run found every dataset empty: the wrong account, or a token that cannot see it. */
1633 empty?: boolean;
1634 /** The hour the latest run read. */
1635 last_run?: string | null;
1636};
1637
1638/** What g1t pays for itself, at cost, against its caps (billing's `budget`). */
1639export type SpendCaps = {
1640 /** Today (UTC), YYYY-MM-DD, and this month, YYYY-MM. */
1641 day: string;
1642 month: string;
1643 /** What g1t paid for itself today across every workspace. */
1644 todayMicros: number;
1645 /** `PLATFORM_DAILY_SPEND_CAP_MICROS`; 0: no breaker. */
1646 dailyCapMicros: number;
1647 /** New workflows, checks and merge queue runs g1t would pay for are paused. */
1648 tripped: boolean;
1649 trippedAt: string | null;
1650 liftedBy: string | null;
1651 liftedAt: string | null;
1652 liftNote: string | null;
1653 /** This month so far, by what paid: comped, trial, oss, given, unpaid. */
1654 monthBuckets: { bucket: string; title: string; micros: number }[];
1655 comped: CompedBudget[];
1656 /** Free workspaces' share of reconciled costs this month (git, storage, platform). */
1657 freeTierMicros: number;
1658 /** Cloudflare's subscriptions a month: read from Cloudflare each day, else `CLOUDFLARE_FIXED_MONTHLY_MICROS`, an estimate. */
1659 fixedMonthlyMicros: number;
1660 fixedSource?: "cloudflare" | "estimate" | string;
1661 fixedReadAt?: string | null;
1662 /** Each subscription, when read from Cloudflare. */
1663 fixedItems?: { name: string; monthlyMicros: number }[];
1664 /** Of fixedMonthlyMicros, this calendar month's days so far, each at its billing cycle's daily share. */
1665 fixedMonthMicros?: number;
1666 /** Money in this month, through the last reconciled day. */
1667 revenueMicros: number;
1668 /**
1669 * Of this month's buckets, what was spent on workspaces whose billing a
1670 * testing reset later wiped (still g1t's spend; the reconciled figures
1671 * have it only where the reset kept it), and those workspaces.
1672 */
1673 resetMicros?: number;
1674 resetWorkspaces?: string[];
1675};
1676
1677/** A comped account's monthly budget, at cost. */
1678export type CompedBudget = {
1679 account: string;
1680 name: string;
1681 usedMicros: number;
1682 /** 0: no budget. */
1683 ceilingMicros: number;
1684 /** `COMPED_MONTHLY_CEILING_MICROS`, not the account's own limit. */
1685 defaultCeiling: boolean;
1686 /** 50, 75, 90, 100, or 0. */
1687 level: number;
1688};
1689
1690export type CostsRun = { lines: number; days: number; proposals: number; alerts: number; problems: string[] };
1691
1692/** The product families the Usage page groups meters into, in order. */
1693export const PRODUCTS = [
1694 { key: "sandboxes", label: "Sandboxes" },
1695 { key: "deployments", label: "Deployments" },
1696 { key: "git_storage", label: "Git & storage" },
1697 { key: "packages", label: "Packages" },
1698 { key: "security", label: "Security & quality" },
1699 { key: "search", label: "Search" },
1700 { key: "observability", label: "Observability" },
1701] as const;
1702
1703export type ProductKey = (typeof PRODUCTS)[number]["key"];
1704
1705/** What usage came to over a range, and what paid for it: price − discount − included − credits = charged. */
1706export type UsageTotals = {
1707 /** Usage at price, pending usage included. */
1708 priceMicros: number;
1709 discountMicros: number;
1710 /** Paid by the plan's included usage, the trial and g1t's pools. */
1711 includedMicros: number;
1712 /** Paid by credit from g1t, and AI credit bought before g1t stopped selling it. */
1713 creditsMicros: number;
1714 /** Left for the workspace to pay. */
1715 chargedMicros: number;
1716 /** Metered this month, charged when it closes. */
1717 pendingMicros: number;
1718 /** What of `pendingMicros` will be charged at the close, after the discount and what g1t covers; absent from an older billing. */
1719 pendingChargedMicros?: number;
1720 costMicros: number;
1721};
1722
1723export type UsageDay = { day: string; product: string; micros: number };
1724
1725/** One agent's (by handle) or one person's (by username) share of the agent product, at price; an empty key for lines attributed to no one. */
1726
1727export type UsageAllowance = { used: number; of: number; unit: string };
1728
1729export type ProjectUsage = { project: string; micros: number; quantity: number };
1730
1731/** One meter over a range. */
1732export type MeterLine = {
1733 key: string;
1734 label: string;
1735 product: string;
1736 /** `tokens`, `seconds`, `bytes`, `operations`, `requests` or `entries`. */
1737 unit: string;
1738 quantity: number;
1739 micros: number;
1740 pendingMicros?: number;
1741 /** Every day of the range, oldest first, at price. */
1742 daily: number[];
1743 allowance?: UsageAllowance | null;
1744 byProject: ProjectUsage[];
1745 /** How the quantity is counted, when that needs saying (the agent rate's token weights). */
1746 note?: string | null;
1747};
1748
1749export type ProductUsage = { key: string; label: string; micros: number; meters: MeterLine[] };
1750
1751export type UsageReport = {
1752 from: string;
1753 until: string;
1754 totals: UsageTotals;
1755 days: UsageDay[];
1756 products: ProductUsage[];
1757 projects: string[];
1758 /** The plan's included usage this month, in micros. */
1759 included?: UsageAllowance | null;
1760 discountPercent?: number | null;
1761 /** AI credit bought before g1t stopped selling it, left now; kept apart from credit for everything. */
1762 aiCreditMicros: number;
1763 creditMicros: number;
1764 trialMicros?: number | null;
1765 plan: PlanKind;
1766 free: boolean;
1767};
1768
1769export type PostalAddress = { line1: string; line2: string; city: string; state: string; postalCode: string; country: string };
1770
1771export type PaymentMethod = {
1772 kind: string;
1773 brand?: string | null;
1774 last4?: string | null;
1775 expMonth?: number | null;
1776 expYear?: number | null;
1777};
1778
1779export type StripeInvoice = {
1780 id: string;
1781 number?: string | null;
1782 status: string;
1783 totalCents: number;
1784 currency: string;
1785 createdAt: string;
1786 description?: string | null;
1787 hostedUrl?: string | null;
1788 pdfUrl?: string | null;
1789};
1790
1791export type UpcomingInvoice = { closesAt: string; subscriptionsMicros: number; usageMicros: number; totalMicros: number };
1792
1793export type BillingDetails = {
1794 customer: boolean;
1795 email: string | null;
1796 name: string | null;
1797 address: PostalAddress | null;
1798 taxIdType: string | null;
1799 taxId: string | null;
1800 poNumber: string | null;
1801 language: string | null;
1802 paymentMethod: PaymentMethod | null;
1803 invoices: StripeInvoice[];
1804 upcoming: UpcomingInvoice;
1805 unavailable?: string | null;
1806 /** Whether Stripe Tax can place the customer from the address; without it nothing is charged. */
1807 taxLocation?: boolean;
1808 /** Set when g1t did not charge for want of a billing address. */
1809 taxAddressNeededAt?: string | null;
1810 /** Stripe's check of the tax ID: pending, verified, unverified or unavailable. */
1811 taxIdStatus?: string | null;
1812 /** none, exempt or reverse, as set at Stripe. */
1813 taxExempt?: string | null;
1814};
1815
1816export type BillingDetailsInput = {
1817 email?: string;
1818 name?: string;
1819 address?: PostalAddress;
1820 taxIdType?: string;
1821 taxId?: string;
1822 poNumber?: string;
1823 language?: string;
1824};
1825
1826/** An AI provider whose own cost report g1t reads, with the organization's admin key. */
1827export type CostProvider = "anthropic" | "openai";
1828
1829export const COST_PROVIDERS: Record<CostProvider, { label: string }> = {
1830 anthropic: { label: "Anthropic" },
1831 openai: { label: "OpenAI" },
1832};
1833
1834export function isCostProvider(value: unknown): value is CostProvider {
1835 return value === "anthropic" || value === "openai";
1836}
1837
1838/** A provider a workspace has connected: never its key, only the key's last four characters. */
1839export type ProviderConnection = {
1840 provider: CostProvider;
1841 /** Such as `…a1B2`. */
1842 hint: string;
1843 /** The owner who connected it. */
1844 connectedBy: string;
1845 connectedAt: string;
1846 /** When its report was last read in full; null until then. */
1847 lastSyncedAt: string | null;
1848 /** What went wrong at the last read, in a sentence that says what to do; null when it worked. */
1849 lastError: string | null;
1850 /** `YYYY-MM-DD`: the first day g1t has asked the provider for; null until the first read. */
1851 syncedFrom?: string | null;
1852};
1853
1854/** One day's cost of one line item at one provider, summed over the provider's own workspaces or projects. */
1855export type ProviderCostDay = {
1856 /** `YYYY-MM-DD`, UTC. */
1857 day: string;
1858 provider: CostProvider;
1859 /** The provider's own words: Anthropic's description, OpenAI's line item. Empty when it gave none. */
1860 item: string;
1861 /** Millionths of a US dollar. */
1862 micros: number;
1863};
1864
1865export type ProviderCosts = {
1866 connections: ProviderConnection[];
1867 /** Oldest first. */
1868 days: ProviderCostDay[];
1869 /**
1870 * True when at least one provider is connected and every one was last read without an error and back to `since`.
1871 * The day in progress is never complete at the provider either.
1872 */
1873 complete: boolean;
1874};