Actualizar README y PLAN con estado actual del sistema
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 16s

README.md:
- Transformado en documentación completa del sistema de trazabilidad
- Agregadas secciones: Modelo de Datos, API Endpoints, Base de Datos
- Documentado estado de persistencia entre deploys
- Agregado próximo objetivo: Visualización del Grafo
- Actualizada estructura del proyecto
- Ejemplos de uso y configuración

PLAN_TRAZABILIDAD.md:
- Agregada sección 'Estado Actual del Proyecto' al inicio
- Lista de características completadas
- Objetivo actual claramente definido: Visualización del Grafo
- Tecnologías a considerar para implementación
This commit is contained in:
2025-11-21 19:39:34 -06:00
parent a14ce46ab3
commit 0f8891f77d
2 changed files with 347 additions and 275 deletions

View File

@@ -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)

584
README.md
View File

@@ -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