¿Qué le falta al sistema para estar 10 de 10?
El reporte AUD-20260925-006 evaluó el WhatsApp CRM en 4.8/10. Tras múltiples sprints, el sistema hoy está en 7.5/10. Este documento mapea exactamente lo que falta para llegar a 10/10 — ordenado por impacto, con estimaciones de esfuerzo realistas.
Lo que ya está hecho — desde AUD-20260925-006
Semana 1 — Bloqueadores críticos
URGENTE · 1-5 días c/uEstas cinco brechas son las que un atacante o un auditor externo encontraría en la primera revisión. Su ausencia baja el score de Seguridad y Rendimiento en 2 puntos.
Los endpoints save_lead_field, update_tags, manual_toggle, clear_chat y send_message aceptan POST sin validar el origen. Un atacante puede forzar al admin a ejecutar acciones por CSRF desde cualquier sitio.
login.php acepta intentos ilimitados por IP — fuerza bruta trivial. Además, no se llama session_regenerate_id(true) post-login, lo que expone a session fixation.
$_SESSION['login_attempts'] + lockout 15 min. Una línea para regenerar sesión.Sin índice en wamid, cada mensaje entrante hace un full-table scan para deduplicación. A 500+ mensajes diarios, esto es una degradación medible en p99 latency.
ALTER TABLE messages ADD UNIQUE INDEX idx_loop_guard (phone_from, wamid);
El campo de búsqueda en el sidebar es decorativo: no tiene id, ni evento, ni lógica backend. Con 20+ contactos activos, los usuarios no pueden filtrar conversaciones — dolor real de usabilidad diaria.
api/search_contacts.php → re-render lista sidebar.El chat usa md:flex lo que lo oculta en viewports menores a 768px. En un negocio de WhatsApp, muchas operaciones son desde celular. El CRM es ciego en móvil.
Mes 1 — Mejoras importantes
Semanas 2-4Estas brechas no bloquean el MVP pero determinan si el producto se siente profesional o artesanal. Son las que separan un 7.5 de un 9.0.
El método ejecuta una subquery correlacionada por cada contacto para traer el último mensaje. Con 300+ contactos activos, esto son 300+ queries en cada carga del panel — se sentirá a partir de los primeros 50 usuarios reales.
ROW_NUMBER(). Una sola query para todos los contactos.Cada mensaje que involucra conversión de moneda llama al API externo de TRM. Eso agrega ~2 segundos de latencia al tiempo de respuesta del bot y puede fallar si el servicio externo cae.
ai_settings con key trm_usd_cop + trm_updated_at. Si tiene menos de 1h de antigüedad, usar el cacheado.Con temperatura 0.7 y un modelo 8B, el bot puede "alucinar" precios o ignorar restricciones de descuento en turns críticos. Los turns donde se informa precio, cuenta bancaria o condiciones de pago necesitan determinismo.
Los diálogos nativos del browser bloquean el hilo principal, tienen aspecto de sistema operativo desactualizado y en algunos browsers móviles no aparecen. Es la señal visual más evidente de software no terminado.
En cada mensaje el bot llama a file_get_contents('products.json') — un I/O que repite la lectura de disco por request. Con alto tráfico es un cuello de botella innecesario.
private static ?array $cache = null;
if (self::$cache !== null) return self::$cache;
self::$cache = json_decode(file_get_contents(...), true);
return self::$cache;
Mes 2-3 — Para calidad comercial 10/10
Sprint 2-3Estas features son las que hacen la diferencia entre un CRM funcional y uno que se puede vender como SaaS. No bloquean el MVP, pero sin ellas el sistema no llega a 10/10.
Conversiones cerradas/día, tasa de cierre por perfil IA, tiempo promedio de respuesta. Sin métricas, no sabes si el bot está vendiendo o perdiendo clientes.
~2 díasCuando el bot detecta "cierre de venta", un webhook al canal de Operaciones muestra nombre, producto y monto. Real-time para el equipo.
~3hmysqldump vía cron diario en Hostinger, exportado a una carpeta fuera del webroot + rotación de 7 copias. Sin backup, cada falla es pérdida permanente.
UptimeRobot (plan gratuito) pinguea el webhook y el panel cada 5 min. Alerta por email si caen. Actualmente el sistema puede estar caído horas sin que nadie lo sepa.
~30 minDescarga de historial de un contacto en CSV o formato legible. Los clientes del CRM necesitan reportes para sus equipos comerciales.
~4hSistema de etiquetas Kanban (Nuevo → En Negociación → Cerrado → Perdido). Permite a un equipo de ventas tener visibilidad del estado del pipeline sin leer cada chat.
~1 díaChecklist completo para el 10/10
| Ítem | Impacto | Esfuerzo | Plazo | Dimensión | Estado |
|---|---|---|---|---|---|
| CSRF tokens en endpoints escritura | +1.5 pts | 2h | Sem 1 | Seguridad | PENDIENTE |
| Rate limiting login + session regen | +1.0 pts | 1h | Sem 1 | Seguridad | PENDIENTE |
| Índice messages.wamid + anti-loop | +0.8 pts | 15 min | Sem 1 | DB & Perf | PENDIENTE |
| Búsqueda funcional en sidebar | +0.7 pts | 3h | Sem 1 | UX | PENDIENTE |
| Mobile layout fix | +0.5 pts | 2h | Sem 1 | UX | PENDIENTE |
| Fix N+1 getActiveConversations() | +0.5 pts | 4h | Mes 1 | DB & Perf | MES 1 |
| TRM cache TTL 1h en DB | +0.3 pts | 2h | Mes 1 | DB & Perf | MES 1 |
| Temperatura LLM 0.3 en turns precio | +0.4 pts | 30 min | Mes 1 | IA Bot | MES 1 |
| Reemplazar confirm/alert con modales | +0.3 pts | 3h | Mes 1 | UX | MES 1 |
| products.json static cache | +0.2 pts | 20 min | Mes 1 | Arquitectura | MES 1 |
| Dashboard Analytics (conversiones) | +0.5 pts | 2 días | Mes 2 | UX | BACKLOG |
| Backup automático MySQL diario | +0.5 pts | 1h | Mes 2 | DevOps | BACKLOG |
| Monitoreo uptime (UptimeRobot) | +0.3 pts | 30 min | Mes 2 | DevOps | BACKLOG |
| Notificaciones Slack ventas cerradas | +0.3 pts | 3h | Mes 2 | DevOps | BACKLOG |
| Exportación conversaciones CSV/PDF | +0.2 pts | 4h | Mes 3 | UX | BACKLOG |
| Pipeline Kanban de conversiones | +0.2 pts | 1 día | Mes 3 | UX | BACKLOG |