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.

g1t.sh
1,639 linesCodeBlameRaw

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.

Fixes from the page sweep1import type { ComputeKind, Reservation } from "./compute";
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)2import type { PauseLevel } from "./platform";
Fixes from the page sweep3import 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;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging72 /** For usage: what the account's discount took off its price. */
73 discountMicros?: number;
74 /** For a credit from g1t, and for what of one expired or was revoked: its kind. */
75 creditKind?: CreditKind;
Fixes from the page sweep76};
77
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging78/**
79 * Why g1t gave a workspace credit. Promotional (a welcome, a referral) and
80 * goodwill (an apology) are given away when spent; a refund gives back
81 * money already paid, and never expires.
82 */
83export type CreditKind = "promotional" | "goodwill" | "refund" | "purchased";
84
85/** One credit g1t gave, with what of it was used: spent before anything paid in advance, the soonest-expiring first. */
86export type CreditGrant = {
87 /** `crd_…`, the grant's ledger reference. */
88 id: string;
89 workspace: string;
90 kind: CreditKind;
91 amountMicros: number;
92 usedMicros: number;
93 /** What can still be spent: nothing once it expired or was revoked. */
94 leftMicros: number;
95 note: string;
96 /** A refund: what it refunds, and the day of it. */
97 refundFor?: string | null;
98 refundDay?: string | null;
99 /** RFC 3339; null never expires. */
100 expiresAt: string | null;
101 createdBy: string;
102 createdAt: string;
103 state: "open" | "used" | "expired" | "revoked";
104 closedAt?: string | null;
105 closedNote?: string | null;
106 closedBy?: string | null;
107 /** What expiring or revoking took off the balance. */
108 closedMicros?: number;
109 /** What it pays for: all usage, or models only (spent first). */
110 scope?: "all" | "models";
111 /** Where it came from. */
Usage, Billing settings and prepaid AI credit; fixes from the UX audit112 source?: "staff" | "purchase" | "promo_code" | "upgrade";
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging113};
114
115/** A workspace's credits from g1t, newest first. */
116export type Credits = { grants: CreditGrant[]; leftMicros: number };
117
118/** One month's credits of one kind: given, spent that month, and taken back unused. */
119export type CreditMonth = {
120 month: string;
121 kind: CreditKind;
122 givenMicros: number;
123 grants: number;
124 usedMicros: number;
125 expiredMicros: number;
126 revokedMicros: number;
127};
128
129/** Every credit g1t gave (at most 200, filtered), the last 12 months by kind, and who gave them. */
130export type AdminCredits = { grants: CreditGrant[]; months: CreditMonth[]; staff: string[] };
131
132/** What a credit from sudo is, past its amount and note. */
133export type CreditOptions = {
134 kind: CreditKind;
135 /** RFC 3339; never for a refund. */
136 expiresAt?: string | null;
137 /** A refund: what it is for, and the day refunded (`YYYY-MM-DD`). */
138 refundFor?: string | null;
139 refundDay?: string | null;
140};
141
Fixes from the page sweep142/**
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging143 * How an account is charged. Standard unless g1t set otherwise in sudo:
144 * custom terms are a discount (0 to 100%), a ceiling, or both. A 100%
145 * discount charges nothing and shows the usage at its price. `comped` is
146 * from before discounts and reads as 100%; billing no longer writes it.
147 */
Fixes from the page sweep148export type Terms = {
149 kind: "standard" | "comped" | "custom";
150 discountPercent: number;
151 ceilingMicros: number | null;
152 note: string;
153 until: string | null;
154 setBy: string | null;
155 setAt: string | null;
156};
157
158/**
159 * Who pays: a workspace's own account, or an enterprise's, which pays for
160 * several workspaces with one bill and one limit.
161 */
162export type PayingAccount = {
163 id: string;
164 kind: "workspace" | "enterprise";
165 name: string;
166 terms: Terms;
167 workspaces: string[];
168 /** Where an enterprise's invoices go. */
169 billingEmail?: string | null;
170 /** An enterprise's invoices, newest first. */
171 invoices?: EnterpriseInvoice[];
172 createdAt: string;
173 /** What g1t staff set for the account beyond its terms. */
174 allowances?: Allowances;
175};
176
177/** Set per account by g1t staff in sudo, on top of its terms. */
178export type Allowances = {
179 /** The g1t plan without its monthly price; usage is charged as usual. Comped accounts have it anyway. */
180 plan: boolean;
181 /** Each public repository's monthly cap on g1t's open-source pool; null for the default. */
182 ossRepoMicros: number | null;
183 /** Each workspace's trial credit, outside the monthly pool; null for the default. */
184 trialMicros: number | null;
185 /** Agents at once, in place of the plan's (2 in the first month or on the trial, then 10); null for the default. */
186 maxConcurrentAgents?: number | null;
187 /** One run's spend cap, in place of the owners' and the default $2; null for none. */
188 runCapMicros?: number | null;
189 /** What one issue's agents may spend in all, in place of the owners' and the default $10; null for none. */
190 issueCapMicros?: number | null;
191 /** 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. */
192 auditRetentionDays?: number | null;
193 /** A hold on new compute, with why; null for none. */
194 hold?: string | null;
195};
196
197// --- Entitlements, and compute started under a reservation ------------------
198//
199// Every service that starts compute asks billing first:
200// 1. `entitlements(workspace)`: what it may do at all, its caps, and whether compute is paused.
201// 2. `reserve(...)`: holds the estimate against what may pay for it, so starts at the same moment
202// cannot overshoot together. Answers who pays first, or refuses with a stable code
203// (`not_paid`, `trial_used`, `limit`, `paused`, `oss_pool_empty`) and a message for the owner.
204// 3. `settle(reservationId, actualMicros)`: releases the hold. The charge goes on the ledger the usual way.
205// A reservation never settled lapses after `RESERVATION_HOURS`.
206
207/** A reservation that is never settled stops holding after this long. */
208export const RESERVATION_HOURS = 3;
209/** What a ceiling reads as when there is none (g1t's own workspaces). */
210export const UNLIMITED_MICROS = 1_000_000_000_000_000;
211
212/** What a workspace pays g1t on, as far as compute is concerned. Mirrors `PlanKind`. */
213export type PlanKind = "free" | "paid" | "internal" | "enterprise";
214
215// `ComputeKind` (what compute is for), `PaidBy` (who pays first: credit, trial, oss, on_demand) and
216// `Reservation` are in `./compute`, with the gate that calls `reserve` and `settle`.
217
218/** One level reached: 50, 75, 90 or 100 percent. */
219export type UsageAlert = {
220 /** `included` (the plan's included usage), `spend_limit` or `ceiling`. */
221 meter: "included" | "spend_limit" | "ceiling" | string;
222 level: number;
223 usedMicros: number;
224 limitMicros: number;
225 message: string;
226};
227
228/** An hour's spend well above the workspace's usual: new compute waits for an owner. */
229export type Spike = {
230 id: string;
231 /** `open` (waiting), `continued` (keep going) or `stopped`. */
232 status: "open" | "continued" | "stopped" | string;
233 hourMicros: number;
234 averageMicros: number;
235 detectedAt: string;
236 decidedBy?: string | null;
237 decidedAt?: string | null;
238 /** While continued: until when, unless spend doubles again first. */
239 until?: string | null;
240};
241
242/** What a workspace may do now. Mirrors `Entitlements` in `crates/contracts/src/billing.rs`. */
243export type Entitlements = {
244 workspace: string;
245 plan: PlanKind;
246 /** May start sandboxes, models, deployments and semantic search at all: paid, internal, enterprise, or free with trial credit left. */
247 compute: boolean;
248 /** The one-time trial credit left; 0 if none or used. */
249 trialMicrosLeft: number;
250 /** A card check has been done; the trial and the open-source pool need it. */
251 trialVerified: boolean;
252 /** A paid workspace still in its first billing cycle. */
253 firstMonth: boolean;
254 /** 2 in the first month or on the trial, 10 after; staff can override it. */
255 maxConcurrentAgents: number;
256 /** 60 in the first month or on the trial; otherwise the guardrails' own caps. */
257 maxRunMinutes: number;
258 /** One run's spend cap, $2 by default; staff can override it. */
259 runCapMicros: number;
260 /** Agent spend on one issue in all, $10 by default. */
261 issueCapMicros: number;
262 /** g1t's ceiling on usage not yet paid for; `UNLIMITED_MICROS` for g1t's own; 0 for free. */
263 ceilingMicros: number;
264 /** Usage not yet paid for this month, prepayment taken off. */
265 exposureMicros: number;
266 /** Why new compute is paused, for the owner; null when it is not. */
267 paused: string | null;
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.268 /** g1t staff put a hold on the account: nothing new is set up for it, such as a self-hosted runner. */
269 held?: boolean;
Fixes from the page sweep270 /** What open reservations hold now. */
271 heldMicros?: number;
272 /** Paid in advance and not used yet. */
273 prepaidMicros?: number;
274 /** The plan's included usage each month, and what of it is used. */
275 includedMicros?: number;
276 includedUsedMicros?: number;
277 /** 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. */
278 auditRetentionDays: number;
279 /** Whether `auditRetentionDays` is what staff set for the account rather than the plan's. */
280 auditRetentionCustom?: boolean;
281 /** Private repository storage free for every workspace: past it, the plan pays and a free workspace's pushes stop. */
282 freePrivateStorageBytes: number;
283 /** The last daily measure of the workspace's private repositories (a lower bound). */
284 privateStorageBytes: number;
285 /** On a paid plan: package storage past the free amounts is charged, never refused. */
286 hasPlan?: boolean;
287 /** Package storage free for every workspace (public, and private): past it a free workspace's pushes are refused. */
288 packagePublicFreeBytes?: number;
289 packagePrivateFreeBytes?: number;
290 /** What g1t's open-source pool paid for the workspace this month. */
291 ossPaidMicros: number;
292 /** Deploy build time this month, every second of it metered. */
293 buildSecondsUsed?: number;
294 /** Git operations this month, and how many are free for every workspace. */
295 gitOperations?: number;
296 gitOperationsIncluded?: number;
297 /** The smallest amount a card is charged when a month closes. */
298 minChargeMicros: number;
299 /** A spend spike waiting for an owner, or decided. */
300 spike?: Spike | null;
301 /** Where usage stands against what is included and the limits, from 50%. */
302 alerts?: UsageAlert[];
303};
304
305/** A hold on a start's estimated cost, as billing answers it (`Reservation` in `./compute`, and more). */
306export type ReservationHeld = Reservation & {
307 /** What is held, at cost; may be less than the estimate for a free workspace's last bit of trial. */
308 heldMicros?: number;
309 /** When the hold lapses if never settled. */
310 expiresAt?: string;
311};
312
313/** A request to g1t: a higher limit, or help with usage past what was meant. */
314export type LimitRequest = {
315 id: string;
316 workspace: string;
317 kind: "limit" | "overage" | string;
318 amountMicros: number;
319 reason: string;
320 expectedMonthlyMicros: number;
321 status: "open" | "approved" | "declined" | string;
322 decidedMicros?: number | null;
323 decidedBy?: string | null;
324 /** The answer, as the owner sees it. */
325 answer?: string | null;
326 createdBy: string;
327 createdAt: string;
328 decidedAt?: string | null;
329};
330
331/** What staff see beside a request. */
332export type WorkspaceHistory = {
333 plan: PlanKind | null;
334 months: MonthFigures[];
335 paidClearedMicros: number;
336 payments: number;
337 disputes: number;
338 declines: number;
339 firstSeen: string | null;
340 ceilingMicros: number | null;
341 maxCeilingMicros: number | null;
342 spendLimitMicros: number | null;
343 lastHourMicros: number;
344 averageHourMicros: number;
345 lastDayMicros: number;
346};
347
348export type LimitRequestReview = { request: LimitRequest; history: WorkspaceHistory };
349
350/** What a one-time goodwill credit comes to: the margin on the overage, always, plus its cost up to the cap. */
351export type Goodwill = {
352 overageMicros: number;
353 marginMicros: number;
354 costMicros: number;
355 creditMicros: number;
356 absorbedMicros: number;
357};
358
359/** A workspace whose month went well past its usual, or hit a spike. */
360export type Overage = {
361 workspace: string;
362 plan: PlanKind;
363 typicalMonthMicros: number;
364 thisMonthMicros: number;
365 costMicros: number;
366 marginMicros: number;
367 spike: Spike | null;
368 topEntries: LedgerEntry[];
369 goodwill: Goodwill;
370 goodwillAvailable: boolean;
371 lastGoodwillAt: string | null;
372 request: LimitRequest | null;
373};
374
375/** One workspace's recent pace. */
376export type Velocity = {
377 workspace: string;
378 plan: PlanKind;
379 lastHourMicros: number;
380 averageHourMicros: number;
381 lastDayMicros: number;
382 thisMonthMicros: number;
383 ratio: number;
384 spike: Spike | null;
385 firstSeen: string | null;
386};
387
388/** g1t's capped budgets for free usage this month. */
389export type Pools = {
390 month: string;
391 trialGrantedMicros: number;
392 trialPoolMicros: number;
393 trialGrants: number;
394 ossUsedMicros: number;
395 ossPoolMicros: number;
396 ossRepoMicros: number;
397};
398
399export type AccountSummary = {
400 account: PayingAccount;
401 limit: Limit;
402 chargedMicros: number;
403 costMicros: number;
404 paidMicros: number;
405 /** The same figures for each of the account's workspaces that has any. */
406 byWorkspace: WorkspaceFigures[];
407 /** The last six months, oldest first. */
408 months?: MonthFigures[];
409};
410
411/** One workspace's share of an `AccountSummary`. */
412export type WorkspaceFigures = { workspace: string; chargedMicros: number; costMicros: number; paidMicros: number };
413
414export type StripeStatus = {
415 /** `test` or `live`, from the key; `off` without one. */
416 mode: "test" | "live" | "off" | string;
417 /** Whether `STRIPE_WEBHOOK_SECRET` is set, so events can be checked. */
418 secretSet: boolean;
419 /** The destination at billing's address in Stripe, as Stripe has it. */
420 webhook: { url: string; endpointId: string; status: "enabled" | "disabled" | string; events: string[]; createdAt: string } | null;
421 /** Events billing handles that the destination does not send. */
422 missingEvents: string[];
423 recentEvents: { id: string; kind: string; outcome: string; receivedAt: string }[];
424 error: string | null;
425};
426
427/** An enterprise's invoice: one line per workspace, paid on Stripe's page. */
428export type EnterpriseInvoice = {
429 invoiceId: string;
430 hostedUrl: string | null;
431 amountMicros: number;
432 status: "open" | "paid" | "overdue" | "void" | string;
433 period: string;
434 lines: { workspace: string; amountMicros: number }[];
435 createdAt: string;
436};
437
438/** A workspace's invoice: monthly, or when charged near its limit. Itemised, in Stripe's billing page. */
439export type WorkspaceInvoice = {
440 invoiceId: string;
441 workspace: string;
442 reason: "month" | "threshold" | string;
443 period: string;
444 amountMicros: number;
445 status: "paid" | "open" | "failed" | "void" | string;
446 hostedUrl: string | null;
447 pdfUrl: string | null;
448 lines: { description: string; amountMicros: number }[];
449 createdAt: string;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person450 /** The card processing fee on top of `amountMicros` when charged to a card, and the tax Stripe added once known. */
451 feeMicros?: number;
452 taxMicros?: number;
Fixes from the page sweep453};
454
455/** A month of the ledger, grouped by day or project, a line per kind of charge. */
456export type Statement = {
457 month: string;
458 months: string[];
459 groups: {
460 key: string;
461 label: string;
462 /** `coveredMicros`: what the plan's included usage, the trial, the open-source pool or g1t paid, not in `chargedMicros`. */
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging463 /** `priceMicros`: usage at its price; `discountMicros`: what the account's discount took off it. */
464 lines: {
465 kind: string;
466 count: number;
467 chargedMicros: number;
468 costMicros: number;
469 coveredMicros?: number;
470 priceMicros?: number;
471 discountMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person472 /** On `Tax` and `Card processing fees` lines: what was paid with payments on top of what reached the balance. Never charged. */
473 passedMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging474 }[];
Fixes from the page sweep475 chargedMicros: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging476 priceMicros?: number;
477 discountMicros?: number;
Fixes from the page sweep478 }[];
479 totals: {
480 chargedMicros: number;
481 paidMicros: number;
482 costMicros: number;
483 entries: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging484 /** Usage at price, and what the discount took off: charged is the price less the discount and what paid for it. */
485 priceMicros?: number;
486 discountMicros?: number;
487 /** The account's discount now, in percent; absent without one. */
488 discountPercent?: number | null;
Fixes from the page sweep489 /** What paid for usage before it was charged, such as "Paid by g1t's open-source pool". */
490 covered?: { source: "included" | "trial" | "oss_pool" | "given" | string; label: string; micros: number }[];
491 /** Owed when the month closed but under the minimum charge: on the next invoice. */
492 carriedMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person493 /** Tax and card processing fees paid with the month's payments, on top of `paidMicros`. */
494 taxMicros?: number;
495 cardFeeMicros?: number;
Fixes from the page sweep496 };
497};
498
499export type MonthFigures = {
500 month: string;
501 /** Usage charged, after what paid for it first. */
502 chargedMicros: number;
503 /** What usage cost g1t: never a workspace's own model provider. */
504 costMicros: number;
505 paidMicros: number;
506 /** The plan's monthly price, paid. */
507 plansMicros?: number;
508 /** What g1t gave at price (internal use, trials, the open-source pool, goodwill, covered). Not margin. */
509 givenMicros?: number;
510};
511
512/** What g1t gave this month from one source. */
513export type GivenFigures = { source: "internal" | "trial" | "oss_pool" | "goodwill" | "covered" | string; label: string; micros: number; costMicros: number };
514
515/** One internal workspace's use this month, and why it is not charged. */
516export type InternalUse = { workspace: string; reason: string; costMicros: number; entries: number };
517
518export type SignalKind = "at_limit" | "near_ceiling" | "declined" | "growing" | "established" | "first_payment" | "high_spend" | "cost_over_revenue";
519
520/** Why a workspace is worth reaching out to. */
521export type Signal = {
522 workspace: string;
523 kind: SignalKind;
524 detail: string;
525 valueMicros: number;
526 stage: string | null;
527 owner: string | null;
528 nextStep?: string | null;
529 /** When the next step is due, YYYY-MM-DD. */
530 nextAt?: string | null;
531};
532
533/** One invoice g1t has sent, a workspace's or an enterprise's. */
534export type InvoiceSummary = {
535 invoiceId: string;
536 kind: "workspace" | "enterprise";
537 account: string;
538 name: string;
539 reason: string;
540 period: string;
541 amountMicros: number;
542 status: string;
543 hostedUrl: string | null;
544 createdAt: string;
545 paidAt: string | null;
546};
547
548export type SalesStage = "none" | "lead" | "contacted" | "negotiating" | "won" | "lost" | "churn_risk";
549
550export type SalesRecord = {
551 workspace: string;
552 stage: SalesStage | string;
553 owner: string | null;
554 nextStep: string | null;
555 nextAt: string | null;
556 notes: { id: string; text: string; by: string; createdAt: string }[];
557 updatedAt: string | null;
558};
559
560export type Overview = {
561 month: string;
562 months: MonthFigures[];
563 byKind: { kind: string; chargedMicros: number; costMicros: number }[];
564 payingWorkspaces: number;
565 stopped: number;
566 nearCeiling: number;
567 declined: number;
568 openInvoicesMicros: number;
569 followUpsDue: number;
570 /** g1t's capped budgets for free usage, this month. */
571 pools?: Pools | null;
572 /** Usage charged plus the plan's price paid, this month. */
573 revenueMicros?: number;
574 activePlans?: number;
575 planMrrMicros?: number;
576 /** What g1t gave this month, by source, apart from its margin. */
577 given?: GivenFigures[];
578 /** g1t's own and Flagon's workspaces: what their use cost, and why they are not charged. */
579 internal?: InternalUse[];
580 openRequests?: number;
581 overages?: number;
582 openSpikes?: number;
583};
584
585/** A customer's Stripe billing page, for staff to send them. */
586export type BillingLink = {
587 /** One-time and short-lived, signed in already. */
588 portalUrl: string;
589 /** The page's sign-in, which does not expire: the customer signs in by email. */
590 loginUrl: string | null;
591 customerEmail: string | null;
592 expiresNote: string;
593};
594
595export type AdminAction = { id: string; account: string; action: string; detail: string; by: string; createdAt: string };
596
597export type AccountDetail = {
598 summary: AccountSummary;
599 workspaces: Limit[];
600 ledger: LedgerEntry[];
601 audit: AdminAction[];
602};
603
604/** Staff-only billing, for sudo.g1t.sh. Every change names who made it. */
605export interface BillingAdminApi {
606 accounts(query?: string): Promise<AccountSummary[]>;
607 account(id: string): Promise<Result<AccountDetail>>;
608 setTerms(id: string, terms: Terms, by: string): Promise<Result<PayingAccount>>;
609 /** Team on or off without charge, and the account's share of the pools. Needs a note. */
610 setAllowances(id: string, allowances: Allowances, note: string, by: string): Promise<Result<PayingAccount>>;
611 createEnterprise(name: string, workspaces: string[], by: string): Promise<Result<PayingAccount>>;
612 attach(workspace: string, account: string | null, by: string): Promise<Result<PayingAccount>>;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging613 /** Credit for a workspace: promotional, goodwill or a refund; the owners are emailed. */
614 credit(workspace: string, amountMicros: number, note: string, by: string, options?: CreditOptions): Promise<Result<LedgerEntry>>;
615 /** Every credit g1t gave, filtered, with each month's totals by kind. */
616 credits(filter?: { workspace?: string | null; kind?: CreditKind | null; month?: string | null; by?: string | null }): Promise<AdminCredits>;
617 /** What is left of a credit, taken back, with why. */
618 revokeCredit(id: string, note: string, by: string): Promise<Result<CreditGrant>>;
sudo: reset a test workspace's billing so it starts again as a new customer; refused on a live Stripe key, for comped workspaces and for an enterprise's619 /** A test workspace's billing wiped, to start again as a new customer. Only on Stripe's test key; never comped or enterprise. Logged. */
620 resetBilling(workspace: string, confirm: string, note: string, by: string): Promise<Result<BillingReset>>;
Fixes from the page sweep621 /** The workspace's Stripe billing page, to send to the customer. Logged. */
622 billingLink(workspace: string, by: string): Promise<Result<BillingLink>>;
623 /** Where billing stands with Stripe; with `setup`, registers the webhook first. */
624 /** Stripe's state for billing; `fix` enables the destination and adds missing events first. */
625 stripe(fix?: boolean, by?: string): Promise<StripeStatus>;
626 /** Where an enterprise's invoices go; makes its Stripe customer. */
627 enterpriseBilling(id: string, email: string, by: string): Promise<Result<PayingAccount>>;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person628 /** The enterprise's billing address and tax ID, on its Stripe customer: Stripe Tax works its invoices out from them. */
629 enterpriseAddress(id: string, address: PostalAddress, taxIdType: string | null, taxId: string | null, by: string): Promise<Result<boolean>>;
Fixes from the page sweep630 /** Sends an enterprise its invoice now, for what its workspaces owe. */
631 invoiceEnterprise(id: string, by: string): Promise<Result<EnterpriseInvoice>>;
632 /** Exactly these workspaces' accounts, such as one page of the list. */
633 accountsFor(workspaces: string[]): Promise<AccountSummary[]>;
634 /** Every workspace worth reaching out to, most urgent first. */
635 signals(): Promise<Signal[]>;
636 /** The business at a glance. */
637 overview(): Promise<Overview>;
638 /** A workspace's sales record. */
639 sales(workspace: string): Promise<SalesRecord>;
640 setSales(workspace: string, record: { stage: string; owner?: string | null; nextStep?: string | null; nextAt?: string | null }, by: string): Promise<Result<SalesRecord>>;
641 addNote(workspace: string, text: string, by: string): Promise<Result<SalesRecord>>;
642 /** A workspace's invoices from g1t, for staff. */
643 workspaceInvoices(workspace: string): Promise<WorkspaceInvoice[]>;
644 /** Every invoice g1t has sent, newest first. */
645 allInvoices(filter?: { status?: string; month?: string }): Promise<InvoiceSummary[]>;
646 /** Every change made in sudo and by Stripe, newest first, 100 at a time. */
647 audit(filter?: { by?: string; action?: string; before?: string }): Promise<AdminAction[]>;
648 /** Limit and overage requests, with each workspace's history; `open` by default. */
649 limitRequests(status?: "open" | "approved" | "declined" | "all"): Promise<LimitRequestReview[]>;
650 /** Approve (at the amount asked, or another) or decline; the owner is told in the app and by email. */
651 decideLimitRequest(id: string, decision: "approve" | "decline", amountMicros: number | null, note: string, by: string): Promise<Result<LimitRequest>>;
652 /** The Overages queue. */
653 overages(): Promise<Overage[]>;
654 /** A goodwill credit; no amount is the one-click credit. Larger, or a second in 12 months, needs a reason. */
655 goodwill(workspace: string, amountMicros: number | null, reason: string, by: string, day?: string | null): Promise<Result<LedgerEntry>>;
656 /** Workspaces spending in the last day, fastest first. */
657 velocity(): Promise<Velocity[]>;
658 /** Money that reached g1t outside the card pages, such as a bank transfer: entered as a payment. */
659 recordPayment(workspace: string, amountMicros: number, reference: string, note: string, by: string): Promise<Result<LedgerEntry>>;
660 /** Costs & margin: Cloudflare's bill against what g1t charged, over the last `days` (7 to 90, 30 by default). */
661 costs(days?: number): Promise<CostsReport>;
662 /** The open margin alerts, for the banner on every page. */
663 costAlerts(): Promise<MarginAlert[]>;
664 /** g1t's own spend against its caps: the daily breaker and comped budgets. */
665 spendCaps(): Promise<SpendCaps>;
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.666 /** Lets compute start again for the rest of today (UTC) after the daily breaker; needs a note. */
Fixes from the page sweep667 liftBreaker(note: string, by: string): Promise<Result<SpendCaps>>;
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)668 /** Platform pauses, the last hour of platform usage, the month so far and the last day's breaches (billing's platform.rs). */
669 platformGuard(): Promise<PlatformGuard>;
670 /** Pauses or resumes one level across g1t; needs a note, recorded in the audit log. */
671 setPause(level: PauseLevel, paused: boolean, note: string, by: string): Promise<Result<PlatformGuard>>;
Fixes from the page sweep672 /** Approve or reject a price proposal; a rejection needs a note. An approved rise waits out the notice period. */
673 decideProposal(id: string, decision: "approve" | "reject", note: string, by: string): Promise<Result<PriceProposal>>;
674 setCostSettings(settings: CostSettings, by: string): Promise<Result<CostSettings>>;
675 setCostMapping(mapping: CostMappingInput, by: string): Promise<Result<CostMapping>>;
676 /** Reads Cloudflare's bill and reconciles now, as the daily run does. */
677 runCosts(by: string): Promise<Result<CostsRun>>;
678}
679
680/** How much a workspace has earned g1t's trust with money. */
681export type Trust = "new" | "paid" | "established" | "reviewed" | "internal";
682
683/**
684 * How far a workspace's unpaid usage has gone this month, and where its
685 * work stops: past `ceilingMicros`, no new sandboxes, builds or app
686 * requests. Usage counts at its cost to g1t or its charge, whichever is
687 * more, so it counts while g1t is free too.
688 */
689export type Limit = {
690 workspace: string;
691 /** The account that pays: the workspace's own (`ws_<slug>`), or its enterprise's. */
692 account: string;
693 accountName: string;
694 trust: Trust;
695 exposureMicros: number;
696 /** The lower of g1t's ceiling and the owner's spend limit; null for g1t's own. */
697 ceilingMicros: number | null;
698 trustCeilingMicros: number | null;
699 spendLimitMicros: number | null;
700 state: "ok" | "warning" | "stopped";
701 message: string | null;
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.702 /**
703 * Charged this month, which the spend limit is measured against: usage at
704 * price less the discount, included usage, the trial, pools and credit,
705 * with usage metered through the month counted on the same terms. The
706 * same number as the month's `UsageTotals.chargedMicros`.
707 */
Fixes from the page sweep708 spentMicros?: number;
709 /** True while the owners have not chosen a limit, so the automatic one applies: $200, or twice last month's spend. */
710 defaultSpendLimit?: boolean;
711 /** The most owners may set their own limit to without asking: the highest ceiling ever, plus what is prepaid. */
712 availableMicros?: number | null;
713 /** How the ceiling grows from here, in a sentence. */
714 growth?: string | null;
715 /** Paid in advance and not used yet; raises what can be used before work stops by as much. */
716 prepaidMicros?: number;
717 /** The highest ceiling the workspace has had. */
718 maxCeilingMicros?: number | null;
719 /** The most owners may raise the limit to themselves, once: twice the highest ceiling. Null once used. */
720 raiseOnceMicros?: number | null;
721 /** When the one-time raise was used. */
722 raisedAt?: string | null;
723 /** A paid workspace's first billing cycle, on the starting ceiling. */
724 firstMonth?: boolean;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit725 /** The budget's alerts, in percent of the spend limit: some of 50, 75, 90 and 100. */
726 alertLevels?: number[];
727 /** Whether usage pauses at the spend limit (the default); off, it only alerts. */
728 pauseAtLimit?: boolean;
729 /** An HTTPS address told of each budget alert. */
730 budgetWebhook?: string | null;
Fixes from the page sweep731};
732
733/** One metered unit: what it costs g1t and what it is sold at; the price follows the cost. */
734export type Price = {
735 meter:
736 | "sandbox_second"
737 | "build_second"
738 | "app_requests"
739 | "app_cpu"
740 | "app_month"
741 | "custom_domain_month"
742 | "private_storage"
743 | "embedding_tokens"
744 | "scan_cpu"
745 | "scan_rows"
746 | string;
747 title: string;
748 unit: string;
749 costMicros: number;
750 markupPercent: number;
751 priceMicros: number;
752 /** `list`: Cloudflare's published price. `cloudflare`: measured from Cloudflare's bill. */
753 source: "list" | "cloudflare" | string;
754 checkedAt: string | null;
755 updatedAt: string;
756};
757
758export type PriceChange = {
759 meter: string;
760 oldCostMicros: number;
761 newCostMicros: number;
762 markupPercent: number;
763 /** The markup before, when the change was to the markup rather than the cost. */
764 oldMarkupPercent?: number;
765 reason: string;
766 createdAt: string;
767 /** When a change still to come takes effect: a rise is announced before it is charged. */
768 effectiveAt?: string;
769};
770
771export type PriceBook = {
772 prices: Price[];
773 changes: PriceChange[];
774 modelMarginPercent: number;
775 /** Every plan, as sold now. */
776 plans?: FeaturePlan[];
777 /** What is free, and the capped budgets that pay for it. */
778 free?: FreeTier | null;
779};
780
781/** One kind of meter's usage this month, from `usage_meters`. */
782export type MeterUsage = {
783 /** `agents`, `builds`, `requests`, `domains`, `git_storage` or `search_scans`. */
784 key: string;
785 label: string;
786 /** At price (cost plus 20%, on the account's terms), before what paid for it. */
787 micros: number;
788 /** How much, when it is known: `12 runs`, `41 build minutes`. */
789 quantity?: string | null;
790};
791
792/** What g1t gives without a plan; each is paid for by a capped budget. */
793export type FreeTier = {
794 /** Each new workspace's trial credit, once. */
795 trialWorkspaceMicros: number;
796 /** Trial grants each month, in all; new trials wait when it is spent. */
797 trialMonthlyPoolMicros: number;
798 /** g1t's open-source pool each month, and any one repository's share. */
799 ossPoolMicros: number;
800 ossRepoMicros: number;
801 /** Private repository storage free for every workspace. Past it, the plan pays; a free workspace's pushes stop. */
802 freePrivateStorageBytes: number;
803 /** Days of audit log a free workspace keeps. */
804 auditRetentionDays: number;
805 /** Days of audit log the g1t plan keeps, and g1t's own and enterprise workspaces; longer by arrangement. */
806 planAuditRetentionDays?: number;
807 /** The smallest amount a card is charged when a month closes; less carries over. */
808 minChargeMicros: number;
809 /** Git operations free for every workspace each month. Past it, the plan pays; a free workspace is slowed down. */
810 gitOperationsIncluded?: number;
811 /** A new paid workspace's ceiling in its first month. */
812 paidStartCeilingMicros?: number;
813 /** The most a one-click goodwill credit can cost g1t. */
814 overageForgiveCostMicros?: number;
815};
816
817/**
818 * A workspace's trial credit: one grant per workspace, made the first time
819 * it uses something, out of a pool that resets each calendar month. Mirrors
820 * `Trial` in `crates/contracts/src/billing.rs`.
821 */
822export type Trial = {
823 open: boolean;
824 usedMicros: number;
825 limitMicros: number;
826 /** No longer used: trials do not end on a date. */
827 endsAt: string | null;
828 /** Why it is closed: `off`, `used` (this workspace's grant is spent) or `pool` (this month's are given out). */
829 reason: "off" | "ended" | "used" | "pool" | null;
830 /** Whether the workspace has its grant already. */
831 granted?: boolean;
832 /** With `pool`: when new trials start again, the first of next month. */
833 waitsUntil?: string | null;
834};
835
836/**
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.837 * What a workspace has: the g1t plan (`plan`), and Security and quality
838 * (`security`), which comes with the plan at no price of its own. Deployments
839 * are part of the plan too; `has_feature` for either answers whether the
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar840 * workspace has the plan. Mirrors `Feature` in `crates/contracts/src/billing.rs`.
Fixes from the page sweep841 */
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar842export type Feature = "plan" | "deployments" | "security";
Fixes from the page sweep843
844/**
845 * What deployments cost g1t, in millionths of a dollar: fallbacks for when
846 * billing's price book cannot be read. Not an allowance: on the plan every
847 * unit is metered from the first, at cost plus 20%, and drawn from the
848 * plan's included usage first. Projects, previews and the apps behind them
849 * are not metered at all. Mirrors `deployment_costs`.
850 */
851export const DEPLOYMENT_COSTS = {
852 microsPerMillionRequests: 300_000,
853 microsPerMillionCpuMs: 20_000,
854 /** One second of a build's sandbox: a fallback; billing charges the price book's `build_second`. */
855 microsPerBuildSecond: 15,
856 /** One custom domain for a month. */
857 microsPerDomainMonth: 100_000,
Merge GitHub pull request #8 (claude/cool-newton-7nm8r9): Docker deployments on g1t.page behind a switch that stays off until Cloudflare's container APIs are checked live, workflows a workspace manages in its repositories, tarball and zipball downloads, refs/pull/* kept to g1t alone, framework detection for g1t.page builds, and a workflow's event payload matching GitHub's.858 /**
859 * Container apps, at Cloudflare Containers' list prices: a vCPU-second
860 * $0.00002, a GiB-second of memory $0.0000025, a GB-second of disk
861 * $0.00000007, the Durable Object in front of each instance while it
862 * runs (128 MB at $12.50 per million GB-seconds), and a GB of egress
863 * at $0.05, the most Cloudflare charges for one anywhere (Oceania, Korea
864 * and Taiwan; $0.025 in North America and Europe), since g1t cannot
865 * tell where a container's traffic went.
866 */
867 container: {
868 vcpuSecond: 20,
869 memoryGibSecond: 2.5,
870 diskGbSecond: 0.07,
871 instanceSecond: 1.5625,
872 egressGb: 50_000,
873 },
Fixes from the page sweep874} as const;
875
876export type FeaturePlan = {
877 feature: Feature;
878 title: string;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person879 /** Charged every month while the plan is on, in cents, excluding tax. */
Fixes from the page sweep880 monthlyCents: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person881 /** The card processing fee on top each month, in cents (0 when off), excluding tax. */
882 cardFeeCents?: number;
Fixes from the page sweep883 /** What the price includes, one line each. */
884 includes: string[];
885 /** How usage past the allowance is charged. */
886 overage: string;
887};
888
889export type SubscriptionStatus = "active" | "canceling" | "past_due" | "canceled";
890
891export type Subscription = {
892 feature: Feature;
893 status: SubscriptionStatus;
894 /** RFC 3339: when the period paid for ends. */
895 periodEnd: string | null;
896 startedBy: string;
897 startedAt: string;
898};
899
900/** A feature as a workspace sees it. */
901export type FeatureState = {
902 plan: FeaturePlan;
903 subscription: Subscription | null;
904 /** Whether the feature works for the workspace now. */
905 on: boolean;
906 /** On without a plan: comped terms, or given by g1t. Nothing to pay or turn off. */
907 included?: boolean;
908};
909
910export interface BillingApi {
911 status(): Promise<BillingStatus>;
912 /** Members of the workspace only. */
913 account(workspace: string, viewer: Viewer): Promise<Result<BillingAccount>>;
914 /** Newest first. Members of the workspace only. */
915 ledger(workspace: string, viewer: Viewer): Promise<Result<LedgerEntry[]>>;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging916 /** Credits from g1t, newest first, with what is left of each. Members only. */
917 credits(workspace: string, viewer: Viewer): Promise<Result<Credits>>;
Fixes from the page sweep918 /** A month of the ledger, grouped by `day` (default) or `project`. Members only. */
919 statement(workspace: string, viewer: Viewer, month?: string | null, group?: "day" | "project"): Promise<Result<Statement>>;
920 /** One statement line's entries, 50 at a time; `before` is the last id seen. */
921 statementEntries(
922 workspace: string,
923 viewer: Viewer,
924 filter: { month: string; kind: string; day?: string | null; project?: string | null; before?: string | null },
925 ): Promise<Result<LedgerEntry[]>>;
926 /** What the workspace's agents cost since `since`, broken down. Members only. */
927 usage(workspace: string, viewer: Viewer, since: string): Promise<Result<Usage>>;
928 /**
929 * Prepays usage ($25 at least) and returns the page to send the person to:
930 * by card with 3-D Secure, or by bank transfer from $1,000. Owners only.
931 * The payment's id comes back to `returnUrl` as `session`.
932 */
933 checkout(
934 actor: User,
935 workspace: string,
936 amountCents: number,
937 returnUrl: string,
938 method?: "card" | "bank_transfer",
939 ): Promise<Result<{ url: string }>>;
940 /**
941 * Stripe's hosted billing page for the workspace: card, invoices, billing
942 * email and address. g1t never handles card numbers. Owners only.
943 */
944 billingPortal(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
945 /** Credits a payment once the processor says it was made. Safe to repeat. */
946 confirm(workspace: string, viewer: Viewer, session: string): Promise<Result<BillingAccount>>;
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.947 /** A workspace's free trial allowance; `exempt` workspaces are open anyway. */
Fixes from the page sweep948 trial(workspace: string, exempt: string[]): Promise<Trial>;
949 /** Every paid feature and the workspace's plan for each. Members only. */
950 features(workspace: string, viewer: Viewer): Promise<Result<FeatureState[]>>;
951 /**
952 * Starts the card page for a feature's monthly plan. Owners only. The
953 * page's id comes back to `returnUrl` as `session`.
954 */
955 subscribe(actor: User, workspace: string, feature: Feature, returnUrl: string): Promise<Result<{ url: string }>>;
956 /** Turns the feature on once the plan is paid for. Safe to repeat. */
957 confirmSubscription(workspace: string, viewer: Viewer, session: string): Promise<Result<FeatureState>>;
958 /** Ends a plan at the end of its period, or (`resume`) takes that back. Owners only. */
959 cancelSubscription(actor: User, workspace: string, feature: Feature, resume?: boolean): Promise<Result<FeatureState>>;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person960 /** Which of the workspaces are free (on no paid plan); none where payments are not set up. */
961 freeWorkspaces(workspaces: string[]): Promise<string[]>;
Fixes from the page sweep962 /** Whether a feature works for a workspace now; a failure with the reason when not. */
963 hasFeature(workspace: string, feature: Feature): Promise<Result<boolean>>;
964 /**
965 * Usage past a plan's allowance, charged from credit at cost plus the
966 * margin, once per `reference`. False if it was charged before.
967 */
968 chargeFeature(charge: {
969 workspace: string;
970 feature: Feature;
971 costMicros: number;
972 description: string;
973 repo?: string | null;
974 reference: string;
975 /** For a build: how long it ran, so the plan's included build time pays for what it can. */
976 buildSeconds?: number | null;
977 }): Promise<Result<boolean>>;
978 /**
979 * What a source cost g1t so far this month, so the workspace's limit
980 * counts it now. Replaces the last report. Billing charges `context`
981 * and `security` itself once the month is over; `deployments` charges
982 * its own.
983 */
984 notePending(
985 workspace: string,
986 source: "deployments" | "domains" | "context" | "security",
987 costMicros: number,
988 /** How much of it, for the Billing page: `1.2 million requests and 3.4 million CPU ms`. */
989 detail?: string | null,
990 ): Promise<boolean>;
991 /**
992 * This month's usage, one line per kind of meter, at what it is charged
993 * before the plan's included usage or a pool paid for it. Members only.
994 */
995 usageMeters(workspace: string, viewer: Viewer): Promise<Result<MeterUsage[]>>;
996 /** What the workspace may do now: its plan, caps, pause, trial, and what the plan gives it. */
997 entitlements(workspace: string): Promise<Entitlements>;
998 /**
999 * Holds a start's estimated cost before the work starts. A failure's code says why not:
1000 * `paused`, `limit`, `not_paid`, `trial_used` or `oss_pool_empty`, with a message for the owner.
1001 */
1002 reserve(reservation: {
1003 workspace: string;
1004 repo: RepoPath;
1005 public: boolean;
1006 kind: ComputeKind;
1007 /** The most the work is expected to cost g1t, before the margin. */
1008 estimateMicros: number;
1009 }): Promise<Result<ReservationHeld>>;
1010 /** Releases a reservation's hold with what the work cost g1t, before the margin. Safe to repeat. */
1011 settle(reservationId: string, actualMicros: number): Promise<Result<boolean>>;
1012 /** Stripe's page to save and verify a card (3-D Secure, never charged). Owners only. */
1013 cardCheck(actor: User, workspace: string, returnUrl: string): Promise<Result<{ url: string }>>;
1014 /** Records the card check once Stripe says it passed, and grants the trial if it can. Safe to repeat. */
1015 confirmCardCheck(workspace: string, viewer: Viewer, session: string): Promise<Result<Entitlements>>;
1016 /** An owner asks for a higher limit, or for help with usage past what was meant. */
1017 requestLimit(
1018 actor: User,
1019 workspace: string,
1020 request: { kind: "limit" | "overage"; amountMicros: number; reason: string; expectedMonthlyMicros: number },
1021 ): Promise<Result<LimitRequest>>;
1022 /** The workspace's requests and their answers, newest first. Members only. */
1023 limitRequests(workspace: string, viewer: Viewer): Promise<Result<LimitRequest[]>>;
1024 /**
1025 * The owners' own caps on agents: one run's spend ($0.10 to $100) and one issue's ($1 to $1,000).
1026 * Null goes back to the default ($2 and $10). A cap staff set wins. Owners only.
1027 */
1028 setCaps(actor: User, workspace: string, caps: { runCapMicros: number | null; issueCapMicros: number | null }): Promise<Result<Entitlements>>;
1029 /** An owner's answer to a spend spike: keep going for 24 hours, or stop. */
1030 confirmSpike(actor: User, workspace: string, keepGoing: boolean): Promise<Result<Entitlements>>;
1031 /** Every metered price and the recent changes. Public. */
1032 prices(): Promise<PriceBook>;
1033 /** A workspace's limit, for its members. */
1034 limit(workspace: string, viewer: Viewer): Promise<Result<Limit>>;
1035 /** The same, for the services that enforce it. */
1036 checkLimit(workspace: string): Promise<Result<Limit>>;
1037 /**
1038 * The owners' own monthly limit, up to what is available; null goes back
1039 * to the default, and `useFullLimit` uses everything available. Owners only.
1040 */
1041 setSpendLimit(
1042 actor: User,
1043 workspace: string,
1044 spendLimitMicros: number | null,
1045 useFullLimit?: boolean,
1046 /** Use the one-time raise: up to twice the highest ceiling, once per workspace. */
1047 raiseOnce?: boolean,
1048 ): Promise<Result<Limit>>;
1049 /** The workspace's invoices from g1t, newest first. Members only. */
1050 invoices(workspace: string, viewer: Viewer): Promise<Result<WorkspaceInvoice[]>>;
1051 /**
1052 * How long a sandbox ran for a workspace, reported when it stops. Its
1053 * cost is recorded and every second is charged, from the first. False if
1054 * `reference` was recorded before.
1055 */
1056 recordSandbox(usage: {
1057 workspace: string;
1058 seconds: number;
1059 description: string;
1060 repo?: string | null;
1061 reference: string;
1062 /** What ran; checks, workflows and the merge queue on public repositories may use the open-source pool. */
1063 kind?: ComputeKind | null;
1064 /** vCPU-seconds used, when the sandbox can tell: the run is priced on its own CPU. */
1065 cpuSeconds?: number | null;
1066 /** The reservation it started under, settled with this cost. */
1067 reservationId?: string | null;
1068 /** It ran on one of the workspace's self-hosted runners: its minutes go on usage at $0. */
1069 selfHosted?: boolean;
1070 /** The machine it ran on, by label (`g1t-4core`); absent, the standard one. */
1071 instance?: string | null;
1072 }): Promise<Result<boolean>>;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1073 /** Usage over a range of days (`YYYY-MM-DD`, both included), at price, by product, meter, project and day. Members only. */
1074 usageReport(
1075 workspace: string,
1076 viewer: Viewer,
1077 range: { from: string; until: string; products?: string[]; projects?: string[] },
1078 ): Promise<Result<UsageReport>>;
1079 /** The monthly budget: the spend limit, its alerts, whether usage pauses at 100%, and a webhook. Owners only. */
1080 setBudget(
1081 actor: User,
1082 workspace: string,
1083 budget: { amountMicros: number | null; alerts: number[]; pauseAtLimit: boolean; webhook: string | null; keepLimit?: boolean },
1084 ): Promise<Result<Limit>>;
1085 /** Invoice details from the Stripe customer, the default payment method, invoices and the next invoice. Members only. */
1086 billingDetails(workspace: string, viewer: Viewer): Promise<Result<BillingDetails>>;
1087 /** Saves invoice details on the Stripe customer; absent fields stay, empty clears. Owners only. */
1088 setBillingDetails(actor: User, workspace: string, details: BillingDetailsInput): Promise<Result<BillingDetails>>;
Fixes from the page sweep1089}
1090
1091
1092/** One slice of usage: what it was for, what it cost, how many runs. */
1093export type UsageSlice = { key: string; micros: number; runs: number };
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1094
Fixes from the page sweep1095/** What a workspace's agents cost over a period. */
1096export type Usage = {
1097 since: string;
1098 /** Charged, including g1t's margin. */
1099 spentMicros: number;
Billing and Usage reconcile: own-provider runs leave Billing's at-price total, and Usage's not-charged part is at price less charged1100 /** 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. */
Billing's usage total is labeled at price, and Usage says what part of it was paid for1101 coveredMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1102 /** What the account's discount took off the price; usage at price is spent + covered + this. */
1103 discountMicros?: number;
1104 /** The account's discount now, in percent; with one, the slices are at price. */
1105 discountPercent?: number | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1106 /** Usage at price: spent + covered + discount, from the same ledger lines. The one usage figure every page shows. */
1107 priceMicros?: number;
Fixes from the page sweep1108 /** What g1t's model provider charged, before the margin. */
1109 costMicros: number;
1110 /** What runs on the workspace's own provider cost there, estimated. Not charged by g1t. */
1111 providerMicros: number;
1112 /** What the runs used, at cost: g1t's models and the workspace's own provider together. */
1113 usedMicros: number;
1114 /** g1t charges nothing for now; the slices then measure usage at cost. */
1115 free: boolean;
1116 runs: number;
1117 /** Spend per day and task, keyed `YYYY-MM-DD/task`. */
1118 byDay: UsageSlice[];
1119 byTask: UsageSlice[];
1120 byRepo: UsageSlice[];
1121 /** Keyed `namespace/name#number`. */
1122 byPull: UsageSlice[];
1123 byModel: UsageSlice[];
1124 /** Credit bought in the period. */
1125 addedMicros: number;
1126};
1127
1128/** One of g1t's products (a "bucket") on one day. Money in micros. */
1129export type CostDay = { day: string; bucket: string; cfCostMicros: number; ownCostMicros: number; valueMicros: number; cashMicros: number };
1130
1131/** One product over the range: what customers were charged at price against what it cost. */
1132export type ProductMargin = {
1133 bucket: string;
1134 title: string;
1135 /** Cloudflare's bill, or g1t's own figure where Cloudflare does not bill it (`costSource`). */
1136 costMicros: number;
1137 cfCostMicros: number;
1138 ownCostMicros: number;
1139 valueMicros: number;
1140 marginMicros: number;
1141 marginPercent: number | null;
1142 costSource: "cloudflare" | "ledger" | string;
1143 /** Running g1t, paid for by the plan. */
1144 overhead: boolean;
1145};
1146
1147/** All of g1t: money in (usage and the plan) against every cost. */
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1148export type OverallMargin = {
1149 usageMicros: number;
1150 plansMicros: number;
1151 costMicros: number;
1152 marginMicros: number;
1153 marginPercent: number | null;
1154 /** Of costMicros, what went on usage g1t gave away on purpose: comped workspaces, free periods, the trial and the open-source pool. */
1155 givenMicros?: number;
1156 /** Money in against costMicros - givenMicros. */
1157 soldMarginMicros?: number;
1158 soldMarginPercent?: number | null;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1159 /** Usage sold: usageMicros against what that usage cost, less what was given. */
1160 usageCostMicros?: number;
1161 usageMarginMicros?: number;
1162 usageMarginPercent?: number | null;
1163 /** Running g1t: plansMicros against the platform's cost, less its given share. */
1164 runningCostMicros?: number;
1165 /** Cost no mapping names, less its given share. */
1166 unmappedCostMicros?: number;
1167 /** givenMicros by why. Free is free periods, free allowances and overruns g1t covered. */
1168 givenCompedMicros?: number;
1169 givenFreeMicros?: number;
1170 givenTrialMicros?: number;
1171 givenPoolMicros?: number;
Merge branch 'worktree-agent-a633ac0f7f66d419d'1172 /** What discounts on an account's terms took below cost plus the margin: given, not margin lost. */
1173 givenDiscountMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1174 /** Credits from g1t spent on usage, by kind: given, never money in. Refunds come off money in instead. */
1175 givenCreditPromotionalMicros?: number;
1176 givenCreditGoodwillMicros?: number;
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb971177 /** What testing resets wiped that g1t paid for: the usage still happened, so its cost is given, never a leak. */
1178 givenResetMicros?: number;
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1179 /** Credits over the range: given (every kind), spent on usage, and refunds' money given back. */
1180 creditsGivenMicros?: number;
1181 creditsUsedMicros?: number;
1182 creditsRefundedMicros?: number;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1183 /** costMicros by who g1t pays: Cloudflare's bill (billed, after included allowances) and model providers (tokens, not on Cloudflare's bill). */
Costs: the plan's included usage counts as paid for the usage it covered, out of what plans leave for running g1t; the run button shows it is running with CSS alone (sudo ships no JavaScript)1184 /** What the plan's included usage paid for, at price: money in for usage, paid out of plansMicros. */
1185 includedMicros?: number;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1186 cloudflareCostMicros?: number;
1187 modelsCostMicros?: number;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1188 /** Tax collected with payments over the range, net of refunds: owed to tax authorities, never cash or revenue. */
1189 taxCollectedMicros?: number;
1190 /** Card processing fees passed on with card payments, net of refunds: they pay Stripe's fee, not revenue. */
1191 cardFeesMicros?: number;
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1192 /** What workspaces were charged while payments were not live (Stripe's test mode): given, never money in. */
1193 givenUnpaidMicros?: number;
1194 /** Cloudflare's subscriptions over the range: each day's share of the billing cycle it is in. */
1195 subscriptionsMicros?: number;
1196 /** What AI Gateway priced g1t's own provider traffic at over the range, beside the ledger's model cost. */
1197 gatewayCostMicros?: number;
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1198};
Fixes from the page sweep1199
1200/** A count, cost or leak that does not add up. */
1201export type CostDrift = {
1202 bucket: string;
1203 title: string;
1204 kind: "count" | "cost" | "leak" | string;
1205 ours: number;
1206 cloudflare: number;
1207 deltaPercent: number | null;
1208 detail: string;
1209 foundAt: string;
1210};
1211
1212export type MarginAlert = {
1213 id: string;
1214 kind: "margin" | "overall" | "leak" | "drift" | "workspace" | string;
1215 /** The product, or the workspace. */
1216 subject: string;
1217 detail: string;
1218 since: string;
1219 openedAt: string;
1220 emailedAt: string | null;
1221};
1222
1223/** A change to a price, measured from what Cloudflare charged. */
1224export type PriceProposal = {
1225 id: string;
1226 meter: string;
1227 title: string;
1228 unit: string;
1229 currentCostMicros: number;
1230 proposedCostMicros: number;
1231 changePercent: number;
1232 markupPercent: number;
1233 reason: string;
1234 source: "keeper" | "reconciler" | string;
1235 /** Far off the current cost: look before approving. */
1236 suspect: boolean;
1237 status: "open" | "applied" | "approved" | "rejected" | "superseded" | string;
1238 createdAt: string;
1239 decidedAt: string | null;
1240 decidedBy: string | null;
1241 note: string | null;
1242 effectiveAt: string | null;
1243};
1244
1245/** One version of one meter's price; never changed once written. */
1246export type PriceVersion = {
1247 id: string;
1248 meter: string;
1249 version: number;
1250 costMicros: number;
1251 markupPercent: number;
1252 priceMicros: number;
1253 effectiveAt: string;
1254 reason: string;
1255 createdBy: string;
1256 appliedAt: string | null;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1257 /**
1258 * What `costMicros` is: `cost`, what g1t pays for a unit; `rate`, a price
1259 * g1t sets with no cost behind it (the agent rate), so it is no cost;
1260 * `weight`, a multiplier in millionths, not money. Absent from older
1261 * billing: read as `cost`.
1262 */
1263 basis?: "cost" | "rate" | "weight" | "";
Fixes from the page sweep1264};
1265
sudo: reset a test workspace's billing so it starts again as a new customer; refused on a live Stripe key, for comped workspaces and for an enterprise's1266/** What `resetBilling` removed. */
sudo: a billing reset runs the costs analysis again so every figure is fresh; every submit button shows it is working (CSS only); no margin percentage on less than a cent sold1267export type BillingReset = { workspace: string; rows: number; refreshed?: boolean };
sudo: reset a test workspace's billing so it starts again as a new customer; refused on a live Stripe key, for comped workspaces and for an enterprise's1268
Costs: margin is measured on what was sold; comped workspaces, free periods, the trial and the pools are given away, a budget shown beside it1269export type WorkspaceCost = { workspace: string; costMicros: number; revenueMicros: number; givenMicros?: number; internal: boolean };
Fixes from the page sweep1270
1271export type CostLineSummary = {
1272 product: string;
1273 meter: string;
1274 rawName: string;
1275 unit: string;
1276 source: string;
1277 quantity: number;
1278 costMicros: number;
1279 /** Absent when no mapping claims it. */
1280 bucket: string | null;
1281};
1282
1283export type CostMapping = {
1284 product: string;
1285 meter: string;
1286 bucket: string;
1287 priceMeter: string | null;
1288 ownMeter: string | null;
1289 scaleToOwn: boolean;
1290 driftPercent: number;
1291 note: string;
1292 updatedAt: string;
1293 updatedBy: string;
1294};
1295
1296export type CostMappingInput = {
1297 product: string;
1298 meter: string;
1299 bucket?: string;
1300 priceMeter?: string | null;
1301 ownMeter?: string | null;
1302 scaleToOwn?: boolean;
1303 driftPercent?: number | null;
1304 note?: string;
1305 remove?: boolean;
1306};
1307
1308export type CostSettings = {
1309 autoApply: boolean;
1310 autoApplyPercent: number;
1311 noticeDays: number;
1312 marginFloorPercent: number;
1313 alertDays: number;
1314 minDailyCostMicros: number;
1315 anomalyFactor: number;
1316 anomalyFloorMicros: number;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1317 /** Pass Stripe's card fee on as its own line when AI credit is bought by card. */
1318 cardFee: boolean;
Fixes from the page sweep1319};
1320
1321export type CostsReport = {
1322 configured: boolean;
1323 fetchedAt: string | null;
1324 since: string;
1325 until: string;
1326 days: CostDay[];
1327 products: ProductMargin[];
1328 overall: OverallMargin;
1329 drift: CostDrift[];
1330 alerts: MarginAlert[];
1331 proposals: PriceProposal[];
1332 versions: PriceVersion[];
1333 topWorkspaces: WorkspaceCost[];
1334 lines: CostLineSummary[];
1335 mappings: CostMapping[];
1336 settings: CostSettings;
1337 /** g1t's own spend against its two caps. */
1338 caps: SpendCaps;
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1339 /** Cloudflare's current billing cycle: usage cost so far by meter, and the projection. Absent until the bill is read. */
1340 cycle?: CloudflareCycle | null;
1341 /** The last read of Cloudflare's billable usage: what came back. */
1342 billRead?: BillRead | null;
1343 /** Of the range's cost, what no workspace's usage could carry: running g1t, attributed to no one. */
1344 unattributedMicros?: number;
1345};
1346
1347/** Cloudflare's billing cycle, as its Billable usage page shows it. */
1348export type CloudflareCycle = {
1349 /** First and last days, YYYY-MM-DD, UTC. */
1350 start: string;
1351 end: string;
1352 days: number;
1353 /** Days from its start to today, today included. */
1354 daysElapsed: number;
1355 /** Usage cost so far, after the included allowances. */
1356 usageMicros: number;
1357 /** usageMicros over the days elapsed, times the cycle's days. */
1358 projectedMicros: number;
1359 averageDailyMicros: number;
1360 /** Cloudflare's subscriptions for the cycle (not on the usage bill). */
1361 subscriptionsMicros: number;
1362 meters: CycleMeter[];
1363};
1364
1365/** One of Cloudflare's meters over the cycle so far. */
1366export type CycleMeter = {
1367 product: string;
1368 meter: string;
1369 rawName: string;
1370 unit: string;
1371 quantity: number;
1372 /** What the cycle includes; null without a list price. */
1373 included: number | null;
1374 billableQuantity: number;
1375 costMicros: number;
1376 /** cloudflare: Cloudflare's own cost; list: the list price past the included amount; none: no list price known. */
1377 basis: "cloudflare" | "list" | "none" | string;
Fixes from the page sweep1378};
1379
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1380/** What the last read of Cloudflare's billable usage got back. */
1381export type BillRead = {
1382 readAt: string;
1383 since: string;
1384 until: string;
1385 rows: number;
1386 pages: number;
1387 consumedRows: number;
1388 pricingOnlyRows: number;
1389 costedRows: number;
1390};
1391
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)1392/** One level of the platform pause, as sudo shows it. Snake case, as billing sends it. */
1393export type PauseState = {
1394 level: PauseLevel;
1395 paused: boolean;
1396 note: string | null;
1397 set_by: string | null;
1398 set_at: string | null;
1399 /** Set by billing's usage watcher, not a person. */
1400 auto: boolean;
1401};
1402
1403/** One platform metric over an hour or the month so far. */
1404export type PlatformMetric = {
1405 metric: string;
1406 title: string;
1407 value: number;
1408 /** Its hourly threshold (`PLATFORM_HOURLY_*`); 0: none. */
1409 threshold: number;
1410 /** The script, queue, database or namespace that counted most. */
1411 top_name: string | null;
1412 top_value: number | null;
1413};
1414
1415/** A breach billing's usage watcher found. */
1416export type PlatformBreach = {
1417 id: string;
1418 metric: string;
1419 hour: string;
1420 rule: "threshold" | "spike";
1421 value: number;
1422 threshold: number;
1423 severe: boolean;
1424 top_name: string | null;
1425 detail: string;
1426 /** Levels it paused. */
1427 paused: PauseLevel[];
1428 opened_at: string;
1429 emailed_at: string | null;
1430};
1431
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.1432/** Billing's `admin_platform_guard`: the platform pause and usage watcher
1433 * (docs.g1t.sh/guides/deploy-to-cloudflare/#spend-guardrails). */
Merge platform pause and the hourly usage watcher: staff can pause compute, schedules, indexing or renders for everyone, the watcher emails on a breach and is never blind quietly, and the models proxy holds each run to its cap (billing 0051, integrations 0006)1434export type PlatformGuard = {
1435 levels: PauseState[];
1436 /** The last hour read, `YYYY-MM-DDTHH:00:00Z`. */
1437 hour: string | null;
1438 last_hour: PlatformMetric[];
1439 month: string;
1440 month_to_date: PlatformMetric[];
1441 breaches: PlatformBreach[];
1442 /** Whether billing can read Cloudflare's analytics. */
1443 can_read: boolean;
1444 /** `AUTO_PAUSE`: the levels a severe breach may pause. */
1445 auto_pause: PauseLevel[];
1446 /** What the latest run could not see: each query that failed, with its error. */
1447 blind?: { key: string; dataset: string; error: string }[];
1448 /** The latest run found every dataset empty: the wrong account, or a token that cannot see it. */
1449 empty?: boolean;
1450 /** The hour the latest run read. */
1451 last_run?: string | null;
1452};
1453
Fixes from the page sweep1454/** What g1t pays for itself, at cost, against its caps (billing's `budget`). */
1455export type SpendCaps = {
1456 /** Today (UTC), YYYY-MM-DD, and this month, YYYY-MM. */
1457 day: string;
1458 month: string;
1459 /** What g1t paid for itself today across every workspace. */
1460 todayMicros: number;
1461 /** `PLATFORM_DAILY_SPEND_CAP_MICROS`; 0: no breaker. */
1462 dailyCapMicros: number;
1463 /** New hosted-model agent runs g1t would pay for are paused. */
1464 tripped: boolean;
1465 trippedAt: string | null;
1466 liftedBy: string | null;
1467 liftedAt: string | null;
1468 liftNote: string | null;
1469 /** This month so far, by what paid: comped, trial, oss, given, unpaid. */
1470 monthBuckets: { bucket: string; title: string; micros: number }[];
1471 comped: CompedBudget[];
1472 /** Free workspaces' share of reconciled costs this month (git, storage, platform). */
1473 freeTierMicros: number;
Costs: Cloudflare's subscriptions read from Cloudflare each day, the estimate only until then; sudo's costs split into Costs & margin and Bill & pricing1474 /** Cloudflare's subscriptions a month: read from Cloudflare each day, else `CLOUDFLARE_FIXED_MONTHLY_MICROS`, an estimate. */
Fixes from the page sweep1475 fixedMonthlyMicros: number;
Costs: Cloudflare's subscriptions read from Cloudflare each day, the estimate only until then; sudo's costs split into Costs & margin and Bill & pricing1476 fixedSource?: "cloudflare" | "estimate" | string;
1477 fixedReadAt?: string | null;
1478 /** Each subscription, when read from Cloudflare. */
1479 fixedItems?: { name: string; monthlyMicros: number }[];
Merge Cloudflare's usage over its billing cycle: every page read, included amounts once a cycle, a projection, test-mode charges never money in (billing 0052)1480 /** Of fixedMonthlyMicros, this calendar month's days so far, each at its billing cycle's daily share. */
1481 fixedMonthMicros?: number;
Fixes from the page sweep1482 /** Money in this month, through the last reconciled day. */
1483 revenueMicros: number;
Merge costs and margin review: gateway query, own spend, discount meters, superseded rises1484 /**
1485 * Of this month's buckets, what was spent on workspaces whose billing a
1486 * testing reset later wiped (still g1t's spend; the reconciled figures
1487 * have it only where the reset kept it), and those workspaces.
1488 */
1489 resetMicros?: number;
1490 resetWorkspaces?: string[];
Fixes from the page sweep1491};
1492
1493/** A comped account's monthly budget, at cost. */
1494export type CompedBudget = {
1495 account: string;
1496 name: string;
1497 usedMicros: number;
1498 /** 0: no budget. */
1499 ceilingMicros: number;
1500 /** `COMPED_MONTHLY_CEILING_MICROS`, not the account's own limit. */
1501 defaultCeiling: boolean;
1502 /** 50, 75, 90, 100, or 0. */
1503 level: number;
1504};
1505
1506export type CostsRun = { lines: number; days: number; proposals: number; alerts: number; problems: string[] };
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1507
1508/** The product families the Usage page groups meters into, in order. */
1509export const PRODUCTS = [
1510 { key: "sandboxes", label: "Sandboxes" },
1511 { key: "deployments", label: "Deployments" },
1512 { key: "git_storage", label: "Git & storage" },
1513 { key: "packages", label: "Packages" },
1514 { key: "security", label: "Security & quality" },
1515 { key: "search", label: "Search" },
1516] as const;
1517
1518export type ProductKey = (typeof PRODUCTS)[number]["key"];
1519
1520/** What usage came to over a range, and what paid for it: price − discount − included − credits = charged. */
1521export type UsageTotals = {
1522 /** Usage at price, pending usage included. */
1523 priceMicros: number;
1524 discountMicros: number;
1525 /** Paid by the plan's included usage, the trial and g1t's pools. */
1526 includedMicros: number;
1527 /** Paid by AI credit and credit from g1t. */
1528 creditsMicros: number;
1529 /** Left for the workspace to pay. */
1530 chargedMicros: number;
1531 /** Metered this month, charged when it closes. */
1532 pendingMicros: number;
Money is written one way. A single formatter turns millionths of a dollar into dollars, rounding half up on whole micros rather than on a float, so the same sum reads the same on every page: under a cent reads <$0.01 on a total and exactly nothing is $0.00, while the statement's lines, a session's receipt, the price book and an agent's effort costs carry up to four places where the fraction of a cent is the point; the six formatters that each rounded their own way are gone. This month is the calendar month in UTC from its first day to today everywhere, and billing counts the month's not-yet-closed usage in any range that reaches into the current month, so the top bar's pill, Spend, Home and Usage ask for the same days and get the same figure; Home now reads the usage report the others read instead of adding up statements. Usage's pending sentence says what of that usage the close will charge after the discount and included usage, which the billing API returns as pending_charged_micros. A reconciliation test holds the pill, Spend, Home and Usage to one number for one month. The usage and billing guide says how amounts are written and what this month means.1533 /** What of `pendingMicros` will be charged at the close, after the discount and what g1t covers; absent from an older billing. */
1534 pendingChargedMicros?: number;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1535 costMicros: number;
1536};
1537
1538export type UsageDay = { day: string; product: string; micros: number };
1539
Spend adds up on one ledger. Charged this month has one definition, price less discount, included usage and credit, shared by the plan card, the spend limit, Spend and the top bar; the limit had counted usage not yet closed at full price before the discount, so a comped workspace read as charged a cent. Every agent line on the ledger names the agent and who asked, repository runs by g1t included, so Spent is the sum of its products, Agents is the agent product, and by agent adds up to it; the billing API returns by_agent and by_person. The usage and billing guide says how spend is counted.1540/** 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. */
1541
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1542export type UsageAllowance = { used: number; of: number; unit: string };
1543
1544export type ProjectUsage = { project: string; micros: number; quantity: number };
1545
1546/** One meter over a range. */
1547export type MeterLine = {
1548 key: string;
1549 label: string;
1550 product: string;
1551 /** `tokens`, `seconds`, `bytes`, `operations`, `requests` or `entries`. */
1552 unit: string;
1553 quantity: number;
1554 micros: number;
1555 pendingMicros?: number;
1556 /** Every day of the range, oldest first, at price. */
1557 daily: number[];
1558 allowance?: UsageAllowance | null;
1559 byProject: ProjectUsage[];
Merge branch 'model-routing'1560 /** How the quantity is counted, when that needs saying (the agent rate's token weights). */
1561 note?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1562};
1563
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.1564export type ProductUsage = { key: string; label: string; micros: number; meters: MeterLine[] };
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1565
1566export type UsageReport = {
1567 from: string;
1568 until: string;
1569 totals: UsageTotals;
1570 days: UsageDay[];
1571 products: ProductUsage[];
1572 projects: string[];
1573 /** The plan's included usage this month, in micros. */
1574 included?: UsageAllowance | null;
1575 discountPercent?: number | null;
The contracts no longer describe g1t's own agents, and workspaces can keep their AI providers. Every consumer had already stopped using them, so the TypeScript and Rust contracts drop the workspace-agent, ability, look, skill-library, context, runner-agent and mention modules, the chat and docs RPCs agents posted and read through, the folio agent methods, the agent_waiting notification, agent.asked and memory.changed events, AI credit, token and gateway billing types, model routes and sessions, team agents, agent tokens, plan, review, message and confidence types, command rules, cost caps and confidence rules. The agents:run and models:* scopes are no longer offered by any preset, OAuth default or permission form, but a stored token or grant that names them still reads; and the removed operations are gone from the scope table, so the API's check that every operation has exactly one scope is strict again. What stored data needs in order to parse (old run and credential kinds, an agent team lead, retired rules and webhook events, old guardrail and integration settings) still parses, and a run's token is still PrincipalKind::Agent, which now means a run's token and the @g1t rows written before. The customize, marketplace, skills and claude-plugin contracts stay only until the mobile app drops its Customize screens.1576 /** AI credit bought before g1t stopped selling it, left now; kept apart from credit for everything. */
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1577 aiCreditMicros: number;
1578 creditMicros: number;
1579 trialMicros?: number | null;
1580 plan: PlanKind;
1581 free: boolean;
1582};
1583
1584export type PostalAddress = { line1: string; line2: string; city: string; state: string; postalCode: string; country: string };
1585
1586export type PaymentMethod = {
1587 kind: string;
1588 brand?: string | null;
1589 last4?: string | null;
1590 expMonth?: number | null;
1591 expYear?: number | null;
1592};
1593
1594export type StripeInvoice = {
1595 id: string;
1596 number?: string | null;
1597 status: string;
1598 totalCents: number;
1599 currency: string;
1600 createdAt: string;
1601 description?: string | null;
1602 hostedUrl?: string | null;
1603 pdfUrl?: string | null;
1604};
1605
1606export type UpcomingInvoice = { closesAt: string; subscriptionsMicros: number; usageMicros: number; totalMicros: number };
1607
1608export type BillingDetails = {
1609 customer: boolean;
1610 email: string | null;
1611 name: string | null;
1612 address: PostalAddress | null;
1613 taxIdType: string | null;
1614 taxId: string | null;
1615 poNumber: string | null;
1616 language: string | null;
1617 paymentMethod: PaymentMethod | null;
1618 invoices: StripeInvoice[];
1619 upcoming: UpcomingInvoice;
1620 unavailable?: string | null;
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1621 /** Whether Stripe Tax can place the customer from the address; without it nothing is charged. */
1622 taxLocation?: boolean;
1623 /** Set when g1t did not charge for want of a billing address. */
1624 taxAddressNeededAt?: string | null;
1625 /** Stripe's check of the tax ID: pending, verified, unverified or unavailable. */
1626 taxIdStatus?: string | null;
1627 /** none, exempt or reverse, as set at Stripe. */
1628 taxExempt?: string | null;
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1629};
1630
1631export type BillingDetailsInput = {
1632 email?: string;
1633 name?: string;
1634 address?: PostalAddress;
1635 taxIdType?: string;
1636 taxId?: string;
1637 poNumber?: string;
1638 language?: string;
1639};

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