From f511253269069ea09ce75806368ee7d210cf72ee Mon Sep 17 00:00:00 2001 From: Isaac_Aracena Date: Wed, 29 Jul 2026 16:26:25 +0000 Subject: [PATCH] =?UTF-8?q?A=C3=B1adir=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 958 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 958 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a26fd0 --- /dev/null +++ b/README.md @@ -0,0 +1,958 @@ +GLM Hub + +Portal interno de GomezLee Marketing para centralizar las aplicaciones corporativas, administrar el catálogo compartido y gestionar solicitudes de acceso mediante Supabase, n8n y autenticación con Google. + +INFORMACIÓN GENERAL + +Campo + +Detalle + +Proyecto + +GLM Hub + +Área + +IT / Corporativo + +Estado + +Listo para producción + +Developer principal + +Isaac Aracena + +IT Manager + +Luis Matos + +Product Owner + +Máximo Gómez + +Fecha de inicio + +2026-07-22 + +Fecha de cierre + +2026-07-29 + +Ciclo Shape Up + +No definido en el repositorio + +Board de ejecución + +Pendiente de enlazar + +PRD del proyecto + +Pendiente de enlazar + +Repositorio + +https://git.digitalcompass.agency/Isaac_Aracena/glm-hub + +URL de producción + +https://home.digitalcompass.agency/ + +OBJETIVO + +Problema que resuelve + +Las aplicaciones internas de GomezLee Marketing estaban distribuidas en diferentes enlaces y dependían de comunicación manual para que los colaboradores pudieran encontrarlas, identificar cuál necesitaban y solicitar acceso. Además, no existía un catálogo central compartido que pudiera ser mantenido por administradores sin modificar el código. + +Solución implementada + +GLM Hub centraliza los portales corporativos en una sola interfaz, permite que los administradores creen y mantengan el catálogo desde la aplicación, muestra a todos los usuarios autorizados las mismas aplicaciones publicadas, conserva favoritos y accesos recientes por usuario, genera íconos con IA y gestiona solicitudes de acceso mediante aprobaciones por correo. + +Usuarios / Beneficiarios + +Colaboradores autorizados de GomezLee Marketing. + +Administradores del catálogo de aplicaciones. + +Equipo de IT Support que recibe las decisiones de acceso. + +Desarrolladores responsables de administrar los permisos dentro de cada aplicación individual. + +ARQUITECTURA + +Diagrama de flujo + +Usuario + | + v +Frontend React + Vite + | + +--> Supabase Auth (Google OAuth) + | + +--> Supabase Postgres + RLS + Realtime + | |-- Usuarios autorizados y roles + | |-- Catálogo compartido + | |-- Favoritos y recientes por usuario + | `-- Solicitudes y decisiones de acceso + | + +--> Supabase Storage + | `-- Íconos del catálogo + | + +--> Webhook n8n: generación de ícono + | `-- Validación de administrador -> Gemini -> imagen + | + `--> Webhook n8n: solicitud de acceso + `-- Supabase -> Gmail -> aprobación/rechazo -> IT Support + +Stack tecnológico + +Componente + +Tecnología + +Propósito + +Frontend + +React 19 + TypeScript + +Interfaz del Hub + +Build + +Vite 6 + +Desarrollo, validación y compilación + +UI + +CSS + Lucide React + +Estilos e iconografía + +Autenticación + +Supabase Auth + Google OAuth + +Inicio de sesión corporativo + +Base de datos + +Supabase / PostgreSQL + +Catálogo, usuarios, favoritos, recientes y solicitudes + +Seguridad + +Row Level Security + +Control de lectura y escritura según usuario y rol + +Archivos + +Supabase Storage + +Almacenamiento de íconos + +Sincronización + +Supabase Realtime + +Actualización del catálogo en sesiones abiertas + +Automatización + +n8n + +Orquestación de generación de íconos y solicitudes + +IA + +Google Gemini + +Generación de íconos para nuevas aplicaciones + +Notificaciones + +Gmail OAuth + +Envío de solicitudes y decisiones por correo + +Repositorio + +Gitea + +Control de versiones + +Hosting + +Servidor web GLM + +Publicación del contenido de dist/ + +Integraciones externas + +Sistema + +Tipo de integración + +Datos que fluyen + +Google OAuth + +OAuth 2.0 mediante Supabase + +Identidad, correo, nombre y foto del usuario + +Supabase + +SDK, REST, RPC, Storage y Realtime + +Usuarios, roles, catálogo, íconos, favoritos, recientes y solicitudes + +n8n + +Webhooks HTTPS + +Solicitudes del frontend y respuestas procesadas + +Google Gemini + +Credencial nativa de n8n + +Nombre y descripción de la app; devuelve una imagen + +Gmail + +OAuth mediante n8n + +Correos de aprobación y notificación a IT Support + +REGLAS DE NEGOCIO + +Solo pueden iniciar sesión usuarios activos registrados en glm_hub_authorized_users y con correo del dominio @gomezleemarketing.com. + +Los roles válidos son admin y member. + +Los administradores autorizados son: + +José Leopoldo Gómez — jgomez@gomezleemarketing.com + +Isaac Aracena — iaracena@gomezleemarketing.com + +Eidan Then — ethen@gomezleemarketing.com + +Máximo Gómez — mgomez@gomezleemarketing.com + +Luis Matos — lmatos@gomezleemarketing.com + +Solo los administradores pueden abrir el apartado Administrar, crear, editar, publicar, ocultar o eliminar aplicaciones. + +Todos los usuarios autorizados ven el mismo catálogo de aplicaciones publicadas. + +El Hub no controla el acceso interno de cada aplicación; ese permiso se administra desde el login o backend de cada portal. + +Las categorías disponibles son Administración, Recursos Humanos y CDC. + +No se puede publicar una aplicación sin ícono. + +El nombre debe tener entre 2 y 60 caracteres y la descripción un máximo de 180 caracteres. + +Los íconos admitidos son PNG, JPG o WebP y no pueden superar 1 MB. + +Los favoritos y accesos recientes son personales y no afectan la vista de otros usuarios. + +Los favoritos se ordenan antes que las demás aplicaciones antes de aplicar la paginación. + +Los usuarios normales pueden solicitar acceso a cualquier aplicación publicada. + +No se permite una segunda solicitud pendiente del mismo usuario para la misma aplicación. + +Las solicitudes se envían individualmente a Isaac Aracena, José Leopoldo Gómez y Máximo Gómez. + +La primera decisión registrada gana; cualquier intento posterior queda bloqueado y no cambia el resultado. + +Después de aprobar o rechazar, IT Support recibe un correo con el solicitante, la aplicación, el resultado y la persona que decidió. + +La generación de íconos con IA solo está disponible para administradores y requiere nombre y descripción. + +CONFIGURACIÓN Y SETUP + +Prerrequisitos + +Node.js y npm instalados. + +Acceso al proyecto Supabase de GLM. + +Proveedor Google habilitado en Supabase Auth. + +Instancia de n8n operativa. + +Credencial de Google Gemini configurada en n8n. + +Credencial Gmail OAuth configurada en n8n. + +Acceso al servidor o subdominio de producción. + +Variables de entorno + +Crear .env a partir de .env.example: + +Variable + +Descripción + +Dónde se obtiene + +VITE_SUPABASE_URL + +URL pública del proyecto Supabase + +Supabase / configuración del proyecto + +VITE_SUPABASE_ANON_KEY + +Clave pública anon para el frontend + +Supabase / API Keys + +VITE_ICON_GENERATOR_WEBHOOK_URL + +Webhook de n8n para generar íconos + +Workflow de generación de íconos + +VITE_ACCESS_REQUEST_WEBHOOK_URL + +Webhook de n8n para solicitudes de acceso + +Workflow de solicitudes y aprobación + +Nunca commitear credenciales reales. El archivo .env, las claves service_role, los tokens y las credenciales de Gmail o Gemini deben mantenerse fuera del repositorio. + +Esquema de base de datos + +Ejecutar en Supabase SQL Editor: + +SUPABASE-GLM-HUB-COMPLETO.sql + +El script crea o actualiza: + +glm_hub_authorized_users + +glm_hub_apps + +glm_hub_favorites + +glm_hub_recent_apps + +glm_hub_access_requests + +glm_hub_access_request_approvers + +Funciones RPC para validación, solicitudes y decisiones. + +Bucket público glm-hub-icons. + +Políticas RLS. + +Publicación Realtime del catálogo. + +Workflows de n8n + +Importar y configurar: + +n8n/GLM-Hub-Generar-Icono-Gemini-Nodo-Nativo.json +n8n/GLM-Hub-Solicitudes-Acceso-Aprobacion.json + +Configuración necesaria: + +Seleccionar una credencial de Gemini en Generate an image. + +Seleccionar una credencial Gmail válida en los dos nodos de envío. + +Usar la clave anon donde la llamada representa al usuario autenticado. + +Usar service_role únicamente en los nodos internos que emiten tokens o registran decisiones. + +Mantener las claves únicamente en n8n; nunca enviarlas al navegador. + +En producción, Enviar solicitud a aprobadores debe usar ={{ $json.sendTo }}. + +En producción, Enviar decisión a IT Support debe enviar a itsupport@gomezleemarketing.com. + +Instalación local + +git clone https://git.digitalcompass.agency/Isaac_Aracena/glm-hub.git +cd glm-hub +npm install +cp .env.example .env +# Editar .env con los valores reales +npm run typecheck +npm run dev + +En PowerShell, puede usarse: + +Copy-Item .env.example .env + +Build + +npm run build + +La compilación se genera en: + +dist/ + +Deploy + +El proyecto se publica en la raíz de un subdominio, por lo que vite.config.ts debe permanecer sin una propiedad base personalizada. + +export default defineConfig({ + plugins: [react()], +}); + +Copiar el contenido de dist/ directamente al Document Root del subdominio: + +DocumentRoot/ +|-- index.html +|-- assets/ +|-- glm-logo.png +`-- archivos de favicon + +No colocar una carpeta dist dentro del Document Root. + +Para probar el mismo build con XAMPP, usar un VirtualHost que apunte directamente a la carpeta donde se copió el contenido de dist/. Servirlo como http://localhost/glm-hub/ sin configurar base hará que los assets se busquen desde una ruta incorrecta. + +Redirects de autenticación + +Registrar en Supabase las URLs permitidas que correspondan al entorno: + +https://home.digitalcompass.agency/ +http://localhost:4173/ + +Si se utiliza un VirtualHost local, registrar también su URL completa. + +CÓMO FUNCIONA + +Flujo general + +El usuario entra al Hub y selecciona Continuar con Google. + +Supabase Auth valida la cuenta de Google. + +El frontend consulta glm_hub_authorized_users para confirmar que el usuario esté activo y conocer su rol. + +El catálogo compartido se carga desde glm_hub_apps. + +Los favoritos y recientes se cargan para el usuario autenticado. + +Supabase Realtime mantiene el catálogo actualizado en sesiones abiertas. + +Los administradores pueden crear, editar, ocultar o eliminar aplicaciones. + +Los usuarios normales pueden solicitar acceso a una aplicación publicada. + +Generación de íconos + +El administrador completa nombre y descripción. + +El frontend llama el webhook glm-hub-generar-icono. + +n8n valida el JWT y confirma el rol de administrador. + +Gemini genera una imagen cuadrada sin texto. + +n8n devuelve el archivo binario al frontend. + +El ícono se previsualiza y se guarda en Supabase Storage al publicar. + +Solicitud de acceso + +El usuario selecciona un área y una aplicación publicada. + +n8n registra la solicitud en Supabase. + +Supabase emite un token único para cada aprobador. + +Gmail envía un correo individual a cada aprobador. + +El aprobador confirma Aceptar o Rechazar. + +Supabase registra atómicamente la primera decisión. + +n8n envía el resultado a itsupport@gomezleemarketing.com. + +Cualquier clic posterior muestra que la solicitud ya fue atendida. + +Triggers + +Trigger + +Frecuencia + +Descripción + +Google OAuth + +Bajo demanda + +Inicio de sesión de un usuario + +Realtime de Supabase + +En tiempo real + +Actualización del catálogo compartido + +POST /webhook/glm-hub-generar-icono + +Bajo demanda + +Generación de ícono con Gemini + +POST /webhook/glm-hub-solicitar-acceso + +Bajo demanda + +Registro y envío de solicitud + +GET /webhook/glm-hub-confirmar-solicitud + +Bajo demanda + +Pantalla de confirmación de decisión + +POST /webhook/glm-hub-resolver-solicitud + +Bajo demanda + +Registro de aprobación o rechazo + +TESTING + +Casos de prueba mínimos + +Caso + +Input + +Output esperado + +Estado + +Login autorizado + +Usuario activo del dominio GLM + +Acceso al Hub + +Validado + +Usuario inactivo + +Registro con is_active = false + +Acceso denegado + +Validado + +Rol administrador + +Cuenta con role = admin + +Muestra Administrar + +Validado + +Rol usuario + +Cuenta con role = member + +No muestra controles administrativos + +Validado + +Catálogo compartido + +Admin publica una app + +Todos ven la misma app + +Validado en Supabase; realizar smoke test final con segundo usuario + +Publicación sin ícono + +Formulario sin archivo + +Publicación bloqueada + +Validado + +Generar ícono + +Nombre y descripción válidos + +Imagen generada y previsualizada + +Validado + +Cambio de pestaña + +Salir y regresar al navegador + +Mantiene vista y formulario + +Validado + +Favoritos + +Marcar una aplicación + +Se guarda solo para el usuario + +Validado + +Paginación + +Más de 10 aplicaciones + +Navegación compacta y usable + +Implementado + +Solicitud de acceso + +Usuario y app válidos + +Correos enviados a aprobadores + +Validado + +Primera decisión + +Un aprobador acepta o rechaza + +Registra resultado y notifica a IT + +Validado + +Segundo clic + +Otro aprobador intenta decidir + +No modifica la primera decisión + +Validado + +Build de producción + +npm run build + +Genera dist/ sin errores + +Validado + +ERRORES CONOCIDOS Y TROUBLESHOOTING + +Error + +Causa probable + +Solución + +Pantalla en blanco en XAMPP + +El build de raíz se sirve dentro de /glm-hub/ + +Usar VirtualHost o npm run preview; no agregar base para producción en subdominio raíz + +Assets con 404 + +index.html apunta a /assets/ pero el servidor usa una subcarpeta + +Servir el contenido de dist/ desde el Document Root + +Google regresa a una URL incorrecta + +Redirect no autorizado + +Agregar la URL exacta en Supabase Auth + +Usuario no ve Administrar + +Rol desactualizado o sesión antigua + +Confirmar role = admin, cerrar sesión y volver a entrar + +HTTP 401 en n8n + +JWT vencido o encabezado incorrecto + +Usar el token dinámico enviado por el frontend + +HTTP 403 en una RPC + +Clave o permisos incorrectos + +Verificar si el nodo requiere anon, JWT o service_role + +Output vacío de HTTP Request + +Respuesta configurada como archivo o envuelta con headers + +Usar Response Format: JSON y revisar la estructura esperada + +Solicitud duplicada + +Ya existe una solicitud pendiente + +Atender o eliminar la solicitud anterior + +No se genera ícono + +Credencial Gemini no seleccionada + +Revisar el nodo Generate an image + +Ícono rechazado + +Archivo mayor a 1 MB o MIME no permitido + +Convertir a PNG/JPG/WebP y reducir tamaño + +MONITOREO + +n8n Executions: revisar ejecuciones fallidas o detenidas en ramas de error. + +Supabase Logs: revisar errores de Auth, REST, RLS y Storage. + +Solicitudes pendientes: consultar glm_hub_access_requests filtrando status = 'pending'. + +Correos: confirmar entregas desde la cuenta Gmail conectada a n8n. + +Output normal: catálogo cargado, sesión persistente, Realtime activo y webhooks respondiendo correctamente. + +Alertas automáticas: no configuradas actualmente; el monitoreo se realiza desde n8n y Supabase. + +Consulta rápida: + +select + requester_name, + requester_email, + app_name, + status, + decided_by_name, + decided_by_email, + created_at, + decided_at +from public.glm_hub_access_requests +order by created_at desc; + +ESTRUCTURA DEL REPOSITORIO + +glm-hub/ +|-- README.md +|-- .env.example +|-- index.html +|-- package.json +|-- package-lock.json +|-- tsconfig.json +|-- vite.config.ts +|-- SUPABASE-GLM-HUB-COMPLETO.sql +|-- dist/ +| |-- index.html +| `-- assets/ +|-- n8n/ +| |-- GLM-Hub-Generar-Icono-Gemini-Nodo-Nativo.json +| `-- GLM-Hub-Solicitudes-Acceso-Aprobacion.json +|-- public/ +| `-- logos y favicons +|-- scripts/ +|-- src/ +| |-- components/ +| |-- lib/ +| |-- App.tsx +| `-- main.tsx +`-- documentación técnica adicional + +node_modules/ y .env nunca deben subirse al repositorio. En el flujo actual de despliegue manual, dist/ puede mantenerse versionado para entregar una compilación ya validada. + +CHANGELOG + +2026-07-29 — v1.0.0 + +Catálogo compartido en Supabase. + +Autenticación con Google y control de roles. + +Favoritos y accesos recientes por usuario. + +Administración completa del catálogo. + +Realtime para aplicaciones publicadas. + +Generación de íconos con Gemini mediante n8n. + +Solicitudes de acceso con aprobación o rechazo por correo. + +Primera decisión protegida de forma atómica. + +Paginación automática en acceso rápido, catálogo y administración. + +Build preparado para la raíz de un subdominio. + +2026-07-28 — v0.9.0 + +Persistencia de pantalla al cambiar de pestaña. + +Correcciones de CORS y JWT para generación de íconos. + +Integración con el nodo nativo de Gemini en n8n. + +2026-07-22 — v0.1.0 + +Inicio del proyecto y diseño inicial del portal. + +DECISIONS LOG + +DEC-001 — Catálogo compartido en Supabase + +Fecha: 2026-07-25 + +Contexto: El catálogo guardado en localStorage solo existía en el navegador del administrador. + +Opciones consideradas: localStorage vs. base de datos compartida. + +Decisión: Guardar aplicaciones en Supabase. + +Razón: Todos los usuarios deben ver el mismo catálogo y los administradores deben actualizarlo sin modificar código. + +DEC-002 — Acceso individual fuera del Hub + +Fecha: 2026-07-29 + +Contexto: Se evaluó controlar permisos por aplicación desde el Hub. + +Opciones consideradas: Permisos centralizados en el Hub vs. permisos en cada aplicación. + +Decisión: El Hub muestra todas las aplicaciones publicadas y cada aplicación controla su propio acceso. + +Razón: Evita duplicar reglas y mantiene la responsabilidad de seguridad en cada portal. + +DEC-003 — Favoritos y recientes por usuario + +Fecha: 2026-07-28 + +Contexto: El catálogo debe ser compartido, pero la personalización no. + +Decisión: Guardar favoritos y accesos recientes asociados al usuario autenticado. + +Razón: Cada persona conserva su propia experiencia sin afectar a los demás. + +DEC-004 — Generación de íconos desde n8n + +Fecha: 2026-07-28 + +Contexto: La clave de Gemini no puede exponerse en el frontend. + +Decisión: Usar un webhook de n8n y el nodo nativo Generate an image. + +Razón: Mantiene las credenciales fuera del navegador y permite validar el rol administrativo. + +DEC-005 — Primera decisión gana + +Fecha: 2026-07-29 + +Contexto: Tres aprobadores reciben botones para la misma solicitud. + +Decisión: Registrar atómicamente la primera aprobación o rechazo y bloquear las siguientes. + +Razón: Evita decisiones contradictorias y correos duplicados a IT Support. + +DEC-006 — Build sin base personalizado + +Fecha: 2026-07-29 + +Contexto: La aplicación se desplegará en la raíz de un subdominio. + +Decisión: No configurar base: '/glm-hub/' en Vite. + +Razón: Los assets deben resolverse desde / en producción. + +CONTACTOS DEL PROYECTO + +Rol + +Nombre + +Contacto + +Product Owner + +Máximo Gómez + +mgomez@gomezleemarketing.com + +IT Manager + +Luis Matos + +lmatos@gomezleemarketing.com + +Developer principal + +Isaac Aracena + +iaracena@gomezleemarketing.com + +Administrador técnico + +Eidan Then + +ethen@gomezleemarketing.com + +Soporte + +GLM IT Support + +itsupport@gomezleemarketing.com + +DEFINITION OF DONE + +Catálogo compartido en Supabase. + +Autenticación con Google operativa. + +Roles de administrador y usuario aplicados. + +RLS configurado para tablas y Storage. + +Favoritos y recientes por usuario. + +Paginación implementada. + +Generación de íconos con IA operativa. + +Workflows de n8n exportados en /n8n. + +SQL completo incluido en el repositorio. + +Variables documentadas en .env.example. + +Solicitudes de acceso y primera decisión validadas. + +Código y build listos para Gitea. + +Probado localmente y con webhooks reales. + +Ejecutar smoke test final con un segundo usuario en producción. + +Enlazar el board y el PRD oficiales. + +Registrar validación final de Luis Matos. + +Registrar aprobación final de Máximo Gómez. + +Documento mantenido por el equipo GLM IT. \ No newline at end of file