/** * Spend governance: credit reservations and org ceilings, enforced at admission. * * The flow: admit() checks every ceiling BEFORE a run enters the queue * (per-run resource envelope, org concurrency, org monthly total) and refuses * with RUN_BUDGET_EXHAUSTED when one is exhausted - the exact error the * negative fixture asserts. reserve() then sets aside the estimate, keyed to * the run, before dispatch. reconcile() runs once at terminal state: the * actual cost is charged (status "charged") or, when nothing was used, the * reservation is released ("released") - the unused half never lingers. * * Each reservation or charge uses integer cents from 0 through 2147483647, * matching the supported PostgreSQL and SQLite schema. Monthly ceilings and * aggregates may exceed that per-row limit but must remain JavaScript-safe * nonnegative integers. Invalid amounts throw RangeError before store access. */ import type { ApiPrincipal } from "../server/types.js"; import { type RunQuota, type SpendCeilings } from "./governance.js"; import type { CreditReservation, GovernanceStore } from "./governance-store.js"; export interface SpendAdmissionInput { principal: ApiPrincipal; slug: string; quota?: RunQuota; /** Integer cents from 0 through 2147483647; omission estimates zero. */ estimatedCents?: number; now?: Date; } export interface SpendService { /** Enforce the org's ceilings; throw RUN_BUDGET_EXHAUSTED with the exact ceiling named. */ admit(input: SpendAdmissionInput): Promise; /** Reserve credits for a run before dispatch. Returns the reservation id. */ reserve(tenantId: string, runId: string, estimatedCents: number): Promise; /** Reconcile at terminal state: charge the actual cost, or release the unused reservation. */ reconcile(tenantId: string, runId: string, actualCents: number): Promise; } export declare function createSpendService(options: { governanceStore: GovernanceStore; ceilings?: SpendCeilings; }): SpendService;