fix(acceptance): 阻断本地控制面漂移污染验收
本地 K3s 节点此前在 Kubelet 中登记为宿主机资源,负载可挤压 etcd 并在 server 重启后继续污染同一 Run。现在为三节点设置真实可调度预算、独立 etcd/数据卷和锁定依赖镜像,并持续核对 server 与 API/etcd 健康。\n\n每次验收生成独立 Run ID,报告使用独占或原子写入,负载错误记录具体阶段;数据库鉴权不可用返回带 Retry-After 的 503,避免基础设施故障被误报为 401。\n\n验证:Go 全量测试、go vet、gofmt、OpenAPI、bash -n、ShellCheck、报告测试和 k3d 配置解析均通过。
This commit is contained in:
@@ -69,9 +69,10 @@ const userContextKey contextKey = "easyai-auth-user"
|
||||
var ErrUnauthorized = errors.New("unauthorized")
|
||||
|
||||
type RequestAuthError struct {
|
||||
Status int
|
||||
Code string
|
||||
Message string
|
||||
Status int
|
||||
Code string
|
||||
Message string
|
||||
RetryAfterSeconds int
|
||||
}
|
||||
|
||||
func (e *RequestAuthError) Error() string { return e.Code }
|
||||
@@ -80,6 +81,12 @@ func NewRequestAuthError(status int, code, message string) error {
|
||||
return &RequestAuthError{Status: status, Code: code, Message: message}
|
||||
}
|
||||
|
||||
func NewRetryableRequestAuthError(status int, code, message string, retryAfterSeconds int) error {
|
||||
return &RequestAuthError{
|
||||
Status: status, Code: code, Message: message, RetryAfterSeconds: retryAfterSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
type Authenticator struct {
|
||||
JWTSecret string
|
||||
ServerMainBaseURL string
|
||||
@@ -127,6 +134,9 @@ func (a *Authenticator) Require(permission Permission, next http.Handler) http.H
|
||||
}
|
||||
var requestError *RequestAuthError
|
||||
if errors.As(err, &requestError) {
|
||||
if requestError.RetryAfterSeconds > 0 {
|
||||
w.Header().Set("Retry-After", strconv.Itoa(requestError.RetryAfterSeconds))
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Header().Set("Cache-Control", "no-store")
|
||||
w.WriteHeader(requestError.Status)
|
||||
@@ -318,7 +328,12 @@ func (a *Authenticator) verifyAPIKey(ctx context.Context, apiKey string) (*User,
|
||||
return user, nil
|
||||
}
|
||||
if !errors.Is(err, ErrUnauthorized) {
|
||||
return nil, err
|
||||
return nil, NewRetryableRequestAuthError(
|
||||
http.StatusServiceUnavailable,
|
||||
"AUTH_STORE_UNAVAILABLE",
|
||||
"authentication service temporarily unavailable",
|
||||
2,
|
||||
)
|
||||
}
|
||||
if strings.HasPrefix(apiKey, "sk-gw-") {
|
||||
return nil, ErrUnauthorized
|
||||
|
||||
Reference in New Issue
Block a user