Received: from mail.netlandish.com (mail.netlandish.com [174.136.98.166])
	by code.netlandish.com (Postfix) with ESMTP id 6761244A
	for <~netlandish/links-dev@lists.code.netlandish.com>; Sat, 25 Oct 2025 14:04:16 +0000 (UTC)
Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=74.125.224.46; helo=mail-yx1-f46.google.com; envelope-from=peter@netlandish.com; receiver=<UNKNOWN> 
Authentication-Results: mail.netlandish.com;
	dkim=pass (1024-bit key; unprotected) header.d=netlandish.com header.i=@netlandish.com header.b=QVG16/So
Received: from mail-yx1-f46.google.com (mail-yx1-f46.google.com [74.125.224.46])
	by mail.netlandish.com (Postfix) with ESMTP id 3F8F11D6437
	for <~netlandish/links-dev@lists.code.netlandish.com>; Sat, 25 Oct 2025 14:05:36 +0000 (UTC)
Received: by mail-yx1-f46.google.com with SMTP id 956f58d0204a3-63e393c4a8aso3706864d50.2
        for <~netlandish/links-dev@lists.code.netlandish.com>; Sat, 25 Oct 2025 07:05:36 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=netlandish.com; s=google; t=1761401135; x=1762005935; darn=lists.code.netlandish.com;
        h=content-transfer-encoding:mime-version:message-id:date:subject:cc
         :to:from:from:to:cc:subject:date:message-id:reply-to;
        bh=sev2ldWEmU12DUJGrjGf7osN/9vWom55Q2RcuPVqsTo=;
        b=QVG16/SoRcI9Zg7C5l5KE7b9LgTeJGnNHGQ8/C99ARvdaQCVoLIuE09mFrUc8gdn+7
         tUPREzt54SG6ZjMerLt+uDjPO1v0zYEKI/4WU4isb8CTnaTDwudwihKa7SHLrADPT5g0
         MRDx1suw4rXCRj2vXU86n6lqhD+L2LGuk3HbU=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20230601; t=1761401135; x=1762005935;
        h=content-transfer-encoding:mime-version:message-id:date:subject:cc
         :to:from:x-gm-message-state:from:to:cc:subject:date:message-id
         :reply-to;
        bh=sev2ldWEmU12DUJGrjGf7osN/9vWom55Q2RcuPVqsTo=;
        b=sdJiLa6TkI+IRs+SYG5k2a8O3D/F66Vq+DSj+ufN/tFwt2tPmi2xmleWxaq3HO2dVF
         ABujQ4fzDj/XbQDDuvxJ4UmlN+mGBzWosSEahCd2rpQSBhT660PfyrIN8Nxxq8AlTzj2
         Jkqxjx7UDR31P28bN338VQmA9VP/Nsy04+EH2jgfFFb4DaBBPhYEpmIw7hKDXBN78QtO
         TzwTR5Craa2Iro1W4K0Qvz7JWVG4rss5x3AXadlOnOX5jcM8QGT4Hxl7FTfSyUPOBpnO
         P4w/1K/OG9TMhAW/K3Sn+uGA6EjxeNMNZAl9DXx8JJGEZBsGIaffmXsUSyw5zMhMluxN
         JAMQ==
X-Gm-Message-State: AOJu0YwYkd9twIi9TrYs2gyKZlS/MLqQ9Aq8V+Sc0riU0fBcJnZQ2tRK
	CUYWY4i/I1+1yqKZ57GlnJsXl2mtNOwMesTnbMi2GDP9+fCU1JUnwod+dEMGk6ZvPxszcfLmU8E
	zgxk5qfMROw==
X-Gm-Gg: ASbGnctoccOm40+FrugRVprblBgSZW8PszBQs33WspzX63HziCVaT/cabzDUoHtrQOh
	R2CnKvN2i65uwbAmWa2dvkDj2ftiOP7FAtZp771WtPMtUIclzGZ6AHcBvSxk53smxVhg3AxlGlq
	LIdkQAzPLVHmSOWtiLX5x5hKjJ3DlCbZCCqx21NKC+N4RYWZ60aOKJOi2iAr3k/1SNdOLYQcnWd
	mRSgb+dcSp1bJWv4/rEmr9ncfFOuXMW/NPVxRcnjWdbOpfvUAhhcRZRFZl0f0yNKNcNapF8rqKZ
	M/0mc63Ho7jkeqIum74DFgPeX5M4LhImJu8dii+xDv9xOaAHFpc7J7fbVZ/CfRqZSGVwbY5ROF8
	lsD6PNtcGCh5GbYnKpSP0IxNh20Ti7jH63Zp1KrzYHYOYYrUiPoJiSihIg3TwVTSBHcXDqxcv12
	A0xf9BNhqtMgY=
X-Google-Smtp-Source: AGHT+IHAAhouxJMMY5YYLl5fwqSLZwFXaq2J7pyU++hgaezhvP064Lydc9oSn5D4LJflyuPJqqVGBw==
X-Received: by 2002:a05:690e:130d:b0:63e:21f9:e1f0 with SMTP id 956f58d0204a3-63e21f9e9e2mr19120516d50.58.1761401135165;
        Sat, 25 Oct 2025 07:05:35 -0700 (PDT)
Received: from localhost ([2803:2d60:1107:87f:c401:aa1e:1539:8e5a])
        by smtp.gmail.com with UTF8SMTPSA id 956f58d0204a3-63f4c2e2fb4sm613594d50.0.2025.10.25.07.05.34
        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
        Sat, 25 Oct 2025 07:05:34 -0700 (PDT)
From: Peter Sanchez <peter@netlandish.com>
To: ~netlandish/links-dev@lists.code.netlandish.com
Cc: Peter Sanchez <peter@netlandish.com>
Subject: [PATCH links] Run modernizer on codebase.
Date: Sat, 25 Oct 2025 08:05:30 -0600
Message-ID: <20251025140532.9956-1-peter@netlandish.com>
X-Mailer: git-send-email 2.49.1
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit

---
 api/api_test.go            | 26 +++++++++++++-------------
 domain/integration_test.go | 30 +++++++++++++++---------------
 slack/commands.go          |  2 +-
 slack/routes.go            |  2 +-
 4 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/api/api_test.go b/api/api_test.go
index 0dabe06..465c019 100644
--- a/api/api_test.go
+++ b/api/api_test.go
@@ -219,7 +219,7 @@ func TestDirective(t *testing.T) {
 			User:    user3,
 		}
 
-		type GraphQLResponse struct{
+		type GraphQLResponse struct {
 			Org models.Organization `json:"addOrganization"`
 		}
 		var result GraphQLResponse
@@ -2813,7 +2813,7 @@ func TestAPI(t *testing.T) {
 				return err
 			}
 
-			for i := 0; i < 2; i++ {
+			for i := range 2 {
 				baseURL := models.BaseURL{
 					URL:        fmt.Sprintf("https://hidden.com/%d", i),
 					Visibility: models.VisibilityPublic,
@@ -2821,7 +2821,7 @@ func TestAPI(t *testing.T) {
 				if err := baseURL.Store(dbCtx); err != nil {
 					return fmt.Errorf("failed to store hidden base URL %d: %w", i, err)
 				}
-				
+
 				link := models.OrgLink{
 					Title:      fmt.Sprintf("Hidden Link %d", i),
 					URL:        fmt.Sprintf("https://hidden.com/%d", i),
@@ -2836,7 +2836,7 @@ func TestAPI(t *testing.T) {
 			}
 
 			// Add 5 links to forced hidden org - it should still stay hidden
-			for i := 0; i < 5; i++ {
+			for i := range 5 {
 				baseURL := models.BaseURL{
 					URL:        fmt.Sprintf("https://forced.com/%d", i),
 					Visibility: models.VisibilityPublic,
@@ -2844,7 +2844,7 @@ func TestAPI(t *testing.T) {
 				if err := baseURL.Store(dbCtx); err != nil {
 					return fmt.Errorf("failed to store forced base URL %d: %w", i, err)
 				}
-				
+
 				link := models.OrgLink{
 					Title:      fmt.Sprintf("Forced Link %d", i),
 					URL:        fmt.Sprintf("https://forced.com/%d", i),
@@ -2858,7 +2858,7 @@ func TestAPI(t *testing.T) {
 				}
 			}
 
-			for i := 0; i < 5; i++ {
+			for i := range 5 {
 				baseURL := models.BaseURL{
 					URL:        fmt.Sprintf("https://public.com/%d", i),
 					Visibility: models.VisibilityPublic,
@@ -2866,7 +2866,7 @@ func TestAPI(t *testing.T) {
 				if err := baseURL.Store(dbCtx); err != nil {
 					return fmt.Errorf("failed to store public base URL %d: %w", i, err)
 				}
-				
+
 				link := models.OrgLink{
 					Title:      fmt.Sprintf("Public Link %d", i),
 					URL:        fmt.Sprintf("https://public.com/%d", i),
@@ -2887,7 +2887,7 @@ func TestAPI(t *testing.T) {
 			if err := baseURL.Store(dbCtx); err != nil {
 				return fmt.Errorf("failed to store personal base URL: %w", err)
 			}
-			
+
 			link := models.OrgLink{
 				Title:      "Personal Link",
 				URL:        "https://personal.com",
@@ -2977,11 +2977,11 @@ func TestAPI(t *testing.T) {
 		op.Var("orgSlug", "personal-org")
 		err := links.Execute(ctx, op, &result)
 		c.NoError(err)
-		
+
 		// Should return all tags for personal-org
 		// At minimum we have 5 from test data, but previous tests may create more
 		c.GreaterOrEqual(len(result.GetTags.Result), 5)
-		
+
 		// Verify expected test data tags are present
 		tagNames := make(map[string]bool)
 		for _, tag := range result.GetTags.Result {
@@ -3018,7 +3018,7 @@ func TestAPI(t *testing.T) {
 		linksOp.Var("service", "LINKS")
 		err := links.Execute(ctx, linksOp, &linksResult)
 		c.NoError(err)
-		
+
 		// Should return at least 3 tags for LINKS service (may have more from previous tests)
 		c.GreaterOrEqual(len(linksResult.GetTags.Result), 3)
 		linksTags := make(map[string]bool)
@@ -3045,7 +3045,7 @@ func TestAPI(t *testing.T) {
 		shortOp.Var("service", "SHORT")
 		err = links.Execute(ctx, shortOp, &shortResult)
 		c.NoError(err)
-		
+
 		// Should return at least 3 tags for SHORT service (may have more from previous tests)
 		c.GreaterOrEqual(len(shortResult.GetTags.Result), 3)
 		shortTags := make(map[string]bool)
@@ -3072,7 +3072,7 @@ func TestAPI(t *testing.T) {
 		listOp.Var("service", "LIST")
 		err = links.Execute(ctx, listOp, &listResult)
 		c.NoError(err)
-		
+
 		// Should return at least 2 tags for LIST service (may have more from previous tests)
 		c.GreaterOrEqual(len(listResult.GetTags.Result), 2)
 		listTags := make(map[string]bool)
diff --git a/domain/integration_test.go b/domain/integration_test.go
index 6f671d7..a05bb1e 100644
--- a/domain/integration_test.go
+++ b/domain/integration_test.go
@@ -56,7 +56,7 @@ func TestDomainValidationContextCancellation(t *testing.T) {
 	// Set up basic test data - create a test domain
 	// First try to delete any existing test domain
 	db.Exec("DELETE FROM domains WHERE lookup_name = 'test.example.com'")
-	
+
 	_, err := db.Exec(`
 		INSERT INTO domains (lookup_name, name, service, status, level, is_active)
 		VALUES ($1, $2, $3, $4, $5, $6)
@@ -78,7 +78,7 @@ func TestDomainValidationContextCancellation(t *testing.T) {
 	cfg := &config.Config{Debug: true}
 	server.New(e, db, cfg).Initialize()
 
-	// Add middleware in same order as production  
+	// Add middleware in same order as production
 	e.Use(
 		// Custom context middleware (matches server.DefaultMiddlewareWithConfig)
 		func(next echo.HandlerFunc) echo.HandlerFunc {
@@ -87,15 +87,15 @@ func TestDomainValidationContextCancellation(t *testing.T) {
 				return next(ctx)
 			}
 		},
-		database.DBIMiddleware(db),                               // DBI must be first
-		func(next echo.HandlerFunc) echo.HandlerFunc {           // Add timezone context
+		database.DBIMiddleware(db), // DBI must be first
+		func(next echo.HandlerFunc) echo.HandlerFunc { // Add timezone context
 			return func(c echo.Context) error {
 				ctx := timezone.Context(c.Request().Context(), "UTC")
 				c.SetRequest(c.Request().WithContext(ctx))
 				return next(c)
 			}
 		},
-		DomainContext(models.DomainServiceLinks),                 // Domain validation
+		DomainContext(models.DomainServiceLinks), // Domain validation
 	)
 
 	// Simple handler that should never be reached due to domain validation failure
@@ -106,7 +106,7 @@ func TestDomainValidationContextCancellation(t *testing.T) {
 	// Test 1: Context cancellation during domain validation
 	req := httptest.NewRequest(http.MethodGet, "/test", nil)
 	req.Host = "test.example.com" // Valid domain that exists in DB
-	
+
 	// Create cancellable context
 	ctx, cancel := context.WithCancel(req.Context())
 	req = req.WithContext(ctx)
@@ -137,18 +137,18 @@ func TestDomainValidationContextCancellation(t *testing.T) {
 	// Verify no connection leak occurred - this is the critical test
 	statsAfter := db.Stats()
 	if statsAfter.OpenConnections > statsBefore.OpenConnections {
-		t.Errorf("Connection leak detected after context cancellation: before=%d, after=%d", 
+		t.Errorf("Connection leak detected after context cancellation: before=%d, after=%d",
 			statsBefore.OpenConnections, statsAfter.OpenConnections)
 	}
 
-	t.Logf("Context cancellation test - Connection stats before: %d, after: %d", 
+	t.Logf("Context cancellation test - Connection stats before: %d, after: %d",
 		statsBefore.OpenConnections, statsAfter.OpenConnections)
 
 	// Test 2: Multiple rapid cancellations (stress test)
-	for i := 0; i < 5; i++ {
+	for range 5 {
 		req := httptest.NewRequest(http.MethodGet, "/test", nil)
 		req.Host = "test.example.com"
-		
+
 		ctx, cancel := context.WithCancel(req.Context())
 		req = req.WithContext(ctx)
 		rec := httptest.NewRecorder()
@@ -165,13 +165,13 @@ func TestDomainValidationContextCancellation(t *testing.T) {
 	// Final connection check after stress test
 	time.Sleep(500 * time.Millisecond)
 	statsFinal := db.Stats()
-	
+
 	if statsFinal.OpenConnections > statsBefore.OpenConnections+2 { // Allow some tolerance
-		t.Errorf("Connection leak detected after stress test: before=%d, final=%d", 
+		t.Errorf("Connection leak detected after stress test: before=%d, final=%d",
 			statsBefore.OpenConnections, statsFinal.OpenConnections)
 	}
 
-	t.Logf("Stress test complete - Connection stats before: %d, final: %d", 
+	t.Logf("Stress test complete - Connection stats before: %d, final: %d",
 		statsBefore.OpenConnections, statsFinal.OpenConnections)
 }
 
@@ -189,7 +189,7 @@ func TestValidDomainWithContextCancellation(t *testing.T) {
 
 	// Call ValidDomain with cancelled context
 	_, err := ValidDomain(ctx, "test.example.com", models.DomainServiceLinks, false)
-	
+
 	// Should get context cancelled error
 	if err == nil {
 		t.Error("Expected error due to context cancellation")
@@ -197,4 +197,4 @@ func TestValidDomainWithContextCancellation(t *testing.T) {
 
 	// The key is that this doesn't leak connections
 	// The WithTx fix should handle the rollback automatically
-}
\ No newline at end of file
+}
diff --git a/slack/commands.go b/slack/commands.go
index e7282a9..3dea6fc 100644
--- a/slack/commands.go
+++ b/slack/commands.go
@@ -404,7 +404,7 @@ func sendInstructionLink(c echo.Context, slackConn *models.SlackConnection, url,
 	block := SlackBlock{}
 	apiURL := "https://slack.com/api/chat.postMessage"
 	msg := lt.Translate("Please link your slack user with link: %s", url)
-	requestBody := []byte(fmt.Sprintf(`{"channel": "%s", "text": "%s"}`, slackUser, msg))
+	requestBody := fmt.Appendf(nil, `{"channel": "%s", "text": "%s"}`, slackUser, msg)
 	req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(requestBody))
 	if err != nil {
 		return nil, err
diff --git a/slack/routes.go b/slack/routes.go
index 879f132..49bc4d3 100644
--- a/slack/routes.go
+++ b/slack/routes.go
@@ -181,7 +181,7 @@ func (s *Service) SlashCommand(c echo.Context) error {
 	}
 	timestamp := req.Header.Get("X-Slack-Request-Timestamp")
 	hasher := hmac.New(sha256.New, []byte(secret))
-	hasher.Write([]byte(fmt.Sprintf("%s:%s:%s", version, timestamp, string(body))))
+	hasher.Write(fmt.Appendf(nil, "%s:%s:%s", version, timestamp, string(body)))
 	hashString := fmt.Sprintf("%s=%s", version, hex.EncodeToString(hasher.Sum(nil)))
 	if hashString != req.Header.Get("X-Slack-Signature") {
 		return fmt.Errorf("Invalid signature")
-- 
2.49.1

