Repository: united-manufacturing-hub/united-manufacturing-hub
Pull request #2038: ENG-3017 Allow insecure TLS setting
Author: login: Scarjit
Created: 2025-05-13T07:28:05Z | Merged: 2025-05-14T14:18:41Z

This pr allows setting a flag to startup the agent in insecure mode.
This flag REQUIRES a restart, as it will be only read once.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
  - Added an option to allow insecure TLS connections via a new configuration setting.
  - Introduced a Makefile target to perform comprehensive cleanup tasks.
  - Added a Makefile target to run TLS-specific tests with fail-fast enabled.

- **Tests**
  - Added tests to verify TLS certificate validation behavior with secure and insecure settings.

- **Refactor**
  - Improved HTTP request handling by modularizing request sending and response processing for better clarity and reuse.

- **Documentation**
  - Updated documentation with guidance on handling TLS certificate issues caused by corporate firewalls and instructions for configuring insecure TLS connections safely.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/umh-core/Makefile b/umh-core/Makefile
index e694a782f5..33418f869f 100644
--- a/umh-core/Makefile
+++ b/umh-core/Makefile
@@ -171,6 +171,8 @@ cleanup-tmp:
 cleanup-data:
 	rm -rf ./data/*
 
+cleanup-all: cleanup-ci cleanup-tmp cleanup-data
+
 vet:
 	go vet -tags=test ./...
 
@@ -184,7 +186,7 @@ test: vet nilaway lint
 	go test -v -tags=test ./...
 
 unit-test: vet nilaway lint
-	ginkgo -r -v --tags=test --label-filter='!integration && !redpanda-extended' --fail-fast ./...
+	ginkgo -r -v --tags=test --label-filter='!integration && !redpanda-extended && !tls' --fail-fast ./...
 
 benchmark:
 	@echo "Running benchmarks..."
@@ -230,6 +232,8 @@ integration-test: pre-test
 redpanda-extended-test: pre-test
 	ginkgo -r -v --tags=test --label-filter='redpanda-extended' --fail-fast --timeout=1.5h ./...
 
+badssl-test: pre-test
+	ginkgo -r -v --tags=test --label-filter='tls' --fail-fast ./...
 
 # integration-test-ci: Runs integration tests in CI environments with proper version tagging
 # - Injects VERSION via ldflags into AppVersion for proper error identification in Sentry
diff --git a/umh-core/README.md b/umh-core/README.md
index 4632e65a86..e80668f87e 100644
--- a/umh-core/README.md
+++ b/umh-core/README.md
@@ -95,6 +95,24 @@ dataFlow:
 Everything under the top-level key `internal:` is reserved for UMH engineers (built-in services, monitors, etc.).
 You should never touch it; in the console UI those fields stay hidden.
 
+### 4.2  Corporate Firewalls & TLS
+
+If you're behind a corporate firewall that performs TLS inspection (MITM), you might see certificate errors. In this case, you can:
+
+1. **Recommended:** Add your corporate CA certificate to the container's trusted certificates
+2. **Last Resort:** Set `allowInsecureTLS: true` in your config:
+
+```yaml
+agent:
+  communicator:
+    allowInsecureTLS: true  # WARNING: Only use if corporate firewall blocks secure connections
+```
+
+⚠️ **Security Warning:** The `allowInsecureTLS` option disables certificate validation. Only use this if:
+- You're behind a corporate firewall that you trust
+- You cannot add your corporate CA certificate
+- You understand the security implications
+
 ---
 
 ## 5  Data Flow Components (DFCs)
diff --git a/umh-core/cmd/main.go b/umh-core/cmd/main.go
index adb6bf049e..7e03ca6a9d 100644
--- a/umh-core/cmd/main.go
+++ b/umh-core/cmd/main.go
@@ -96,7 +96,7 @@ func main() {
 		configManager,
 		configData.Agent.APIURL,
 		logger.For(logger.ComponentCommunicator),
-		false, // InsecureTLS
+		configData.Agent.AllowInsecureTLS,
 	)
 
 	if configData.Agent.APIURL != "" && configData.Agent.AuthToken != "" {
@@ -174,7 +174,7 @@ func enableBackendConnection(config *config.FullConfig, communicationState *comm
 	if config.Agent.APIURL != "" && config.Agent.AuthToken != "" {
 		// This can temporarely deactivated, e.g., during integration tests where just the mgmtcompanion-config is changed directly
 
-		login := v2.NewLogin(config.Agent.AuthToken, false, config.Agent.APIURL, logger)
+		login := v2.NewLogin(config.Agent.AuthToken, config.Agent.AllowInsecureTLS, config.Agent.APIURL, logger)
 		if login == nil {
 			sentry.ReportIssuef(sentry.IssueTypeError, logger, "[v2.NewLogin] Failed to create login object")
 			return
diff --git a/umh-core/pkg/communicator/api/v2/http/http_suite_test.go b/umh-core/pkg/communicator/api/v2/http/http_suite_test.go
new file mode 100644
index 0000000000..775f044b71
--- /dev/null
+++ b/umh-core/pkg/communicator/api/v2/http/http_suite_test.go
@@ -0,0 +1,27 @@
+// Copyright 2025 UMH Systems GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package http_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+func TestHttp(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "HTTP Suite")
+}
diff --git a/umh-core/pkg/communicator/api/v2/http/requester.go b/umh-core/pkg/communicator/api/v2/http/requester.go
index f738f76322..cc6c3e7336 100644
--- a/umh-core/pkg/communicator/api/v2/http/requester.go
+++ b/umh-core/pkg/communicator/api/v2/http/requester.go
@@ -67,6 +67,7 @@ func GetClient(insecureTLS bool) *http.Client {
 			TLSNextProto:      make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
 			TLSClientConfig: &tls.Config{
 				InsecureSkipVerify: insecureTLS,
+				MinVersion:         tls.VersionTLS10, // Allow older TLS versions
 			},
 		}
 
@@ -208,19 +209,12 @@ func enhanceConnectionError(err error) error {
 	return fmt.Errorf("connection error: %w (no response received from server, status code 0)", err)
 }
 
-// GetRequest does a GET request to the given endpoint, with optional header and cookies
-func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
-	// Set up context with default 30 second timeout if none provided
-	if ctx == nil {
-		var cancel context.CancelFunc
-		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
-		defer cancel()
-	}
-
-	url := apiURL + string(endpoint)
+// DoHTTPRequest performs the actual HTTP request and returns the response and any errors
+// This is an internal function, better use GetRequest or PostRequest instead
+func DoHTTPRequest(ctx context.Context, url string, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*http.Response, error) {
 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
 	if err != nil {
-		return nil, 0, err
+		return nil, err
 	}
 
 	// Set headers
@@ -252,22 +246,11 @@ func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string
 	response, err := GetClient(insecureTLS).Do(req.WithContext(httptrace.WithClientTrace(req.Context(), trace)))
 	if err != nil {
 		if response != nil {
-			return nil, response.StatusCode, err
+			return response, err
 		}
 		// Enhance error message for connection failures
-		return nil, 0, enhanceConnectionError(err)
+		return nil, enhanceConnectionError(err)
 	}
-	defer func() {
-		if err := response.Body.Close(); err != nil {
-			if responseErr != nil {
-				// If we already have an error, just log this one
-				logger.Errorf("Error closing response body: %v", err)
-			} else {
-				// No previous error, so return this one
-				responseErr = fmt.Errorf("error closing response body: %w", err)
-			}
-		}
-	}()
 
 	// Record latencies
 	now := time.Now()
@@ -278,7 +261,19 @@ func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string
 
 	processLatencyHeaders(response, timings.firstByte, logger)
 
-	// Read and process response
+	return response, nil
+}
+
+// processJSONResponse processes the HTTP response and unmarshals the JSON body
+func processJSONResponse[R any](response *http.Response, cookies *map[string]string, endpoint Endpoint, logger *zap.SugaredLogger) (*R, int, error) {
+	defer func() {
+		if err := response.Body.Close(); err != nil {
+			// Log error but don't return it since we're in a defer
+			// The main error handling will be done by the caller
+			logger.Warnf("Failed to close response body: %s", err)
+		}
+	}()
+
 	bodyBytes, err := io.ReadAll(response.Body)
 	if err != nil {
 		return nil, response.StatusCode, err
@@ -318,14 +313,12 @@ func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string
 		LatestExternalIp = ip
 	}
 
-	statusCode = response.StatusCode
-	result = &typedResult
-	return
+	return &typedResult, response.StatusCode, nil
 }
 
-// PostRequest does a POST request to the given endpoint, with optional header and cookies
-// Note: Cookies will be updated with the response cookies, if not nil
-func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
+// GetRequest does a GET request to the given endpoint, with optional header and cookies
+// It is a wrapper around DoHTTPRequest
+func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
 	// Set up context with default 30 second timeout if none provided
 	if ctx == nil {
 		var cancel context.CancelFunc
@@ -334,11 +327,24 @@ func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T,
 	}
 
 	url := apiURL + string(endpoint)
+	response, err := DoHTTPRequest(ctx, url, header, cookies, insecureTLS, logger)
+	if err != nil {
+		if response != nil {
+			return nil, response.StatusCode, err
+		}
+		return nil, 0, err
+	}
 
+	result, statusCode, responseErr = processJSONResponse[R](response, cookies, endpoint, logger)
+	return
+}
+
+// DoHTTPPostRequest performs the actual HTTP POST request and returns the response and any errors
+func DoHTTPPostRequest[T any](ctx context.Context, url string, data *T, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*http.Response, error) {
 	// Marshal the data into JSON format
 	body, err := safejson.Marshal(data)
 	if err != nil {
-		return nil, 0, err
+		return nil, err
 	}
 
 	// Create a reader from the body
@@ -347,7 +353,7 @@ func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T,
 	// Create a new HTTP request with context
 	req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bodyReader)
 	if err != nil {
-		return nil, 0, err
+		return nil, err
 	}
 
 	// Set content type to application/json
@@ -383,72 +389,36 @@ func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T,
 	response, err := GetClient(insecureTLS).Do(req.WithContext(httptrace.WithClientTrace(req.Context(), trace)))
 	if err != nil {
 		if response != nil {
-			return nil, response.StatusCode, err
+			return response, err
 		}
 		// Enhance error message for connection failures
-		return nil, 0, enhanceConnectionError(err)
+		return nil, enhanceConnectionError(err)
 	}
 	latenciesFRB.Set(time.Now(), timeTillFirstByte)
 
-	// Read response body
-	defer func() {
-		if err := response.Body.Close(); err != nil {
-			if responseErr != nil {
-				// If we already have an error, just log this one
-				logger.Errorf("Error closing response body: %v", err)
-			} else {
-				// No previous error, so return this one
-				responseErr = fmt.Errorf("error closing response body: %w", err)
-			}
-		}
-	}()
-
-	bodyBytes, err := io.ReadAll(response.Body)
-	if err != nil {
-		return nil, response.StatusCode, err
-	}
-
-	// Check if the response was successful (status code 2XX-3XX)
-	if response.StatusCode < 200 || response.StatusCode > 399 {
-		// Handle error reporting internally
-		error_handler.ReportHTTPErrors(
-			errors.New("error response code: "+response.Status),
-			response.StatusCode,
-			string(endpoint),
-			http.MethodPost,
-			data,
-			bodyBytes,
-		)
-
-		if len(bodyBytes) != 0 {
-			var parseResult R
-			err = safejson.Unmarshal(bodyBytes, &parseResult)
-			if err != nil {
-				return nil, response.StatusCode, err
-			}
-
-			if strings.Contains(fmt.Sprint(parseResult), "channel is full") {
-				return nil, response.StatusCode, nil
-			}
-		}
-		return nil, response.StatusCode, errors.New("error response code: " + response.Status)
-	}
+	return response, nil
+}
 
-	// If response body is empty
-	if len(bodyBytes) == 0 {
-		return nil, response.StatusCode, nil
+// PostRequest does a POST request to the given endpoint, with optional header and cookies
+// Note: Cookies will be updated with the response cookies, if not nil
+// It is a wrapper around DoHTTPPostRequest
+func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
+	// Set up context with default 30 second timeout if none provided
+	if ctx == nil {
+		var cancel context.CancelFunc
+		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
+		defer cancel()
 	}
 
-	// Unmarshal response body
-	var typedResult R
-	err = safejson.Unmarshal(bodyBytes, &typedResult)
+	url := apiURL + string(endpoint)
+	response, err := DoHTTPPostRequest(ctx, url, data, header, cookies, insecureTLS, logger)
 	if err != nil {
-		return nil, response.StatusCode, err
+		if response != nil {
+			return nil, response.StatusCode, err
+		}
+		return nil, 0, err
 	}
 
-	processCookies(response, cookies)
-
-	statusCode = response.StatusCode
-	result = &typedResult
+	result, statusCode, responseErr = processJSONResponse[R](response, cookies, endpoint, logger)
 	return
 }
diff --git a/umh-core/pkg/communicator/api/v2/http/requester_test.go b/umh-core/pkg/communicator/api/v2/http/requester_test.go
index ecf34490fd..3db08ace43 100644
--- a/umh-core/pkg/communicator/api/v2/http/requester_test.go
+++ b/umh-core/pkg/communicator/api/v2/http/requester_test.go
@@ -16,6 +16,10 @@ package http_test
 
 import (
 	"context"
+	"fmt"
+	netHTTP "net/http"
+	"strings"
+	"time"
 
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
@@ -29,14 +33,36 @@ var _ = Describe("Requester", func() {
 
 	var log *zap.SugaredLogger
 
-	// Set API_URL to the production API URL in order for the gock library to correctly
-	// intercept the requests to the production API done by the code under test
 	const apiUrl = "https://management.umh.app/api"
 
 	BeforeEach(func() {
 		log = logger.For("RequesterTest")
 	})
 
+	// doHTTPRequestWithRetry is a test helper that retries HTTP requests on connection issues
+	doHTTPRequestWithRetry := func(ctx context.Context, url string, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*netHTTP.Response, error) {
+		var lastErr error
+		for i := 0; i < 10; i++ {
+			response, err := http.DoHTTPRequest(ctx, url, header, cookies, insecureTLS, logger)
+			if err == nil {
+				return response, nil
+			}
+
+			// Only retry on connection-related errors
+			if strings.Contains(err.Error(), "connection") ||
+				strings.Contains(err.Error(), "timeout") ||
+				strings.Contains(err.Error(), "EOF") {
+				lastErr = err
+				time.Sleep(time.Second * time.Duration(i+1)) // Exponential backoff
+				continue
+			}
+
+			// For non-connection errors, return immediately
+			return response, err
+		}
+		return nil, fmt.Errorf("failed after 10 retries, last error: %w", lastErr)
+	}
+
 	// The tests in this context are ported from the old requester_test.go file
 	Context("Requester", func() {
 		var header map[string]string
@@ -56,17 +82,135 @@ var _ = Describe("Requester", func() {
 		})
 
 		Context("GetRequest", func() {
-			It("should return error for non 200 response", func() {
-				_, err, _ := http.GetRequest[any](context.Background(), http.LoginEndpoint, header, &cookies, false, apiUrl, log)
-				Expect(err).To(HaveOccurred())
+			It("should return no error", func() {
+				ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+				defer cancel()
+				_, status, err := http.GetRequest[any](ctx, http.LoginEndpoint, header, &cookies, false, apiUrl, log)
+				Expect(err).ToNot(HaveOccurred())
+				Expect(status).To(Equal(200))
 			})
 		})
 
 		Context("PostRequest", func() {
-			It("should return error for non 200 response", func() {
-				_, err, _ := http.PostRequest[any](context.Background(), http.LoginEndpoint, &data, header, &cookies, false, apiUrl, log)
+			It("should return error an error", func() {
+				ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+				defer cancel()
+				_, status, err := http.PostRequest[any](ctx, http.LoginEndpoint, &data, header, &cookies, false, apiUrl, log)
 				Expect(err).To(HaveOccurred())
+				Expect(status).To(Equal(401))
 			})
 		})
 	})
+
+	// badssl.com is not ment for automated testing, therefore we will only run the tests when the label is provided
+	// These tests check if umh-core can be deployed in environment with insecure TLS (e.g corporate proxies with there own self-signed certificates)
+	Context("TLS Security", Label("tls"), func() {
+		Describe("Certificate Validation", func() {
+			// https://badssl.com/ is a website from the chromium project that provides various TLS test sites
+			// These test sites help verify different TLS security scenarios
+			testCases := map[string]string{
+				"expired":        "https://expired.badssl.com",
+				"wrong-host":     "https://wrong.host.badssl.com",
+				"self-signed":    "https://self-signed.badssl.com",
+				"untrusted-root": "https://untrusted-root.badssl.com",
+				// The revoked certificate test is disabled, as go's crypto/tls requires the user to implement certificate revocation checking
+				// See also: https://www.cossacklabs.com/blog/tls-validation-implementing-ocsp-and-crl-in-go/
+				// "revoked":        "https://revoked.badssl.com",
+				// The pinning test is disabled, as go's crypto/tls ignores HPKP (HTTP Public Key Pinning)
+				// See also: https://blog.ordina-jworks.io/security/2018/02/12/HPKP-deprecated-what-now.html
+				// "pinning-test":   "https://pinning-test.badssl.com"
+			}
+
+			for name, url := range testCases {
+				It(fmt.Sprintf("should fail with secure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
+					Expect(err).To(HaveOccurred())
+					Expect(err.Error()).To(ContainSubstring("certificate"))
+				})
+
+				It(fmt.Sprintf("should succeed with insecure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, true, log)
+					Expect(err).ToNot(HaveOccurred())
+				})
+			}
+		})
+		Describe("Key exchange", Label("tls"), func() {
+			// These will always fail, as the go crypto/tls does not allow them anymore (For good reasons)
+			testCases := map[string]string{
+				"dh480":             "https://dh480.badssl.com",
+				"dh512":             "https://dh512.badssl.com",
+				"dh1024":            "https://dh1024.badssl.com",
+				"dh2048":            "https://dh2048.badssl.com",
+				"dh-small-subgroup": "https://dh-small-subgroup.badssl.com",
+				"dh-composite":      "https://dh-composite.badssl.com",
+			}
+			for name, url := range testCases {
+				It(fmt.Sprintf("should fail with secure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
+					Expect(err).To(HaveOccurred())
+				})
+
+				It(fmt.Sprintf("should fail with insecure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, true, log)
+					Expect(err).To(HaveOccurred())
+				})
+			}
+		})
+
+		Describe("Protocol", Label("tls"), func() {
+			// By default go only allows TLS 1.2 and above
+			testCases := map[string]string{
+				"tls-v1-0": "https://tls-v1-0.badssl.com",
+				"tls-v1-1": "https://tls-v1-1.badssl.com",
+			}
+			for name, url := range testCases {
+				It(fmt.Sprintf("should fail with secure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
+					Expect(err).To(HaveOccurred())
+				})
+
+				It(fmt.Sprintf("should succeed with insecure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, true, log)
+					Expect(err).ToNot(HaveOccurred())
+				})
+			}
+		})
+
+		Describe("Cipher Suites", Label("tls"), func() {
+			// These cipher suites where removed from go, using them requires custom args when building the executable
+			testCases := map[string]string{
+				"rc4-md5": "https://rc4-md5.badssl.com",
+				"rc4":     "https://rc4.badssl.com",
+				"3des":    "https://3des.badssl.com",
+				"null":    "https://null.badssl.com",
+			}
+			for name, url := range testCases {
+				It(fmt.Sprintf("should fail with secure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
+					Expect(err).To(HaveOccurred())
+				})
+
+				It(fmt.Sprintf("should fail with insecure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, true, log)
+					Expect(err).To(HaveOccurred())
+				})
+			}
+		})
+	})
 })
diff --git a/umh-core/pkg/config/config.go b/umh-core/pkg/config/config.go
index 1bf397191a..32ac588374 100644
--- a/umh-core/pkg/config/config.go
+++ b/umh-core/pkg/config/config.go
@@ -49,8 +49,9 @@ type AgentConfig struct {
 }
 
 type CommunicatorConfig struct {
-	APIURL    string `yaml:"apiUrl,omitempty"`
-	AuthToken string `yaml:"authToken,omitempty"`
+	APIURL           string `yaml:"apiUrl,omitempty"`
+	AuthToken        string `yaml:"authToken,omitempty"`
+	AllowInsecureTLS bool   `yaml:"allowInsecureTLS,omitempty"` // Allow TLS connections without verifying the certificate.
 }
 
 // FSMInstanceConfig is the config for a FSM instance


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between a9c720102c478227096cfc8aee88c158a5c36ad3 and 230a685b8a6486c5fc646fd8cd3aebd0bdb29209.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `umh-core/Makefile` (1 hunks)
* `umh-core/cmd/main.go` (2 hunks)
* `umh-core/pkg/communicator/api/v2/http/requester_test.go` (1 hunks)
* `umh-core/pkg/config/config.go` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct fo...</summary>

> `**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct format to help improve clarity and usability.
> 
> Quick Guidelines for Writing Effective Error Messages
> 	1.	Structure Your Message with Three Key Parts
> 	•	Context:
> Explain what the system was doing.
> Example: “Couldn’t parse config file: /etc/sample-config.properties.”
> 	•	Error Description:
> Clearly state what failed without generic wording.
> Example: “Invalid snapshot mode ‘nevr’ provided.”
> 	•	Mitigation/Next Steps:
> Tell the user what to do next. For complex issues, include an error code or documentation link.
> Example: “Please update the mode; refer to our docs for valid options.”
> 	2.	Clarity & Conciseness
> 	•	Use plain, simple language and avoid unnecessary jargon (unless targeting technical users).
> 	•	Aim for short sentences (ideally 8–14 words) for better understanding.
> 	3.	Consistent Tone & Style
> 	•	Uniformity: Use the same voice, terminology, and punctuation across all messages.
> 	•	Empathy: Maintain a neutral, supportive tone; avoid blaming the user.
> 	•	Avoid overly casual language (skip “oops”/“whoops” and excessive exclamation points).
> 	4.	Visibility & Placement (User-Facing Messages)
> 	•	Proximity: Place error messages close to the related UI element to reduce cognitive load.
> 	•	Design: Use high-contrast text, icons, or subtle animations; follow accessibility guidelines (don’t rely solely on color).
> 	5.	Actionability & Efficiency
> 	•	Clearly indicate the next steps (e.g., “Retry later”, “Log in again”, “Check your input”).
> 	•	Preserve user input when possible to minimize frustration.
> 	•	Where relevant, provide error codes or links for further troubleshooting.
> 	6.	Security & Privacy Considerations
> 	•	User-Facing: Avoid exposing internal details or sensitive data.
> 	•	Developer/Logging: Include detailed context (like file paths or exception chains) for debugging, but be cautious about sensitive information.
> 	7.	Logging & Exception Best Practices (for Developer/Operations Messages)
> 	•	Log the full context—including exception chains—to aid troubleshooting.
> 	•	Use structured logging (e.g., JSON) for filtering and analysis.
> 	•	Choose a consistent method: either raise an exception or log an error (not both) to avoid redundancy.
> 	•	Don’t make error messages an API contract; expose machine-readable error codes or types instead.
> 	8.	Additional Best Practices
> 	•	Fail Early: Report errors as soon as possible (e.g., during input validation or startup).
> 	•	One Concept, One Term: Use consistent terminology across messages and documentation.
> 	•	Localization: For internal logs, use English; if localizing for users, follow a vetted process.

- `umh-core/Makefile`
- `umh-core/pkg/config/config.go`
- `umh-core/pkg/communicator/api/v2/http/requester_test.go`
- `umh-core/cmd/main.go`

</details>
<details>
<summary>`**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behin...</summary>

> `**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behind the decision. So e.g., why something was preferred over other options, or why a certain loop needs to be executed.

- `umh-core/Makefile`
- `umh-core/pkg/config/config.go`
- `umh-core/pkg/communicator/api/v2/http/requester_test.go`
- `umh-core/cmd/main.go`

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: Unit Tests
* GitHub Check: Integration Tests (2)
* GitHub Check: Integration Tests (3)
* GitHub Check: Integration Tests (1)
* GitHub Check: Build and Push (amd64)
* GitHub Check: Build and Push (arm64)

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>umh-core/Makefile (1)</summary>

`174-174`: **LGTM: New cleanup-all target provides a convenient way to run all cleanup steps**

The new target combines existing cleanup tasks into a single command, which is a useful addition for simplifying workflows.

</details>
<details>
<summary>umh-core/cmd/main.go (2)</summary>

`99-99`: **Parameter uses new AllowInsecureTLS config instead of hardcoded value**

The change correctly uses the configuration value instead of a hardcoded `false`, aligning with the new feature.

---

`177-177`: **Parameter uses new AllowInsecureTLS config instead of hardcoded value**

The change correctly uses the configuration value instead of a hardcoded `false`, aligning with the new feature.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T07:31:04Z
user: login: Scarjit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:10:57Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:11:19Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (1)</summary><blockquote>

`105-117`: **Consider a more reliable test environment for TLS testing.**

While badssl.com is perfect for validating TLS behavior, it's a volunteer-maintained external service that may introduce test flakiness in CI environments.


```web
Are there alternatives to badssl.com for reliable TLS testing in Go applications?
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (1)</summary><blockquote>

`102-137`: **Well-structured TLS certificate validation tests.**

The test suite comprehensively validates certificate validation behavior against known test endpoints. Good job including both secure and insecure TLS paths, along with comments explaining why certain tests (revoked certificates, pinning) are disabled.

One minor improvement: consider closing the response body after reading it in the debugging section.


```diff
if response != nil {
    body, err := io.ReadAll(response.Body)
    Expect(err).ToNot(HaveOccurred())
    GinkgoWriter.Println(string(body))
+   response.Body.Close()
}
```

</blockquote></details>
<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester.go (2)</summary><blockquote>

`70-70`: **Carefully document the security implications of allowing older TLS versions.**

Setting `MinVersion: tls.VersionTLS10` allows deprecated TLS 1.0 and 1.1 protocols which have known security vulnerabilities. While appropriate for the `insecureTLS` mode, this decision should be documented with a comment explaining:
1. Why older versions are being allowed
2. What security risks this introduces
3. When this option should be used


```diff
TLSClientConfig: &tls.Config{
    InsecureSkipVerify: insecureTLS,
-   MinVersion:         tls.VersionTLS10, // Allow older TLS versions
+   MinVersion:         tls.VersionTLS10, // Allow older TLS versions (1.0, 1.1) when insecureTLS is true.
+                                         // WARNING: These versions have known vulnerabilities and should only be
+                                         // used for compatibility with legacy systems that can't be upgraded.
},
```

---

`342-399`: **Document the "why" behind HTTP POST implementation decisions.**

Following your coding guidelines, add a comment explaining why the POST request implementation:
1. Uses chunked transfer encoding (by setting ContentLength to -1)
2. Resets content-type headers even if they're in the provided headers
3. Needs different trace handling than GET requests


```diff
// DoHTTPPostRequest performs the actual HTTP POST request and returns the response and any errors
func DoHTTPPostRequest[T any](ctx context.Context, url string, data *T, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*http.Response, error) {
+   // This implementation uses chunked transfer encoding instead of fixed content length
+   // to support large or streaming request bodies without memory limitations.
+   // We explicitly set Content-Type to application/json regardless of provided headers
+   // to ensure proper server-side processing of the marshaled JSON data.

    // Marshal the data into JSON format
    body, err := safejson.Marshal(data)
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 230a685b8a6486c5fc646fd8cd3aebd0bdb29209 and 914f5f4adf47972c7c02e6ea15cbe9ab6a0c82a7.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `umh-core/pkg/communicator/api/v2/http/http_suite_test.go` (1 hunks)
* `umh-core/pkg/communicator/api/v2/http/requester.go` (8 hunks)
* `umh-core/pkg/communicator/api/v2/http/requester_test.go` (3 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* umh-core/pkg/communicator/api/v2/http/http_suite_test.go

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct fo...</summary>

> `**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct format to help improve clarity and usability.
> 
> Quick Guidelines for Writing Effective Error Messages
> 	1.	Structure Your Message with Three Key Parts
> 	•	Context:
> Explain what the system was doing.
> Example: “Couldn’t parse config file: /etc/sample-config.properties.”
> 	•	Error Description:
> Clearly state what failed without generic wording.
> Example: “Invalid snapshot mode ‘nevr’ provided.”
> 	•	Mitigation/Next Steps:
> Tell the user what to do next. For complex issues, include an error code or documentation link.
> Example: “Please update the mode; refer to our docs for valid options.”
> 	2.	Clarity & Conciseness
> 	•	Use plain, simple language and avoid unnecessary jargon (unless targeting technical users).
> 	•	Aim for short sentences (ideally 8–14 words) for better understanding.
> 	3.	Consistent Tone & Style
> 	•	Uniformity: Use the same voice, terminology, and punctuation across all messages.
> 	•	Empathy: Maintain a neutral, supportive tone; avoid blaming the user.
> 	•	Avoid overly casual language (skip “oops”/“whoops” and excessive exclamation points).
> 	4.	Visibility & Placement (User-Facing Messages)
> 	•	Proximity: Place error messages close to the related UI element to reduce cognitive load.
> 	•	Design: Use high-contrast text, icons, or subtle animations; follow accessibility guidelines (don’t rely solely on color).
> 	5.	Actionability & Efficiency
> 	•	Clearly indicate the next steps (e.g., “Retry later”, “Log in again”, “Check your input”).
> 	•	Preserve user input when possible to minimize frustration.
> 	•	Where relevant, provide error codes or links for further troubleshooting.
> 	6.	Security & Privacy Considerations
> 	•	User-Facing: Avoid exposing internal details or sensitive data.
> 	•	Developer/Logging: Include detailed context (like file paths or exception chains) for debugging, but be cautious about sensitive information.
> 	7.	Logging & Exception Best Practices (for Developer/Operations Messages)
> 	•	Log the full context—including exception chains—to aid troubleshooting.
> 	•	Use structured logging (e.g., JSON) for filtering and analysis.
> 	•	Choose a consistent method: either raise an exception or log an error (not both) to avoid redundancy.
> 	•	Don’t make error messages an API contract; expose machine-readable error codes or types instead.
> 	8.	Additional Best Practices
> 	•	Fail Early: Report errors as soon as possible (e.g., during input validation or startup).
> 	•	One Concept, One Term: Use consistent terminology across messages and documentation.
> 	•	Localization: For internal logs, use English; if localizing for users, follow a vetted process.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`
- `umh-core/pkg/communicator/api/v2/http/requester.go`

</details>
<details>
<summary>`**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behin...</summary>

> `**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behind the decision. So e.g., why something was preferred over other options, or why a certain loop needs to be executed.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`
- `umh-core/pkg/communicator/api/v2/http/requester.go`

</details>

</details><details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (1)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester.go (4)</summary>

* `DoHTTPRequest` (213-264)
* `GetRequest` (320-339)
* `LoginEndpoint` (41-41)
* `PostRequest` (404-423)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: Integration Tests (2)
* GitHub Check: Integration Tests (3)
* GitHub Check: Integration Tests (1)
* GitHub Check: Unit Tests
* GitHub Check: Build and Push (arm64)
* GitHub Check: Build and Push (amd64)

</details>

<details>
<summary>🔇 Additional comments (11)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (6)</summary>

`43-65`: **Good implementation of HTTP request retry mechanism.**

The helper function effectively implements exponential backoff with targeted retry for connection-related errors. This improves test reliability when testing against external services like badssl.com.

One enhancement would be to include a comment explaining why connection-related errors specifically warrant retries while other errors don't.

---

`86-90`: **LGTM. Updated test expectations match the API behavior.**

The GetRequest test now properly expects a successful response with status code 200, which matches the actual endpoint behavior.

---

`94-98`: **LGTM. Fixed grammatical error in the test name.**

The test properly expects an authentication error with status code 401 for unauthorized requests.

---

`138-159`: **Good coverage of key exchange testing scenarios.**

The tests correctly expect failures in both secure and insecure TLS modes for outdated Diffie-Hellman key exchanges, which Go's crypto/tls library rejects for security reasons.

---

`161-178`: **Comprehensive TLS protocol version testing.**

The test suite correctly validates that older TLS versions (1.0, 1.1) fail in secure mode but succeed in insecure mode, matching the implementation's behavior with `MinVersion: tls.VersionTLS10` setting.

---

`180-199`: **Complete coverage of deprecated cipher suite handling.**

The tests verify that removed cipher suites fail regardless of TLS security settings, which is the expected behavior since these ciphers are no longer compiled into Go's standard library.

</details>
<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester.go (5)</summary>

`213-264`: **Good separation of HTTP request handling from response processing.**

The `DoHTTPRequest` function is well-structured, handling request preparation, headers, cookies, tracing, and error enhancement. This refactoring improves code reuse and maintainability by separating concerns.

The code correctly handles response errors and implements proper latency tracking.

---

`266-316`: **Well-implemented response processing with proper resource management.**

The `processJSONResponse` function:
- Properly defers closing the response body
- Handles error status codes with specific handling for 401 unauthorized errors
- Processes cookies and external IP data from response headers

Good job implementing generic return types with the `R` type parameter.

---

`320-339`: **LGTM. Simplified GetRequest implementation using modularized components.**

The `GetRequest` function is now a clean wrapper around `DoHTTPRequest` and `processJSONResponse`, making the code more maintainable and easier to test.

---

`341-399`: **Well-structured HTTP POST request implementation.**

The `DoHTTPPostRequest` function properly handles:
- JSON marshaling of the request body
- Setting headers and cookies
- Using chunked transfer encoding
- Request tracing for performance monitoring
- Enhanced error messages for connection failures

The generic type parameter approach allows for type-safe request bodies.

---

`404-423`: **Clean implementation of PostRequest using modularized components.**

The function now follows the same pattern as `GetRequest`, delegating to `DoHTTPPostRequest` and `processJSONResponse` for better separation of concerns.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:13:41Z
user: login: Scarjit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:14:19Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:14:38Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (4)</summary><blockquote>

`43-65`: **Well-structured retry helper function**

This helper function adds robustness to the tests by retrying on connection issues with exponential backoff. The code is clear and well-commented.

Consider adding a brief comment explaining why these specific error strings were chosen for retrying. This would help future developers understand the rationale.

```diff
 	// doHTTPRequestWithRetry is a test helper that retries HTTP requests on connection issues
+	// It specifically looks for connection errors, timeouts, and EOF errors which are common
+	// transient failures when testing against external services like badssl.com
 	doHTTPRequestWithRetry := func(ctx context.Context, url string, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*netHTTP.Response, error) {
```

---

`106-106`: **Fix typo in comment**

Small typo in the comment.

```diff
-	// badssl.com is not ment for automated testing, therefore we will only run the tests when the label is provided
+	// badssl.com is not meant for automated testing, therefore we will only run the tests when the label is provided
```

---

`147-147`: **Remove redundant label**

The "tls" label is already applied to the parent context, so it's redundant here.

```diff
-		Describe("Key exchange", Label("tls"), func() {
+		Describe("Key exchange", func() {
```

---

`198-198`: **Fix typo in comment**

Small typo in the comment.

```diff
-			// These cipher suites where removed from go, using them requires custom args when building the executable
+			// These cipher suites were removed from go, using them requires custom args when building the executable
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 914f5f4adf47972c7c02e6ea15cbe9ab6a0c82a7 and 3e205a6c19a9cd65cf2d3230cd46cc36cad26679.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `umh-core/README.md` (1 hunks)
* `umh-core/pkg/communicator/api/v2/http/requester_test.go` (3 hunks)
* `umh-core/pkg/config/config.go` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (1)</summary>

* umh-core/README.md

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* umh-core/pkg/config/config.go

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct fo...</summary>

> `**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct format to help improve clarity and usability.
> 
> Quick Guidelines for Writing Effective Error Messages
> 	1.	Structure Your Message with Three Key Parts
> 	•	Context:
> Explain what the system was doing.
> Example: “Couldn’t parse config file: /etc/sample-config.properties.”
> 	•	Error Description:
> Clearly state what failed without generic wording.
> Example: “Invalid snapshot mode ‘nevr’ provided.”
> 	•	Mitigation/Next Steps:
> Tell the user what to do next. For complex issues, include an error code or documentation link.
> Example: “Please update the mode; refer to our docs for valid options.”
> 	2.	Clarity & Conciseness
> 	•	Use plain, simple language and avoid unnecessary jargon (unless targeting technical users).
> 	•	Aim for short sentences (ideally 8–14 words) for better understanding.
> 	3.	Consistent Tone & Style
> 	•	Uniformity: Use the same voice, terminology, and punctuation across all messages.
> 	•	Empathy: Maintain a neutral, supportive tone; avoid blaming the user.
> 	•	Avoid overly casual language (skip “oops”/“whoops” and excessive exclamation points).
> 	4.	Visibility & Placement (User-Facing Messages)
> 	•	Proximity: Place error messages close to the related UI element to reduce cognitive load.
> 	•	Design: Use high-contrast text, icons, or subtle animations; follow accessibility guidelines (don’t rely solely on color).
> 	5.	Actionability & Efficiency
> 	•	Clearly indicate the next steps (e.g., “Retry later”, “Log in again”, “Check your input”).
> 	•	Preserve user input when possible to minimize frustration.
> 	•	Where relevant, provide error codes or links for further troubleshooting.
> 	6.	Security & Privacy Considerations
> 	•	User-Facing: Avoid exposing internal details or sensitive data.
> 	•	Developer/Logging: Include detailed context (like file paths or exception chains) for debugging, but be cautious about sensitive information.
> 	7.	Logging & Exception Best Practices (for Developer/Operations Messages)
> 	•	Log the full context—including exception chains—to aid troubleshooting.
> 	•	Use structured logging (e.g., JSON) for filtering and analysis.
> 	•	Choose a consistent method: either raise an exception or log an error (not both) to avoid redundancy.
> 	•	Don’t make error messages an API contract; expose machine-readable error codes or types instead.
> 	8.	Additional Best Practices
> 	•	Fail Early: Report errors as soon as possible (e.g., during input validation or startup).
> 	•	One Concept, One Term: Use consistent terminology across messages and documentation.
> 	•	Localization: For internal logs, use English; if localizing for users, follow a vetted process.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`

</details>
<details>
<summary>`**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behin...</summary>

> `**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behind the decision. So e.g., why something was preferred over other options, or why a certain loop needs to be executed.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: Integration Tests (2)
* GitHub Check: Integration Tests (3)
* GitHub Check: Integration Tests (1)
* GitHub Check: Unit Tests
* GitHub Check: Build and Push (arm64)
* GitHub Check: Build and Push (amd64)

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (2)</summary>

`107-221`: **Excellent comprehensive TLS security test suite**

This test suite thoroughly validates both secure and insecure TLS behavior across multiple security scenarios. The tests are well-structured, include helpful comments about Go's TLS implementation details, and use appropriate gating with the "tls" label.

The test design distinguishes correctly between:
1. Certificate validation issues (that should pass in insecure mode)
2. Protocol version issues (that should pass in insecure mode)
3. Key exchange and cipher suite issues (that should fail regardless of mode)

This aligns perfectly with the PR objective of allowing insecure TLS when necessary.


As noted in past review comments, be aware that badssl.com might not be stable for CI/CD. Could you monitor test reliability and consider a backup plan if issues arise?

---

`85-104`: **Improved existing request tests with timeouts**

Adding context timeouts to the existing tests is a good practice to prevent tests from hanging indefinitely.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:26:32Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (2)</summary><blockquote>

`129-135`: **Missing response body closure**

The code reads the response body for debugging but doesn't close it afterward, which could lead to resource leaks.

```diff
// Read response body for debugging
if response != nil {
    body, err := io.ReadAll(response.Body)
    Expect(err).ToNot(HaveOccurred())
    GinkgoWriter.Println(string(body))
+   response.Body.Close()
}
```

---

`174-195`: **Add documentation explaining why insecure protocols are needed**

The tests correctly validate both secure and insecure protocol scenarios, but there's no explanation of why allowing insecure protocols is necessary in some cases.


Consider adding a comment at the beginning of this section explaining the business or technical requirements that necessitate supporting older TLS protocols in insecure mode. This would help clarify the "why" behind this feature as required by the coding guidelines.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (2)</summary><blockquote>

`43-65`: **Well-structured retry mechanism for HTTP request testing**

The helper function implements a robust retry strategy with exponential backoff, selectively retrying only on connection-related issues. This approach improves test stability when dealing with external services like badssl.com.

One suggestion to enhance logging and debugging:

```diff
func doHTTPRequestWithRetry(ctx context.Context, url string, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*netHTTP.Response, error) {
    var lastErr error
    for i := 0; i < 10; i++ {
+       if i > 0 {
+           logger.Debugf("Retry attempt %d for URL %s", i, url)
+       }
        response, err := http.DoHTTPRequest(ctx, url, header, cookies, insecureTLS, logger)
        if err == nil {
            return response, nil
        }

        // Only retry on connection-related errors
        if strings.Contains(err.Error(), "connection") ||
            strings.Contains(err.Error(), "timeout") ||
            strings.Contains(err.Error(), "EOF") {
            lastErr = err
+           logger.Debugf("Retryable error encountered: %v", err)
            time.Sleep(time.Second * time.Duration(i+1)) // Exponential backoff
            continue
        }

        // For non-connection errors, return immediately
        return response, err
    }
    return nil, fmt.Errorf("failed after 10 retries, last error: %w", lastErr)
}
```

---

`107-221`: **Comprehensive TLS security test coverage**

The test suite thoroughly covers various TLS security aspects (certificate validation, key exchange, protocols, and cipher suites) against real-world test cases from badssl.com. This ensures the insecure TLS feature works as expected while maintaining security by default.

Two suggestions for improvement:


1. Consider implementing a function to handle the common test logic for each TLS category to reduce code duplication:

```go
func runTLSTestCase(name, url string, secureExpectSuccess, insecureExpectSuccess bool) {
    It(fmt.Sprintf("should %s with secure TLS for %s", 
       secureExpectSuccess ? "succeed" : "fail", name), func() {
        ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
        defer cancel()
        response, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
        if response != nil {
            body, err := io.ReadAll(response.Body)
            Expect(err).ToNot(HaveOccurred())
            GinkgoWriter.Println(string(body))
            response.Body.Close()
        }
        if secureExpectSuccess {
            Expect(err).ToNot(HaveOccurred())
        } else {
            Expect(err).To(HaveOccurred())
        }
    })

    It(fmt.Sprintf("should %s with insecure TLS for %s", 
       insecureExpectSuccess ? "succeed" : "fail", name), func() {
        ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
        defer cancel()
        response, err := doHTTPRequestWithRetry(ctx, url, nil, nil, true, log)
        if response != nil {
            body, err := io.ReadAll(response.Body)
            Expect(err).ToNot(HaveOccurred())
            GinkgoWriter.Println(string(body))
            response.Body.Close()
        }
        if insecureExpectSuccess {
            Expect(err).ToNot(HaveOccurred())
        } else {
            Expect(err).To(HaveOccurred())
        }
    })
}
```

2. Add a descriptive comment at the top of the TLS Security context explaining:
   - Why this feature was added (what business/technical requirements it addresses)
   - The security implications of enabling insecure TLS
   - When it's appropriate to use this feature

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3e205a6c19a9cd65cf2d3230cd46cc36cad26679 and ee5245192f410fbc860863d82be5d4f6ae66f114.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `umh-core/Makefile` (2 hunks)
* `umh-core/pkg/communicator/api/v2/http/requester_test.go` (3 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* umh-core/Makefile

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct fo...</summary>

> `**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct format to help improve clarity and usability.
> 
> Quick Guidelines for Writing Effective Error Messages
> 	1.	Structure Your Message with Three Key Parts
> 	•	Context:
> Explain what the system was doing.
> Example: “Couldn’t parse config file: /etc/sample-config.properties.”
> 	•	Error Description:
> Clearly state what failed without generic wording.
> Example: “Invalid snapshot mode ‘nevr’ provided.”
> 	•	Mitigation/Next Steps:
> Tell the user what to do next. For complex issues, include an error code or documentation link.
> Example: “Please update the mode; refer to our docs for valid options.”
> 	2.	Clarity & Conciseness
> 	•	Use plain, simple language and avoid unnecessary jargon (unless targeting technical users).
> 	•	Aim for short sentences (ideally 8–14 words) for better understanding.
> 	3.	Consistent Tone & Style
> 	•	Uniformity: Use the same voice, terminology, and punctuation across all messages.
> 	•	Empathy: Maintain a neutral, supportive tone; avoid blaming the user.
> 	•	Avoid overly casual language (skip “oops”/“whoops” and excessive exclamation points).
> 	4.	Visibility & Placement (User-Facing Messages)
> 	•	Proximity: Place error messages close to the related UI element to reduce cognitive load.
> 	•	Design: Use high-contrast text, icons, or subtle animations; follow accessibility guidelines (don’t rely solely on color).
> 	5.	Actionability & Efficiency
> 	•	Clearly indicate the next steps (e.g., “Retry later”, “Log in again”, “Check your input”).
> 	•	Preserve user input when possible to minimize frustration.
> 	•	Where relevant, provide error codes or links for further troubleshooting.
> 	6.	Security & Privacy Considerations
> 	•	User-Facing: Avoid exposing internal details or sensitive data.
> 	•	Developer/Logging: Include detailed context (like file paths or exception chains) for debugging, but be cautious about sensitive information.
> 	7.	Logging & Exception Best Practices (for Developer/Operations Messages)
> 	•	Log the full context—including exception chains—to aid troubleshooting.
> 	•	Use structured logging (e.g., JSON) for filtering and analysis.
> 	•	Choose a consistent method: either raise an exception or log an error (not both) to avoid redundancy.
> 	•	Don’t make error messages an API contract; expose machine-readable error codes or types instead.
> 	8.	Additional Best Practices
> 	•	Fail Early: Report errors as soon as possible (e.g., during input validation or startup).
> 	•	One Concept, One Term: Use consistent terminology across messages and documentation.
> 	•	Localization: For internal logs, use English; if localizing for users, follow a vetted process.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`

</details>
<details>
<summary>`**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behin...</summary>

> `**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behind the decision. So e.g., why something was preferred over other options, or why a certain loop needs to be executed.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: Unit Tests
* GitHub Check: Integration Tests (1)
* GitHub Check: Integration Tests (2)
* GitHub Check: Integration Tests (3)
* GitHub Check: Build and Push (arm64)
* GitHub Check: Build and Push (amd64)

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (3)</summary>

`106-107`: **Good decision to label TLS tests separately**

Labeling these tests with "tls" and making them opt-in is a smart approach since they depend on an external service. This prevents potential CI pipeline failures when the external service is unavailable.

---

`111-122`: **Good documentation for test cases**

The comments explaining the purpose of badssl.com and why certain tests are disabled (revoked certificates and pinning) are thorough and educational. This provides valuable context for other developers.

---

`85-102`: **Improved test robustness with timeouts**

Adding context timeouts to the original requester tests is a good improvement that prevents tests from hanging indefinitely if there are connection issues.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T08:28:59Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (2)</summary><blockquote>

`105-107`: **Expand comment to explain why insecure TLS is necessary**

The comment explains what the feature is used for (corporate proxies with self-signed certificates) but doesn't fully explain the business or technical requirements driving this need.


```diff
 // badssl.com is not ment for automated testing, therefore we will only run the tests when the label is provided
-// These tests check if umh-core can be deployed in environment with insecure TLS (e.g corporate proxies with there own self-signed certificates)
+// These tests check if umh-core can be deployed in environments with insecure TLS (e.g., corporate proxies with their own self-signed certificates).
+// This capability is necessary because many industrial environments operate behind corporate proxies using self-signed certificates,
+// and requiring secure TLS would prevent the agent from functioning in these common deployment scenarios.
+// The AllowInsecureTLS flag should only be enabled in controlled environments where the security implications are understood.
```

---

`73-89`: **Consider a more stable test environment than badssl.com**

While the tests are well-designed, the dependence on badssl.com (an external service) could introduce test flakiness.



Badssl.com is maintained by volunteers and not officially supported for automated testing. According to its maintainers, it's "a single small Nginx instance maintained in spare time" which may not be ideal for CI/CD pipelines.

For more reliable testing, consider:
1. Setting up a local badssl instance
2. Using a mock TLS server in your test suite

```web
Is badssl.com recommended for automated testing in CI/CD pipelines?
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (2)</summary><blockquote>

`43-64`: **Consider closing response body to prevent resource leaks**

The helper function doesn't close the response body, which could lead to resource leaks during testing.

```diff
 doHTTPRequestWithRetry := func(ctx context.Context, url string, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*netHTTP.Response, error) {
 	var lastErr error
 	for i := 0; i < 10; i++ {
 		response, err := http.DoHTTPRequest(ctx, url, header, cookies, insecureTLS, logger)
 		if err == nil {
+			// Note: Caller is responsible for closing response.Body
 			return response, nil
 		}

 		// Only retry on connection-related errors
 		if strings.Contains(err.Error(), "connection") ||
 			strings.Contains(err.Error(), "timeout") ||
 			strings.Contains(err.Error(), "EOF") {
 			lastErr = err
 			time.Sleep(time.Second * time.Duration(i+1)) // Exponential backoff
 			continue
 		}

 		// For non-connection errors, return immediately
 		return response, err
 	}
 	return nil, fmt.Errorf("failed after 10 retries, last error: %w", lastErr)
}
```

---

`111-122`: **Fix typo in the comments**

There's a typo in the comment.

```diff
 			// https://badssl.com/ is a website from the chromium project that provides various TLS test sites
 			// These test sites help verify different TLS security scenarios
 			testCases := map[string]string{
 				"expired":        "https://expired.badssl.com",
 				"wrong-host":     "https://wrong.host.badssl.com",
 				"self-signed":    "https://self-signed.badssl.com",
 				"untrusted-root": "https://untrusted-root.badssl.com",
-				// The revoked certificate test is disabled, as go's crypto/tls requires the user to implement certificate revocation checking
+				// The revoked certificate test is disabled, as Go's crypto/tls requires the user to implement certificate revocation checking
 				// See also: https://www.cossacklabs.com/blog/tls-validation-implementing-ocsp-and-crl-in-go/
 				// "revoked":        "https://revoked.badssl.com",
-				// The pinning test is disabled, as go's crypto/tls ignores HPKP (HTTP Public Key Pinning)
+				// The pinning test is disabled, as Go's crypto/tls ignores HPKP (HTTP Public Key Pinning)
 				// See also: https://blog.ordina-jworks.io/security/2018/02/12/HPKP-deprecated-what-now.html
 				// "pinning-test":   "https://pinning-test.badssl.com"
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 3b032fd970efc397d8ca26208825ac1d1ff9276f and c99f974d893ea4057b77876060a9af1662669600.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `umh-core/pkg/communicator/api/v2/http/requester_test.go` (3 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (2)</summary>

<details>
<summary>`**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct fo...</summary>

> `**/*`: When reviewing an error message, ensure it meets these guidelines. If a message is lacking (e.g., missing clear next steps or context), provide an example of the correct format to help improve clarity and usability.
> 
> Quick Guidelines for Writing Effective Error Messages
> 	1.	Structure Your Message with Three Key Parts
> 	•	Context:
> Explain what the system was doing.
> Example: “Couldn’t parse config file: /etc/sample-config.properties.”
> 	•	Error Description:
> Clearly state what failed without generic wording.
> Example: “Invalid snapshot mode ‘nevr’ provided.”
> 	•	Mitigation/Next Steps:
> Tell the user what to do next. For complex issues, include an error code or documentation link.
> Example: “Please update the mode; refer to our docs for valid options.”
> 	2.	Clarity & Conciseness
> 	•	Use plain, simple language and avoid unnecessary jargon (unless targeting technical users).
> 	•	Aim for short sentences (ideally 8–14 words) for better understanding.
> 	3.	Consistent Tone & Style
> 	•	Uniformity: Use the same voice, terminology, and punctuation across all messages.
> 	•	Empathy: Maintain a neutral, supportive tone; avoid blaming the user.
> 	•	Avoid overly casual language (skip “oops”/“whoops” and excessive exclamation points).
> 	4.	Visibility & Placement (User-Facing Messages)
> 	•	Proximity: Place error messages close to the related UI element to reduce cognitive load.
> 	•	Design: Use high-contrast text, icons, or subtle animations; follow accessibility guidelines (don’t rely solely on color).
> 	5.	Actionability & Efficiency
> 	•	Clearly indicate the next steps (e.g., “Retry later”, “Log in again”, “Check your input”).
> 	•	Preserve user input when possible to minimize frustration.
> 	•	Where relevant, provide error codes or links for further troubleshooting.
> 	6.	Security & Privacy Considerations
> 	•	User-Facing: Avoid exposing internal details or sensitive data.
> 	•	Developer/Logging: Include detailed context (like file paths or exception chains) for debugging, but be cautious about sensitive information.
> 	7.	Logging & Exception Best Practices (for Developer/Operations Messages)
> 	•	Log the full context—including exception chains—to aid troubleshooting.
> 	•	Use structured logging (e.g., JSON) for filtering and analysis.
> 	•	Choose a consistent method: either raise an exception or log an error (not both) to avoid redundancy.
> 	•	Don’t make error messages an API contract; expose machine-readable error codes or types instead.
> 	8.	Additional Best Practices
> 	•	Fail Early: Report errors as soon as possible (e.g., during input validation or startup).
> 	•	One Concept, One Term: Use consistent terminology across messages and documentation.
> 	•	Localization: For internal logs, use English; if localizing for users, follow a vetted process.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`

</details>
<details>
<summary>`**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behin...</summary>

> `**/*`: Whenever in a new PR a new function or code is introduced, ensure that there is at least somewhere as a code comment, in the README or wherer ever explained the "why" behind the decision. So e.g., why something was preferred over other options, or why a certain loop needs to be executed.

- `umh-core/pkg/communicator/api/v2/http/requester_test.go`

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: Integration Tests (2)
* GitHub Check: Integration Tests (1)
* GitHub Check: Unit Tests
* GitHub Check: Integration Tests (3)
* GitHub Check: Build and Push (amd64)
* GitHub Check: Build and Push (arm64)

</details>

<details>
<summary>🔇 Additional comments (7)</summary><blockquote>

<details>
<summary>umh-core/pkg/communicator/api/v2/http/requester_test.go (7)</summary>

`42-64`: **Well-implemented retry mechanism with exponential backoff**

The helper function provides a robust retry mechanism that only retries on connection-related errors with exponential backoff. This improves test stability, especially when dealing with external dependencies.

---

`85-91`: **Good use of context with timeout**

The addition of context with timeout improves test robustness by preventing tests from hanging indefinitely.

---

`95-101`: **Updated test expectations match the API behavior**

The test now correctly expects a 401 status code which aligns with the API behavior for unauthorized requests.

---

`108-140`: **Comprehensive certificate validation test cases**

The certificate validation tests thoroughly check both secure and insecure behavior against various invalid certificate scenarios. The comments explaining why some tests are disabled (revoked certificates, pinning) provide valuable context.

---

`141-166`: **Well-documented key exchange test cases**

The key exchange tests properly document that these should fail in both secure and insecure modes because Go's crypto/tls implementation doesn't support these insecure key exchange methods.

---

`168-189`: **Protocol version tests align with Go's TLS behavior**

These tests correctly verify that older TLS protocol versions (1.0 and 1.1) fail in secure mode but succeed in insecure mode. This aligns with the behavior of Go's TLS implementation and the purpose of the AllowInsecureTLS flag.

---

`191-214`: **Comprehensive cipher suite tests**

These tests correctly verify that insecure cipher suites fail in both secure and insecure modes since they've been removed from Go's crypto/tls implementation.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T09:13:50Z
user: login: JeremyTheocharis
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-13T14:39:11Z
user: login: Scarjit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T15:26:50Z
user: login: Scarjit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T15:28:42Z
user: login: kanapuli
body: Looks good to me
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T09:21:34Z
user: login: kanapuli
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T09:22:02Z
user: login: FreiPaul
body: Should we also read the AllowInsecureTLS from the env vars when executing docker run?
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T09:42:35Z
user: login: JeremyTheocharis
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-14T11:21:10Z
user: login: Scarjit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T12:39:53Z
user: login: JeremyTheocharis
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-14T13:55:53Z

Review comments:
diff_hunk: @@ -46,6 +46,7 @@ type AgentConfig struct {
 	CommunicatorConfig `yaml:"communicator,omitempty"`
 	ReleaseChannel     ReleaseChannel `yaml:"releaseChannel,omitempty"`
 	Location           map[int]string `yaml:"location,omitempty"`
+	AllowInsecureTLS   bool           `yaml:"allowInsecureTLS,omitempty"` // Allow TLS connections without verifying the certificate.
path: umh-core/pkg/config/config.go
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**New AllowInsecureTLS flag needs security warning documentation**

While the implementation of this flag is technically correct, allowing insecure TLS connections bypasses certificate validation which poses significant security risks.


Consider adding a more detailed comment warning about the security implications:

```diff
-	AllowInsecureTLS   bool           `yaml:"allowInsecureTLS,omitempty"` // Allow TLS connections without verifying the certificate.
+	AllowInsecureTLS   bool           `yaml:"allowInsecureTLS,omitempty"` // Allow TLS connections without verifying the certificate. WARNING: This should only be used in development/testing environments or with trusted internal networks. Using this in production environments exposes the system to man-in-the-middle attacks.
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
	AllowInsecureTLS   bool           `yaml:"allowInsecureTLS,omitempty"` // Allow TLS connections without verifying the certificate. WARNING: This should only be used in development/testing environments or with trusted internal networks. Using this in production environments exposes the system to man-in-the-middle attacks.
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T07:31:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,4 +69,22 @@ var _ = Describe("Requester", func() {
 			})
 		})
 	})
+
+	Context("TLS Security", func() {
+		// https://badssl.com/ is a website from the chromium project that provides various TLS test sites
+		// The one we choose here is the untrusted-root.badssl.com site, which is a site that has a certificate
+		// that is not trusted by default.
+		const untrustedURL = "https://untrusted-root.badssl.com"
+
+		It("should fail with secure TLS", func() {
+			_, _, err := http.GetRequest[any](context.Background(), "/", nil, nil, false, untrustedURL, log)
+			Expect(err).To(HaveOccurred())
+			Expect(err.Error()).To(ContainSubstring("certificate"))
+		})
+
+		It("should succeed with insecure TLS", func() {
+			_, _, err := http.GetRequest[any](context.Background(), "/", nil, nil, true, untrustedURL, log)
+			Expect(err).ToNot(HaveOccurred())
+		})
+	})
path: umh-core/pkg/communicator/api/v2/http/requester_test.go
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Well-implemented TLS security tests with external dependency consideration**

The tests effectively validate both secure and insecure TLS behaviors using a known test site.



While the use of badssl.com is a good practice for testing TLS behaviors, be aware that relying on an external service can potentially make tests brittle if the service changes. Consider verifying that this site is reliable for long-term testing:

---

🌐 Web query:

```web
Is badssl.com a stable and reliable service for long-term TLS testing in CI/CD pipelines?
```

💡 Result:

BadSSL.com is a website designed to help developers test their clients against various SSL/TLS configurations, including expired certificates, self-signed certificates, and weak ciphers. While it serves as a valuable resource for manual testing, its suitability for long-term integration into CI/CD pipelines is limited.

The BadSSL.com project is maintained by volunteers and is not an official Google product. Its primary purpose is for manual testing of security UI in web clients. The site is hosted on Google Cloud infrastructure and co-maintained by individuals from Mozilla Firefox and Google Chrome. However, the project is not officially supported by these organizations. ([github.com](https://github.com/chromium/badssl.com?utm_source=openai))

In August 2023, a GitHub issue was opened expressing concerns about the site's reliability for automated testing in CI/CD pipelines. The issue highlighted that BadSSL.com is a single small Nginx instance maintained in spare time, which may not be ideal for automated testing. The maintainers acknowledged these concerns and suggested hosting a local test server to avoid depending on a potentially flaky live site. ([github.com](https://github.com/chromium/badssl.com/issues/527?utm_source=openai))

Given these factors, BadSSL.com may not be the most stable and reliable service for long-term TLS testing in CI/CD pipelines. For more consistent and controlled testing environments, consider setting up a local instance of BadSSL.com or using other dedicated testing tools designed for automated integration.

Citations:

- 1: https://github.com/chromium/badssl.com?utm_source=openai
- 2: https://github.com/chromium/badssl.com/issues/527?utm_source=openai

---



</details>

**Require a controlled TLS test environment**

While these tests correctly validate secure vs. insecure TLS using badssl.com, relying on a volunteer-maintained external site can introduce CI flakiness. BadSSL.com is not officially supported and has known reliability concerns ([1],[2]). To ensure long-term stability, host a local BadSSL instance or use a dedicated in-process TLS test server.

• File: umh-core/pkg/communicator/api/v2/http/requester_test.go (Lines 73–89)  
• Update the `untrustedURL` constant to point at a locally hosted test server (e.g. dockerized BadSSL) or a mock TLS endpoint.  
• Consider adding setup/teardown logic to start and stop the local server within your test suite.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-13T07:31:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,4 +69,22 @@ var _ = Describe("Requester", func() {
 			})
 		})
 	})
+
+	Context("TLS Security", func() {
+		// https://badssl.com/ is a website from the chromium project that provides various TLS test sites
+		// The one we choose here is the untrusted-root.badssl.com site, which is a site that has a certificate
+		// that is not trusted by default.
+		const untrustedURL = "https://untrusted-root.badssl.com"
+
+		It("should fail with secure TLS", func() {
+			_, _, err := http.GetRequest[any](context.Background(), "/", nil, nil, false, untrustedURL, log)
+			Expect(err).To(HaveOccurred())
+			Expect(err.Error()).To(ContainSubstring("certificate"))
+		})
+
+		It("should succeed with insecure TLS", func() {
+			_, _, err := http.GetRequest[any](context.Background(), "/", nil, nil, true, untrustedURL, log)
+			Expect(err).ToNot(HaveOccurred())
+		})
+	})
path: umh-core/pkg/communicator/api/v2/http/requester_test.go
user: login: Scarjit
body: Ill monitor this, and if we have issues setup our own instance.
created_at: 2025-05-13T08:10:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,4 +69,22 @@ var _ = Describe("Requester", func() {
 			})
 		})
 	})
+
+	Context("TLS Security", func() {
+		// https://badssl.com/ is a website from the chromium project that provides various TLS test sites
+		// The one we choose here is the untrusted-root.badssl.com site, which is a site that has a certificate
+		// that is not trusted by default.
+		const untrustedURL = "https://untrusted-root.badssl.com"
+
+		It("should fail with secure TLS", func() {
+			_, _, err := http.GetRequest[any](context.Background(), "/", nil, nil, false, untrustedURL, log)
+			Expect(err).To(HaveOccurred())
+			Expect(err.Error()).To(ContainSubstring("certificate"))
+		})
+
+		It("should succeed with insecure TLS", func() {
+			_, _, err := http.GetRequest[any](context.Background(), "/", nil, nil, true, untrustedURL, log)
+			Expect(err).ToNot(HaveOccurred())
+		})
+	})
path: umh-core/pkg/communicator/api/v2/http/requester_test.go
user: login: coderabbitai[bot]
body: @Scarjit Sounds like a good plan! Monitoring first and then setting up your own instance if needed is a practical approach. Let me know if you encounter any issues with the external service later on.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-13T08:11:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -383,72 +388,36 @@ func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T,
 	response, err := GetClient(insecureTLS).Do(req.WithContext(httptrace.WithClientTrace(req.Context(), trace)))
 	if err != nil {
 		if response != nil {
-			return nil, response.StatusCode, err
+			return response, err
 		}
 		// Enhance error message for connection failures
-		return nil, 0, enhanceConnectionError(err)
+		return nil, enhanceConnectionError(err)
 	}
 	latenciesFRB.Set(time.Now(), timeTillFirstByte)
 
-	// Read response body
-	defer func() {
-		if err := response.Body.Close(); err != nil {
-			if responseErr != nil {
-				// If we already have an error, just log this one
-				logger.Errorf("Error closing response body: %v", err)
-			} else {
-				// No previous error, so return this one
-				responseErr = fmt.Errorf("error closing response body: %w", err)
-			}
-		}
-	}()
-
-	bodyBytes, err := io.ReadAll(response.Body)
-	if err != nil {
-		return nil, response.StatusCode, err
-	}
-
-	// Check if the response was successful (status code 2XX-3XX)
-	if response.StatusCode < 200 || response.StatusCode > 399 {
-		// Handle error reporting internally
-		error_handler.ReportHTTPErrors(
-			errors.New("error response code: "+response.Status),
-			response.StatusCode,
-			string(endpoint),
-			http.MethodPost,
-			data,
-			bodyBytes,
-		)
-
-		if len(bodyBytes) != 0 {
-			var parseResult R
-			err = safejson.Unmarshal(bodyBytes, &parseResult)
-			if err != nil {
-				return nil, response.StatusCode, err
-			}
-
-			if strings.Contains(fmt.Sprint(parseResult), "channel is full") {
-				return nil, response.StatusCode, nil
-			}
-		}
-		return nil, response.StatusCode, errors.New("error response code: " + response.Status)
-	}
+	return response, nil
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Missing latency processing for POST requests.**

The `DoHTTPPostRequest` function sets `latenciesFRB` with the first byte timing but doesn't call `processLatencyHeaders` like the GET version does. This inconsistency might lead to missing latency data for POST requests.


```diff
latenciesFRB.Set(time.Now(), timeTillFirstByte)

+ // Process latency headers like in DoHTTPRequest
+ processLatencyHeaders(response, timeTillFirstByte, logger)

return response, nil
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
	latenciesFRB.Set(time.Now(), timeTillFirstByte)
	// Process latency headers like in DoHTTPRequest
	processLatencyHeaders(response, timeTillFirstByte, logger)
	return response, nil
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-13T08:13:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -383,72 +388,36 @@ func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T,
 	response, err := GetClient(insecureTLS).Do(req.WithContext(httptrace.WithClientTrace(req.Context(), trace)))
 	if err != nil {
 		if response != nil {
-			return nil, response.StatusCode, err
+			return response, err
 		}
 		// Enhance error message for connection failures
-		return nil, 0, enhanceConnectionError(err)
+		return nil, enhanceConnectionError(err)
 	}
 	latenciesFRB.Set(time.Now(), timeTillFirstByte)
 
-	// Read response body
-	defer func() {
-		if err := response.Body.Close(); err != nil {
-			if responseErr != nil {
-				// If we already have an error, just log this one
-				logger.Errorf("Error closing response body: %v", err)
-			} else {
-				// No previous error, so return this one
-				responseErr = fmt.Errorf("error closing response body: %w", err)
-			}
-		}
-	}()
-
-	bodyBytes, err := io.ReadAll(response.Body)
-	if err != nil {
-		return nil, response.StatusCode, err
-	}
-
-	// Check if the response was successful (status code 2XX-3XX)
-	if response.StatusCode < 200 || response.StatusCode > 399 {
-		// Handle error reporting internally
-		error_handler.ReportHTTPErrors(
-			errors.New("error response code: "+response.Status),
-			response.StatusCode,
-			string(endpoint),
-			http.MethodPost,
-			data,
-			bodyBytes,
-		)
-
-		if len(bodyBytes) != 0 {
-			var parseResult R
-			err = safejson.Unmarshal(bodyBytes, &parseResult)
-			if err != nil {
-				return nil, response.StatusCode, err
-			}
-
-			if strings.Contains(fmt.Sprint(parseResult), "channel is full") {
-				return nil, response.StatusCode, nil
-			}
-		}
-		return nil, response.StatusCode, errors.New("error response code: " + response.Status)
-	}
+	return response, nil
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: Scarjit
body: That one never had it
created_at: 2025-05-13T08:14:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -383,72 +388,36 @@ func PostRequest[R any, T any](ctx context.Context, endpoint Endpoint, data *T,
 	response, err := GetClient(insecureTLS).Do(req.WithContext(httptrace.WithClientTrace(req.Context(), trace)))
 	if err != nil {
 		if response != nil {
-			return nil, response.StatusCode, err
+			return response, err
 		}
 		// Enhance error message for connection failures
-		return nil, 0, enhanceConnectionError(err)
+		return nil, enhanceConnectionError(err)
 	}
 	latenciesFRB.Set(time.Now(), timeTillFirstByte)
 
-	// Read response body
-	defer func() {
-		if err := response.Body.Close(); err != nil {
-			if responseErr != nil {
-				// If we already have an error, just log this one
-				logger.Errorf("Error closing response body: %v", err)
-			} else {
-				// No previous error, so return this one
-				responseErr = fmt.Errorf("error closing response body: %w", err)
-			}
-		}
-	}()
-
-	bodyBytes, err := io.ReadAll(response.Body)
-	if err != nil {
-		return nil, response.StatusCode, err
-	}
-
-	// Check if the response was successful (status code 2XX-3XX)
-	if response.StatusCode < 200 || response.StatusCode > 399 {
-		// Handle error reporting internally
-		error_handler.ReportHTTPErrors(
-			errors.New("error response code: "+response.Status),
-			response.StatusCode,
-			string(endpoint),
-			http.MethodPost,
-			data,
-			bodyBytes,
-		)
-
-		if len(bodyBytes) != 0 {
-			var parseResult R
-			err = safejson.Unmarshal(bodyBytes, &parseResult)
-			if err != nil {
-				return nil, response.StatusCode, err
-			}
-
-			if strings.Contains(fmt.Sprint(parseResult), "channel is full") {
-				return nil, response.StatusCode, nil
-			}
-		}
-		return nil, response.StatusCode, errors.New("error response code: " + response.Status)
-	}
+	return response, nil
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: coderabbitai[bot]
body: @Scarjit I understand, and you're right. The POST request function didn't previously include the latency header processing. Thanks for clarifying - I'll respect the existing implementation design.

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-05-13T08:14:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -56,17 +83,140 @@ var _ = Describe("Requester", func() {
 		})
 
 		Context("GetRequest", func() {
-			It("should return error for non 200 response", func() {
-				_, err, _ := http.GetRequest[any](context.Background(), http.LoginEndpoint, header, &cookies, false, apiUrl, log)
-				Expect(err).To(HaveOccurred())
+			It("should return no error", func() {
+				ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+				defer cancel()
+				_, status, err := http.GetRequest[any](ctx, http.LoginEndpoint, header, &cookies, false, apiUrl, log)
+				Expect(err).ToNot(HaveOccurred())
+				Expect(status).To(Equal(200))
 			})
 		})
 
 		Context("PostRequest", func() {
-			It("should return error for non 200 response", func() {
-				_, err, _ := http.PostRequest[any](context.Background(), http.LoginEndpoint, &data, header, &cookies, false, apiUrl, log)
+			It("should return error an error", func() {
+				ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+				defer cancel()
+				_, status, err := http.PostRequest[any](ctx, http.LoginEndpoint, &data, header, &cookies, false, apiUrl, log)
 				Expect(err).To(HaveOccurred())
+				Expect(status).To(Equal(401))
 			})
 		})
 	})
+
+	// badssl.com is not ment for automated testing, therefore we will only run the tests when the label is provided
+	Context("TLS Security", Label("tls"), func() {
+		Describe("Certificate Validation", func() {
+			// https://badssl.com/ is a website from the chromium project that provides various TLS test sites
+			// These test sites help verify different TLS security scenarios
+			testCases := map[string]string{
+				"expired":        "https://expired.badssl.com",
+				"wrong-host":     "https://wrong.host.badssl.com",
+				"self-signed":    "https://self-signed.badssl.com",
+				"untrusted-root": "https://untrusted-root.badssl.com",
+				// The revoked certificate test is disabled, as go's crypto/tls requires the user to implement certificate revocation checking
+				// See also: https://www.cossacklabs.com/blog/tls-validation-implementing-ocsp-and-crl-in-go/
+				// "revoked":        "https://revoked.badssl.com",
+				// The pinning test is disabled, as go's crypto/tls ignores HPKP (HTTP Public Key Pinning)
+				// See also: https://blog.ordina-jworks.io/security/2018/02/12/HPKP-deprecated-what-now.html
+				// "pinning-test":   "https://pinning-test.badssl.com"
+			}
+
+			for name, url := range testCases {
+				It(fmt.Sprintf("should fail with secure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+					defer cancel()
+					response, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
+					// Read response body for debugging
+					if response != nil {
+						body, err := io.ReadAll(response.Body)
+						Expect(err).ToNot(HaveOccurred())
+						GinkgoWriter.Println(string(body))
+					}
+					Expect(err).To(HaveOccurred())
+					Expect(err.Error()).To(ContainSubstring("certificate"))
+				})
+
+				It(fmt.Sprintf("should succeed with insecure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, true, log)
+					Expect(err).ToNot(HaveOccurred())
+				})
+			}
+		})
+		Describe("Key exchange", Label("tls"), func() {
+			// These will always fail, as the go crypto/tls does not allow them anymore (For good reasons)
+			testCases := map[string]string{
+				"dh480":             "https://dh480.badssl.com",
+				"dh512":             "https://dh512.badssl.com",
+				"dh1024":            "https://dh1024.badssl.com",
+				"dh2048":            "https://dh2048.badssl.com",
+				"dh-small-subgroup": "https://dh-small-subgroup.badssl.com",
+				"dh-composite":      "https://dh-composite.badssl.com",
+			}
+			for name, url := range testCases {
+				It(fmt.Sprintf("should fail with secure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
+					Expect(err).To(HaveOccurred())
+				})
+
+				It(fmt.Sprintf("should fail with insecure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+					defer cancel()
+					_, err := doHTTPRequestWithRetry(ctx, url, nil, nil, true, log)
+					Expect(err).To(HaveOccurred())
+				})
+			}
+		})
+
+		Describe("Protocol", Label("tls"), func() {
path: umh-core/pkg/communicator/api/v2/http/requester_test.go
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Add documentation explaining why insecure protocols are needed**

The tests correctly validate both secure and insecure protocol scenarios, but there's no explanation of why allowing insecure protocols is necessary in some cases.

Add a comment explaining the business or technical requirements that necessitate supporting older TLS protocols in insecure mode, which would help with the "why" behind this feature.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T08:26:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -56,17 +83,140 @@
 		})
 
 		Context("GetRequest", func() {
-			It("should return error for non 200 response", func() {
-				_, err, _ := http.GetRequest[any](context.Background(), http.LoginEndpoint, header, &cookies, false, apiUrl, log)
-				Expect(err).To(HaveOccurred())
+			It("should return no error", func() {
+				ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+				defer cancel()
+				_, status, err := http.GetRequest[any](ctx, http.LoginEndpoint, header, &cookies, false, apiUrl, log)
+				Expect(err).ToNot(HaveOccurred())
+				Expect(status).To(Equal(200))
 			})
 		})
 
 		Context("PostRequest", func() {
-			It("should return error for non 200 response", func() {
-				_, err, _ := http.PostRequest[any](context.Background(), http.LoginEndpoint, &data, header, &cookies, false, apiUrl, log)
+			It("should return error an error", func() {
+				ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+				defer cancel()
+				_, status, err := http.PostRequest[any](ctx, http.LoginEndpoint, &data, header, &cookies, false, apiUrl, log)
 				Expect(err).To(HaveOccurred())
+				Expect(status).To(Equal(401))
 			})
 		})
 	})
+
+	// badssl.com is not ment for automated testing, therefore we will only run the tests when the label is provided
+	Context("TLS Security", Label("tls"), func() {
+		Describe("Certificate Validation", func() {
+			// https://badssl.com/ is a website from the chromium project that provides various TLS test sites
+			// These test sites help verify different TLS security scenarios
+			testCases := map[string]string{
+				"expired":        "https://expired.badssl.com",
+				"wrong-host":     "https://wrong.host.badssl.com",
+				"self-signed":    "https://self-signed.badssl.com",
+				"untrusted-root": "https://untrusted-root.badssl.com",
+				// The revoked certificate test is disabled, as go's crypto/tls requires the user to implement certificate revocation checking
+				// See also: https://www.cossacklabs.com/blog/tls-validation-implementing-ocsp-and-crl-in-go/
+				// "revoked":        "https://revoked.badssl.com",
+				// The pinning test is disabled, as go's crypto/tls ignores HPKP (HTTP Public Key Pinning)
+				// See also: https://blog.ordina-jworks.io/security/2018/02/12/HPKP-deprecated-what-now.html
+				// "pinning-test":   "https://pinning-test.badssl.com"
+			}
+
+			for name, url := range testCases {
+				It(fmt.Sprintf("should fail with secure TLS for %s", name), func() {
+					ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+					defer cancel()
+					response, err := doHTTPRequestWithRetry(ctx, url, nil, nil, false, log)
+					// Read response body for debugging
+					if response != nil {
+						body, err := io.ReadAll(response.Body)
+						Expect(err).ToNot(HaveOccurred())
+						GinkgoWriter.Println(string(body))
+					}
+					Expect(err).To(HaveOccurred())
path: umh-core/pkg/communicator/api/v2/http/requester_test.go
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Ensure proper response body handling**

The code successfully reads the response body for debugging but doesn't close it afterward, which could lead to resource leaks in tests.

```diff
 					// Read response body for debugging
 					if response != nil {
 						body, err := io.ReadAll(response.Body)
 						Expect(err).ToNot(HaveOccurred())
 						GinkgoWriter.Println(string(body))
+						response.Body.Close()
 					}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
					// Read response body for debugging
					if response != nil {
						body, err := io.ReadAll(response.Body)
						Expect(err).ToNot(HaveOccurred())
						GinkgoWriter.Println(string(body))
						response.Body.Close()
					}
					Expect(err).To(HaveOccurred())
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-13T08:26:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -208,19 +209,11 @@ func enhanceConnectionError(err error) error {
 	return fmt.Errorf("connection error: %w (no response received from server, status code 0)", err)
 }
 
-// GetRequest does a GET request to the given endpoint, with optional header and cookies
-func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
-	// Set up context with default 30 second timeout if none provided
-	if ctx == nil {
-		var cancel context.CancelFunc
-		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
-		defer cancel()
-	}
-
-	url := apiURL + string(endpoint)
+// DoHTTPRequest performs the actual HTTP request and returns the response and any errors
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: JeremyTheocharis
body: for what are these changes here? i remember in the mornign it was jsut a couple of lines, now it seems there are a lot of code changes cleaning up the HTTP handling. can you explain what they are there fore, and maybe include some explanations also in the code comments?
created_at: 2025-05-13T14:37:55Z
author_association: MEMBER
diff_hunk: @@ -208,19 +209,11 @@ func enhanceConnectionError(err error) error {
 	return fmt.Errorf("connection error: %w (no response received from server, status code 0)", err)
 }
 
-// GetRequest does a GET request to the given endpoint, with optional header and cookies
-func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
-	// Set up context with default 30 second timeout if none provided
-	if ctx == nil {
-		var cancel context.CancelFunc
-		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
-		defer cancel()
-	}
-
-	url := apiURL + string(endpoint)
+// DoHTTPRequest performs the actual HTTP request and returns the response and any errors
+func DoHTTPRequest(ctx context.Context, url string, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*http.Response, error) {
 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
 	if err != nil {
-		return nil, 0, err
+		return nil, err
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: JeremyTheocharis
body: i remember the 0 was needed for some type of error handling
created_at: 2025-05-13T14:38:21Z
author_association: MEMBER
diff_hunk: @@ -208,19 +209,11 @@ func enhanceConnectionError(err error) error {
 	return fmt.Errorf("connection error: %w (no response received from server, status code 0)", err)
 }
 
-// GetRequest does a GET request to the given endpoint, with optional header and cookies
-func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
-	// Set up context with default 30 second timeout if none provided
-	if ctx == nil {
-		var cancel context.CancelFunc
-		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
-		defer cancel()
-	}
-
-	url := apiURL + string(endpoint)
+// DoHTTPRequest performs the actual HTTP request and returns the response and any errors
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: Scarjit
body: This allows testing of the actual http handling, without also needing to feed it valid JSON.
created_at: 2025-05-13T15:26:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -208,19 +209,11 @@ func enhanceConnectionError(err error) error {
 	return fmt.Errorf("connection error: %w (no response received from server, status code 0)", err)
 }
 
-// GetRequest does a GET request to the given endpoint, with optional header and cookies
-func GetRequest[R any](ctx context.Context, endpoint Endpoint, header map[string]string, cookies *map[string]string, insecureTLS bool, apiURL string, logger *zap.SugaredLogger) (result *R, statusCode int, responseErr error) {
-	// Set up context with default 30 second timeout if none provided
-	if ctx == nil {
-		var cancel context.CancelFunc
-		ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
-		defer cancel()
-	}
-
-	url := apiURL + string(endpoint)
+// DoHTTPRequest performs the actual HTTP request and returns the response and any errors
+func DoHTTPRequest(ctx context.Context, url string, header map[string]string, cookies *map[string]string, insecureTLS bool, logger *zap.SugaredLogger) (*http.Response, error) {
 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
 	if err != nil {
-		return nil, 0, err
+		return nil, err
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: Scarjit
body: The logic is still the same, see line 335
created_at: 2025-05-13T15:28:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -67,6 +67,7 @@ func GetClient(insecureTLS bool) *http.Client {
 			TLSNextProto:      make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
 			TLSClientConfig: &tls.Config{
 				InsecureSkipVerify: insecureTLS,
+				MinVersion:         tls.VersionTLS10, // Allow older TLS versions
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: JeremyTheocharis
body: shouldnt this only be activated if insecureTLS is also set?
created_at: 2025-05-14T11:20:56Z
author_association: MEMBER
diff_hunk: @@ -67,6 +67,7 @@ func GetClient(insecureTLS bool) *http.Client {
 			TLSNextProto:      make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
 			TLSClientConfig: &tls.Config{
 				InsecureSkipVerify: insecureTLS,
+				MinVersion:         tls.VersionTLS10, // Allow older TLS versions
path: umh-core/pkg/communicator/api/v2/http/requester.go
user: login: Scarjit
body: It is:

	if insecureTLS && insecureHTTPClient == nil {
		// Create a custom transport with HTTP/2 disabled and insecure TLS
		transport := &http.Transport{
			ForceAttemptHTTP2: false,
			TLSNextProto:      make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: insecureTLS,
				MinVersion:         tls.VersionTLS10, // Allow older TLS version
created_at: 2025-05-14T12:39:50Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-05-13T07:28:12Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

A new `AllowInsecureTLS` configuration flag was added to the agent, enabling optional insecure TLS connections. The main application logic and login initialization were updated to respect this flag. HTTP request handling was refactored for modularity, and extensive TLS-related tests were added. A composite `cleanup-all` target was introduced in the Makefile.

## Changes

| File(s)                                                                                  | Change Summary                                                                                                                      |
|------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
| umh-core/pkg/config/config.go                                                            | Added `AllowInsecureTLS` boolean field to `CommunicatorConfig` struct with YAML tag and documentation.                              |
| umh-core/cmd/main.go                                                                     | Updated initialization to use the `AllowInsecureTLS` config value for TLS validation logic in `CommunicationState` and login setup. |
| umh-core/pkg/communicator/api/v2/http/requester.go                                      | Refactored HTTP GET and POST request functions into smaller reusable functions; centralized response processing and error handling. |
| umh-core/pkg/communicator/api/v2/http/requester_test.go                                 | Added helper function for retrying HTTP requests; added comprehensive TLS security tests covering cert validation, protocols, ciphers. |
| umh-core/pkg/communicator/api/v2/http/http_suite_test.go                                | Added new test suite file to integrate Ginkgo testing framework for HTTP package.                                                  |
| umh-core/Makefile                                                                        | Added `cleanup-all` target that sequentially runs `cleanup-ci`, `cleanup-tmp`, and `cleanup-data`; added `badssl-test` target for TLS tests.                                  |
| umh-core/README.md                                                                       | Added documentation on handling TLS certificate errors caused by corporate firewalls, including instructions for `allowInsecureTLS`. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Config as AgentConfig
    participant Main as MainApp
    participant Login as Login
    participant HTTP as HTTPRequester

    Config->>Main: Provide AllowInsecureTLS flag
    Main->>Login: Initialize with AllowInsecureTLS
    Main->>HTTP: Initialize with AllowInsecureTLS
    HTTP->>HTTP: Perform HTTP requests with TLS validation based on flag
```

## Assessment against linked issues

| Objective                                                                 | Addressed | Explanation                      |
|---------------------------------------------------------------------------|-----------|--------------------------------|
| Allow insecure TLS connections for companies with restrictive firewalls (ENG-3017) | ✅        |                                |

## Suggested reviewers

- kanapuli  
- led0nk

## Poem

> 🐇 Hop, hop, the TLS flag’s here,  
> Secure or loose, no need to fear.  
> Cleanup commands all in a line,  
> Tests that check each cert and sign.  
> With nimble paws and code so bright,  
> This bunny’s ready for the fight! ✨🐰

<!-- walkthrough_end -->
<!-- This is an auto-generated comment: all tool run failures by coderabbit.ai -->

> [!WARNING]
> There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.
> 
> <details>
> <summary>🔧 golangci-lint (1.64.8)</summary>
> 
> Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
> Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
> 
> 
> 
> </details>

<!-- end of auto-generated comment: all tool run failures by coderabbit.ai -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro (Legacy)**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between c99f974d893ea4057b77876060a9af1662669600 and 32294d89a7be6021db6f01db1dcda16102dbd636.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `umh-core/pkg/communicator/api/v2/http/requester.go` (8 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* umh-core/pkg/communicator/api/v2/http/requester.go

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (6)</summary>

* GitHub Check: Integration Tests (1)
* GitHub Check: Unit Tests
* GitHub Check: Integration Tests (3)
* GitHub Check: Integration Tests (2)
* GitHub Check: Build and Push (amd64)
* GitHub Check: Build and Push (arm64)

</details>

</details>
<!-- internal state start -->


<!-- DwQgtGAEAqAWCWBnSTIEMB26CuAXA9mAOYCmGJATmriQCaQDG+Ats2bgFyQAOFk+AIwBWJBrngA3EsgEBPRvlqU0AgfFwA6NPEgQAfACgjoCEYDEZyAAUASpETZWaCrKNxU3bABsvkCiQBHbGlcABpIcVwvOkgAIgBRADkAcTAAZgAGAEYAdkgAQR98AHcUDERRbH8YABkAZXsSXHEMIlDYyGK0ZAcBZnUaejkI2BJIbAq+OoZnIXV0DHpUeCUMcQAzeBjuyAxHAUpIACYMtIAODRhRxlhMUjLcCkVsBml0XZJS9a80IhHqSBkFTRHq4ZwtP64a6/dhlBZlCoMKpjZiKMb+IjOWjwVq1BoVZo4oiIS5wMbfX6QZgTXCQA6NWkHdb4aqIMEUXDYbh00RoCZjeaofAYLzyfxoejC16QWhVIkjMYwtYAcmQOPU8DQXngAC9qPBheE2Jh5Wg/CFwShkP4gvB/PRmXwoWMGLdWmMCBE0ABrMYkdbrUSaK5jTwUbj4Cr8dYjVBc2jUAXIT28fASFaKrD4bjiYURfB+bBYZ3oUhrTrqWAIyrVaD1BQYTZEKr64XIYqjLDkV6IRDOWQacwWSAAVW4CcG/GEQckbwcThcbnU0S4SVSmVykEgBkS+0oXBO5y3BhHky401m6iM+mM4CgZElMb5BGIZGUk6YrHYXF4U5EYlnGR5CYJQqFUdQtB0G8TCgdw1WQTAcBfMt3xiT82DWLgqFKedmH7OlgLRMC1E0bRdDAQxb1MAxHFgMAmH8AB6ABZH1/XgFcDFibiDGHfIAElX3IKhJ1w/D8BjV07mkIx8g+UpWN9TZoi9ChSFpAADBhokwLkwC1LwNM6HYJSUWhwg7eBXRlEhuAfZA80wegKiCdhNR8MUi2Ta4SAADyQCFGB0vZuXZdTEC4LTgr0hh4A08IopIXTuDAXBmG4eKFnoRLkrACc0A00lrg0ot1FSkIjLCppjOQVFsU2GJPT87TsCUCIQmQH4DmiehikrSANKiRAjJxdBaGxXNiwLEs/IC+Vmq8CYDXKaMBpxGgiBE5ajKcgb7W4Jy0DAPyaEWOhCoKeT2rZVT1IGgQJV7LxyrZIyujVNYnllV56ChAElDsxYHKwDTeBIF7cB2xZCxW5IcW9Ihpo6yBlJoe0CIVSAupIXxBq8YaKyhFHtGe9ZulpIEBB6y5EgLfBnT4Or4E2GZJuTAtZrZeUqtwBy+C8fAiCszpKBRCUSEHIxeMsQo0dbFbPRLJRtOceWHJjPyIw5GIWR4bAqeFtzxBkgwoEU9iVJ5sazMi7SkpC/SfDehBrIB+z+BBu3ctizKcodtKMvCXa/b0/KNNNyBzeUj1nDu+NE1oSLStwCGjOx3xUcOKT3QdJ5mAG5UQHWkhNvlyAADJy8gEB9sO47fNOszlUqgsNML4vS8miuq5rugDsWI6TofGJK+robm4jqOOJjtTqtMuhIoe2gntTzoXarN2gY9gawdX3aKC8yA4YwBGkbZdt+vTlGOLRgahvD7jYmvajaPolkSEYhhmFoRi8JxDREYcC4jxPigkUIiRiGJFwq1s6kEQG4a4sC3hM3WPIEs6pxBal1GXCSmMNIAGEWDUgwFZeWdQwQ0Chr9RB4ou64JLBpAWQsMBGUEP+RkYpbI/FiriEstwKC0BAjEDSZN8YkCMhILUwQUa6wYfxcoNYSB1jqEZA6VA2C3z6kTEsTBGzwGbGBFSGlCgC2KPIxEyJlESKkeSPOmMlS0l0U2Fsk0iqoDQAGIMyZigFgFqzZaEU8GENYKVfxwpyGJiMrotkB8xC6xmD4OEGk/4YAABQAEoqF4IkEcDQiRPg1EFjiKJBkEQZjwZTaIAAhNADBfSLEIRgbsk0jLrCLABYURUxhMOFhgEo5pEB2TEN5MYxiihmIUUifwViGzOK2nmCkkICxKDRv0cga8mijCdAWAy/ScQWNrPWXRzSAkIhoBKVaWouiyGQNiPs4zuajGYJLIcBQvByzZvmTGysfjzJWrgzWLJJy608AbBggI1gahNrTcgg5H7PzAEYV+DEP7cARp/IhoTqAskYmgbg8BGI5MYrAZo3BGI2mCGySgAB9GgbIAH4CAfC0BQlULOUcHhaBuCkHwIMHJcgpRRheDsnwNpGAOkg1oPgAAEtAaAthAiUtwAAdUrDYJoLg3o7HWl9F4jVprXDpbSBw6gPQFn8I8eQsr5XmlcufcYoUCxZAyBEeAbBgYNhOcKMA/gfiTkoE8CgyBUnHJnHmJADhpDhHEGwfAeBEDhHiAAeQAGLpMJlWQF5BIVajpLU70El1jhAtVUEhuI3VsGxImUU296ZbMBBQQNJIQyAn8lzXEsR1V2rRh0I17ZRZUkUMzLYic8HJCaF2pVlUQi7H6ZrLxs6G2Bqyu8E4Lq2TUAmAoNqWiqxmiyAAVjAIiYU9BdE0Abq62NeAg7QwYVYSMuBJ0VWuhTXyQzebwgDbrXaZoAAs2R7AUK3UIoO+MCy7veOek6V6SBxs0LJBQ6V/CdkQLOK6sRlGQDqDWdQshe0zug5e961s6DhExJOYYZpYhDQ6FfT0aAJD4BWDDMtfxhhKDJt4YMcEGwXtpDiFqShkDMiqPYfWrMS4si2IE2I+DKAbFITQSAAA1LBE5lrtDiAAaRIPIZqbpSBadiFYJ4BAmBeC07tOT8BuD1rqNgU1JIOjxFqVWXoknEbQL7VSbjtmVLKJ9TjBO9hXgYGcAaBCmJ9mOJZP4QZp75QaSXk9DQn4jJSpSc2+THJh2ScgJI7UGm8w+akBQZmaDbjGsUXiT1YaVpkw4hmxgCm8uJiXSyBC0MHAMFeDEDsZBauFZWGXVAdzgR0EuLp/TvkkGvuQE4u0+dGuLWqKNAQdbGhTMzEsSZyJat1TeI6GyYNJP0AACLMwamAaVOMvB4SwGotAGjKDNtM/TfAFn5s3FEN6f4tIsNZA0C63aQOsh1YlSJkmW3kQ1oEHgcTvWSAxH2Yo0Ulx8G2frSa5TpXKAVeJhxfb63NsHJ29Wbbg7hMyL4P4VEUgz1Y8ODj6QlwTHff5JjC10ChUipp34QQNJyC9hXXi7gNaiO0hjXB+Nks+LvPfKcxW1wfmq0+QC99QKdZ8FBdqcFRsZNGFpjcaS/bqh4TasrsYqu/nq1bVrYFOv9Z64hZEGTcKeKmxfswOiKLGJoqIBivRgfFtEAZUykBMswFvggeyhc8huWGZNvyz4dJ8D4GCtfHG2UTElHMYomZJH56/QNaM4JxClMskaU2IyMSXg8YQCJrYXgljJl+KQB0usACa+RmI1EaOVrBeou47A0rsiZZOZm7TG59xw7B9VlGxPlgbDNauhsh/YWAcaW88nQOM/rlZ4MFfx6gx5LpWss0TDTOmq+eVfJ6QwcI36+BuloNqVo4R4nCkeBnlGpiRbm7ixy4ywK625fJKyiC/JqyrSArayShO5gqu5Qq8pQAprN70DF6RS54T4F71gbYZ4jRYB15iADTl5YoEAUDV76KEEDTIrvz+7oqh5B5NgMoPye4QCIo0Q+5vxMQB4YohIkKsw4p4oEpEokq4BkriHcDUos60ohDh7AJPwsrgIhZQIJ6SRJ68op6lDJBnzGqObKbRz84ljWpWA8D5owjjBnR8AlTcF+58HoTkHCH4qEpHDEqkpGS3AyDI5YDF5uJN4qQEjIBciYzHynyvryjrDqKfAsh/Ydx/IYxuoO7yhhGIwrq6FsCYjmF1IwgJrmhCxUrla8LXCpEFgraQCv7RAUC3r0AHxNJn6vr2BDLBHWGYws67DPZjCxCmHYYGESwdBkjXwqSCaLTU4boDwCIFAHSuhjC5Iup65kBRijDixBorqcY4hvAljTHeiWGj5SFyGvSXD8SxZrDaArRmhoatAqSwGThGooztJdwaTQAhDSoeFrxWRVgYLuS6ibElHwxpF3F1HCTGGN7ZE7GkAvLSxvIfJK6l42QqxgEa4O7a56yIEG4myoEPHLSkajoiLtIwAvGkqpK0gABURqRIGg0AmScI2xlhGk+xRqNBthvu9BDhmKgh2KFAuKLhYhpK7hEhMhfRBxmgiMbBT8XunBdBvBjB7JleXJIhrh/JZKFKIQlAChzKUerKse4m8eMCmhCCLomh5oZMcSTo1wPRyQ8Q0AK6VgSadQ1pKpN0lR8owwOqzwPCfwpilAYA0QUgGcWJbYA052MqcqCq3aWSGkwZphD6bIz6r0/2PAlAjo+cJY2EkAPRCS+MK6JaFAIMJJUhGg6qCWCiWSz+F8UIR+qYPYlxkI1w8WEYCiaetACefA2kkY8oEELa0mzCuaGk46T6iqL6wcMZA54Z9x4qnyzgYwfSpQxQVA3AIqCETwRY1C0g3SJQ3pvpOM45kOQc408okusGR+nGfI7yXWZ6BkpoV0vOhwoMTw1ZAAUnUEmokEWQ2RUC3BUU5CpOKNiB/lYZyogLcD4PKE+S+U/o2rrM6biA9BUJKEQcBgtmiHkUwPgN6FsDwPedIDWTUVjImOKvIMsaBJhZ9thRSS2vWW2GMBts2UFO2eWgtuwFQNqDqCjiDFWdhWBa+dIO+eIs1s/ljILMwn8AsiTMiJLIMVhtpFsOWKHi4ticdqjpTuvp8nGOOCFk1O+nrsuPIOPvwC3ocFhmVmhoGcMASIFBpMxDiCpq9stFwENBoDZUGstMos6oVEYPEJBS/t+R2cWNcF6RQD6SQH6bakqjuapT0EkdqA1CXuaJyLmVzmgKUJRY2btAJbukfm2TWZjDRS2QBc4EBZea0F0hUfolskFSFXOWLq9gqFgJmTvFhb2FxW+VRZ+ZUR6KMFGGCIgN6CSAaZhcFQaFujiO/tbv6AGmhALNlbgilVGDRTJiuiNRsZAFxflUGsBe/n8KNH2ROoOfGcOY+nGZDFaOaPTtsNDGFo8EPmxQ1aRU1c+dxcWR+RJcVCOUda0gGV2L4sKKQK2d/mcR9KNYJULOCsdr+aaNDEWIBRtQ0bNWMLrAJf4Mka0AANxnJJTmQoC0hKDRAUa/FrlfJ3l3WIDNU8WtXoDrC3yZlJZRmhlvV7WQySxJplYGTRqILf5PAZz/6oB1TeARasWjqOmOK0LYm7QVCLCmisi2Rq4xBREsADK8UkXVkQ30ACXQVtAoDIZpgHm/J4bZkkD8jAHQmK6BlW7wlQHq4aya5wH8AIEu7okoEFDjSy2fWRRirgq03ypHUhq4C+R8YnQaCNL8bhBVC+AxJEjhBEWHB4TcAADa4drQAAugnRrahehW8CSTHfHY8ESMnTnf+UpZYngenpZsDb9ZACSXqNwBoA5piPaIUkQL9emqkvmaSoWWTQohBYGpkhHPkM7Q6K7QNO7UrZxQ9S1QorHXYJgLIInaknDRXQWePRUOEGnQtZnXitnUUUQHnVvU/osBGOtJAPEPvcxmsOEEwuXZXXijXdgHXXQA3U3ZAC3TYOEOtF3SyD3VAH3WZOFXZUPfiZ7VYPTd2rHdadPbPWIH7ZLoHd/idCHRQGHfnRrflBXdAJHRjdHRvSnTvRHQoGhWvVndgyna/XttMsXRnufUJYcFfdXbXVObQA/ZQM3a3RIe3U9SQO/RQJ/aOOpZOO7V3GhkQOFvFeTlFSQBhBQn/XieKkfLtSA1PRgDPT7VA7Aw3DA2sHAxCrQAfeWMfdo6fWEBURg4zFg0gzg/+avRnYQ2Y8QxTkXQ0PgaXSISODYP3rYxfdQ1XTfXfQw1Q1w0/fFtxhXS/UBpuogIQm1G/QrVRZ5XwM/tw2OBOC7ROdiYI8I/ttPulNEBI/LG7ficA0qpPQsLIOEGA4oxA77f7Wo0HZow+Do7SHo/U+ECgySWg0YysVSKY1veY6nenuncgOvXHUQ0gyQ5PuQ04/ii424yM2XZ49fXQ/XX483YE+8sE+EBupyOE2iA8MWh3RULEx1lw2KQikinYfQTYPEPkOdsxPEBoN/BHkoZqSoaJByuJBoabohgKuJgIIiF3LEH+hoEcJAIQuGCyO1mgf4F0D4MgFXMoh0EXv3VYcRSWFQQYmXGgYEfVkcbSKZPFhUPBJGuWVWFJRfkpn6F5QtnyHBRjAxFrO1psJCwZMgCKsmfKFhvsh+tiaksxPxNAMxOkiVVKkiDk13DOWNOmPixED4vwDmAElwKklkOmqmaIEQsPBgQuU8G5l8qZJjLS2C8pvgnJK8LlpfrjnCeemcZQIAJgEyYB8VKZ6pLkmeRu0qSRw6aZoPwbIQWiAQKMrXcnoBIA04++e22yi9lB8fFo0JYDiSGFeQhf1weXy42VM5+JrZLBW6m8sbOMO5WuA8gXQuZOtEWDU3kAIUIQosreYQF2+8FcOYw/ISwMYJYDLnwpSqAjwNIZG1sDRhrLWab+WqAfStIEYvY8AKbuFJY/IfAK5r2YIW8qZSAvVJVxekAPefe9gJCC51U1bxQyAW+pQTU4WKbQb4yIb9jF0xudahw/Dy0uaX+n0v+3w/Sd+xQA6FuEsUsUJssJtCscJNu0BSJWu8BqJ9tkKxsvKMKH78KXulEMEWjlyeAhAzzaEqrmEfgSVOpnK8gwwQixEEEZE0Ed4sb6g1KKwiA1K/g6YnwdAMh7ItIN4BgcHRwmQaAAAbGcAegIGcGx3+mcKxwwAeusAwKx3+qx+sLQGcAwLQGkGgCQAILQBkPJwIEcAAJwnAqfkSGBwcqdZB/rrCCd/oSjrB/o5Aqc5BHAMA5AMAZBHAkCsdJSHoMAHAqcqCsdoAZAMBnBHBoB5CEcQCQBpAkAnAHpscMBZAucqdSescHoMDrBHDSfMcee0Cie9ZpD8cShHCsesemeaeMdEfI4HpHB/oHrhdHDGfOrrACCeescZB8dpASdHAHAHrJfrBud2didZC6e5dwdpACCnBle0BmcZD+gMBpBmcSczCZcnBnBechdhe0BZABhqc5BifddEcMAqcqfrBmd/oScqeBdoAAYHo5ACA5A5BnArcZA1doAufrBZBZeZescqc1cup+dQBpBHCqe7dnAucnd2c2dZC0ACBifZBA+A9SdoD3fOrxfyesdpe5d5f+foQkdkcUeDXUe0DUoPiadAA== -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=united-manufacturing-hub/united-manufacturing-hub&utm_content=2038):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: Scarjit
created_at: 2025-05-14T11:10:35Z
body: > Should we also read the AllowInsecureTLS from the env vars when executing docker run?

I think setting it via config is good enough, as this is already a last resort feature.
author_association: CONTRIBUTOR