Files
glm-hub/README.md
T
2026-07-29 16:26:25 +00:00

958 lines
18 KiB
Markdown

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.