Files
soft_usite/pkg/models/umind_evento.go
T
Lizandro GuarnizoandClaude Sonnet 5 997e3cc790 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>
2026-08-13 09:58:59 -05:00

52 lines
2.2 KiB
Go

package models
import (
"log"
"github.com/sujit-baniya/fiber-boilerplate/app"
"gorm.io/gorm"
)
// UmindEventoLog es el registro de auditoría técnica de un agente — errores
// y eventos que hoy solo quedaban en el log del servidor (invisibles desde
// el panel): fallos al llamar al AI, tools/webhooks que fallan, canales que
// no logran procesar un mensaje, etc. No es el historial de conversación
// (eso es UmindMensaje) ni el estado de ingesta (eso ya se ve por
// documento en UmindDocumento.Estado/Error) — es específicamente lo que
// antes solo se podía ver pidiendo los logs del servidor.
type UmindEventoLog struct {
gorm.Model
AgenteID uint `json:"agente_id" gorm:"column:agente_id;index"`
Nivel string `json:"nivel" gorm:"column:nivel;size:10"` // error | warn
Origen string `json:"origen" gorm:"column:origen;size:40"` // ai | tool | email | canal_telegram | canal_whatsapp
Mensaje string `json:"mensaje" gorm:"column:mensaje;type:text"`
Detalle string `json:"detalle" gorm:"column:detalle;type:text"` // JSON crudo opcional, para diagnosticar sin pedir logs
}
func (UmindEventoLog) TableName() string { return "umind_eventos_log" }
// RegistrarEventoUmind guarda un evento de auditoría. No devuelve error a
// propósito — es un side-channel de diagnóstico, nunca debe interrumpir el
// flujo principal (responderle al visitante) si la escritura falla.
func RegistrarEventoUmind(agenteID uint, nivel, origen, mensaje, detalle string) {
e := &UmindEventoLog{AgenteID: agenteID, Nivel: nivel, Origen: origen, Mensaje: mensaje, Detalle: detalle}
if err := app.Http.Database.DB.Create(e).Error; err != nil {
log.Printf("[UMIND] No se pudo guardar el evento de auditoría (agente %d): %v", agenteID, err)
}
}
// GetUmindEventosByAgente retorna los últimos eventos del agente, más
// reciente primero — acotado para no crecer sin límite en la respuesta.
func GetUmindEventosByAgente(agenteID uint, limit int) ([]UmindEventoLog, error) {
if limit <= 0 || limit > 200 {
limit = 100
}
var items []UmindEventoLog
err := app.Http.Database.DB.
Where("agente_id = ?", agenteID).
Order("id DESC").
Limit(limit).
Find(&items).Error
return items, err
}