diff --git a/integrations/slack-gateway/gateway_test.go b/integrations/slack-gateway/gateway_test.go index fb1dd95..b5b61b2 100644 --- a/integrations/slack-gateway/gateway_test.go +++ b/integrations/slack-gateway/gateway_test.go @@ -235,7 +235,8 @@ func TestOAuthCallbackReturnsBadGatewayWhenBackendUpsertFails(t *testing.T) { HTTPTimeout: 5 * time.Second, DedupeTTL: time.Minute, } - gateway := newSlackGateway(cfg, slog.New(slog.NewTextHandler(io.Discard, nil))) + var logBuffer bytes.Buffer + gateway := newSlackGateway(cfg, slog.New(slog.NewTextHandler(&logBuffer, nil))) state, err := gateway.state.generate() if err != nil { t.Fatalf("state generate failed: %v", err) @@ -248,6 +249,13 @@ func TestOAuthCallbackReturnsBadGatewayWhenBackendUpsertFails(t *testing.T) { if rec.Code != http.StatusBadGateway { t.Fatalf("expected 502, got %d: %s", rec.Code, rec.Body.String()) } + logOutput := logBuffer.String() + if !strings.Contains(logOutput, "slack oauth callback installation upsert failed") { + t.Fatalf("expected upsert failure to be logged, got %q", logOutput) + } + if !strings.Contains(logOutput, "backend unavailable") { + t.Fatalf("expected backend error details in logs, got %q", logOutput) + } } func TestExtractACPTextSupportsResourceBlocks(t *testing.T) { diff --git a/integrations/slack-gateway/slack_oauth.go b/integrations/slack-gateway/slack_oauth.go index 09e3ccd..ddfcfd9 100644 --- a/integrations/slack-gateway/slack_oauth.go +++ b/integrations/slack-gateway/slack_oauth.go @@ -74,23 +74,40 @@ func (g *slackGateway) handleOAuthCallback(w http.ResponseWriter, r *http.Reques state := strings.TrimSpace(r.URL.Query().Get("state")) code := strings.TrimSpace(r.URL.Query().Get("code")) if err := g.state.validate(state); err != nil { + g.logger.ErrorContext(r.Context(), "slack oauth callback state validation failed", "err", err) http.Error(w, err.Error(), http.StatusBadRequest) return } if code == "" { + g.logger.ErrorContext(r.Context(), "slack oauth callback missing code") http.Error(w, "code is required", http.StatusBadRequest) return } installation, err := g.exchangeSlackOAuthCode(r.Context(), code) if err != nil { + g.logger.ErrorContext(r.Context(), "slack oauth callback code exchange failed", "err", err) http.Error(w, err.Error(), http.StatusBadGateway) return } if err := g.upsertInstallation(r.Context(), &installation); err != nil { + g.logger.ErrorContext( + r.Context(), + "slack oauth callback installation upsert failed", + "err", + err, + "team_id", + installation.TeamID, + ) http.Error(w, err.Error(), http.StatusBadGateway) return } + g.logger.InfoContext( + r.Context(), + "slack oauth callback installed workspace", + "team_id", + installation.TeamID, + ) writeJSON(w, http.StatusOK, map[string]any{ "status": "installed", "teamId": installation.TeamID,