feat: classify extraction store failures
This commit is contained in:
parent
3da836aeff
commit
1785f4505a
@ -364,9 +364,13 @@ func TestHandlerExtractMapsErrorsToProblemResponsesWithoutSensitiveLeakage(t *te
|
||||
name: "extraction unavailable",
|
||||
requestBody: `{"count":1}`,
|
||||
contentType: "application/json",
|
||||
extractErr: controllerExtraction.ErrUnavailable,
|
||||
wantStatus: http.StatusServiceUnavailable,
|
||||
wantCode: "SERVICE_UNAVAILABLE",
|
||||
extractErr: errors.Join(
|
||||
controllerExtraction.ErrUnavailable,
|
||||
domainExtraction.ErrStoreUnavailable,
|
||||
errors.New("redis dial failed: TOKEN"),
|
||||
),
|
||||
wantStatus: http.StatusServiceUnavailable,
|
||||
wantCode: "SERVICE_UNAVAILABLE",
|
||||
},
|
||||
}
|
||||
|
||||
@ -410,7 +414,8 @@ func TestHandlerExtractMapsErrorsToProblemResponsesWithoutSensitiveLeakage(t *te
|
||||
if problem.Status != test.wantStatus || problem.Code != test.wantCode {
|
||||
t.Fatalf("problem = %+v", problem)
|
||||
}
|
||||
if body := response.Body.String(); strings.Contains(body, `"password"`) || strings.Contains(body, "secret") {
|
||||
if body := response.Body.String(); strings.Contains(body, `"password"`) ||
|
||||
strings.Contains(body, "secret") || strings.Contains(body, "redis") || strings.Contains(body, "TOKEN") {
|
||||
t.Fatalf("error body leaked sensitive data: %s", body)
|
||||
}
|
||||
})
|
||||
|
||||
@ -140,6 +140,9 @@ func (s *Service) Extract(ctx context.Context, request Request) (Response, error
|
||||
Upstreams: append([]string(nil), request.Filters.Upstreams...),
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, domain.ErrStoreUnavailable) {
|
||||
return response, errors.Join(ErrUnavailable, err)
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
|
||||
@ -145,6 +145,27 @@ func TestServiceUsesSourceIdentityForEphemeralIdempotency(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceClassifiesStoreUnavailableAndPreservesCause(t *testing.T) {
|
||||
t.Parallel()
|
||||
storeErr := errors.Join(domain.ErrStoreUnavailable, errors.New("redis dial failed: TOKEN"))
|
||||
service, err := NewService(&recordingStore{err: storeErr}, Policy{
|
||||
MaxCountPerRequest: 1,
|
||||
DefaultFulfillment: domain.Partial,
|
||||
}, allowAllAdmission{}, time.Now)
|
||||
if err != nil {
|
||||
t.Fatalf("NewService(): %v", err)
|
||||
}
|
||||
|
||||
_, err = service.Extract(context.Background(), Request{
|
||||
RequestID: "req-1",
|
||||
ClientID: "client-1",
|
||||
Count: 1,
|
||||
})
|
||||
if !errors.Is(err, ErrUnavailable) || !errors.Is(err, domain.ErrStoreUnavailable) {
|
||||
t.Fatalf("Extract() error = %v, want unavailable classification with store cause", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceIdempotentReplayKeepsOriginalExtractionTime(t *testing.T) {
|
||||
firstTime := time.Date(2026, 7, 28, 12, 0, 0, 0, time.UTC)
|
||||
secondTime := firstTime.Add(time.Minute)
|
||||
|
||||
@ -24,6 +24,7 @@ var (
|
||||
ErrInsufficientProxies = errors.New("insufficient proxies")
|
||||
ErrIdempotencyConflict = errors.New("idempotency key was reused with a different extraction request")
|
||||
ErrInvalidCommand = errors.New("invalid extraction command")
|
||||
ErrStoreUnavailable = errors.New("extraction store unavailable")
|
||||
)
|
||||
|
||||
type Candidate struct {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user