mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
## Description Adds pre-request AI budget enforcement to `aibridged`. Requests are rejected with HTTP 403 when the user's aggregated spend for the current period has reached their effective limit. ## Changes - Add `IsBudgetExceeded` RPC to `aibridgedserver`. Resolves the user's effective budget, aggregates spend over the caller-supplied `[period_start, now]` window, and returns whether the limit has been reached along with the effective limit. - Wire the check into `aibridged`'s HTTP handler. The caller computes the period start (monthly for now) and passes it in the request. - Reject exceeded requests with HTTP 403 Forbidden and a message directing the user to contact an administrator. - Add `dbtime.StartOfMonth` alongside `StartOfDay` for period computation. - Add real-DB tests covering the enforcement path: month-boundary excludes prior-period spend, and a new user override unblocks a previously-exceeded user. Closes https://linear.app/codercom/issue/AIGOV-428/add-pre-request-budget-enforcement > [!NOTE] > Initially generated by Claude Opus 4.7, modified and reviewed by @ssncferreira
31 lines
1.0 KiB
Go
31 lines
1.0 KiB
Go
package dbtime
|
|
|
|
import "time"
|
|
|
|
// Now returns a standardized timezone used for database resources.
|
|
func Now() time.Time {
|
|
return Time(time.Now().UTC())
|
|
}
|
|
|
|
// Time returns a time compatible with Postgres. Postgres only stores dates with
|
|
// microsecond precision.
|
|
// FIXME(dannyk): refactor all calls to Time() to expect the input time to be modified to UTC; there are currently a
|
|
//
|
|
// few calls whose behavior would change subtly.
|
|
// See https://github.com/coder/coder/pull/14274#discussion_r1718427461
|
|
func Time(t time.Time) time.Time {
|
|
return t.Round(time.Microsecond)
|
|
}
|
|
|
|
// StartOfDay returns the first timestamp of the day of the input timestamp in its location.
|
|
func StartOfDay(t time.Time) time.Time {
|
|
year, month, day := t.Date()
|
|
return time.Date(year, month, day, 0, 0, 0, 0, t.Location())
|
|
}
|
|
|
|
// StartOfMonth returns the first timestamp of the month of the input timestamp in its location.
|
|
func StartOfMonth(t time.Time) time.Time {
|
|
year, month, _ := t.Date()
|
|
return time.Date(year, month, 1, 0, 0, 0, 0, t.Location())
|
|
}
|