package httpapi import ( "errors" "net/http" "net/http/httptest" "testing" "github.com/easyai/easyai-ai-gateway/apps/api/internal/identity" ) func TestRequiredIdentityWriteHeaders(t *testing.T) { request := httptest.NewRequest(http.MethodPost, "/identity", nil) recorder := httptest.NewRecorder() if _, ok := requiredIdentityVersion(recorder, request); ok || recorder.Code != http.StatusPreconditionRequired { t.Fatalf("missing If-Match status=%d", recorder.Code) } request.Header.Set("If-Match", `W/"7"`) recorder = httptest.NewRecorder() version, ok := requiredIdentityVersion(recorder, request) if !ok || version != 7 { t.Fatalf("weak ETag version=%d ok=%v", version, ok) } } func TestIdentityErrorProjectionProtectsInternalDetails(t *testing.T) { status, message, code := identityErrorProjection(assertionError("upstream response contained secret-token")) if status != http.StatusBadGateway || code != "IDENTITY_SERVICE_UNAVAILABLE" || message == "upstream response contained secret-token" { t.Fatalf("unsafe error projection status=%d code=%q message=%q", status, code, message) } } func TestIdentityPairingRecoveryErrorsUseStableConflictResponses(t *testing.T) { for _, test := range []struct { err error code string }{ {err: identity.ErrPairingInProgress, code: "IDENTITY_PAIRING_IN_PROGRESS"}, {err: identity.ErrPairingNotCancellable, code: "IDENTITY_PAIRING_NOT_CANCELLABLE"}, {err: identity.ErrPairingConflictNotResolvable, code: "IDENTITY_PAIRING_CONFLICT_NOT_RESOLVABLE"}, } { status, message, code := identityErrorProjection(test.err) if status != http.StatusConflict || code != test.code || message == "" || errors.Is(assertionError(message), test.err) { t.Fatalf("err=%v status=%d code=%q message=%q", test.err, status, code, message) } } } func TestIdentityWriteHashScopesPairingCancellationToTarget(t *testing.T) { type cancellationRequest struct { PairingID string `json:"pairingId"` } first := identityRequestHash("pairing.cancel", 7, cancellationRequest{PairingID: "pairing-a"}) second := identityRequestHash("pairing.cancel", 7, cancellationRequest{PairingID: "pairing-b"}) if first == second { t.Fatal("pairing cancellation idempotency hash must include the target pairing") } } func TestIdentityWriteAuditFailsClosedBeforeMutation(t *testing.T) { server := &Server{} request := httptest.NewRequest(http.MethodPost, "/api/admin/system/identity/disable", nil) recorder := httptest.NewRecorder() if _, ok := server.requireIdentityConfigurationAudit(recorder, request, "revision.disable", "active", "trace-test"); ok { t.Fatal("identity write unexpectedly continued without durable audit storage") } if recorder.Code != http.StatusServiceUnavailable { t.Fatalf("audit failure status=%d, want 503", recorder.Code) } } type assertionError string func (err assertionError) Error() string { return string(err) }