Skip to content

Commit c077242

Browse files
committed
feat(billing): make spend_limit a hard usage cap enforced at the proxy (#1048)
Synced from sferarc/pgbeam@c96d5d0
1 parent d50c25f commit c077242

2 files changed

Lines changed: 12 additions & 2 deletions

File tree

src/generated/describe-map.gen.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ export const describeByOperationId: Record<string, DescribeEndpoint> = {
4444
"listAuditLogs": {"operationId":"listAuditLogs","method":"GET","path":"/v1/projects/{project_id}/audit-logs","summary":"List agent audit logs","description":"Returns agent statement audit entries for the project, newest first, with optional credential, event, decision, source and date-range filters.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"credential_id","in":"query","required":false,"type":"string","description":"Filter to a single agent credential."},{"name":"event","in":"query","required":false,"type":"string","description":"Filter to a single event type (e.g. blocked, masked, query)."},{"name":"decision","in":"query","required":false,"type":"\"allow\" | \"block\" | \"mask\" | \"truncate\"","description":"Coarse outcome filter that groups events. `allow` = query; `block` = blocked, budget_exhausted, auth_failed, credential_expired; `mask` = masked; `truncate` = truncated."},{"name":"source","in":"query","required":false,"type":"\"wire\" | \"mcp\" | \"control\"","description":"Filter by statement origin (wire, mcp, or control)."},{"name":"start","in":"query","required":false,"type":"string","description":"Return entries at or after this timestamp (inclusive lower bound)."},{"name":"end","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (cursor / upper bound)."},{"name":"before","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (keyset pagination cursor)."},{"name":"page_size","in":"query","required":false,"type":"number","description":"Maximum number of items to return (1-100, default 20)."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ entries: ({ bytes_out?: number; cache_status?: string; client_ip?: string; credential_id?: string; decision_rule?: string; event: string; id: string; latency_ms?: number; normalized_sql?: string; project_id: string; query_hash?: string; reason?: string; region?: string; rows_returned?: number; session_id?: string; source?: string; sql?: string; statement_kind?: string; ts: string })[]; next_page_token?: string }","responseStatus":"200"},
4545
"exportAuditLogs": {"operationId":"exportAuditLogs","method":"GET","path":"/v1/projects/{project_id}/audit-logs/export","summary":"Export agent audit logs as CSV","description":"Streams the project's agent audit entries as a CSV file, newest first, honoring the same credential, event, decision, source and date-range filters as the list endpoint. The full filtered set is streamed (no pagination); the result is suitable for spreadsheets, SIEM ingestion, and compliance archives.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"credential_id","in":"query","required":false,"type":"string","description":"Filter to a single agent credential."},{"name":"event","in":"query","required":false,"type":"string","description":"Filter to a single event type (e.g. blocked, masked, query)."},{"name":"decision","in":"query","required":false,"type":"\"allow\" | \"block\" | \"mask\" | \"truncate\"","description":"Coarse outcome filter that groups events. `allow` = query; `block` = blocked, budget_exhausted, auth_failed, credential_expired; `mask` = masked; `truncate` = truncated."},{"name":"source","in":"query","required":false,"type":"\"wire\" | \"mcp\" | \"control\"","description":"Filter by statement origin (wire, mcp, or control)."},{"name":"start","in":"query","required":false,"type":"string","description":"Return entries at or after this timestamp (inclusive lower bound)."},{"name":"end","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (cursor / upper bound)."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"","responseStatus":"200"},
4646
"listPlans": {"operationId":"listPlans","method":"GET","path":"/v1/plans","summary":"List available plans","description":"Returns all available plan tiers with their limits and pricing.","parameters":[],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ plans: ({ annual_price?: number; description?: string; label: string; limits: { bytes_per_month: number; included_seats: number; max_connections: number; max_databases: number; max_projects: number; max_query_shapes: number; queries_per_day: number; queries_per_second: number }; monthly_price: number; name: string; overage_text?: string; trial_days?: number })[] }","responseStatus":"200"},
47-
"getOrganizationPlan": {"operationId":"getOrganizationPlan","method":"GET","path":"/v1/organizations/{org_id}/plan","summary":"Get organization plan","description":"Returns the current plan and limits for the organization.","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ billing_provider?: \"stripe\" | \"vercel\" | \"aws\" | \"manual\"; created_at?: string; current_period_end?: string; custom_pricing?: boolean; enabled?: boolean; limits: { bytes_per_month: number; included_seats: number; max_connections: number; max_databases: number; max_projects: number; max_query_shapes: number; queries_per_day: number; queries_per_second: number }; org_id: string; plan: \"starter\" | \"pro\" | \"scale\" | \"enterprise\"; spend_limit?: number; subscription_status?: \"none\" | \"active\" | \"trialing\" | \"past_due\" | \"canceled\" | \"unpaid\" | \"incomplete\" | \"incomplete_expired\" | \"paused\"; updated_at?: string }","responseStatus":"200"},
47+
"getOrganizationPlan": {"operationId":"getOrganizationPlan","method":"GET","path":"/v1/organizations/{org_id}/plan","summary":"Get organization plan","description":"Returns the current plan and limits for the organization.","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ billing_provider?: \"stripe\" | \"vercel\" | \"aws\" | \"manual\"; created_at?: string; current_period_end?: string; custom_pricing?: boolean; enabled?: boolean; limits: { bytes_per_month: number; included_seats: number; max_connections: number; max_databases: number; max_projects: number; max_query_shapes: number; queries_per_day: number; queries_per_second: number }; org_id: string; plan: \"starter\" | \"pro\" | \"scale\" | \"enterprise\"; spend_capped?: boolean; spend_capped_at?: string; spend_limit?: number; subscription_status?: \"none\" | \"active\" | \"trialing\" | \"past_due\" | \"canceled\" | \"unpaid\" | \"incomplete\" | \"incomplete_expired\" | \"paused\"; updated_at?: string }","responseStatus":"200"},
4848
"getVercelInstallation": {"operationId":"getVercelInstallation","method":"GET","path":"/v1/organizations/{org_id}/vercel-installation","summary":"Get Vercel Marketplace installation status","description":"Returns the Vercel Marketplace installation for the organization,\nincluding its provisioned resources and their current-period usage.\nReturns 404 when the organization was not provisioned through the\nVercel Marketplace. Powers the dashboard's Vercel integration page.\n","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ created_at?: string; installation_id: string; plan: string; resources: ({ billing_plan_id: string; name: string; period_bytes: number; period_queries: number; project_id: string; resource_id: string; status: \"ready\" | \"suspended\" | \"deleted\" })[]; status: string; vercel_account_id: string }","responseStatus":"200"},
49-
"updateSpendLimit": {"operationId":"updateSpendLimit","method":"PUT","path":"/v1/organizations/{org_id}/spend-limit","summary":"Update spend limit","description":"Sets the monthly spend limit for an organization. Null removes the limit.","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"{ spend_limit?: number }","requestBodyRequired":true,"responseType":"{ billing_provider?: \"stripe\" | \"vercel\" | \"aws\" | \"manual\"; created_at?: string; current_period_end?: string; custom_pricing?: boolean; enabled?: boolean; limits: { bytes_per_month: number; included_seats: number; max_connections: number; max_databases: number; max_projects: number; max_query_shapes: number; queries_per_day: number; queries_per_second: number }; org_id: string; plan: \"starter\" | \"pro\" | \"scale\" | \"enterprise\"; spend_limit?: number; subscription_status?: \"none\" | \"active\" | \"trialing\" | \"past_due\" | \"canceled\" | \"unpaid\" | \"incomplete\" | \"incomplete_expired\" | \"paused\"; updated_at?: string }","responseStatus":"200"},
49+
"updateSpendLimit": {"operationId":"updateSpendLimit","method":"PUT","path":"/v1/organizations/{org_id}/spend-limit","summary":"Update spend limit","description":"Sets the monthly spend limit for an organization. Null removes the limit.","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"{ spend_limit?: number }","requestBodyRequired":true,"responseType":"{ billing_provider?: \"stripe\" | \"vercel\" | \"aws\" | \"manual\"; created_at?: string; current_period_end?: string; custom_pricing?: boolean; enabled?: boolean; limits: { bytes_per_month: number; included_seats: number; max_connections: number; max_databases: number; max_projects: number; max_query_shapes: number; queries_per_day: number; queries_per_second: number }; org_id: string; plan: \"starter\" | \"pro\" | \"scale\" | \"enterprise\"; spend_capped?: boolean; spend_capped_at?: string; spend_limit?: number; subscription_status?: \"none\" | \"active\" | \"trialing\" | \"past_due\" | \"canceled\" | \"unpaid\" | \"incomplete\" | \"incomplete_expired\" | \"paused\"; updated_at?: string }","responseStatus":"200"},
5050
"submitCancellationFeedback": {"operationId":"submitCancellationFeedback","method":"POST","path":"/v1/organizations/{org_id}/cancellation-feedback","summary":"Submit cancellation feedback","description":"Records optional feedback when a user cancels their subscription.","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"{ feedback?: string; reason?: string }","requestBodyRequired":true,"responseType":"","responseStatus":"204"},
5151
"listDatabaseBranches": {"operationId":"listDatabaseBranches","method":"GET","path":"/v1/projects/{project_id}/branches","summary":"List sandbox branches","description":"Lists ephemeral sandbox branches for the project's databases.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"status","in":"query","required":false,"type":"\"pending\" | \"ready\" | \"error\" | \"discarded\"","description":"Filter to a single status."},{"name":"page_size","in":"query","required":false,"type":"number","description":"Maximum number of items to return (1-100, default 20)."},{"name":"page_token","in":"query","required":false,"type":"string","description":"Opaque token for cursor-based pagination."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ branches: ({ branch_name: string; created_at: string; credential_id?: string; database_id: string; discarded_at?: string; error?: string; expires_at?: string; id: string; session_id?: string; status: \"pending\" | \"ready\" | \"error\" | \"discarded\" })[]; next_page_token?: string }","responseStatus":"200"},
5252
"discardDatabaseBranch": {"operationId":"discardDatabaseBranch","method":"DELETE","path":"/v1/projects/{project_id}/branches/{branch_id}","summary":"Discard a sandbox branch","description":"Marks an ephemeral sandbox branch as discarded for teardown.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"branch_id","in":"path","required":true,"type":"string","description":"Unique sandbox branch identifier (prefixed, e.g. brn_xxx)."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"","responseStatus":"204"},

src/generated/types/OrganizationPlan.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ export type OrganizationPlan = {
8484
* @type number
8585
*/
8686
spend_limit?: number | null;
87+
/**
88+
* @description Whether the organization has hit its spend limit and agent access is paused at the proxy. Lifts automatically when usage resets for the new billing period, or immediately when the spend limit is raised or removed.
89+
* @type boolean | undefined
90+
*/
91+
spend_capped?: boolean;
92+
/**
93+
* @description When the spend cap was applied. Null when not capped.
94+
* @type string
95+
*/
96+
spend_capped_at?: string | null;
8797
/**
8898
* @description Effective usage limits enforced for an organization plan.
8999
* @type object

0 commit comments

Comments
 (0)