fix(billing): extend quantity validation and saturating conversions to remaining paths

Bound max-tokens fields across all relay format validators, saturate
tiered-expression rounding and audio/tool/task token conversions, and
route legacy remix ratios through the guarded setter.
This commit is contained in:
CaIon
2026-07-07 01:08:52 +08:00
parent d0bd8aac74
commit c9943d37ad
13 changed files with 155 additions and 30 deletions
+6
View File
@@ -291,6 +291,12 @@ func TestQuotaRound(t *testing.T) {
{999.4999, 999},
{999.5, 1000},
{1e9 + 0.5, 1e9 + 1},
// Oversized expression results must saturate at int32 bounds
// instead of wrapping into a negative charge.
{3.6893488147419103e19, math.MaxInt32},
{-3.6893488147419103e19, math.MinInt32},
{math.Inf(1), math.MaxInt32},
{math.NaN(), 0},
}
for _, tt := range tests {
got := billingexpr.QuotaRound(tt.in)
+15 -1
View File
@@ -5,6 +5,20 @@ import "math"
// QuotaRound converts a float64 quota value to int using half-away-from-zero
// rounding. Every tiered billing path (pre-consume, settlement, breakdown
// validation, log fields) MUST use this function to avoid +-1 discrepancies.
//
// The result saturates at int32 bounds: quota columns are 32-bit integers in
// the database, and an oversized expression result must never wrap around
// and turn a charge into a credit.
func QuotaRound(f float64) int {
return int(math.Round(f))
r := math.Round(f)
if math.IsNaN(r) {
return 0
}
if r >= math.MaxInt32 {
return math.MaxInt32
}
if r <= math.MinInt32 {
return math.MinInt32
}
return int(r)
}