feat: log de auditoría técnica por agente

Nueva tabla umind_eventos_log + tab "Auditoría" en el panel: errores y
eventos que hasta ahora solo se podían ver pidiendo los logs del servidor
(fallos al llamar al AI, respuestas sin texto usable, tools/webhooks que
fallan, tokens de correo que no se pueden refrescar, firmas de WhatsApp
inválidas, errores procesando mensajes de Telegram/WhatsApp) quedan
registrados por agente, visibles directo en el panel con el JSON crudo
expandible para diagnosticar sin acceso al servidor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-13 09:58:59 -05:00
co-authored by Claude Sonnet 5
parent 5febbd24d5
commit 997e3cc790
13 changed files with 157 additions and 31 deletions
@@ -46,6 +46,7 @@ func UmindTelegramWebhook(c *fiber.Ctx) error {
if err := services.ProcesarMensajeTelegramUmind(canal, update.Message.Chat.ID, texto); err != nil {
log.Printf("[UMIND_TELEGRAM] canal %d: %v", canal.ID, err)
models.RegistrarEventoUmind(canal.AgenteID, "error", "canal_telegram", "Error procesando un mensaje de Telegram", err.Error())
}
return c.SendStatus(fiber.StatusOK)
}
@@ -112,11 +113,13 @@ func UmindWhatsAppWebhook(c *fiber.Ctx) error {
credenciales, err := services.DescifrarCredencialesCanal(canal.CredencialesEnc)
if err != nil {
log.Printf("[UMIND_WHATSAPP] canal %d: credenciales corruptas: %v", canal.ID, err)
models.RegistrarEventoUmind(canal.AgenteID, "error", "canal_whatsapp", "Credenciales del canal corruptas", err.Error())
return c.SendStatus(fiber.StatusOK)
}
if !services.ValidarFirmaWhatsApp(credenciales["app_secret"], c.Body(), c.Get("X-Hub-Signature-256")) {
log.Printf("[UMIND_WHATSAPP] canal %d: firma inválida", canal.ID)
models.RegistrarEventoUmind(canal.AgenteID, "error", "canal_whatsapp", "Firma X-Hub-Signature-256 inválida en un webhook entrante", "")
return c.SendStatus(fiber.StatusUnauthorized)
}
@@ -132,6 +135,7 @@ func UmindWhatsAppWebhook(c *fiber.Ctx) error {
}
if err := services.ProcesarMensajeWhatsAppUmind(canal, msg.From, strings.TrimSpace(msg.Text.Body)); err != nil {
log.Printf("[UMIND_WHATSAPP] canal %d: %v", canal.ID, err)
models.RegistrarEventoUmind(canal.AgenteID, "error", "canal_whatsapp", "Error procesando un mensaje de WhatsApp", err.Error())
}
}
}