23 KiB
Lucozade Store Audit Dashboard
Dashboard web seguro para consultar y analizar auditorías de tiendas Lucozade, con autenticación por usuario/contraseña, recuperación de acceso y despliegue en DigitalCompass.
INFORMACIÓN GENERAL
| Campo | Detalle |
|---|---|
| Proyecto | Lucozade Store Audit Dashboard |
| Área | Cliente externo / Trade Marketing / Auditoría de Punto de Venta |
| Estado | En despliegue final |
| Developer Principal | Isaac Aracena |
| IT Manager | Luis Matos |
| Fecha de Inicio | 2026-08-05 |
| Fecha de Cierre Estimada | Pendiente de validación final en servidor |
| Ciclo Shape Up | No especificado |
| Board de Ejecución | No especificado |
| PRD del Proyecto | No especificado |
| Repositorio | https://git.digitalcompass.agency/Isaac_Aracena/lucozade-audit-dashboard |
| URL de Producción | https://digitalcompass.agency/lucozade/ |
OBJETIVO
Problema que resuelve
El dashboard de auditorías podía ser accedido únicamente conociendo la URL, sin un mecanismo de autenticación para usuarios externos. Esto representaba un riesgo de acceso no autorizado y dificultaba controlar quién podía consultar la información de auditorías de tiendas.
Adicionalmente, el dashboard necesita consolidar de forma simple la información de tiendas y respuestas de auditoría provenientes de Google Sheets, permitiendo revisar cobertura, disponibilidad, OOS, exhibiciones, inventario, facings, precios y evidencia fotográfica.
Solución implementada
Se implementó una capa completa de autenticación para la aplicación:
- Inicio de sesión con correo y contraseña.
- Registro de usuarios externos.
- Control de acceso mediante Supabase.
- Recuperación de contraseña por correo.
- Correos transaccionales enviados por n8n mediante Gmail OAuth.
- Opción Remember me.
- Sesiones persistentes o temporales según elección del usuario.
- Botón Sign out dentro del dashboard.
- Despliegue preparado bajo la ruta
/lucozade/. - Compatibilidad tanto con desarrollo local como con producción.
La aplicación mantiene además su funcionalidad principal de auditoría y consume información desde Google Sheets para construir el dashboard.
Usuarios / Beneficiarios
- Cliente externo.
- Usuarios autorizados responsables de consultar auditorías de punto de venta.
- Equipos de ejecución y seguimiento de Lucozade.
- Administradores responsables de gestionar accesos.
ARQUITECTURA
Diagrama de flujo
┌───────────────────────────────┐
│ Lucozade Store Audit │
│ React + Vite SPA │
└──────────────┬────────────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
Supabase Auth n8n Auth Webhook Google Sheets
Sign in / Session Register / Recover Stores + Audits
│ │ │
│ ▼ │
│ Supabase Admin API │
│ │ │
│ lucozade_access │
│ │ │
│ ▼ │
│ Gmail OAuth │
│ │ │
└──────────────────┴──────────────────┘
│
▼
Dashboard autenticado
Flujo de autenticación
Registro
App -> n8n Webhook -> Supabase Auth Admin -> lucozade_access -> Gmail -> Usuario
Inicio de sesión
App -> Supabase Auth -> Verificación lucozade_access -> Dashboard
Recuperación
App -> n8n Webhook -> Supabase generate_link -> Gmail -> Usuario
-> Supabase Recovery Session -> Pantalla New Password -> Supabase Auth
Stack tecnológico
| Componente | Tecnología | Propósito |
|---|---|---|
| Frontend | React 19 + TypeScript | Interfaz del dashboard |
| Bundler | Vite 6 | Desarrollo y compilación |
| UI | Tailwind CSS 4 + Lucide React | Diseño e iconografía |
| Autenticación | Supabase Auth | Usuarios, contraseñas y sesiones |
| Base de datos | Supabase / PostgreSQL | Control de acceso de la aplicación |
| Automatización | n8n | Registro, recuperación y envío de correos |
| Notificaciones | Gmail OAuth | Correos transaccionales |
| Datos de auditoría | Google Sheets | Tiendas y respuestas de auditoría |
| Parsing CSV | PapaParse | Lectura de exportaciones de Google Sheets |
| Infraestructura | DigitalCompass + EasyPanel | Hosting y servicios |
| Control de versiones | Gitea | Repositorio del proyecto |
Integraciones externas
| Sistema | Tipo de integración | Datos que fluyen |
|---|---|---|
| Supabase Auth | REST API | Registro, login, sesión, recuperación y cambio de contraseña |
| Supabase PostgREST | REST API | Autorización mediante lucozade_access |
| n8n | Webhook POST | Solicitudes de registro y recuperación |
| Gmail | OAuth 2.0 | Correos de bienvenida y recuperación |
| Google Sheets | CSV publicado / API v4 | Tiendas, auditorías y evidencia de campo |
| DigitalCompass | Hosting web | Publicación del dist de producción |
REGLAS DE NEGOCIO
- El sistema acepta usuarios externos; no existe restricción por dominio de correo.
- La cuenta real del usuario vive en
auth.usersde Supabase. public.lucozade_accessdetermina si una cuenta puede acceder a esta aplicación.- Eliminar una fila de
lucozade_accessrevoca el acceso, pero no elimina la cuenta de Supabase Auth. - Para eliminar completamente una cuenta se debe eliminar el usuario desde Supabase Authentication → Users.
- Solo usuarios con
is_active = truepueden ingresar al dashboard. - El registro se realiza desde n8n utilizando la API administrativa de Supabase.
- La
service_rolede Supabase nunca debe estar disponible en el navegador ni commiteada en Gitea. - El inicio de sesión se realiza directamente contra Supabase Auth utilizando la clave pública
anon. - Remember me conserva correo y sesión de forma persistente.
- Si Remember me no está seleccionado, la sesión se conserva únicamente durante la sesión actual del navegador/pestaña.
- La recuperación utiliza enlaces nativos de recuperación de Supabase generados desde n8n.
- Los correos de autenticación utilizan George Mendieta como Sender Name en los nodos Gmail.
- El workflow debe permitir CORS para los orígenes locales aprobados y para
https://digitalcompass.agency. - La aplicación de producción se publica obligatoriamente bajo
/lucozade/. - No se deben incluir referencias visuales a GomezLee Marketing dentro de la interfaz de autenticación orientada al cliente.
- Si Google Sheets no está disponible, la aplicación dispone de un dataset de fallback para evitar que el dashboard falle completamente.
CONFIGURACIÓN Y SETUP
Prerrequisitos
- Node.js y npm instalados.
- Acceso al repositorio Gitea.
- Acceso al proyecto Supabase.
- Acceso a n8n.
- Credencial Gmail OAuth configurada en n8n.
- Permisos para publicar archivos en el servidor de DigitalCompass.
ADDITIONAL_REDIRECT_URLSconfigurado en el entorno de Supabase/EasyPanel.
Variables de entorno de la aplicación
Crear .env a partir de .env.example.
| Variable | Descripción | Dónde se obtiene |
|---|---|---|
VITE_SUPABASE_URL |
URL pública del proyecto Supabase | Infraestructura / Supabase |
VITE_SUPABASE_ANON_KEY |
Clave pública anon utilizada por el frontend |
Supabase |
VITE_N8N_AUTH_WEBHOOK_URL |
Webhook de producción del workflow de autenticación | n8n |
Ejemplo:
VITE_SUPABASE_URL="https://YOUR-SUPABASE-DOMAIN"
VITE_SUPABASE_ANON_KEY="YOUR_ANON_KEY"
VITE_N8N_AUTH_WEBHOOK_URL="https://YOUR-N8N-DOMAIN/webhook/lucozade-auth-v6"
NUNCA commitear
.env,SERVICE_ROLE_KEY, contraseñas ni credenciales OAuth al repositorio.
Configuración de n8n
Workflow actual:
Lucozade - Auth Direct via n8n V6
Webhook:
POST /webhook/lucozade-auth-v6
El workflow debe tener configurados:
- URL de Supabase.
service_rolede Supabase únicamente dentro de n8n.- Credencial Gmail OAuth.
- Sender Name
George Mendieta. - CORS para producción y ambientes locales autorizados.
La versión corregida debe mantener expresiones booleanas válidas en todos los nodos IF, por ejemplo:
={{ $json.valid }}
y no:
={ $json.valid }
ADDITIONAL_REDIRECT_URLS
Mantener los valores existentes de la instalación Supabase y agregar las URLs de Lucozade necesarias para producción y pruebas locales.
Producción:
https://digitalcompass.agency/lucozade/
https://digitalcompass.agency/lucozade
Desarrollo Vite:
http://localhost:3000/
http://127.0.0.1:3000/
http://localhost:5173/
http://127.0.0.1:5173/
Preview:
http://localhost:4173/lucozade/
http://127.0.0.1:4173/lucozade/
XAMPP:
http://localhost/lucozade/
http://localhost/lucozade
http://127.0.0.1/lucozade/
http://127.0.0.1/lucozade
CORS del Webhook n8n
Orígenes permitidos:
https://digitalcompass.agency,http://localhost,http://127.0.0.1,http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://127.0.0.1:5173,http://localhost:4173,http://127.0.0.1:4173
No colocar rutas como /lucozade/ en Allowed Origins (CORS); se configuran únicamente los orígenes.
ESQUEMA DE BASE DE DATOS
El script versionado en el repositorio es:
Lucozade_Auth_V6_Supabase.sql
La tabla principal de autorización es:
public.lucozade_access
Campos:
| Campo | Tipo | Descripción |
|---|---|---|
user_id |
uuid |
ID del usuario en auth.users |
email |
text |
Correo normalizado |
full_name |
text |
Nombre del usuario |
is_active |
boolean |
Habilita o bloquea el acceso |
created_at |
timestamptz |
Fecha de creación |
updated_at |
timestamptz |
Última actualización |
La tabla usa RLS y permite al usuario autenticado consultar únicamente su propio acceso activo.
El script también instala un trigger para crear automáticamente lucozade_access cuando un usuario nuevo de la aplicación es creado en Supabase Auth.
INSTALACIÓN / DEPLOY
Clonar el repositorio
git clone https://git.digitalcompass.agency/Isaac_Aracena/lucozade-audit-dashboard.git
cd lucozade-audit-dashboard
Preparar variables
cp .env.example .env
Editar .env con los valores reales.
Instalar dependencias
npm install
Desarrollo local
npm run dev
URL:
http://localhost:3000/
Validación TypeScript
npm run lint
Build de producción
npm run build
El resultado se genera en:
/dist
Deploy en DigitalCompass
La configuración de Vite utiliza:
base: '/lucozade/'
Por lo tanto, en el servidor debe existir:
/lucozade/
y dentro se debe copiar el contenido interno de dist:
lucozade/
├── index.html
└── assets/
No subir la carpeta así:
lucozade/dist/index.html
URL final:
https://digitalcompass.agency/lucozade/
CÓMO FUNCIONA
Flujo paso a paso — Registro
- El usuario selecciona Create account.
- Ingresa nombre, correo y contraseña.
- La aplicación envía la solicitud al webhook de n8n.
- n8n crea el usuario mediante Supabase Auth Admin.
- Se crea o actualiza
lucozade_access. - n8n envía el correo de bienvenida mediante Gmail.
- El usuario puede iniciar sesión con sus credenciales.
Flujo paso a paso — Inicio de sesión
- El usuario ingresa correo y contraseña.
- La aplicación autentica directamente contra Supabase Auth.
- La aplicación verifica que exista un acceso activo en
lucozade_access. - Si está autorizado, se muestra el dashboard.
- Si Remember me está seleccionado, la sesión queda persistente.
- El botón Sign out invalida/limpia la sesión local.
Flujo paso a paso — Recuperación
- El usuario selecciona Forgot password?.
- Ingresa su correo.
- La aplicación llama al webhook de n8n.
- n8n valida que el usuario tenga acceso activo.
- n8n solicita a Supabase un enlace nativo de recuperación.
- Gmail envía el correo al usuario.
- El usuario pulsa Create new password.
- Supabase procesa el token y redirige a la aplicación.
- La aplicación detecta la sesión de recuperación.
- Se muestra la pantalla para establecer la contraseña nueva.
- Supabase actualiza la contraseña.
- El usuario vuelve a Sign in.
Flujo del dashboard
- La aplicación carga la lista maestra de tiendas.
- Carga las respuestas de auditoría desde Google Sheets.
- Normaliza y relaciona tiendas con respuestas.
- Calcula KPIs y estado de auditoría.
- Presenta filtros, métricas, detalle por tienda, inventario, OOS y evidencia.
- Si falla Google Sheets, utiliza el dataset fallback incluido en la aplicación.
SCHEDULES / TRIGGERS
| Trigger | Frecuencia | Descripción |
|---|---|---|
POST /webhook/lucozade-auth-v6 |
On demand | Registro y recuperación solicitados desde la aplicación |
| Supabase Auth REST | On demand | Login, refresh de sesión y cambio de contraseña |
| Carga Google Sheets | Al abrir/refrescar dashboard | Obtiene tiendas y respuestas para construir el dashboard |
TESTING
Casos de prueba mínimos
| Caso | Input | Output esperado | Estado |
|---|---|---|---|
| Registro nuevo | Correo no existente + contraseña válida | Usuario en Auth + acceso activo | Verificado en local |
| Registro duplicado | Correo ya existente | No sobrescribir contraseña silenciosamente | Verificado |
| Login válido | Credenciales correctas | Acceso al dashboard | Verificado |
| Login inválido | Contraseña incorrecta | Error controlado | Verificado |
| Remember me | Checkbox activo | Correo/sesión persistentes | Implementado |
| Sesión temporal | Checkbox inactivo | Sesión no persistente entre sesiones del navegador | Implementado |
| Recuperación | Usuario activo | Correo de recuperación enviado | Verificado en local |
| Link recovery | Token válido | Pantalla para crear contraseña | Pendiente de validación final en servidor |
| Usuario bloqueado | is_active=false |
Acceso denegado | Implementado |
| CORS Vite | localhost:3000 |
Webhook accesible | Configurado |
| CORS XAMPP | http://localhost |
Webhook accesible | Configurado |
| Build producción | npm run build |
dist/index.html + dist/assets/ |
Verificado |
| Base de Vite | /lucozade/ |
Assets resueltos bajo la subcarpeta | Verificado en build |
| Google Sheets inaccesible | Error de red/API | Dataset fallback, sin crash | Implementado |
ERRORES CONOCIDOS Y TROUBLESHOOTING
| Error | Causa probable | Solución |
|---|---|---|
Invalid authentication credentials |
Contraseña incorrecta o cuenta Auth diferente al acceso público | Revisar Authentication → Users; lucozade_access no almacena contraseñas |
The authentication service could not be reached |
CORS, webhook no publicado o URL incorrecta | Revisar VITE_N8N_AUTH_WEBHOOK_URL, CORS y ejecución de n8n |
Wrong type ... expected a boolean en n8n |
Expresión IF importada como texto | Usar ={{ $json.valid }} y expresiones equivalentes |
| Correo no llega | Credencial Gmail o rama de n8n falla | Revisar n8n → Executions y nodos Gmail |
| Recovery abre 404 | App aún no publicada en /lucozade/ o redirect incorrecto |
Publicar dist y revisar ADDITIONAL_REDIRECT_URLS |
| Assets 404 en producción | base de Vite o estructura del deploy incorrecta |
Confirmar base: '/lucozade/' y contenido de dist directamente en /lucozade/ |
| Cuenta “existe” después de borrar tabla pública | El usuario continúa en auth.users |
Eliminar desde Supabase Authentication → Users si se necesita borrado total |
| Dashboard muestra demo | Google Sheets no pudo ser leído | Revisar publicación/permisos del Sheet y consola del navegador |
| Webhook funciona en Vite pero no XAMPP | Falta http://localhost en CORS |
Agregar el origen exacto al Webhook |
MONITOREO
- n8n Executions: revisar errores del workflow de autenticación.
- Supabase Authentication → Users: revisar usuarios reales del sistema.
public.lucozade_access: verificar usuarios habilitados y bloqueados.- Gmail OAuth: confirmar que los correos se están enviando correctamente.
- Browser Console: revisar errores de CORS, Supabase y Google Sheets.
- Output normal esperado: usuario autenticado, acceso activo, dashboard cargado y datos de auditoría visibles.
ESTRUCTURA DEL REPOSITORIO
lucozade-audit-dashboard/
├── dist/ # Build listo para publicar en servidor
│ ├── index.html
│ └── assets/
├── src/
│ ├── components/ # UI del dashboard y autenticación
│ ├── data/ # Dataset fallback
│ ├── services/
│ │ ├── supabaseAuth.ts # Auth, sesiones y recuperación
│ │ └── googleSheets.ts # Lectura y normalización de Sheets
│ ├── utils/
│ ├── App.tsx
│ ├── main.tsx
│ └── index.css
├── .env.example
├── .gitignore
├── index.html
├── Lucozade_Auth_V6_Supabase.sql
├── metadata.json
├── package.json
├── package-lock.json
├── SETUP_RAPIDO.txt
├── tsconfig.json
├── VALIDACION_V6.txt
├── vite.config.ts
└── README.md
Workflow n8n
El workflow se ejecuta en la instancia de n8n y contiene configuración sensible.
Si se decide versionarlo en Gitea, debe exportarse sin secretos a una ruta como:
/automation/Lucozade_Auth_Direct_n8n_V6_READY.json
Antes de commitearlo, eliminar cualquier SERVICE_ROLE_KEY, token o credencial incrustada.
CHANGELOG
2026-08-07 — v1.0
- Login por correo y contraseña operativo.
- Registro mediante n8n + Supabase.
- Control de acceso con
lucozade_access. - Recuperación de contraseña mediante n8n + Gmail.
- Corrección de expresiones booleanas del workflow.
- Remember me agregado.
- Sign out agregado.
- Base Vite
/lucozade/configurada. - Compatibilidad con Vite, XAMPP y producción.
distgenerado y versionado para despliegue en servidor.- Repositorio inicial publicado en Gitea.
2026-08-06 — v0.6
- Integración completa de Supabase Auth.
- Flujo de recuperación y correos HTML.
- Configuración de redirect URLs y CORS.
- Preparación de build para DigitalCompass.
2026-08-05 — v0.1
- Inicio de implementación de autenticación.
- Setup inicial de Supabase, n8n y aplicación.
DECISIONS LOG
DEC-001 — Supabase Auth como fuente de identidad
- Fecha: 2026-08-05
- Contexto: Se necesitaba proteger el dashboard con usuarios externos.
- Opciones consideradas: Autenticación propia vs Supabase Auth.
- Decisión: Usar Supabase Auth.
- Razón: Centraliza usuarios, contraseñas, sesiones y recuperación de forma segura.
DEC-002 — n8n para correos de autenticación
- Fecha: 2026-08-05
- Contexto: Se requerían correos HTML modernos sin depender de SMTP directo en Supabase.
- Opciones consideradas: SMTP/GoTrue Hook vs webhook directo desde la aplicación.
- Decisión: Usar n8n como backend de registro/recuperación y Gmail OAuth para envío.
- Razón: Mantiene las claves administrativas fuera del navegador y permite controlar completamente el HTML de los correos.
DEC-003 — Separar identidad de autorización
- Fecha: 2026-08-06
- Contexto: Borrar datos de acceso no debía confundirse con eliminar la cuenta real.
- Opciones consideradas: Solo
auth.usersvs tabla de acceso por aplicación. - Decisión:
auth.usersmantiene la identidad ylucozade_accesscontrola el acceso a Lucozade. - Razón: Permite bloquear acceso sin destruir la cuenta.
DEC-004 — Base Vite /lucozade/
- Fecha: 2026-08-06
- Contexto: La aplicación se desplegará en una subcarpeta de DigitalCompass.
- Decisión: Configurar el build con
base: '/lucozade/'. - Razón: Garantiza rutas correctas de JavaScript, CSS y assets en producción.
DEC-005 — Sin branding de GomezLee en la autenticación
- Fecha: 2026-08-05
- Contexto: La aplicación está orientada a un cliente externo.
- Decisión: Mantener la pantalla de autenticación neutral y alineada visualmente con Lucozade.
- Razón: Evitar referencias internas en una aplicación de cliente.
DEC-006 — service_role solo en backend
- Fecha: 2026-08-05
- Contexto: El registro y generación de enlaces requieren permisos administrativos.
- Decisión: La
service_rolenunca se expone en el frontend. - Razón: Es una credencial crítica que omite restricciones de seguridad de Supabase.
CONTACTOS DEL PROYECTO
| Rol | Nombre | Contacto |
|---|---|---|
| Product Owner / Cliente | No especificado | No especificado |
| IT Manager | Luis Matos | Contacto interno |
| Developer Principal | Isaac Aracena | iaracena@gomezleemarketing.com |
DEFINITION OF DONE
- Autenticación por correo y contraseña implementada.
- Registro de usuarios implementado.
- Control de acceso con Supabase implementado.
- Recuperación de contraseña implementada.
- Correos HTML enviados mediante n8n + Gmail.
- Remember me implementado.
- Sign out implementado.
- Variables de frontend documentadas en
.env.example. - Script SQL versionado.
- Build
distgenerado y agregado al repositorio. - Código commiteado y pusheado a Gitea.
- README actualizado.
- Pruebas principales realizadas en ambiente local.
- Publicar
disten/lucozade/del servidor. - Validar recuperación completa desde la URL de producción.
- Validación final del cliente / responsable del proyecto.
Documento basado en el estándar interno de documentación de repositorios y mantenido por el equipo responsable del proyecto.