From a2e8fbb403bcd1c6cf5a72632433dcf61fb91ce6 Mon Sep 17 00:00:00 2001 From: Isaac_Aracena Date: Wed, 29 Jul 2026 16:34:51 +0000 Subject: [PATCH] Subir archivos a "/" --- README.md | 580 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d8841d --- /dev/null +++ b/README.md @@ -0,0 +1,580 @@ +
+ +GomezLee Marketing + +# GLM Hub + +### El punto de entrada a las aplicaciones internas de GomezLee Marketing + +

+ Estado + Versión + Frontend + Backend +

+ +> Portal interno para centralizar aplicaciones corporativas, administrar un catálogo compartido y gestionar solicitudes de acceso mediante Supabase, n8n y autenticación con Google. + +[Producción](https://home.digitalcompass.agency/) · [Repositorio](https://git.digitalcompass.agency/Isaac_Aracena/glm-hub) + +
+ +--- + +## Navegación rápida + +| | | | +|---|---|---| +| [Información general](#-información-general) | [Objetivo](#-objetivo) | [Arquitectura](#-arquitectura) | +| [Reglas de negocio](#-reglas-de-negocio) | [Configuración](#-configuración-y-setup) | [Cómo funciona](#-cómo-funciona) | +| [Testing](#-testing) | [Troubleshooting](#-errores-conocidos-y-troubleshooting) | [Monitoreo](#-monitoreo) | +| [Estructura](#-estructura-del-repositorio) | [Changelog](#-changelog) | [Definition of Done](#-definition-of-done) | + +--- + +## 📌 Información general + + + + + + + + +
Estado
🟢 Listo para producción
Versión
v1.0.0
Producción
home.digitalcompass.agency
Responsable
Isaac Aracena
+ +| 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/` | + +--- + +## ✨ Capacidades principales + +| Catálogo compartido | Experiencia personalizada | Automatización | +|---|---|---| +| Aplicaciones publicadas visibles para todos los usuarios autorizados | Favoritos y accesos recientes por usuario | Generación de íconos con Gemini | +| Administración sin modificar código | Rol **Administrador** o **Usuario** | Solicitudes y decisiones por correo | +| Actualización en tiempo real | Paginación y búsqueda | Primera decisión protegida en Supabase | + +--- + +## 🎯 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 + +```mermaid +flowchart LR + U[Usuario] --> F[GLM Hub
React + Vite] + F --> A[Supabase Auth
Google OAuth] + F --> D[(Supabase Postgres)] + F --> S[Supabase Storage] + F --> N1[n8n
Generar ícono] + F --> N2[n8n
Solicitar acceso] + N1 --> G[Google Gemini] + N2 --> M[Gmail] + D --> R[Roles · Catálogo · Favoritos · Solicitudes] + M --> AP[Aprobadores] + AP --> IT[IT Support] +``` + +
+Ver flujo técnico en formato texto + +```text +Usuario + └── Frontend React + Vite + ├── Supabase Auth (Google OAuth) + ├── Supabase Postgres + RLS + Realtime + ├── Supabase Storage (íconos) + ├── n8n → Gemini (generación de íconos) + └── n8n → Gmail → aprobadores → 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 + +1. Solo pueden iniciar sesión usuarios activos registrados en `glm_hub_authorized_users` y con correo del dominio `@gomezleemarketing.com`. +2. Los roles válidos son `admin` y `member`. +3. 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` +4. Solo los administradores pueden abrir el apartado **Administrar**, crear, editar, publicar, ocultar o eliminar aplicaciones. +5. Todos los usuarios autorizados ven el mismo catálogo de aplicaciones publicadas. +6. El Hub no controla el acceso interno de cada aplicación; ese permiso se administra desde el login o backend de cada portal. +7. Las categorías disponibles son **Administración**, **Recursos Humanos** y **CDC**. +8. No se puede publicar una aplicación sin ícono. +9. El nombre debe tener entre 2 y 60 caracteres y la descripción un máximo de 180 caracteres. +10. Los íconos admitidos son PNG, JPG o WebP y no pueden superar 1 MB. +11. Los favoritos y accesos recientes son personales y no afectan la vista de otros usuarios. +12. Los favoritos se ordenan antes que las demás aplicaciones antes de aplicar la paginación. +13. Los usuarios normales pueden solicitar acceso a cualquier aplicación publicada. +14. No se permite una segunda solicitud pendiente del mismo usuario para la misma aplicación. +15. Las solicitudes se envían individualmente a Isaac Aracena, José Leopoldo Gómez y Máximo Gómez. +16. La primera decisión registrada gana; cualquier intento posterior queda bloqueado y no cambia el resultado. +17. Después de aprobar o rechazar, IT Support recibe un correo con el solicitante, la aplicación, el resultado y la persona que decidió. +18. 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 | + +> [!CAUTION] +> **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: + +```text +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: + +```text +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 + +```bash +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: + +```powershell +Copy-Item .env.example .env +``` + +### Build + +```bash +npm run build +``` + +La compilación se genera en: + +```text +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. + +```ts +export default defineConfig({ + plugins: [react()], +}); +``` + +Copiar el contenido de `dist/` directamente al Document Root del subdominio: + +```text +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: + +```text +https://home.digitalcompass.agency/ +http://localhost:4173/ +``` + +Si se utiliza un VirtualHost local, registrar también su URL completa. + +--- + +## 🔄 Cómo funciona + +### Flujo general + +1. El usuario entra al Hub y selecciona **Continuar con Google**. +2. Supabase Auth valida la cuenta de Google. +3. El frontend consulta `glm_hub_authorized_users` para confirmar que el usuario esté activo y conocer su rol. +4. El catálogo compartido se carga desde `glm_hub_apps`. +5. Los favoritos y recientes se cargan para el usuario autenticado. +6. Supabase Realtime mantiene el catálogo actualizado en sesiones abiertas. +7. Los administradores pueden crear, editar, ocultar o eliminar aplicaciones. +8. Los usuarios normales pueden solicitar acceso a una aplicación publicada. + +### Generación de íconos + +1. El administrador completa nombre y descripción. +2. El frontend llama el webhook `glm-hub-generar-icono`. +3. n8n valida el JWT y confirma el rol de administrador. +4. Gemini genera una imagen cuadrada sin texto. +5. n8n devuelve el archivo binario al frontend. +6. El ícono se previsualiza y se guarda en Supabase Storage al publicar. + +### Solicitud de acceso + +1. El usuario selecciona un área y una aplicación publicada. +2. n8n registra la solicitud en Supabase. +3. Supabase emite un token único para cada aprobador. +4. Gmail envía un correo individual a cada aprobador. +5. El aprobador confirma **Aceptar** o **Rechazar**. +6. Supabase registra atómicamente la primera decisión. +7. n8n envía el resultado a `itsupport@gomezleemarketing.com`. +8. 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: + +```sql +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 + +```text +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 + +- [x] Catálogo compartido en Supabase. +- [x] Autenticación con Google operativa. +- [x] Roles de administrador y usuario aplicados. +- [x] RLS configurado para tablas y Storage. +- [x] Favoritos y recientes por usuario. +- [x] Paginación implementada. +- [x] Generación de íconos con IA operativa. +- [x] Workflows de n8n exportados en `/n8n`. +- [x] SQL completo incluido en el repositorio. +- [x] Variables documentadas en `.env.example`. +- [x] Solicitudes de acceso y primera decisión validadas. +- [x] Código y build listos para Gitea. +- [x] 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** +GomezLee Marketing · 2026 + +