diff --git a/aggregator-agent/cmd/agent/main.go b/aggregator-agent/cmd/agent/main.go index 6912c35..db876e5 100644 --- a/aggregator-agent/cmd/agent/main.go +++ b/aggregator-agent/cmd/agent/main.go @@ -476,7 +476,7 @@ func registerAgent(cfg *config.Config, serverURL string) error { log.Printf("Agent will not be able to verify update signatures") // Don't fail registration - key can be fetched later } else { - log.Println("✓ Server public key cached successfully") + log.Println("[INFO] [agent] [crypto] server_public_key_cached") } return nil @@ -491,11 +491,11 @@ func fetchAndCachePublicKey(serverURL string) error { // renewTokenIfNeeded handles 401 errors by renewing the agent token using refresh token func renewTokenIfNeeded(apiClient *client.Client, cfg *config.Config, err error) (*client.Client, error) { if err != nil && strings.Contains(err.Error(), "401 Unauthorized") { - log.Printf("🔄 Access token expired - attempting renewal with refresh token...") + log.Printf("[INFO] [agent] [auth] access_token_expired attempting_renewal") // Check if we have a refresh token if cfg.RefreshToken == "" { - log.Printf("❌ No refresh token available - re-registration required") + log.Printf("[ERROR] [agent] [auth] no_refresh_token re-registration_required") return nil, fmt.Errorf("refresh token missing - please re-register agent") } @@ -504,20 +504,20 @@ func renewTokenIfNeeded(apiClient *client.Client, cfg *config.Config, err error) // Attempt to renew access token using refresh token if err := tempClient.RenewToken(cfg.AgentID, cfg.RefreshToken, version.Version); err != nil { - log.Printf("❌ Refresh token renewal failed: %v", err) - log.Printf("💡 Refresh token may be expired (>90 days) - re-registration required") + log.Printf("[ERROR] [agent] [auth] refresh_token_renewal_failed error=%v", err) + log.Printf("[INFO] [agent] [auth] refresh_token_may_be_expired re-registration_required") return nil, fmt.Errorf("refresh token renewal failed: %w - please re-register agent", err) } - // Update config with new access token (agent ID and refresh token stay the same!) + // Update config with new access token cfg.Token = tempClient.GetToken() // Save updated config if err := cfg.Save(constants.GetAgentConfigPath()); err != nil { - log.Printf("⚠️ Warning: Failed to save renewed access token: %v", err) + log.Printf("[WARNING] [agent] [auth] save_renewed_token_failed error=%v", err) } - log.Printf("✅ Access token renewed successfully - agent ID maintained: %s", cfg.AgentID) + log.Printf("[INFO] [agent] [auth] access_token_renewed agent_id=%s", cfg.AgentID) return tempClient, nil } @@ -841,7 +841,7 @@ func runAgent(cfg *config.Config) error { log.Printf("Failed to report system info: %v\n", err) } else { lastSystemInfoUpdate = time.Now() - log.Printf("✓ System information updated\n") + log.Printf("[INFO] [agent] [installer]System information updated\n") } } @@ -1396,12 +1396,12 @@ func handleInstallUpdates(apiClient *client.Client, cfg *config.Config, ackTrack } if result.Success { - log.Printf("✓ Installation completed successfully in %d seconds\n", result.DurationSeconds) + log.Printf("[INFO] [agent] [installer]Installation completed successfully in %d seconds\n", result.DurationSeconds) if len(result.PackagesInstalled) > 0 { log.Printf(" Packages installed: %v\n", result.PackagesInstalled) } } else { - log.Printf("✗ Installation failed after %d seconds\n", result.DurationSeconds) + log.Printf("[ERROR] [agent] [installer]Installation failed after %d seconds\n", result.DurationSeconds) log.Printf(" Error: %s\n", result.ErrorMessage) } @@ -1510,14 +1510,14 @@ func handleDryRunUpdate(apiClient *client.Client, cfg *config.Config, ackTracker } if result.Success { - log.Printf("✓ Dry run completed successfully in %d seconds\n", result.DurationSeconds) + log.Printf("[INFO] [agent] [installer]Dry run completed successfully in %d seconds\n", result.DurationSeconds) if len(result.Dependencies) > 0 { log.Printf(" Dependencies found: %v\n", result.Dependencies) } else { log.Printf(" No additional dependencies found\n") } } else { - log.Printf("✗ Dry run failed after %d seconds\n", result.DurationSeconds) + log.Printf("[ERROR] [agent] [installer]Dry run failed after %d seconds\n", result.DurationSeconds) log.Printf(" Error: %s\n", result.ErrorMessage) } @@ -1623,12 +1623,12 @@ func handleConfirmDependencies(apiClient *client.Client, cfg *config.Config, ack } if result.Success { - log.Printf("✓ Installation with dependencies completed successfully in %d seconds\n", result.DurationSeconds) + log.Printf("[INFO] [agent] [installer]Installation with dependencies completed successfully in %d seconds\n", result.DurationSeconds) if len(result.PackagesInstalled) > 0 { log.Printf(" Packages installed: %v\n", result.PackagesInstalled) } } else { - log.Printf("✗ Installation with dependencies failed after %d seconds\n", result.DurationSeconds) + log.Printf("[ERROR] [agent] [installer]Installation with dependencies failed after %d seconds\n", result.DurationSeconds) log.Printf(" Error: %s\n", result.ErrorMessage) } diff --git a/aggregator-agent/cmd/ethos_emoji_test.go b/aggregator-agent/cmd/ethos_emoji_test.go index 7f3df7f..d728a74 100644 --- a/aggregator-agent/cmd/ethos_emoji_test.go +++ b/aggregator-agent/cmd/ethos_emoji_test.go @@ -1,9 +1,8 @@ package main -// ethos_emoji_test.go — Pre-fix tests for emoji in agent main.go log statements. -// D-2: main.go has emoji in token renewal and install result log paths. -// EXCLUDES: registration CLI output (lines 294-322) and startup banner -// (lines 691-697) which are intentional user-facing output. +// ethos_emoji_test.go — Tests for emoji in agent main.go log statements. +// D-2 FIXED: emoji removed from token renewal and install result log paths. +// EXCLUDES: registration CLI output and startup banner (exempt). import ( "os" @@ -20,34 +19,46 @@ func hasEmojiRune(s string) bool { return false } +// isExemptLine checks if a line number falls in an exempt range. +// Exempt ranges are user-facing CLI output (registration, startup banner). +func isExemptLine(lineNum int) bool { + // Registration CLI output: ~lines 294-322 + if lineNum >= 290 && lineNum <= 330 { + return true + } + // Startup banner: ~lines 691-700 + if lineNum >= 685 && lineNum <= 705 { + return true + } + return false +} + func TestMainGoHasEmojiInLogStatements(t *testing.T) { - // D-2: main.go has emoji in log statements for token renewal - // and install results. These are NOT user-facing CLI output. + // POST-FIX: No emoji in non-exempt log statements. content, err := os.ReadFile("agent/main.go") if err != nil { t.Fatalf("failed to read agent/main.go: %v", err) } - src := string(content) - lines := strings.Split(src, "\n") + lines := strings.Split(string(content), "\n") - // Count emoji in log.Printf lines only (not fmt.Printf CLI output) emojiLogCount := 0 - for _, line := range lines { + for i, line := range lines { + if isExemptLine(i + 1) { + continue + } trimmed := strings.TrimSpace(line) - if strings.Contains(trimmed, "log.Printf") && hasEmojiRune(trimmed) { - emojiLogCount++ - } - if strings.Contains(trimmed, "log.Println") && hasEmojiRune(trimmed) { + isLog := strings.Contains(trimmed, "log.Printf") || strings.Contains(trimmed, "log.Println") + if isLog && hasEmojiRune(trimmed) { emojiLogCount++ } } - if emojiLogCount == 0 { - t.Error("[ERROR] [agent] [main] D-2 already fixed: no emoji in main.go log statements") + if emojiLogCount > 0 { + t.Errorf("[ERROR] [agent] [main] D-2 NOT FIXED: %d non-exempt log statements with emoji", emojiLogCount) } - t.Logf("[INFO] [agent] [main] D-2 confirmed: %d log.Printf/Println with emoji in main.go", emojiLogCount) + t.Log("[INFO] [agent] [main] D-2 FIXED: no emoji in non-exempt log statements") } func TestMainGoLogStatementsHaveNoEmoji(t *testing.T) { @@ -56,14 +67,16 @@ func TestMainGoLogStatementsHaveNoEmoji(t *testing.T) { t.Fatalf("failed to read agent/main.go: %v", err) } - src := string(content) - lines := strings.Split(src, "\n") + lines := strings.Split(string(content), "\n") for i, line := range lines { + if isExemptLine(i + 1) { + continue + } trimmed := strings.TrimSpace(line) isLog := strings.Contains(trimmed, "log.Printf") || strings.Contains(trimmed, "log.Println") if isLog && hasEmojiRune(trimmed) { - t.Errorf("[ERROR] [agent] [main] emoji in log at line %d", i+1) + t.Errorf("[ERROR] [agent] [main] emoji in non-exempt log at line %d", i+1) } } } diff --git a/aggregator-agent/internal/migration/ethos_emoji_test.go b/aggregator-agent/internal/migration/ethos_emoji_test.go index 0c5b672..9e03ef1 100644 --- a/aggregator-agent/internal/migration/ethos_emoji_test.go +++ b/aggregator-agent/internal/migration/ethos_emoji_test.go @@ -36,11 +36,11 @@ func TestMigrationExecutorHasEmojiInOutput(t *testing.T) { } } - if emojiCount == 0 { - t.Error("[ERROR] [agent] [migration] D-2 already fixed: no emoji in executor.go") + if emojiCount > 0 { + t.Errorf("[ERROR] [agent] [migration] D-2 NOT FIXED: %d output lines with emoji", emojiCount) } - t.Logf("[INFO] [agent] [migration] D-2 confirmed: %d output lines with emoji in executor.go", emojiCount) + t.Log("[INFO] [agent] [migration] D-2 FIXED: no emoji in executor.go") } func TestMigrationExecutorHasNoEmojiInOutput(t *testing.T) { diff --git a/aggregator-agent/internal/migration/executor.go b/aggregator-agent/internal/migration/executor.go index 6150534..1fd8fc2 100644 --- a/aggregator-agent/internal/migration/executor.go +++ b/aggregator-agent/internal/migration/executor.go @@ -340,7 +340,7 @@ func (e *MigrationExecutor) validateMigration() error { } } - fmt.Printf("[MIGRATION] ✅ Migration validation successful\n") + fmt.Printf("[INFO] [agent] [migration] validation_successful\n") return nil } @@ -501,9 +501,9 @@ func (e *MigrationExecutor) completeMigration(success bool, err error) (*Migrati } if success { - fmt.Printf("[MIGRATION] ✅ Migration completed successfully in %v\n", e.result.Duration) + fmt.Printf("[INFO] [agent] [migration] completed duration=%v\n", e.result.Duration) if e.result.RollbackAvailable { - fmt.Printf("[MIGRATION] 📦 Rollback available at: %s\n", e.result.BackupPath) + fmt.Printf("[INFO] [agent] [migration] rollback_available path=%s\n", e.result.BackupPath) } // Clean up old directories after successful migration @@ -511,7 +511,7 @@ func (e *MigrationExecutor) completeMigration(success bool, err error) (*Migrati fmt.Printf("[MIGRATION] Warning: Failed to cleanup old directories: %v\n", err) } } else { - fmt.Printf("[MIGRATION] ❌ Migration failed after %v\n", e.result.Duration) + fmt.Printf("[ERROR] [agent] [migration] failed duration=%v\n", e.result.Duration) if len(e.result.Errors) > 0 { for _, errMsg := range e.result.Errors { fmt.Printf("[MIGRATION] Error: %s\n", errMsg) diff --git a/aggregator-server/internal/api/handlers/agent_updates.go b/aggregator-server/internal/api/handlers/agent_updates.go index 2ffc06c..cb062b6 100644 --- a/aggregator-server/internal/api/handlers/agent_updates.go +++ b/aggregator-server/internal/api/handlers/agent_updates.go @@ -401,7 +401,7 @@ func (h *AgentUpdateHandler) BulkUpdateAgents(c *gin.Context) { log.Printf("Warning: Failed to log bulk agent update to system_events: %v", err) } - log.Printf("✅ Bulk update initiated for %s: %s (%s)", agent.Hostname, req.Version, req.Platform) + log.Printf("[INFO] [server] [updates]Bulk update initiated for %s: %s (%s)", agent.Hostname, req.Version, req.Platform) } response := gin.H{ @@ -492,7 +492,7 @@ func (h *AgentUpdateHandler) SignUpdatePackage(c *gin.Context) { return } - log.Printf("✅ Update package signed and saved: %s %s/%s (ID: %s)", + log.Printf("[INFO] [server] [updates]Update package signed and saved: %s %s/%s (ID: %s)", pkg.Version, pkg.Platform, pkg.Architecture, pkg.ID) c.JSON(http.StatusOK, gin.H{ diff --git a/aggregator-server/internal/api/handlers/agents.go b/aggregator-server/internal/api/handlers/agents.go index 3603383..1bc4648 100644 --- a/aggregator-server/internal/api/handlers/agents.go +++ b/aggregator-server/internal/api/handlers/agents.go @@ -314,10 +314,10 @@ func (h *AgentHandler) GetCommands(c *gin.Context) { if err == nil { // Log version check if updateAvailable { - log.Printf("🔄 Agent %s (%s) version %s has update available: %s", + log.Printf("[INFO] [server] [agents]Agent %s (%s) version %s has update available: %s", agent.Hostname, agentID, metrics.Version, h.latestAgentVersion) } else { - log.Printf("✅ Agent %s (%s) version %s is up to date", + log.Printf("[INFO] [server] [agents]Agent %s (%s) version %s is up to date", agent.Hostname, agentID, metrics.Version) } @@ -439,10 +439,10 @@ func (h *AgentHandler) GetCommands(c *gin.Context) { } else { // Log version check for agent without version reporting if updateAvailable { - log.Printf("🔄 Agent %s (%s) stored version %s has update available: %s", + log.Printf("[INFO] [server] [agents]Agent %s (%s) stored version %s has update available: %s", agent.Hostname, agentID, agent.CurrentVersion, h.latestAgentVersion) } else { - log.Printf("✅ Agent %s (%s) stored version %s is up to date", + log.Printf("[INFO] [server] [agents]Agent %s (%s) stored version %s is up to date", agent.Hostname, agentID, agent.CurrentVersion) } } @@ -1118,7 +1118,7 @@ func (h *AgentHandler) RenewToken(c *gin.Context) { return } - log.Printf("✅ Token renewed successfully for agent %s (%s)", agent.Hostname, req.AgentID) + log.Printf("[INFO] [server] [agents]Token renewed successfully for agent %s (%s)", agent.Hostname, req.AgentID) // Return new access token response := models.TokenRenewalResponse{ @@ -1300,7 +1300,7 @@ func (h *AgentHandler) ReportSystemInfo(c *gin.Context) { return } - log.Printf("✅ System info updated for agent %s (%s): CPU=%s, Cores=%d, Memory=%dMB", + log.Printf("[INFO] [server] [agents]System info updated for agent %s (%s): CPU=%s, Cores=%d, Memory=%dMB", agent.Hostname, agentID, req.CPUModel, req.CPUCores, req.MemoryTotal/1024/1024) c.JSON(http.StatusOK, gin.H{"message": "system info updated successfully"}) @@ -1328,19 +1328,19 @@ func (h *AgentHandler) EnableRapidPollingMode(agentID uuid.UUID, durationMinutes if currentUntil, err := time.Parse(time.RFC3339, untilStr); err == nil { // If current heartbeat expires later than the new duration, keep the longer duration if currentUntil.After(newRapidPollingUntil) { - log.Printf("💓 Heartbeat already active for agent %s (%s), keeping longer duration (expires: %s)", + log.Printf("[INFO] [server] [agents] heartbeatHeartbeat already active for agent %s (%s), keeping longer duration (expires: %s)", agent.Hostname, agentID, currentUntil.Format(time.RFC3339)) return nil } // Otherwise extend the heartbeat - log.Printf("💓 Extending heartbeat for agent %s (%s) from %s to %s", + log.Printf("[INFO] [server] [agents] heartbeatExtending heartbeat for agent %s (%s) from %s to %s", agent.Hostname, agentID, currentUntil.Format(time.RFC3339), newRapidPollingUntil.Format(time.RFC3339)) } } } else { - log.Printf("💓 Enabling heartbeat mode for agent %s (%s) for %d minutes", + log.Printf("[INFO] [server] [agents] heartbeatEnabling heartbeat mode for agent %s (%s) for %d minutes", agent.Hostname, agentID, durationMinutes) } @@ -1406,7 +1406,7 @@ func (h *AgentHandler) SetRapidPollingMode(c *gin.Context) { duration = req.DurationMinutes } - log.Printf("🚀 Rapid polling mode %s for agent %s (%s) for %d minutes", + log.Printf("[INFO] [server] [agents]Rapid polling mode %s for agent %s (%s) for %d minutes", status, agent.Hostname, agentID, duration) c.JSON(http.StatusOK, gin.H{ diff --git a/aggregator-server/internal/api/handlers/docker_reports.go b/aggregator-server/internal/api/handlers/docker_reports.go index 1fa0a09..fe8470d 100644 --- a/aggregator-server/internal/api/handlers/docker_reports.go +++ b/aggregator-server/internal/api/handlers/docker_reports.go @@ -1,7 +1,7 @@ package handlers import ( - "fmt" + "log" "net/http" "strconv" "strings" @@ -94,7 +94,7 @@ func (h *DockerReportsHandler) ReportDockerImages(c *gin.Context) { } if err := h.commandQueries.MarkCommandCompleted(commandID, result); err != nil { - fmt.Printf("Warning: Failed to mark docker command %s as completed: %v\n", commandID, err) + log.Printf("[WARNING] [server] [docker] mark_command_completed_failed command_id=%s error=%v", commandID, err) } c.JSON(http.StatusOK, gin.H{ diff --git a/aggregator-server/internal/api/handlers/ethos_emoji_test.go b/aggregator-server/internal/api/handlers/ethos_emoji_test.go index dd16251..b707107 100644 --- a/aggregator-server/internal/api/handlers/ethos_emoji_test.go +++ b/aggregator-server/internal/api/handlers/ethos_emoji_test.go @@ -41,11 +41,11 @@ func TestAgentsHandlerHasEmojiInLogs(t *testing.T) { t.Fatalf("failed to read agents.go: %v", err) } - if count == 0 { - t.Error("[ERROR] [server] [handlers] D-2 already fixed: no emoji in agents.go logs") + if count > 0 { + t.Errorf("[ERROR] [server] [handlers] D-2 NOT FIXED: %d emoji log lines in agents.go", count) } - t.Logf("[INFO] [server] [handlers] D-2 confirmed: %d log statements with emoji in agents.go", count) + t.Log("[INFO] [server] [handlers] D-2 FIXED: no emoji in agents.go logs") } func TestAgentsHandlerHasNoEmojiInLogs(t *testing.T) { @@ -73,11 +73,11 @@ func TestUpdateHandlersHaveEmojiInLogs(t *testing.T) { total += count } - if total == 0 { - t.Error("[ERROR] [server] [handlers] D-2 already fixed: no emoji in update handler logs") + if total > 0 { + t.Errorf("[ERROR] [server] [handlers] D-2 NOT FIXED: %d emoji log lines in update handlers", total) } - t.Logf("[INFO] [server] [handlers] D-2 confirmed: %d emoji log lines across update handlers", total) + t.Log("[INFO] [server] [handlers] D-2 FIXED: no emoji in update handler logs") } func TestUpdateHandlersHaveNoEmojiInLogs(t *testing.T) { diff --git a/aggregator-server/internal/api/handlers/ethos_logging_test.go b/aggregator-server/internal/api/handlers/ethos_logging_test.go index b9ce135..affa970 100644 --- a/aggregator-server/internal/api/handlers/ethos_logging_test.go +++ b/aggregator-server/internal/api/handlers/ethos_logging_test.go @@ -26,11 +26,11 @@ func TestHandlerFilesUseFmtPrintfForLogging(t *testing.T) { total += count } - if total == 0 { - t.Error("[ERROR] [server] [handlers] D-2 already fixed: no fmt.Printf in handler logs") + if total > 0 { + t.Errorf("[ERROR] [server] [handlers] D-2 NOT FIXED: %d fmt.Printf in handler logs", total) } - t.Logf("[INFO] [server] [handlers] D-2 confirmed: %d fmt.Printf in docker_reports.go + metrics.go", total) + t.Log("[INFO] [server] [handlers] D-2 FIXED: no fmt.Printf in handler logs") } func TestHandlerFilesUseStructuredLogging(t *testing.T) { diff --git a/aggregator-server/internal/api/handlers/metrics.go b/aggregator-server/internal/api/handlers/metrics.go index c79c9c4..2dfad47 100644 --- a/aggregator-server/internal/api/handlers/metrics.go +++ b/aggregator-server/internal/api/handlers/metrics.go @@ -1,7 +1,7 @@ package handlers import ( - "fmt" + "log" "net/http" "strconv" "time" @@ -93,7 +93,7 @@ func (h *MetricsHandler) ReportMetrics(c *gin.Context) { } if err := h.commandQueries.MarkCommandCompleted(commandID, result); err != nil { - fmt.Printf("Warning: Failed to mark metrics command %s as completed: %v\n", commandID, err) + log.Printf("[WARNING] [server] [metrics] mark_command_completed_failed command_id=%s error=%v", commandID, err) } c.JSON(http.StatusOK, gin.H{ diff --git a/aggregator-server/internal/api/handlers/update_handler.go b/aggregator-server/internal/api/handlers/update_handler.go index 43ced3d..a0f0386 100644 --- a/aggregator-server/internal/api/handlers/update_handler.go +++ b/aggregator-server/internal/api/handlers/update_handler.go @@ -303,7 +303,7 @@ func (h *UnifiedUpdateHandler) ReportLog(c *gin.Context) { if err := h.updateQueries.UpdatePackageStatus(agentID, packageType, packageName, "updated", nil, completionTime); err != nil { log.Printf("Warning: Failed to update package status for %s/%s: %v", packageType, packageName, err) } else { - log.Printf("✅ Package %s (%s) marked as updated after successful installation", packageName, packageType) + log.Printf("[INFO] [server] [updates] package_updated package=%s type=%s", packageName, packageType) } } } diff --git a/aggregator-server/internal/api/handlers/updates.go b/aggregator-server/internal/api/handlers/updates.go index a5b9f63..a1a0912 100644 --- a/aggregator-server/internal/api/handlers/updates.go +++ b/aggregator-server/internal/api/handlers/updates.go @@ -296,7 +296,7 @@ func (h *UpdateHandler) ReportLog(c *gin.Context) { if err := h.updateQueries.UpdatePackageStatus(agentID, packageType, packageName, "updated", nil, completionTime); err != nil { log.Printf("Warning: Failed to update package status for %s/%s: %v", packageType, packageName, err) } else { - log.Printf("✅ Package %s (%s) marked as updated after successful installation", packageName, packageType) + log.Printf("[INFO] [server] [updates] package_updated package=%s type=%s", packageName, packageType) } } } diff --git a/aggregator-server/internal/api/middleware/ethos_emoji_test.go b/aggregator-server/internal/api/middleware/ethos_emoji_test.go index 5da3bcc..714403e 100644 --- a/aggregator-server/internal/api/middleware/ethos_emoji_test.go +++ b/aggregator-server/internal/api/middleware/ethos_emoji_test.go @@ -38,11 +38,11 @@ func TestMachineBindingMiddlewareHasEmojiInLogs(t *testing.T) { } } - if emojiLogCount == 0 { - t.Error("[ERROR] [server] [middleware] D-2 already fixed: no emoji in machine_binding.go logs") + if emojiLogCount > 0 { + t.Errorf("[ERROR] [server] [middleware] D-2 NOT FIXED: %d emoji log lines remain", emojiLogCount) } - t.Logf("[INFO] [server] [middleware] D-2 confirmed: %d log statements with emoji in machine_binding.go", emojiLogCount) + t.Log("[INFO] [server] [middleware] D-2 FIXED: no emoji in machine_binding.go logs") } func TestMachineBindingMiddlewareHasNoEmojiInLogs(t *testing.T) { diff --git a/aggregator-server/internal/api/middleware/machine_binding.go b/aggregator-server/internal/api/middleware/machine_binding.go index 82f8f79..6696aa3 100644 --- a/aggregator-server/internal/api/middleware/machine_binding.go +++ b/aggregator-server/internal/api/middleware/machine_binding.go @@ -147,7 +147,7 @@ func MachineBindingMiddleware(agentQueries *queries.AgentQueries, minAgentVersio } if *agent.MachineID != reportedMachineID { - log.Printf("[MachineBinding] ⚠️ SECURITY ALERT: Agent %s (%s) machine ID mismatch! DB=%s, Reported=%s", + log.Printf("[WARNING] [server] [auth] machine_id_mismatch agent=%s (%s) db=%s reported=%s", agent.Hostname, agentID, *agent.MachineID, reportedMachineID) c.JSON(http.StatusForbidden, gin.H{ "error": "machine ID mismatch - config file copied to different machine", @@ -159,7 +159,7 @@ func MachineBindingMiddleware(agentQueries *queries.AgentQueries, minAgentVersio } // Machine ID validated - allow request - log.Printf("[MachineBinding] ✓ Agent %s (%s) machine ID validated: %s", + log.Printf("[INFO] [server] [auth] machine_id_validated agent=%s (%s) id=%s", agent.Hostname, agentID, reportedMachineID[:16]+"...") c.Next() } diff --git a/aggregator-server/internal/database/queries/docker.go b/aggregator-server/internal/database/queries/docker.go index 90b44e3..16065d1 100644 --- a/aggregator-server/internal/database/queries/docker.go +++ b/aggregator-server/internal/database/queries/docker.go @@ -3,6 +3,7 @@ package queries import ( "database/sql" "fmt" + "log" "github.com/Fimeg/RedFlag/aggregator-server/internal/models" "github.com/google/uuid" @@ -59,7 +60,7 @@ func (q *DockerQueries) CreateDockerEventsBatch(events []models.StoredDockerImag ) if err != nil { // Log error but continue with other events - fmt.Printf("Warning: Failed to insert docker image event %s: %v\n", event.ID, err) + log.Printf("[WARNING] [server] [database] docker_event_insert_failed event_id=%s error=%v", event.ID, err) continue } } @@ -312,7 +313,7 @@ func (q *DockerQueries) DeleteOldDockerImages(days int) error { } if rowsAffected > 0 { - fmt.Printf("Deleted %d old docker image records\n", rowsAffected) + log.Printf("[INFO] [server] [database] docker_cleanup removed=%d", rowsAffected) } return nil diff --git a/aggregator-server/internal/database/queries/ethos_logging_test.go b/aggregator-server/internal/database/queries/ethos_logging_test.go index 0adc16f..79e3908 100644 --- a/aggregator-server/internal/database/queries/ethos_logging_test.go +++ b/aggregator-server/internal/database/queries/ethos_logging_test.go @@ -26,11 +26,11 @@ func TestQueriesUseFmtPrintfForLogging(t *testing.T) { total += count } - if total == 0 { - t.Error("[ERROR] [server] [database] D-2 already fixed: no fmt.Printf in query files") + if total > 0 { + t.Errorf("[ERROR] [server] [database] D-2 NOT FIXED: %d fmt.Printf calls in query files", total) } - t.Logf("[INFO] [server] [database] D-2 confirmed: %d fmt.Printf calls across query files", total) + t.Log("[INFO] [server] [database] D-2 FIXED: no fmt.Printf in query files") } func TestQueriesUseStructuredLogging(t *testing.T) { diff --git a/aggregator-server/internal/database/queries/metrics.go b/aggregator-server/internal/database/queries/metrics.go index 868f36d..9d38ca6 100644 --- a/aggregator-server/internal/database/queries/metrics.go +++ b/aggregator-server/internal/database/queries/metrics.go @@ -3,6 +3,7 @@ package queries import ( "database/sql" "fmt" + "log" "github.com/Fimeg/RedFlag/aggregator-server/internal/models" "github.com/google/uuid" @@ -59,7 +60,7 @@ func (q *MetricsQueries) CreateMetricsEventsBatch(events []models.StoredMetric) ) if err != nil { // Log error but continue with other events - fmt.Printf("Warning: Failed to insert metric event %s: %v\n", event.ID, err) + log.Printf("[WARNING] [server] [database] metric_event_insert_failed event_id=%s error=%v", event.ID, err) continue } } @@ -278,7 +279,7 @@ func (q *MetricsQueries) DeleteOldMetrics(days int) error { } if rowsAffected > 0 { - fmt.Printf("Deleted %d old metric records\n", rowsAffected) + log.Printf("[INFO] [server] [database] metrics_cleanup removed=%d", rowsAffected) } return nil diff --git a/aggregator-server/internal/database/queries/updates.go b/aggregator-server/internal/database/queries/updates.go index 2fc0483..f77657b 100644 --- a/aggregator-server/internal/database/queries/updates.go +++ b/aggregator-server/internal/database/queries/updates.go @@ -3,6 +3,7 @@ package queries import ( "encoding/json" "fmt" + "log" "strings" "time" @@ -371,7 +372,7 @@ func (q *UpdateQueries) CreateUpdateEventsBatch(events []models.UpdateEvent) err // Update current state if err := q.updateCurrentStateInTx(tx, &event); err != nil { // Log error but don't fail the entire batch - fmt.Printf("Warning: failed to update current state for %s: %v\n", event.PackageName, err) + log.Printf("[WARNING] [server] [database] update_state_failed package=%s error=%v", event.PackageName, err) } } } @@ -589,7 +590,7 @@ func (q *UpdateQueries) CleanupOldEvents(olderThan time.Duration) error { } rowsAffected, _ := result.RowsAffected() - fmt.Printf("Cleaned up %d old update events\n", rowsAffected) + log.Printf("[INFO] [server] [database] update_events_cleanup removed=%d", rowsAffected) return nil } diff --git a/aggregator-server/internal/services/ethos_logging_test.go b/aggregator-server/internal/services/ethos_logging_test.go index f49911f..01b0e14 100644 --- a/aggregator-server/internal/services/ethos_logging_test.go +++ b/aggregator-server/internal/services/ethos_logging_test.go @@ -16,11 +16,11 @@ func TestServicesUseFmtPrintfForLogging(t *testing.T) { } count := strings.Count(string(content), "fmt.Printf") - if count == 0 { - t.Error("[ERROR] [server] [services] D-2 already fixed: no fmt.Printf in security_settings_service.go") + if count > 0 { + t.Errorf("[ERROR] [server] [services] D-2 NOT FIXED: %d fmt.Printf in security_settings_service.go", count) } - t.Logf("[INFO] [server] [services] D-2 confirmed: %d fmt.Printf calls in security_settings_service.go", count) + t.Log("[INFO] [server] [services] D-2 FIXED: no fmt.Printf in security_settings_service.go") } func TestServicesUseStructuredLogging(t *testing.T) { diff --git a/aggregator-server/internal/services/security_settings_service.go b/aggregator-server/internal/services/security_settings_service.go index b0f1496..e056d35 100644 --- a/aggregator-server/internal/services/security_settings_service.go +++ b/aggregator-server/internal/services/security_settings_service.go @@ -7,6 +7,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "log" "os" "strconv" "strings" @@ -134,7 +135,7 @@ func (s *SecuritySettingsService) SetSetting(category, key string, value interfa reason, ); err != nil { // Log error but don't fail the operation - fmt.Printf("Warning: failed to create audit log: %v\n", err) + log.Printf("[WARNING] [server] [security] audit_log_create_failed error=%v", err) } return nil diff --git a/docs/D2_Fix_Implementation.md b/docs/D2_Fix_Implementation.md new file mode 100644 index 0000000..e3f53b5 --- /dev/null +++ b/docs/D2_Fix_Implementation.md @@ -0,0 +1,45 @@ +# D-2 ETHOS Compliance Fix Implementation + +**Date:** 2026-03-29 +**Branch:** culurien + +--- + +## Files Modified + +### Server — Emoji Removed +| File | Violations Fixed | +|------|-----------------| +| `middleware/machine_binding.go` | 2 (security alert, validation) | +| `handlers/agents.go` | 10 (version, token, heartbeat, rapid mode) | +| `handlers/agent_updates.go` | 2 (bulk update, package signed) | +| `handlers/update_handler.go` | 1 (package updated) | +| `handlers/updates.go` | 1 (package updated) | + +### Server — fmt.Printf Replaced +| File | Violations Fixed | +|------|-----------------| +| `handlers/docker_reports.go` | 1 (command completion) | +| `handlers/metrics.go` | 1 (command completion) | +| `services/security_settings_service.go` | 1 (audit log) | +| `queries/docker.go` | 2 (event insert, cleanup) | +| `queries/metrics.go` | 2 (event insert, cleanup) | +| `queries/updates.go` | 2 (state update, cleanup) | + +### Agent — Emoji Removed +| File | Violations Fixed | +|------|-----------------| +| `cmd/agent/main.go` | ~10 (key cache, token renewal, install results) | +| `internal/migration/executor.go` | 4 (validation, completion, rollback, failure) | + +## Exempt Files (NOT touched) +- `display/terminal.go` — intentional terminal UI +- `handlers/setup.go` — CLI wizard output +- `cmd/agent/main.go` lines 294-322 — registration CLI output +- `cmd/agent/main.go` lines 691-697 — startup banner + +## Totals +- Emoji violations fixed: ~36 +- fmt.Printf violations fixed: 9 +- **Total: ~45 violations fixed** +- All tests pass. No regressions.