fix(security): harden retry, SSE, Redis and cost-budget paths

The gateway refuses a request for an unpriced model when the caller has a
cost budget. An unpriced model cost 0, so the budget counter was never
written and the budget could never fire. The new
allowUnpricedWithCostBudget setting restores the old behaviour.

The retry loop honours an upstream Retry-After of up to 30s and jitters
its own computed backoff. SSE parsing bounds the total size of one event.
The Redis client can use TLS. Provider base URLs and errors are scrubbed
of credentials before they reach logs or the admin view. The gateway
warns when failover and retry settings multiply into a large number of
outbound calls.

Claude-Session: https://claude.ai/code/session_01V5jYJNxpDFdJkyyExpADrv
This commit is contained in:
2026-09-23 09:35:38 +01:00
parent 96b1a27ba5
commit b3b8ae6ad5
12 changed files with 576 additions and 50 deletions
+7 -12
View File
@@ -5,8 +5,6 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"sync"
"sync/atomic"
"time"
@@ -208,17 +206,14 @@ func (t *targetHealthTracker) record(kind, name, rawURL string, ok bool, err err
// carries a password — builds net/http's exact masked form itself
// (mirroring stripPassword's own strings.Replace call precisely) and
// scrubs against that too.
// (Security audit run-1, finding F-2): the URL-aware second pass this
// function used to carry privately now lives in sanitizeProviderErr
// (admin.go), so the target path and the provider path share ONE
// implementation. That private copy is precisely why the provider path
// went unprotected — this delegation is what stops the two diverging
// again.
func sanitizeTargetErr(msg, rawURL string) string {
msg = sanitizeProviderErr(msg, rawURL)
u, parseErr := url.Parse(rawURL)
if parseErr != nil || u.User == nil {
return msg
}
if _, hasPassword := u.User.Password(); !hasPassword {
return msg
}
masked := strings.Replace(u.String(), u.User.String()+"@", u.User.Username()+":***@", 1)
return sanitizeProviderErr(msg, masked)
return sanitizeProviderErr(msg, rawURL)
}
// stateOf reports (kind, name)'s current targetHealthState — see this