mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: add agent chat spend limiting (backend) (#23071)
Introduces deployment-scoped spend limiting for Coder Agents, enabling administrators to control LLM costs at global, group, and individual user levels. ## Changes - **Database migration (000437)**: `chat_usage_limit_config` (singleton), `chat_usage_limit_overrides` (per-user), `chat_usage_limit_group_overrides` (per-group) - **Single-query limit resolution**: individual override > min(group) > global default via `ResolveUserChatSpendLimit` - **Fail-open enforcement** in chatd with documented TOCTOU trade-off - **Experimental API** under `/api/experimental/chats/usage-limits` for CRUD on limits - **`AsChatd` RBAC subject** for narrowly-scoped daemon access (replaces `AsSystemRestricted`) - **Generated TypeScript types** for the frontend SDK ## Hierarchy 1. Individual user override (highest) 2. Minimum of group limits 3. Global default 4. Disabled / unlimited Currency stored as micro-dollars (`1,000,000` = $1.00). Frontend PR: #23072
This commit is contained in:
@@ -4196,6 +4196,16 @@ type ChatQueuedMessage struct {
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
}
|
||||
|
||||
type ChatUsageLimitConfig struct {
|
||||
ID int64 `db:"id" json:"id"`
|
||||
Singleton bool `db:"singleton" json:"singleton"`
|
||||
Enabled bool `db:"enabled" json:"enabled"`
|
||||
DefaultLimitMicros int64 `db:"default_limit_micros" json:"default_limit_micros"`
|
||||
Period string `db:"period" json:"period"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
}
|
||||
|
||||
type ConnectionLog struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
ConnectTime time.Time `db:"connect_time" json:"connect_time"`
|
||||
@@ -4308,7 +4318,8 @@ type Group struct {
|
||||
// Display name is a custom, human-friendly group name that user can set. This is not required to be unique and can be the empty string.
|
||||
DisplayName string `db:"display_name" json:"display_name"`
|
||||
// Source indicates how the group was created. It can be created by a user manually, or through some system process like OIDC group sync.
|
||||
Source GroupSource `db:"source" json:"source"`
|
||||
Source GroupSource `db:"source" json:"source"`
|
||||
ChatSpendLimitMicros sql.NullInt64 `db:"chat_spend_limit_micros" json:"chat_spend_limit_micros"`
|
||||
}
|
||||
|
||||
// Joins group members with user information, organization ID, group name. Includes both regular group members and organization members (as part of the "Everyone" group).
|
||||
@@ -5078,7 +5089,8 @@ type User struct {
|
||||
// Determines if a user is a system user, and therefore cannot login or perform normal actions
|
||||
IsSystem bool `db:"is_system" json:"is_system"`
|
||||
// Determines if a user is an admin-managed account that cannot login
|
||||
IsServiceAccount bool `db:"is_service_account" json:"is_service_account"`
|
||||
IsServiceAccount bool `db:"is_service_account" json:"is_service_account"`
|
||||
ChatSpendLimitMicros sql.NullInt64 `db:"chat_spend_limit_micros" json:"chat_spend_limit_micros"`
|
||||
}
|
||||
|
||||
type UserConfig struct {
|
||||
|
||||
Reference in New Issue
Block a user