Subir archivos a "/"

This commit is contained in:
2026-08-07 22:06:41 +00:00
parent 76573ece52
commit c4de16e313
+651
View File
@@ -0,0 +1,651 @@
# 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
```text
┌───────────────────────────────┐
│ 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
```text
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
1. El sistema acepta usuarios externos; no existe restricción por dominio de correo.
2. La cuenta real del usuario vive en `auth.users` de Supabase.
3. `public.lucozade_access` determina si una cuenta puede acceder a esta aplicación.
4. Eliminar una fila de `lucozade_access` revoca el acceso, pero no elimina la cuenta de Supabase Auth.
5. Para eliminar completamente una cuenta se debe eliminar el usuario desde **Supabase Authentication → Users**.
6. Solo usuarios con `is_active = true` pueden ingresar al dashboard.
7. El registro se realiza desde n8n utilizando la API administrativa de Supabase.
8. La `service_role` de Supabase nunca debe estar disponible en el navegador ni commiteada en Gitea.
9. El inicio de sesión se realiza directamente contra Supabase Auth utilizando la clave pública `anon`.
10. **Remember me** conserva correo y sesión de forma persistente.
11. Si **Remember me** no está seleccionado, la sesión se conserva únicamente durante la sesión actual del navegador/pestaña.
12. La recuperación utiliza enlaces nativos de recuperación de Supabase generados desde n8n.
13. Los correos de autenticación utilizan **George Mendieta** como Sender Name en los nodos Gmail.
14. El workflow debe permitir CORS para los orígenes locales aprobados y para `https://digitalcompass.agency`.
15. La aplicación de producción se publica obligatoriamente bajo `/lucozade/`.
16. No se deben incluir referencias visuales a GomezLee Marketing dentro de la interfaz de autenticación orientada al cliente.
17. 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_URLS` configurado 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:
```env
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:
```text
Lucozade - Auth Direct via n8n V6
```
Webhook:
```text
POST /webhook/lucozade-auth-v6
```
El workflow debe tener configurados:
- URL de Supabase.
- `service_role` de 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:
```text
={{ $json.valid }}
```
y no:
```text
={ $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:
```text
https://digitalcompass.agency/lucozade/
https://digitalcompass.agency/lucozade
```
Desarrollo Vite:
```text
http://localhost:3000/
http://127.0.0.1:3000/
http://localhost:5173/
http://127.0.0.1:5173/
```
Preview:
```text
http://localhost:4173/lucozade/
http://127.0.0.1:4173/lucozade/
```
XAMPP:
```text
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:
```text
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:
```text
Lucozade_Auth_V6_Supabase.sql
```
La tabla principal de autorización es:
```text
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
```bash
git clone https://git.digitalcompass.agency/Isaac_Aracena/lucozade-audit-dashboard.git
cd lucozade-audit-dashboard
```
### Preparar variables
```bash
cp .env.example .env
```
Editar `.env` con los valores reales.
### Instalar dependencias
```bash
npm install
```
### Desarrollo local
```bash
npm run dev
```
URL:
```text
http://localhost:3000/
```
### Validación TypeScript
```bash
npm run lint
```
### Build de producción
```bash
npm run build
```
El resultado se genera en:
```text
/dist
```
### Deploy en DigitalCompass
La configuración de Vite utiliza:
```ts
base: '/lucozade/'
```
Por lo tanto, en el servidor debe existir:
```text
/lucozade/
```
y dentro se debe copiar **el contenido interno de `dist`**:
```text
lucozade/
├── index.html
└── assets/
```
No subir la carpeta así:
```text
lucozade/dist/index.html
```
URL final:
```text
https://digitalcompass.agency/lucozade/
```
---
## CÓMO FUNCIONA
### Flujo paso a paso — Registro
1. El usuario selecciona **Create account**.
2. Ingresa nombre, correo y contraseña.
3. La aplicación envía la solicitud al webhook de n8n.
4. n8n crea el usuario mediante Supabase Auth Admin.
5. Se crea o actualiza `lucozade_access`.
6. n8n envía el correo de bienvenida mediante Gmail.
7. El usuario puede iniciar sesión con sus credenciales.
### Flujo paso a paso — Inicio de sesión
1. El usuario ingresa correo y contraseña.
2. La aplicación autentica directamente contra Supabase Auth.
3. La aplicación verifica que exista un acceso activo en `lucozade_access`.
4. Si está autorizado, se muestra el dashboard.
5. Si **Remember me** está seleccionado, la sesión queda persistente.
6. El botón **Sign out** invalida/limpia la sesión local.
### Flujo paso a paso — Recuperación
1. El usuario selecciona **Forgot password?**.
2. Ingresa su correo.
3. La aplicación llama al webhook de n8n.
4. n8n valida que el usuario tenga acceso activo.
5. n8n solicita a Supabase un enlace nativo de recuperación.
6. Gmail envía el correo al usuario.
7. El usuario pulsa **Create new password**.
8. Supabase procesa el token y redirige a la aplicación.
9. La aplicación detecta la sesión de recuperación.
10. Se muestra la pantalla para establecer la contraseña nueva.
11. Supabase actualiza la contraseña.
12. El usuario vuelve a **Sign in**.
### Flujo del dashboard
1. La aplicación carga la lista maestra de tiendas.
2. Carga las respuestas de auditoría desde Google Sheets.
3. Normaliza y relaciona tiendas con respuestas.
4. Calcula KPIs y estado de auditoría.
5. Presenta filtros, métricas, detalle por tienda, inventario, OOS y evidencia.
6. 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
```text
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:
```text
/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.
- `dist` generado 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.users` vs tabla de acceso por aplicación.
- **Decisión:** `auth.users` mantiene la identidad y `lucozade_access` controla 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_role` nunca 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
- [x] Autenticación por correo y contraseña implementada.
- [x] Registro de usuarios implementado.
- [x] Control de acceso con Supabase implementado.
- [x] Recuperación de contraseña implementada.
- [x] Correos HTML enviados mediante n8n + Gmail.
- [x] **Remember me** implementado.
- [x] **Sign out** implementado.
- [x] Variables de frontend documentadas en `.env.example`.
- [x] Script SQL versionado.
- [x] Build `dist` generado y agregado al repositorio.
- [x] Código commiteado y pusheado a Gitea.
- [x] README actualizado.
- [x] Pruebas principales realizadas en ambiente local.
- [ ] Publicar `dist` en `/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.