diff --git a/PLAN_TRAZABILIDAD.md b/PLAN_TRAZABILIDAD.md index c79e47f..fec0823 100644 --- a/PLAN_TRAZABILIDAD.md +++ b/PLAN_TRAZABILIDAD.md @@ -1,8 +1,44 @@ # Plan de Trazabilidad de Lotes - Seguidor de Lotes +## Estado Actual del Proyecto + +🌐 **Producción**: https://lotes.nucleoriofrio.com + +### ✅ Completado + +- [x] Modelo de base de datos (grafo DAG) +- [x] Scripts de inicialización y seed con datos de ejemplo +- [x] API REST completa (11 endpoints) +- [x] Función recursiva de trazabilidad SQL +- [x] Autenticación con Authentik Proxy +- [x] CI/CD con Gitea Actions +- [x] Despliegue automático con Docker Compose +- [x] Persistencia de datos entre deploys +- [x] Configuración automática de autenticación PostgreSQL +- [x] Botones de prueba de API en frontend + +### 🎯 Objetivo Actual: Visualización del Grafo + +**Meta**: Implementar un componente visual que muestre el grafo de trazabilidad de forma interactiva. + +**Requisitos**: +- Visualizar el flujo completo de un lote desde origen hasta estado actual +- Mostrar nodos (lotes) y aristas (operaciones) +- Interactividad: zoom, pan, click en nodos +- Metadatos al hacer hover +- Indicadores visuales por tipo de operación + +**Tecnologías a considerar**: +- D3.js (máximo control, curva de aprendizaje) +- vis.js (redes y grafos, fácil de usar) +- Cytoscape.js (grafos complejos, buena performance) +- ELK.js (layout automático de grafos) + +--- + ## Descripción General -El **Sistema de Trazabilidad de Lotes** es una aplicación web diseñada para rastrear el flujo completo del café desde el ingreso de uva hasta el secado final. Implementa un **modelo de grafo** que permite representar operaciones complejas como: +El **Sistema de Trazabilidad de Lotes** rastrea el flujo completo del café desde el ingreso de uva hasta el secado final. Implementa un **modelo de grafo (DAG)** que permite representar operaciones complejas: - **División**: Un lote se divide en varios (ej: despulpado → primera, segunda, rechazos) - **Combinación**: Varios lotes se mezclan en uno (ej: varios reposos → un secado) diff --git a/README.md b/README.md index 2a8fd5f..4580e0d 100644 --- a/README.md +++ b/README.md @@ -1,241 +1,331 @@ -# Seguidor de Lotes +# Seguidor de Lotes - Sistema de Trazabilidad de Café -Aplicación Nuxt 4 para seguimiento y gestión de lotes, con autenticación mediante Authentik Proxy Outpost. +Sistema completo de trazabilidad para café, desde ingreso de uva hasta secado final, implementando un modelo de grafo (DAG) para rastrear transformaciones, divisiones y combinaciones de lotes. -## Estructura del Proyecto +🌐 **URL**: https://lotes.nucleoriofrio.com + +## 🎯 Características Principales + +- ✅ **Trazabilidad Completa**: Rastreo desde ingreso de uva hasta café secado +- ✅ **Modelo de Grafo (DAG)**: Soporta divisiones (1→N), combinaciones (N→1) y transformaciones (1→1) +- ✅ **API REST Completa**: 11 endpoints para gestión de lotes y operaciones +- ✅ **Frontend Interactivo**: Interfaz con Nuxt UI para visualización y gestión +- ✅ **Función Recursiva de Trazabilidad**: Consulta SQL que recorre todo el historial +- ✅ **PostgreSQL sin ORM**: Queries directas con driver `pg` +- ✅ **Autenticación Authentik**: Protección mediante Proxy Outpost +- ✅ **CI/CD Automático**: Gitea Actions para build y deploy + +## 📊 Modelo de Datos + +### Estructura del Grafo + +El sistema usa 3 tablas principales que forman un grafo dirigido acíclico (DAG): + +``` +┌─────────────┐ ┌──────────────────┐ ┌─────────────┐ +│ LOTES │◄─────│ OPERACION_LOTES │─────►│ OPERACIONES │ +│ │ │ │ │ │ +│ - id │ │ - operacion_id │ │ - id │ +│ - codigo │ │ - lote_id │ │ - tipo │ +│ - tipo │ │ - rol (in/out) │ │ - fecha │ +│ - cantidad │ │ - cantidad_kg │ │ - meta │ +└─────────────┘ └──────────────────┘ └─────────────┘ +``` + +### Tipos de Operaciones Soportadas + +- **Ingreso**: Recepción de uva del productor +- **Despulpado**: 1→3 (genera primera, segunda, rechazos) +- **Oreado**: 1→1 (reducción de humedad en patio) +- **Presecado**: 1→1 (reducción adicional de humedad) +- **Reposo**: 1→1 (estabilización en bodega) +- **Secado**: N→1 (combinación de lotes para secado final) +- **Ajustes**: Corrección de mermas o tipos + +### Ejemplo de Flujo + +``` +UVA-001 (2086kg) + │ + ├─[Despulpado]─┬─► PRIM-001 (1500kg) + │ ├─► SEG-001 (400kg) + │ └─► RECH-001 (150kg) + │ + └─[Oreado]────► ORE-001 (1500kg) + │ + ├─[Ajuste merma]────► ORE-001A (1480kg) + │ + ├─[Ajuste tipo]─────► PRE-001 (1480kg) + │ + └─[Reposo]──────────► REP-001 (1480kg) + │ + ├─[Secado]─► SEC-001 (2000kg) + │ + REP-002 (520kg) +``` + +## 🚀 Inicio Rápido + +### Requisitos Previos + +- Docker y Docker Compose +- Gitea con Actions habilitado +- Traefik con red `traefik-network` +- Authentik con Proxy Outpost configurado + +### Despliegue Automático + +1. **Fork/Clone del repositorio** en tu Gitea + +2. **Configurar variables en Gitea** (`Settings > Actions`): + + **Secrets:** + - `REGISTRY_USERNAME` - Usuario del registro Docker + - `REGISTRY_PASSWORD` - Contraseña del registro + - `POSTGRES_PASSWORD` - Contraseña de PostgreSQL + + **Variables:** + - `REGISTRY_URL` - `gitea.nucleoriofrio.com` + - `APP_NAME` - `lotes` + - `APP_DOMAIN` - `lotes.nucleoriofrio.com` + - `NUXT_PUBLIC_APP_URL` - `https://lotes.nucleoriofrio.com` + - `POSTGRES_USER` - `seguidor` + - `POSTGRES_DB` - `seguidor_lotes` + +3. **Push al repositorio** - El workflow automáticamente: + - Construye la imagen Docker + - Sube la imagen al registro + - Despliega con docker-compose + - Inicializa PostgreSQL (solo primera vez) + - Carga datos de ejemplo (solo primera vez) + +## 📁 Estructura del Proyecto ``` . -├── nuxt4/ # Aplicación Nuxt 4 -├── docker-compose.yml # Configuración de despliegue -└── .gitea/ # Gitea Actions CI/CD +├── nuxt4/ +│ ├── app/ +│ │ ├── components/ +│ │ │ ├── lotes/ # Componentes de lotes +│ │ │ ├── operaciones/ # Componentes de operaciones +│ │ │ └── auth/ # Componentes de autenticación +│ │ ├── composables/ +│ │ │ ├── useLotes.ts # Lógica de negocio +│ │ │ └── useAuthentik.ts # Autenticación +│ │ └── app.vue # Aplicación principal +│ ├── server/ +│ │ ├── api/ +│ │ │ ├── lotes/ # Endpoints de lotes (6) +│ │ │ └── operaciones/ # Endpoints de operaciones (3) +│ │ ├── utils/ +│ │ │ ├── db.ts # Pool de PostgreSQL +│ │ │ └── queries.ts # Funciones SQL +│ │ └── database/ +│ │ ├── 00_configure_auth.sh # Config autenticación +│ │ ├── 01_schema.sql # Esquema DB +│ │ └── 02_seed.sql # Datos de ejemplo +│ └── package.json +├── docker-compose.yml # Servicios (app + postgres) +├── .gitea/workflows/ +│ └── build-and-deploy.yml # CI/CD +└── README.md ``` -## Características +## 🔌 API Endpoints -- ✅ Nuxt 4 -- ✅ Autenticación con Authentik Proxy Outpost -- ✅ Docker y Docker Compose -- ✅ CI/CD con Gitea Actions -- ✅ Traefik para proxy reverso y SSL -- ✅ Claude Code hooks para monitoreo de Actions -- ✅ Sin configuración OAuth necesaria (todo manejado por el proxy) +### Lotes -## Desarrollo Local +- `GET /api/lotes` - Listar lotes (con filtros) +- `POST /api/lotes` - Crear lote +- `GET /api/lotes/:id` - Obtener lote específico +- `PATCH /api/lotes/:id` - Actualizar lote +- `DELETE /api/lotes/:id` - Eliminar lote +- `GET /api/lotes/:id/trazabilidad` - Obtener trazabilidad completa + +### Operaciones + +- `GET /api/operaciones` - Listar operaciones +- `POST /api/operaciones` - Crear operación con lotes +- `GET /api/operaciones/:id` - Obtener operación específica + +### Ejemplo de Respuesta - Trazabilidad + +```json +{ + "success": true, + "data": { + "historial": [ + { + "lote_id": "...", + "codigo": "SEC-001", + "tipo": "secado", + "profundidad": 0, + "operacion_tipo": "secado", + "fecha_operacion": "2025-11-20T01:12:19.489Z" + }, + // ... historial completo hasta origen + ], + "estadisticas": { + "total_ancestros": 7, + "profundidad_maxima": 6, + "kg_iniciales": "2086.00" + } + } +} +``` + +## 🗄️ Base de Datos + +### Persistencia + +- ✅ **Los datos persisten entre deploys** (volumen Docker `lotes_postgres_data`) +- ✅ Scripts de inicialización solo se ejecutan si no existen tablas +- ✅ Configuración de autenticación (md5) se aplica automáticamente + +### Reiniciar BD a Estado Inicial + +Para volver a los datos de ejemplo: + +```bash +# Detener y eliminar volumen +docker compose --project-name lotes down -v + +# Próximo deploy reinicializará todo +git commit --allow-empty -m "Trigger redeploy" && git push +``` + +### Consultas Útiles + +```sql +-- Ver todos los lotes +SELECT * FROM lotes ORDER BY fecha_creado DESC; + +-- Ver trazabilidad completa de un lote +SELECT * FROM get_trazabilidad('id-del-lote'); + +-- Ver estadísticas de un lote +SELECT * FROM get_estadisticas_lote('id-del-lote'); +``` + +## 🎨 Frontend + +### Tecnologías + +- **Nuxt 4** - Framework Vue.js +- **Nuxt UI** - Componentes basados en Tailwind +- **TypeScript** - Tipado estático + +### Componentes Principales + +- **LotesTable** - Tabla con filtros y acciones +- **LoteForm** - Formulario crear/editar lote +- **TrazabilidadTree** - Árbol de trazabilidad con estadísticas +- **OperacionForm** - Wizard de 3 pasos para crear operaciones + +### Modo Debug + +El sistema incluye botones de prueba para verificar la API: + +1. Abre https://lotes.nucleoriofrio.com +2. Abre consola del navegador (F12) +3. Usa los botones "Probar API" +4. Verifica resultados en consola + +## 🔐 Autenticación + +Sistema protegido con Authentik Proxy Outpost: + +- **Forward Auth**: Authentik intercepta todas las peticiones +- **Headers automáticos**: Usuario inyectado en cada request SSR +- **Sin OAuth**: No requiere configuración OAuth en la app +- **Rutas públicas**: PWA assets accesibles sin auth + +Ver configuración detallada en la sección de Traefik al final del README. + +## 🛠️ Desarrollo Local + +**Nota**: El desarrollo local tiene limitaciones debido a la dependencia de Authentik Proxy. + +### Opción 1: Desarrollo con PostgreSQL local ```bash cd nuxt4 npm install + +# Configurar PostgreSQL local +export POSTGRES_USER=seguidor +export POSTGRES_PASSWORD=seguidor_password +export POSTGRES_DB=seguidor_lotes +export POSTGRES_HOST=localhost + +# Ejecutar scripts SQL +psql -U seguidor -d seguidor_lotes < server/database/01_schema.sql +psql -U seguidor -d seguidor_lotes < server/database/02_seed.sql + +# Iniciar dev server npm run dev ``` -## Claude Code Hooks +### Opción 2: Desarrollo contra servidor -Este proyecto incluye hooks de Claude Code para monitorear automáticamente las Gitea Actions. +```bash +cd nuxt4 +npm install -### Configuración Rápida: +# Apuntar a BD de producción +export POSTGRES_HOST=server.interno.com +export POSTGRES_PORT=5432 +# ... resto de variables -1. **Crear token de Gitea:** - - Ve a tu instancia de Gitea → Settings → Applications - - Genera un token con permisos `repo` - -2. **Configurar token:** - ```bash - echo "export GITEA_TOKEN='tu_token_aqui'" >> ~/.bashrc - source ~/.bashrc - ``` - -3. **Listo!** Cuando Claude Code haga `git push`, automáticamente: - - Monitoreará la Gitea Action - - Te notificará cuando termine con información detallada - - Te mostrará un link directo a los logs - -📖 Ver documentación completa en [`.claude/hooks/README.md`](.claude/hooks/README.md) - -## Chrome DevTools MCP - -Este proyecto está configurado para usar su propia instancia de Chrome con debugging remoto, permitiendo múltiples proyectos con navegadores independientes. - -### Inicio Rápido: - -1. **Iniciar el navegador del proyecto:** - ```bash - ./start-browser.sh - ``` - -2. **Configurar MCP en Claude Code** (solo primera vez): - - Editá `~/.config/claude-code/config.json` - - Agregá la configuración del navegador (puerto 9235) - -3. **Reiniciar Claude Code** para aplicar cambios - -📖 Ver documentación completa en [`.claude/CHROME_SETUP.md`](.claude/CHROME_SETUP.md) - -## Arquitectura de Componentes - -### Componentes de Autenticación - -La aplicación utiliza componentes Vue modulares para manejar la autenticación: - -#### 1. **UserAvatar** (`app/components/auth/UserAvatar.vue`) -- Muestra el avatar del usuario (generado por UI Avatars) -- Información básica: nombre/username, email y UID -- Se renderiza solo cuando el usuario está autenticado - -#### 2. **UserMetadata** (`app/components/auth/UserMetadata.vue`) -- Card detallada con todos los metadatos del usuario -- Muestra: username, email, nombre completo, UID y grupos -- Incluye badges para visualizar los grupos del usuario - -#### 3. **Botones de Acción** (componentes individuales) -Cada botón es un componente independiente con su propia lógica: - -- **SessionStatusButton**: Verifica el estado de la sesión contra Authentik - - Hace una petición a `/api/auth/status` - - Muestra notificaciones toast con el resultado - - Maneja casos offline y errores de conexión - -- **ProfileButton**: Redirige al perfil de usuario en Authentik - - Abre el panel de usuario de Authentik en nueva pestaña - - URL: `{authentikUrl}/if/user/` - -- **LogoutButton**: Cierra sesión en Authentik - - Invalida la sesión en todas las aplicaciones - - Redirige a: `{authentikUrl}/flows/-/default/invalidation/` - -- **LoginButton**: Fuerza re-autenticación - - Recarga la página para activar el flujo de login de Authentik - -### Composable `useAuthentik()` - -Composable centralizado para manejar autenticación (`app/composables/useAuthentik.ts`): - -**Funcionalidades:** -- Lee headers de Authentik en el servidor (SSR) -- Almacena información del usuario en `useState` (compartido entre cliente/servidor) -- Proporciona funciones reactivas: `user`, `isAuthenticated` -- Métodos: `logout()`, `goToProfile()`, `checkSessionStatus()` - -**Headers leídos del Proxy:** -```typescript -X-authentik-username // Nombre de usuario -X-authentik-email // Email -X-authentik-name // Nombre completo -X-authentik-groups // Grupos (separados por |) -X-authentik-uid // ID único del usuario +npm run dev ``` -## Despliegue +## 📈 Próximos Pasos -El proyecto incluye Gitea Actions que automáticamente: -1. Construye la imagen Docker -2. La sube al registro -3. Despliega usando docker-compose +### Objetivo Actual: Visualización del Grafo -### Variables Requeridas en Gitea +**Meta**: Mostrar correctamente el grafo de trazabilidad creado con los datos de ejemplo. -Para configurar el despliegue automático, ve a tu repositorio en Gitea: -- **Secrets**: `Settings > Actions > Secrets` -- **Variables**: `Settings > Actions > Variables` +**Tareas pendientes**: +- [ ] Componente de visualización de grafo (D3.js, vis.js, o similar) +- [ ] Layout de árbol o grafo dirigido +- [ ] Interactividad (zoom, pan, click en nodos) +- [ ] Mostrar metadatos al hacer hover +- [ ] Indicadores visuales de tipos de operación -**Secrets (valores sensibles):** -- `REGISTRY_USERNAME` - Usuario del registro Docker -- `REGISTRY_PASSWORD` - Contraseña del registro Docker +### Mejoras Futuras -**Variables (valores públicos):** -- `REGISTRY_URL` - URL del registro Docker (ej: `gitea.nucleoriofrio.com`) - - El owner del repositorio se agrega automáticamente - - Imagen final: `REGISTRY_URL/owner/APP_NAME:latest` -- `APP_NAME` - Nombre de la aplicación (ej: `mi-app`) - usado para container, imagen y Traefik -- `APP_DOMAIN` - Dominio de la aplicación (ej: `miapp.ejemplo.com`) -- `NUXT_PUBLIC_APP_URL` - URL pública de la app (ej: `https://miapp.ejemplo.com`) +- [ ] Exportar trazabilidad a PDF +- [ ] Búsqueda avanzada de lotes +- [ ] Dashboard con estadísticas +- [ ] Alertas de mermas excesivas +- [ ] Integración con básculas IoT +- [ ] App móvil con PWA +- [ ] Reportes personalizables -📄 Ver ejemplo completo en [`.env.example`](.env.example) +## 📚 Documentación Adicional -## Configuración de Traefik y Authentik +- [PLAN_TRAZABILIDAD.md](PLAN_TRAZABILIDAD.md) - Plan detallado del sistema +- [nuxt4/server/database/README.md](nuxt4/server/database/README.md) - Documentación de BD +- [.claude/hooks/README.md](.claude/hooks/README.md) - Gitea Actions Hooks +- [.claude/CHROME_SETUP.md](.claude/CHROME_SETUP.md) - Chrome DevTools MCP -### 🔐 Cómo Funciona Authentik Proxy Outpost +--- -Authentik Proxy Outpost actúa como un **Forward Auth** middleware que intercepta todas las peticiones antes de que lleguen a tu aplicación: +## 🔧 Configuración de Traefik y Authentik + +### Arquitectura de Autenticación ``` -Usuario → Traefik → Authentik Forward Auth → Aplicación Nuxt - ↓ (si no auth) +Usuario → Traefik → Authentik Forward Auth → App Nuxt + ↓ (sin sesión) Redirect a Login ``` -**Flujo de autenticación:** - -1. **Usuario hace petición** → Traefik recibe la petición a tu dominio -2. **Traefik consulta Authentik** → Envía la petición al middleware de Forward Auth -3. **Authentik valida sesión:** - - ✅ **Con sesión válida**: Authentik agrega headers con info del usuario y envía la petición a tu app - - ❌ **Sin sesión**: Authentik redirige al usuario al flujo de login -4. **Tu app recibe la petición** → Con headers de usuario ya inyectados (SSR) - -**Ventajas:** -- ✅ No necesitas implementar OAuth en tu app -- ✅ La autenticación se maneja completamente fuera de tu código -- ✅ Los headers llegan automáticamente en cada petición SSR -- ✅ Funciona con cualquier framework (Nuxt, Next.js, PHP, etc.) - -### 🚦 Configuración de Reglas de Traefik - -El `docker-compose.yml` configura **dos routers** en Traefik para balancear seguridad y funcionalidad PWA: - -#### Router 1: Rutas Públicas (Sin Autenticación) - Prioridad 100 - -```yaml -# Rutas que NO requieren autenticación -- PathPrefix(`/manifest.webmanifest`) # Manifest PWA -- PathPrefix(`/sw.js`) # Service Worker -- PathPrefix(`/workbox-`) # Workbox (PWA) -- PathPrefix(`/icon-`) # Iconos de la app -- PathPrefix(`/apple-touch-icon`) # Icono iOS -- PathPrefix(`/favicon.ico`) # Favicon -- PathPrefix(`/robots.txt`) # SEO -- PathPrefix(`/offline.html`) # Página offline PWA -- PathPrefix(`/api/_nuxt_icon/`) # API de iconos de Nuxt -``` - -**Middlewares aplicados:** -- `${APP_NAME}-headers`: Headers personalizados (X-Forwarded-Proto) -- `${APP_NAME}-cors`: Configuración CORS para recursos públicos - -**¿Por qué sin autenticación?** -- Los Service Workers necesitan acceso sin auth para funcionar offline -- Los manifests PWA deben ser públicos para instalación -- Prioridad 100 asegura que estas rutas se evalúen primero - -#### Router 2: Aplicación Protegida (Con Autenticación) - Prioridad 10 - -```yaml -# Todas las demás rutas (Host match) -Host(`${APP_DOMAIN}`) -``` - -**Middlewares aplicados:** -- `authentik-forward-auth@file`: Forward Auth de Authentik -- `${APP_NAME}-headers`: Headers personalizados - -**Características:** -- Prioridad menor (10) → se evalúa después de las rutas públicas -- Cualquier ruta no pública pasa por autenticación -- Authentik inyecta headers con información del usuario - -### 📋 Configuración de Authentik Proxy Outpost - -**Requisitos previos:** -- Traefik corriendo con las redes `traefik-network` y `principal` -- Authentik instalado y funcionando - -**Pasos de configuración:** - -#### 1. Crear el Middleware en Traefik - -Crea o edita el archivo de configuración dinámica de Traefik (ej: `dynamic/middlewares.yml`): +### Configuración de Middleware (Traefik) ```yaml +# dynamic/middlewares.yml http: middlewares: authentik-forward-auth: @@ -250,84 +340,30 @@ http: - X-authentik-uid ``` -**Importante:** Cambia `authentik-server` por el nombre de tu contenedor/servicio de Authentik. +### Configuración de Proxy Provider (Authentik) -#### 2. Configurar Authentik +1. **Crear Proxy Provider**: + - Type: `Forward auth (single application)` + - External host: `https://lotes.nucleoriofrio.com` -**a) Crear un Proxy Provider:** -- Ve a **Admin > Applications > Providers** -- Click en **Create** -- Tipo: **Proxy Provider** -- Configuración: - - **Name**: `Mi App - Forward Auth` - - **Authorization flow**: Selecciona tu flujo (ej: `default-provider-authorization-implicit-consent`) - - **Type**: `Forward auth (single application)` - - **External host**: `https://miapp.ejemplo.com` (tu dominio) +2. **Crear Application**: + - Name: `Seguidor de Lotes` + - Slug: `lotes` + - Provider: (el creado arriba) -**b) Crear una Application:** -- Ve a **Admin > Applications > Applications** -- Click en **Create** -- Configuración: - - **Name**: `Mi App` - - **Slug**: `mi-app` - - **Provider**: Selecciona el provider creado arriba +3. **Vincular a Outpost**: + - Agregar la aplicación al Outpost existente -**c) Vincular al Outpost:** -- Ve a **Admin > Outposts > Outposts** -- Edita tu Outpost (o crea uno nuevo si no existe) -- En **Applications**: Agrega la aplicación creada +### Headers Disponibles en la App -#### 3. Configurar las Redes en Docker Compose +| Header | Descripción | +|--------|-------------| +| `X-authentik-username` | Nombre de usuario | +| `X-authentik-email` | Email | +| `X-authentik-name` | Nombre completo | +| `X-authentik-groups` | Grupos (separados por `\|`) | +| `X-authentik-uid` | ID único | -Tu aplicación necesita estar en ambas redes: - -```yaml -networks: - principal: # Red de tu infraestructura - external: true - traefik-network: # Red donde corre Traefik - external: true -``` - -Asegúrate de que estas redes existan: - -```bash -docker network create principal -docker network create traefik-network -``` - -### 🔍 Headers Disponibles en tu Aplicación - -Una vez configurado, Authentik inyecta estos headers en cada petición: - -| Header | Descripción | Ejemplo | -|--------|-------------|---------| -| `X-authentik-username` | Nombre de usuario | `nucleo000` | -| `X-authentik-email` | Email del usuario | `user@example.com` | -| `X-authentik-name` | Nombre completo | `John Doe` | -| `X-authentik-groups` | Grupos (separados por `\|`) | `admins\|users` | -| `X-authentik-uid` | ID único del usuario | `703cae063c59...` | - -**En Nuxt**, estos headers se leen automáticamente en SSR mediante `useRequestHeaders()`. - -### 🐛 Troubleshooting - -**Problema: "Cannot find name 'process'"** -- ✅ Usa `import.meta.server` en lugar de `process.server` (Nuxt 4) - -**Problema: Redirect loop infinito** -- Verifica que el middleware `authentik-forward-auth@file` esté correctamente configurado -- Revisa que la aplicación esté asociada al Outpost en Authentik -- Comprueba que el External host coincida con tu dominio - -**Problema: Headers no llegan a la aplicación** -- Verifica que `authResponseHeaders` incluya todos los headers necesarios -- Asegúrate de que estés leyendo headers en SSR (`import.meta.server`) - -**Problema: PWA no funciona offline** -- Verifica que las rutas públicas tengan prioridad 100 -- Confirma que `/sw.js`, `/manifest.webmanifest` y `/offline.html` estén en el router público - -## Licencia +## 📄 Licencia MIT