Plataforma de Nueva Generación · Propuesta Técnica y Comercial
+
+
+
+ Preparado por: Jess Miller · Arquitecta de Software Senior · Junio 2026
+
+
+
+
+
+
01 / 19
+
Resumen Ejecutivo
+
Una plataforma integrada y lista para producción
+
+
+
5
+
Módulos core
+
Directorio · Espacios · Workflow · CMS · Tickets
+
+
+
SSO
+
Azure Entra ID
+
Autenticación nativa de nivel empresarial
+
+
+
100%
+
Código Abierto
+
Angular 18 · NestJS 10 · PostgreSQL 15
+
+
+
+
+ LA PLATAFORMA NO ES UN PROTOTIPO. Se presenta como una solución central de intranet corporativa completamente funcional en desarrollo activo, con frontends y backends estables. Consolida procesos dispersos, garantiza seguridad empresarial y otorga propiedad total del código al cliente sin dependencias ni vendor lock-in.
+
+
+
+
+
+
+
02 / 19
+
El Diagnóstico
+
El impacto de la fragmentación de herramientas
+
+
+
+
Síntoma Operativo
+
Impacto en el Negocio
+
+
+
+
+
Fragmentación de herramientas
+
Pérdida de tiempo, ineficiencia operativa y errores de coordinación interdepartamental.
+
+
+
Sin integración con Active Directory
+
Onboarding y offboarding lentos, gestión manual de accesos y serios riesgos de seguridad.
+
+
+
Reservas de salas sin control centralizado
+
Conflictos de disponibilidad, overbooking y salas de reuniones subutilizadas.
+
+
+
Aprobaciones de contenidos por correo/chats
+
Falta absoluta de trazabilidad, cuellos de botella operativos y pérdida de historial.
+
+
+
Directorio de personal desactualizado
+
Dificultad para localizar habilidades internas, baja colaboración y silos de información.
+
+
+
+
+
+
+
+
03 / 19
+
La Propuesta
+
Un ecosistema. Todos los procesos internos en uno.
+
+
+
+
+ 🏢
+
Directorio (IAM)
+
+
+ 📅
+
Espacios & IA
+
+
+ ⚙️
+
Aprobaciones BPM
+
+
+ 📰
+
Info Hub CMS
+
+
+ 🎫
+
Ticketing SLA
+
+
+
+
+
🔑 Autenticación SSO: Microsoft Azure Entra ID / Tokens JWT
+
🐘 Persistencia: PostgreSQL (ACID) & Prisma ORM
+
🐳 Infraestructura: Docker / Cloud Ready
+
+
+
+
+ La solución consolida la seguridad y la experiencia del usuario bajo un mismo diseño unificado y coherente.
+
+
+
+
+
+
04 / 19
+
Módulos de la Solución
+
Módulo 1: Directorio Corporativo (IAM / HR)
+
+
+
+
👥 Sincronización Azure Entra ID
+
Lectura directa de usuarios, departamentos y jerarquías sin replicar datos sensibles de manera local.
+
+
+
🔍 Búsqueda Reactiva en Tiempo Real
+
Búsqueda instantánea integrada con Angular Signals. Filtros por rol, departamento o habilidades específicas de manera fluida.
+
+
+
+
+
+
🆔 Perfiles de Colaborador Detallados
+
Muestra ID del directorio (AD-XXXX), tarifa por hora, badge de calificación y datos de contacto integrados.
+
+
+
⚡ Interfaz Ergónomica e Inmersiva
+
Tarjetas de personal dinámicas con micro-interacciones de hover y navegación rápida a información de contacto.
+
+
+
+
+
+
+
+
05 / 19
+
Módulos de la Solución
+
Módulo 2: Autogestión de Espacios y Reservas (PMS)
+
+
+
+
📅 Calendario Interactivo
+
Vistas completas de Mes, Semana y Día. Clic en cualquier bloque de tiempo disponible redirige al formulario con parámetros precargados.
+
+
+
🛡️ Anti-Overbooking Garantizado
+
Control transaccional estricto en base de datos PostgreSQL, asegurando consistencia absoluta sin duplicidad de reservas.
+
+
+
⚙️ Filtros por Tipo de Activo
+
Filtrado de recursos en tiempo real: salas de reuniones, equipos tecnológicos, vehículos y áreas comunes.
+
+
+
+
+
🤖 ASISTENTE DE IA INTEGRADO (NLP)
+
+ El usuario puede agendar recursos usando lenguaje natural de forma intuitiva:
+
+
+ Entrada libre:
+ "Reservar la sala Londres para mañana a las 10 am para 8 personas"
+
+ Variables detectadas por IA:
+ • Espacio: London Hall (ID: SALA-02)
+ • Fecha: 2026-06-17 (Calculado)
+ • Hora: 10:00 AM - 11:00 AM
+ • Participantes: 8 colaboradores
+
+
+
+
+
+
+
+
06 / 19
+
Módulos de la Solución
+
Módulo 3: Workflow de Aprobación y Publicación (BPM)
+
+
+
+
⚙️ Motor de Reglas Jerárquicas
+
Flujo estructurado multinivel basado en roles de Active Directory. Asigna aprobadores de manera automática según el departamento.
+
+
+
📈 Trazabilidad de Estados
+
Control exacto del estado de cada solicitud (Borrador → En Aprobación → Aprobado → Publicado) con auditoría histórica detallada.
+
+
+
+
+
+
🔔 Notificaciones y Alertas Reactivas
+
Integración directa con el sistema de mensajería para avisos de solicitudes pendientes, garantizando flujos de trabajo sin demoras.
+
+
+
📰 Integración con Canales CMS
+
Una vez aprobado el contenido corporativo, el motor realiza la publicación automática en los tableros del Info Hub de la empresa.
+
+
+
+
+
+
+
+
07 / 19
+
Módulos de la Solución
+
Módulos 4 & 5: Info Hub CMS y Ticketing
+
+
+ 📰
+
Módulo 4: Info Hub / CMS Corporativo
+
Gestión y publicación de información interna en un portal centralizado de noticias corporativas.
+
+
Editor WYSIWYG de contenidos enriquecidos
+
Categorías y taxonomías customizables
+
Programación de comunicados a futuro
+
Publicación segmentada por departamento o rol
+
+
+
+
+ 🎫
+
Módulo 5: Soporte Técnico e Incidencias
+
Mesa de ayuda integrada para gestionar requerimientos de soporte interno técnico, operacional y de RR.HH.
+
+
Creación de solicitudes con prioridades claras
+
Asignación automatizada según especialidad del agente
+
Control de Tiempos de Respuesta y SLAs por ticket
+
Dashboard de resolución para coordinadores de mesa
+
+
+
+
+
+
+
+
08 / 19
+
Arquitectura de Software
+
Stack Tecnológico Moderno y Open Source
+
+
+
+
+
Capa
+
Tecnología Utilizada
+
Versión
+
Justificación y Beneficio
+
+
+
+
+
Frontend
+
Angular (Standalone Components & Signals)
+
18.0
+
Framework enterprise mantenido por Google, alta reactividad y orden.
+
+
+
Backend
+
NestJS (REST API)
+
10.0
+
Arquitectura modular sólida basada en TypeScript, fácil mantenimiento.
+
+
+
Autenticación
+
Azure Entra ID + JWT (SSO)
+
Estándar
+
Integración corporativa directa con el Active Directory de la empresa.
+
+
+
Base de Datos
+
PostgreSQL + Prisma ORM
+
15 / v5
+
Garantiza transacciones ACID indispensables para evitar overbooking de salas.
+
+
+
Infraestructura
+
Docker + Docker Compose
+
v3.8
+
Asegura portabilidad absoluta y despliegue rápido en local o cloud.
+
+
+
+
+
+
+
+
09 / 19
+
Seguridad Corporativa
+
Arquitectura SSO: Cero almacenamiento de credenciales
+
+
+
+
1. Usuario
+
Accede a la plataforma web desde el navegador.
+
+
➔
+
+
2. Azure Entra ID
+
Autenticación delegada (OAuth2) con credenciales corporativas.
+
+
➔
+
+
3. Token JWT
+
Retorna token con identidad y pertenencia a grupos de AD.
+
+
➔
+
+
4. NestJS API
+
Decodifica y valida firma del JWT por cada petición HTTP.
+
+
➔
+
+
5. Autorización
+
Acceso concedido según rol: employee, manager o admin.
+
+
+
+
+
+
+ OWASP Top 10 Compliance: Toda la transmisión de datos corre sobre HTTPS y los permisos expiran automáticamente mediante tokens JWT firmados.
+
+
+
+
+ Control Centralizado: Si se da de baja un colaborador en el AD corporativo de la empresa, pierde acceso de forma inmediata y automática a la intranet.
+
+
+
+
+
+
+
+
10 / 19
+
Ingeniería de Software
+
Arquitectura de Repositorio Estructurado
+
+
+ proyecto-intranet/
+ ├── frontend/← Aplicación Angular 18 (Standalone Components + Signals)
+ │ └── src/app/
+ │ ├── core/← Guard SSO, interceptores HTTP, auth services y manejo de tokens
+ │ ├── shared/← Componentes del Design System y pipes comunes
+ │ └── features/← Módulos funcionales (directorio, calendar-booking, etc.)
+ ├── backend/← REST API en NestJS (TypeScript modular estructurado)
+ │ └── src/
+ │ ├── auth/← Módulo Passport con validación JWT de Azure Entra ID
+ │ ├── directory/ / spaces/ / workflow/← Módulos con lógica empresarial
+ ├── standards/← Documentación de calidad de código y especificaciones de diseño
+ ├── docker-compose.yml← Orquestación local: base de datos PostgreSQL + administradores
+ └── setup.ps1 / .sh← Scripts de automatización y despliegue rápido para desarrollo
+
+
+
+ → Código limpio, modular y documentado que permite la adición de nuevos desarrolladores de forma ágil.
+
+
+
+
+
+
11 / 19
+
Experiencia de Usuario
+
Executive Suite Design System
+
+ Diseñado bajo directrices premium que mezclan sobriedad corporativa y tecnología de vanguardia.
+
+
+
+
+
✨ Tipografía Limpia
+
Inter para titulares de gran peso, brindando jerarquía y firmeza, complementada con Outfit para lecturas extensas fluidas.
+
+
+
🖼️ Card System Joya
+
Glows de fondo en colores oscuros pero ricos (Navy, Plum, Viridian, Espresso). Estructura elegante sin bordes cargados.
+
+
+
🔮 Micro-animaciones
+
Efectos de hover sutiles en tarjetas y botones, feedback inmediato al clickear y transiciones fluidas de página.
+
+
+
+
+
+
+
Ivory (#F5F4F1)
+
Color primario para contraste de textos limpios y de alta legibilidad.
+
+
+
+
Gold (#C9973C)
+
Dorado corporativo para estados activos, botones primarios y tags.
+
+
+
+
Navy (#0D1B2A)
+
Color de fondo para el Directorio IAM y elementos de seguridad.
+
+
+
+
Plum (#1A0E2E)
+
Fondo sofisticado reservado para calendario, reservas e IA.
+
+
+
+
Viridian (#0A2520)
+
Tonalidad verde para el motor de reglas y aprobaciones BPM.
+
+
+
+
+
+
+
12 / 19
+
Estado del Proyecto
+
Módulos desarrollados y nivel de avance
+
+
+
+
+
Módulo o Componente
+
Avance
+
Detalles Técnicos Implementados
+
+
+
+
+
Autenticación SSO corporativo
+
✅ Implementado
+
Módulo Auth JWT en NestJS, interceptores en Angular y Guards SSO.
Búsqueda reactiva con Signals, filtros por departamento, tarjetas de AD.
+
+
+
Calendario de Reservas
+
✅ Implementado
+
Calendario reactivo en frontend con vistas de Mes, Semana y Día.
+
+
+
Formulario de Reservas + IA
+
✅ Implementado
+
Parser NLP configurado con mock local y listado de consumo HTTP.
+
+
+
Workflow de Aprobación BPM
+
🔄 En Desarrollo
+
Estructuración del motor de jerarquías y vistas de historial de cambios.
+
+
+
Info Hub CMS / Ticketing SLA
+
📋 Planificado
+
Diseño de tablas de base de datos definidos en esquemas de Prisma.
+
+
+
+
+
+
+
+
13 / 19
+
Roadmap de Entrega
+
Fase 0: Diagnóstico & Fase 1: Setup e Integración
+
+
+
+
+
+ Fase 0 — Diagnóstico y NDA (Semanas 1–2)
+
+
+
📋 Kickoff e Inventario Técnico
+
Alineación de objetivos con el departamento de IT y negocio. Definición de ambientes de desarrollo y sandbox.
+
+
+
🔍 Auditoría de Active Directory
+
Revisión de grupos, jerarquías de aprobadores y políticas de acceso a la tenant del cliente.
+
+
+
+
+
+
+ Fase 1 — Setup y Conexión SSO (Semanas 3–4)
+
+
+
🛡️ Integración Microsoft Entra ID
+
Conexión directa de SSO vía OAuth2 en entorno de Staging. Traspaso de token JWT con claims asignados.
+
+
+
🐘 Despliegue de DB de Producción
+
Instalación de base de datos PostgreSQL, ejecución de esquemas Prisma y pruebas de concurrencia base.
+
+
+
+
+
+ 🔑 HITO CLAVE FASE 1: Inicio de sesión exitoso de usuarios del cliente en ambiente de Staging usando sus credenciales corporativas reales.
+
+
+
+
+
+
14 / 19
+
Roadmap de Entrega
+
Fases 2, 3 & 4: Módulos Core, Secundarios y Go-Live
+
+
+
+
+ Fase 2 (Sem 5–10)
+
Módulos Core
+
Desarrollo final de los módulos esenciales:
+
+
Directorio IAM en Staging
+
Reservas e IA integradas
+
Motor de Workflow BPM
+
Piloto con 50 usuarios
+
+
+
+
+
+ Fase 3 (Sem 11–14)
+
Módulos Secundarios
+
Construcción de soporte e información:
+
+
Info Hub CMS con editor
+
Ticketing y asignación SLA
+
Pruebas de aceptación globales (UAT)
+
Congelamiento de código
+
+
+
+
+
+ Fase 4 (Sem 15–16)
+
Go-Live & Traspaso
+
Despliegue y estabilización:
+
+
Paso a Producción Cloud
+
Capacitación de usuarios
+
Traspaso de Runbooks y código
+
30 días de garantía incluidos
+
+
+
+
+
+
🚀 HITO CLAVE FASE 4: Plataforma 100% en vivo para todos los colaboradores de la empresa.
+
+
+
+
+
+
15 / 19
+
Roadmap de Entrega
+
Cronograma General de Trabajo (16 Semanas)
+
+
+
+
+
Fase 0: Diagnóstico
+
+
Diagnóstico & AD Audit
+
+
+
+
+
Fase 1: Setup & SSO
+
+
SSO Azure Staging
+
+
+
+
+
Fase 2: Módulos Core
+
+
Dir + Espacios IA + BPM + Piloto
+
+
+
+
+
Fase 3: Módulos Secundarios
+
+
CMS + Tickets + UAT General
+
+
+
+
+
Fase 4: Lanzamiento
+
+
Go-Live & Traspaso
+
+
+
+
+
+ Mes 1 (Sem 1-4)
+ Mes 2 (Sem 5-8)
+ Mes 3 (Sem 9-12)
+ Mes 4 (Sem 13-16)
+
+
+
+
+ Cada hito requiere aprobación y pruebas UAT de cara al cliente antes del paso a la siguiente fase del proyecto.
+
+
+
+
+
+
16 / 19
+
Presupuesto y Adquisición
+
Esquema de Presupuesto y Modalidades de Contratación
+
+
+
+
+
+
+
+
Concepto de Trabajo
+
Descripción del Entregable
+
+
+
+
+
Licenciamiento base
+
Entrega de la plataforma e infraestructura base preconfigurada.
+
+
+
Integración SSO e Infra
+
Fases 0 y 1: Configuración de Azure Entra ID, base de datos PostgreSQL.
+
+
+
Desarrollo Core & BPM
+
Fase 2: Conexión de Directorio, Calendario + IA, workflow BPM.
+
+
+
Desarrollo CMS & Tickets
+
Fase 3: Info Hub, Ticketing y SLA. Pruebas UAT.
+
+
+
Go-Live & Garantía
+
Despliegue, manuales, capacitación y 30 días de garantía inicial.
+
+
+
+
+
+
+
+
+ Modalidades de Adquisición
+
+
+
🔑 Proyecto Llave en Mano
+
Precio y plazos fijos por la entrega del alcance completo de las 16 semanas. Ideal para presupuestos definidos.
+
+
+
⏳ Tiempo y Materiales (T&M)
+
Facturación mensual por sprints según requerimientos variables y flexibilidad de prioridades.
+
+
+
☁️ SaaS Mensual (OpEx)
+
Suscripción mensual recurrente con hosting, soporte continuo y actualizaciones evolutivas incluidas.
+
+
+
+
+
+
+
+
17 / 19
+
Análisis del Mercado
+
Por qué nuestra solución frente a las alternativas
+
+
+
+
+
Criterio
+
Nuestra Plataforma
+
SharePoint
+
Confluence
+
Desarrollo desde 0
+
+
+
+
+
Integración AD Nativa
+
✅ Sí (SSO)
+
✅ Sí
+
⚠️ Vía Plugin
+
✅ Sí
+
+
+
Personalización UI/UX
+
✅ 100% Libre
+
⚠️ Limitada
+
⚠️ Limitada
+
✅ 100% Libre
+
+
+
Asistente IA NLP
+
✅ Integrado
+
❌ No
+
❌ No
+
⚠️ Costo Extra
+
+
+
Plazos de Entrega
+
✅ 16 Semanas
+
3 - 12 meses
+
2 - 6 meses
+
12 - 18 meses
+
+
+
Propiedad de Código
+
✅ Del Cliente
+
❌ Microsoft
+
❌ Atlassian
+
✅ Del Cliente
+
+
+
Vendor Lock-in
+
✅ Cero (Open Source)
+
❌ Alto
+
❌ Alto
+
✅ Cero
+
+
+
+
+
+
+
+
18 / 19
+
Transparencia
+
Garantías y Respaldos del Proyecto
+
+
+
+
📦 Propiedad Intelectual Total
+
El cliente es dueño absoluto del código fuente, base de datos y documentación técnica al cierre del proyecto. Sin regalías.
+
+
+
🔓 Cero Dependencias
+
Uso de stack open source estándar (Angular, NestJS, PostgreSQL). Cualquier equipo de desarrollo puede asumir y escalar el sistema en el futuro.
+
+
+
📈 Escalabilidad Enterprise
+
Arquitectura desacoplada en backend y frontend, preparada para soportar 10,000+ usuarios concurrentes sin degradar velocidad.
+
+
+
🛡️ Seguridad by Design
+
Cumplimiento estricto de lineamientos OWASP Top 10, cifrado SSL/TLS obligatorio y validación de sesiones delegadas en el SSO.
+
+
+
📄 Soporte y Operatividad
+
30 días de soporte técnico reactivo de primer nivel tras el Go-Live, garantizando una transición operativa suave.
+
+
+
⚙️ Documentación Exhaustiva
+
Traspaso completo de guías de desarrollo, runbooks de DevOps, esquemas de bases de datos y manuales de usuario.
+
+
+
+
+
+
+
Propuesta de Intranet · 2026
+
+ Unificando procesos para potenciar tu organización.
+
+
+
+
+ PRÓXIMOS PASOS
+ 1. Demo en vivo de la plataforma actual (30 min)
+ 2. Workshop técnico sobre Active Directory (2h)
+ 3. Propuesta comercial formal ajustada a usuarios
+ 4. Firma de acuerdo NDA y Contrato de Desarrollo
+ 5. Kick-off de Fase 0
+
+
+
+
+
+
+ Jess Miller — Arquitecta de Software Senior & Full-Stack Engineer
+ 📧 jess@intranet.dev | 🔗 github.com/intranet-platform
+
+ Para descargar o imprimir a PDF: Ctrl+P (Chrome) → Guardar como PDF → Habilitar "Gráficos de fondo" e imprimir horizontal.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/propuesta_kinetix.md b/doc/propuesta_kinetix.md
new file mode 100644
index 0000000..2278406
--- /dev/null
+++ b/doc/propuesta_kinetix.md
@@ -0,0 +1,329 @@
+# Propuesta Técnica y Comercial
+## Plataforma de Intranet Corporativa · **Kinetix**
+
+---
+
+> **Preparado por:** Jess Miller · Arquitecta de Software Senior
+> **Fecha:** Junio 2026
+> **Versión:** 1.0 — Confidencial
+> **Para:** [Nombre de la Empresa Objetivo]
+
+---
+
+## Resumen Ejecutivo
+
+**Kinetix** es una plataforma de intranet corporativa de nueva generación, diseñada para consolidar en un único ecosistema digital todos los procesos internos de una organización empresarial moderna: gestión de identidades, reserva de espacios, aprobación de contenidos, directorio de personal y ticketing de incidencias.
+
+La plataforma está operativa, con frontend y backend en producción local, y lista para su despliegue en infraestructura cloud o on-premise. Está construida sobre un stack tecnológico de primer nivel —**Angular 18, NestJS 10 y PostgreSQL 15**— con autenticación nativa vía **Microsoft Azure Entra ID (Active Directory)**, lo que garantiza integración inmediata con el ecosistema Microsoft de cualquier empresa.
+
+> [!IMPORTANT]
+> Kinetix no es un prototipo. Es un producto en desarrollo activo con arquitectura escalable, código limpio y documentación técnica estructurada. Esta propuesta presenta su adopción como solución central de intranet para [Empresa].
+
+---
+
+## 1. Problema que Resuelve
+
+Las empresas modernas operan con herramientas fragmentadas: un sistema para reservas, otro para el directorio, formularios manuales para workflows de aprobación y correos internos para incidencias. Este modelo genera:
+
+| Problema | Impacto |
+|---|---|
+| Fragmentación de herramientas | Pérdida de tiempo y errores de coordinación |
+| Sin integración con Active Directory | Onboarding lento, acceso manual, riesgos de seguridad |
+| Reservas de salas sin control centralizado | Conflictos de disponibilidad, overbooking |
+| Aprobaciones por correo | Sin trazabilidad, cuellos de botella operativos |
+| Directorio desactualizado | Información incorrecta, baja colaboración |
+
+**Kinetix resuelve todos estos problemas en una sola plataforma integrada.**
+
+---
+
+## 2. La Solución: Plataforma Kinetix
+
+### 2.1 Visión General
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ KINETIX INTRANET │
+│ "Un ecosistema. Todos los procesos internos en uno." │
+├──────────────┬──────────────┬──────────────┬────────────────┤
+│ Directorio │ Espacios │ Workflows │ Info Hub CMS │
+│ Corporativo │ & Reservas │ de Aprobación│ + Ticketing │
+│ (Entra ID) │ (Calendar) │ (BPM Multi- │ (SLA/Tickets) │
+│ │ + IA Parser │ nivel) │ │
+└──────────────┴──────────────┴──────────────┴────────────────┘
+ ↑ ↑ ↑
+ SSO / JWT PostgreSQL DB Azure Entra ID
+```
+
+### 2.2 Módulos Implementados
+
+#### 🏢 Módulo 1 — Directorio Corporativo (IAM/HR)
+Sincronizado con **Microsoft Entra ID (Azure AD)**. Muestra el organigrama real de la empresa con perfiles dinámicos: nombre, rol, departamento, skills, métricas y contacto directo.
+
+- Búsqueda en tiempo real por nombre, rol o habilidad
+- Filtrado por departamento
+- ID de Active Directory (AD-XXXX) en cada perfil
+- Badge de calificación y tarifa por hora
+- Diseño de tarjetas con micro-animaciones y hover
+
+#### 📅 Módulo 2 — Autogestión de Espacios y Activos (PMS)
+Sistema completo de reservas con **calendario dinámico** con vistas Mes/Semana/Día.
+
+- Clic en cualquier slot del calendario → redirige a formulario de reserva
+- Filtros en tiempo real por tipo de recurso (salas, equipos, vehículos)
+- **Asistente IA de lenguaje natural**: el usuario escribe "Reservar sala para el jueves 5 personas" y el sistema auto-completa el formulario usando un parser de IA
+- Confirmación y notificación a calendario de Active Directory
+
+#### ⚙️ Módulo 3 — Workflow de Aprobación y Publicación (BPM)
+Motor de reglas multinivel integrado con SSO y Active Directory para jerarquías de aprobación de contenidos institucionales.
+
+- Creación → Validación → Publicación automática
+- Estados de aprobación trazables
+- Publicación en canales de comunicación interna
+
+#### 📰 Módulo 4 — Info Hub / CMS Corporativo
+Gestión de contenidos corporativos: artículos, comunicados y publicaciones institucionales con editor integrado.
+
+#### 🎫 Módulo 5 — Ticketing e Incidencias
+Creación, flujo y asignación de tickets internos con gestión de SLAs y prioridades de soporte técnico y operativo.
+
+---
+
+## 3. Stack Tecnológico
+
+| Capa | Tecnología | Versión | Justificación |
+|---|---|---|---|
+| **Frontend** | Angular | 18.0 | Framework enterprise estándar de Google. Signals natively reactive. |
+| **Backend** | NestJS | 10.0 | Framework TypeScript para APIs REST escalables y modulares |
+| **Autenticación** | Azure Entra ID + JWT | — | SSO corporativo con Passport.js. Sin gestión de contraseñas propias |
+| **Base de Datos** | PostgreSQL | 15 | Transaccional, ACID-compliant. Crítico para reservas sin overbooking |
+| **ORM** | Prisma | — | Migraciones tipeadas, esquema declarativo |
+| **Contenedores** | Docker + Docker Compose | — | Portabilidad total entre entornos |
+| **Estilos** | TailwindCSS + Vanilla CSS | — | Sistema de diseño Executive Suite personalizado |
+| **IA Parser** | API de IA (NLP) | — | Procesamiento de lenguaje natural para reservas conversacionales |
+
+### 3.1 Arquitectura de Seguridad SSO
+
+```
+Usuario → App Angular → Azure Entra ID (login)
+ ↓
+ Token JWT (con roles AD)
+ ↓
+ Backend NestJS valida token
+ con passport-azure-ad / passport-jwt
+ ↓
+ Acceso según rol: employee | manager | admin
+```
+
+**Ninguna contraseña se almacena en Kinetix.** La autenticación es 100% delegada a Active Directory de la empresa.
+
+---
+
+## 4. Arquitectura del Sistema
+
+```
+kinetix/
+├── frontend/ ← SPA Angular 18 (Standalone Components + Signals)
+│ └── src/app/
+│ ├── core/ ← Guards SSO, interceptores HTTP, auth services
+│ ├── shared/ ← Componentes reutilizables del Design System
+│ └── features/ ← Módulos por dominio (reservas, directorio, etc.)
+│
+├── backend/ ← API REST NestJS (TypeScript modular)
+│ └── src/
+│ ├── auth/ ← Módulo SSO Active Directory / JWT
+│ ├── cms/ ← Gestión de contenidos
+│ ├── directory/ ← Directorio corporativo
+│ ├── workflow/ ← Motor de aprobaciones
+│ ├── spaces/ ← Reservas de espacios (con anti-overbooking)
+│ └── ticketing/ ← Sistema de incidencias
+│
+├── standards/ ← Documentación técnica y estándares del proyecto
+├── docker-compose.yml ← Infraestructura local: PostgreSQL + pgAdmin
+└── setup.ps1 / .sh ← Scripts de onboarding para nuevos devs
+```
+
+---
+
+## 5. Diseño e Interfaz de Usuario
+
+Kinetix utiliza el **Executive Suite Design System**, un sistema de diseño corporativo premium desarrollado a medida:
+
+- **Paleta:** Ivory `#F5F4F1` + Negro sofisticado `#0F0D0A` + Dorado bronce `#C9973C`
+- **Tarjetas Joya (Blackjack System):** Fondos oscuros en Navy, Plum, Viridian, Espresso para los módulos principales
+- **Tipografía:** Inter (titulares) + Outfit (cuerpo)
+- **Glassmorphism y micro-animaciones** para interactividad premium
+- **Responsive design** completo: mobile, tablet, desktop
+- **Sidebar colapsable** con estado de sistema en tiempo real
+
+> El diseño fue validado contra estándares documentados en `standards/04-ui-ux-neon.md`.
+
+---
+
+## 6. Estado Actual del Proyecto
+
+| Módulo | Estado | Detalle |
+|---|---|---|
+| Autenticación SSO | ✅ Implementado | JWT + Guards + Interceptores HTTP |
+| Dashboard principal | ✅ Implementado | KPIs, cards de módulos, navegación |
+| Directorio de Personal | ✅ Implementado | Búsqueda reactiva, filtros, tarjetas AD |
+| Calendario de Reservas | ✅ Implementado | Vistas Mes/Semana/Día, filtros dinámicos |
+| Formulario de Reserva + IA | ✅ Implementado | Parser NLP con mock local y API IA |
+| Workflow de Aprobación | 🔄 En desarrollo | Motor de reglas, vistas de simulación |
+| Info Hub / CMS | 📋 Planificado | Editor WYSIWYG, taxonomías |
+| Ticketing | 📋 Planificado | SLA, asignación, prioridades |
+| Base de datos PostgreSQL | ✅ Configurado | Docker Compose, schema documentado |
+| Despliegue cloud | 📋 Pendiente | Azure / AWS / on-premise |
+
+---
+
+## 7. Plan de Acción (Roadmap de Entrega)
+
+### Fase 0 — Diagnóstico e Integración *(Semanas 1–2)*
+
+| Actividad | Responsable | Entregable |
+|---|---|---|
+| Reunión de kickoff con equipo técnico | Arquitecta + IT Cliente | Acta de requerimientos |
+| Auditoría del Active Directory existente | Arquitecta + Admin AD | Mapeo de grupos, roles y UOs |
+| Definición de ambientes (dev / staging / prod) | DevOps | Documento de infraestructura |
+| Firma de NDA y contrato de desarrollo | Legal | Contrato ejecutado |
+
+### Fase 1 — Setup e Integración SSO *(Semanas 3–4)*
+
+| Actividad | Entregable |
+|---|---|
+| Configurar Azure Entra ID con la tenant del cliente | App registrada en Azure Portal |
+| Integrar OAuth2 + JWT con roles reales de AD | Auth funcional en entorno del cliente |
+| Onboarding técnico al equipo de IT interno | Workshop de 4 horas |
+| Setup de base de datos PostgreSQL en producción | DB productiva con migraciones aplicadas |
+
+**Hito:** ✅ Login con credenciales reales de la empresa funcionando.
+
+### Fase 2 — Módulos Core *(Semanas 5–10)*
+
+| Semana | Módulo | Entregable |
+|---|---|---|
+| 5–6 | Directorio Corporativo | Perfiles sincronizados con AD real |
+| 7–8 | Gestión de Espacios + IA | Calendario + reservas en producción |
+| 9–10 | Workflow de Aprobación | Motor de reglas con notificaciones |
+
+**Hito:** ✅ Piloto con 50 usuarios internos en entorno staging.
+
+### Fase 3 — Módulos Secundarios *(Semanas 11–14)*
+
+| Semana | Módulo | Entregable |
+|---|---|---|
+| 11–12 | Info Hub / CMS | Editor de artículos operativo |
+| 13–14 | Ticketing e Incidencias | Sistema de tickets con SLA |
+
+**Hito:** ✅ Plataforma completa en staging. UAT (User Acceptance Testing).
+
+### Fase 4 — Lanzamiento *(Semanas 15–16)*
+
+| Actividad | Entregable |
+|---|---|
+| Despliegue en producción cloud/on-premise | Plataforma 100% en vivo |
+| Capacitación a usuarios finales (por roles) | Manual de usuario + sesiones |
+| Documentación técnica de operación | Runbook de DevOps |
+| Soporte post-lanzamiento (30 días incluidos) | Canal de soporte dedicado |
+
+**Hito:** 🚀 Go-Live oficial de Kinetix para [Empresa].
+
+---
+
+## 8. Diagrama de Fases
+
+```mermaid
+gantt
+ title Roadmap de Implementación Kinetix
+ dateFormat YYYY-MM-DD
+ section Fase 0 — Diagnóstico
+ Kickoff & Auditoría AD :2026-07-01, 7d
+ Definición de Ambientes :2026-07-07, 7d
+ section Fase 1 — SSO & Setup
+ Azure Entra ID Integration :2026-07-14, 7d
+ PostgreSQL Producción :2026-07-21, 7d
+ section Fase 2 — Core
+ Directorio Corporativo :2026-07-28, 14d
+ Gestión de Espacios + IA :2026-08-11, 14d
+ Workflow de Aprobación :2026-08-25, 14d
+ section Fase 3 — Secundarios
+ Info Hub / CMS :2026-09-08, 14d
+ Ticketing & Incidencias :2026-09-22, 14d
+ section Fase 4 — Lanzamiento
+ Despliegue Producción :2026-10-06, 7d
+ Capacitación & Go-Live :2026-10-13, 7d
+```
+
+---
+
+## 9. Propuesta Económica
+
+### Modelo de Precios Sugerido
+
+> [!NOTE]
+> Los siguientes valores son referenciales y ajustables según el tamaño de la organización, cantidad de usuarios y requerimientos adicionales de personalización.
+
+| Concepto | Descripción | Estimado |
+|---|---|---|
+| **Licencia de Plataforma** | Uso de la plataforma Kinetix base | A negociar |
+| **Implementación e Integración** | Fases 0–1: Setup, SSO, infraestructura | 4–6 semanas |
+| **Desarrollo de Módulos Core** | Fase 2: Directorio, Espacios, Workflow | 6 semanas |
+| **Módulos Secundarios** | Fase 3: CMS, Ticketing | 4 semanas |
+| **Soporte Post-Lanzamiento** | 30 días incluidos + contratos de mantenimiento opcionales | Incluido |
+
+#### Modalidades de Contratación
+
+| Modalidad | Descripción | Recomendado para |
+|---|---|---|
+| **Llave en mano** | Precio fijo por entrega completa | Empresas con presupuesto definido |
+| **Tiempo y materiales** | Pago por hora/sprint según avance | Proyectos con alcance variable |
+| **SaaS Mensual** | Hosting + mantenimiento + actualizaciones | Empresas que prefieren OpEx |
+
+---
+
+## 10. Por Qué Kinetix sobre Alternativas
+
+| Criterio | Kinetix | SharePoint | Confluence | Desarrollo a medida desde cero |
+|---|---|---|---|---|
+| Integración AD nativa | ✅ | ✅ | ⚠️ Plugin | ✅ |
+| Personalizable 100% | ✅ | ⚠️ Limitado | ⚠️ Limitado | ✅ |
+| Stack moderno (Angular + NestJS) | ✅ | ❌ | ❌ | ✅ |
+| Asistente IA integrado | ✅ | ❌ | ❌ | Solo si se desarrolla |
+| Tiempo de implementación | **~4 meses** | 3–12 meses | 2–6 meses | 12–18 meses |
+| Costo de implementación | **Medio** | Alto | Medio | Muy alto |
+| Curva de aprendizaje usuarios | Baja | Alta | Media | Variable |
+
+---
+
+## 11. Garantías y Compromisos
+
+- ✅ **Código fuente entregado:** La empresa es propietaria del código al finalizar el proyecto
+- ✅ **Documentación técnica completa:** Estándares, esquemas DB, guías de API
+- ✅ **Sin vendor lock-in:** Stack 100% open source (Angular, NestJS, PostgreSQL)
+- ✅ **Seguridad by design:** OWASP Top 10, JWT validation, HTTPS obligatorio
+- ✅ **Escalabilidad:** Arquitectura modular preparada para 10,000+ usuarios
+- ✅ **Soporte 30 días post-lanzamiento** incluido en el contrato base
+
+---
+
+## 12. Próximos Pasos
+
+1. **Reunión de presentación** (30–45 min): Demo en vivo de la plataforma actual
+2. **Workshop técnico** (2h): Revisión de requerimientos específicos con IT y RR.HH.
+3. **Propuesta económica formal** ajustada al volumen de usuarios y módulos requeridos
+4. **Firma de NDA** para compartir acceso al repositorio y documentación interna
+5. **Kick-off** de Fase 0
+
+---
+
+## Contacto
+
+**Jess Miller**
+Arquitecta de Software Senior · Full-Stack Engineer
+📧 jess@kinetix.dev
+🔗 github.com/kinetix
+
+---
+
+*Documento confidencial. Preparado exclusivamente para [Nombre de la Empresa]. Prohibida su reproducción parcial o total sin autorización expresa.*
diff --git a/doc/walkthrough.md b/doc/walkthrough.md
new file mode 100644
index 0000000..77fc232
--- /dev/null
+++ b/doc/walkthrough.md
@@ -0,0 +1,29 @@
+# Walkthrough: Módulo de Autogestión de Espacios y Activos con Asistente IA
+
+Se ha completado la arquitectura e implementación del módulo de gestión de reservas en el frontend de Kinetix utilizando Angular 18 (Standalone Components, Signals y enrutamiento perezoso).
+
+## Cambios Realizados
+
+### Servicio de IA
+- [ia-parser.service.ts](file:///d:/Jess/agent/Kinetix/frontend/src/app/features/reservas/services/ia-parser.service.ts): Servicio de comunicación NLP/IA con parseo heurístico inteligente como fallback de desarrollo para auto-llenar los formularios mediante prompts en lenguaje natural.
+
+### Componentes de Presentación e Interfaz
+- [calendar-booking.component.ts](file:///d:/Jess/agent/Kinetix/frontend/src/app/features/reservas/calendar-booking/calendar-booking.component.ts): Vista del calendario interactivo a pantalla completa con soporte de vistas y filtrado reactivo de salas, escritorios y activos.
+- [calendar-booking.component.html](file:///d:/Jess/agent/Kinetix/frontend/src/app/features/reservas/calendar-booking/calendar-booking.component.html): Estructura visual responsiva estilizada con el **Executive Suite Design System** (paleta Ivory y tarjetas joya de alta gama).
+- [reserva-form.component.ts](file:///d:/Jess/agent/Kinetix/frontend/src/app/features/reservas/reserva-form/reserva-form.component.ts): Lógica del formulario de reserva que escucha `QueryParams` para pre-seleccionar fecha/tipo de recurso y gestiona el binding con el Asistente IA.
+- [reserva-form.component.html](file:///d:/Jess/agent/Kinetix/frontend/src/app/features/reservas/reserva-form/reserva-form.component.html): Diseño elegante de dos paneles que destaca la interfaz del Asistente de IA y provee inputs completamente accesibles.
+
+### Enrutamiento
+- [app.routes.ts](file:///d:/Jess/agent/Kinetix/frontend/src/app/app.routes.ts): Agregado el cargado perezoso (Lazy Loading) para las rutas principales del módulo de reservas (`/reservas/calendario` y `/reservas/nuevo`).
+
+---
+
+## Verificación de Compilación
+
+La compilación se completó exitosamente sin errores:
+```bash
+npx ng build --configuration development
+```
+Generó los siguientes fragmentos perezosos sin comprometer el tamaño inicial del bundle principal:
+- `features-reservas-reserva-form-reserva-form-component` (407.74 kB)
+- `features-reservas-calendar-booking-calendar-booking-component` (27.11 kB)
diff --git a/frontend/angular.json b/frontend/angular.json
index b6ff011..9541579 100644
--- a/frontend/angular.json
+++ b/frontend/angular.json
@@ -34,15 +34,11 @@
"configurations": {
"production": {
"budgets": [
- {
- "type": "initial",
- "maximumWarning": "500kb",
- "maximumError": "1mb"
- },
{
"type": "anyComponentStyle",
- "maximumWarning": "6kb",
- "maximumError": "8kb"
+ "baseline": "5kb",
+ "maximumWarning": "15kb",
+ "maximumError": "20kb"
}
],
"outputHashing": "all"
@@ -73,4 +69,4 @@
"cli": {
"analytics": "fc6d1cf8-556d-44ba-883b-4df33dd8aff3"
}
-}
+}
\ No newline at end of file
diff --git a/frontend/dist/kinetix-frontend/3rdpartylicenses.txt b/frontend/dist/kinetix-frontend/3rdpartylicenses.txt
deleted file mode 100644
index fa316c1..0000000
--- a/frontend/dist/kinetix-frontend/3rdpartylicenses.txt
+++ /dev/null
@@ -1,259 +0,0 @@
-@angular/common
-MIT
-
-@angular/core
-MIT
-
-@angular/forms
-MIT
-
-@angular/platform-browser
-MIT
-
-@angular/router
-MIT
-
-rxjs
-Apache-2.0
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
-
-tslib
-0BSD
-Copyright (c) Microsoft Corporation.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-zone.js
-MIT
-The MIT License
-
-Copyright (c) 2010-2024 Google LLC. https://angular.io/license
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/frontend/dist/kinetix-frontend/index.html b/frontend/dist/kinetix-frontend/index.html
deleted file mode 100644
index a8fd441..0000000
--- a/frontend/dist/kinetix-frontend/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- Kinetix Intranet
-
-
-
-
-
-
-
-
diff --git a/frontend/dist/kinetix-frontend/polyfills.db3ad031cea79ddb.js b/frontend/dist/kinetix-frontend/polyfills.db3ad031cea79ddb.js
deleted file mode 100644
index bcd78a3..0000000
--- a/frontend/dist/kinetix-frontend/polyfills.db3ad031cea79ddb.js
+++ /dev/null
@@ -1 +0,0 @@
-"use strict";(self.webpackChunkkinetix_frontend=self.webpackChunkkinetix_frontend||[]).push([[461],{853:()=>{const te=globalThis;function ee(e){return(te.__Zone_symbol_prefix||"__zone_symbol__")+e}const ke=Object.getOwnPropertyDescriptor,Ne=Object.defineProperty,Le=Object.getPrototypeOf,_t=Object.create,Et=Array.prototype.slice,Ie="addEventListener",Me="removeEventListener",Ze=ee(Ie),Ae=ee(Me),ae="true",le="false",ve=ee("");function je(e,r){return Zone.current.wrap(e,r)}function He(e,r,c,t,i){return Zone.current.scheduleMacroTask(e,r,c,t,i)}const j=ee,we=typeof window<"u",Te=we?window:void 0,$=we&&Te||globalThis,Tt="removeAttribute";function xe(e,r){for(let c=e.length-1;c>=0;c--)"function"==typeof e[c]&&(e[c]=je(e[c],r+"_"+c));return e}function We(e){return!e||!1!==e.writable&&!("function"==typeof e.get&&typeof e.set>"u")}const qe=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,Re=!("nw"in $)&&typeof $.process<"u"&&"[object process]"===$.process.toString(),Ve=!Re&&!qe&&!(!we||!Te.HTMLElement),Xe=typeof $.process<"u"&&"[object process]"===$.process.toString()&&!qe&&!(!we||!Te.HTMLElement),Ce={},yt=j("enable_beforeunload"),Ye=function(e){if(!(e=e||$.event))return;let r=Ce[e.type];r||(r=Ce[e.type]=j("ON_PROPERTY"+e.type));const c=this||e.target||$,t=c[r];let i;return Ve&&c===Te&&"error"===e.type?(i=t&&t.call(this,e.message,e.filename,e.lineno,e.colno,e.error),!0===i&&e.preventDefault()):(i=t&&t.apply(this,arguments),"beforeunload"===e.type&&$[yt]&&"string"==typeof i?e.returnValue=i:null!=i&&!i&&e.preventDefault()),i};function $e(e,r,c){let t=ke(e,r);if(!t&&c&&ke(c,r)&&(t={enumerable:!0,configurable:!0}),!t||!t.configurable)return;const i=j("on"+r+"patched");if(e.hasOwnProperty(i)&&e[i])return;delete t.writable,delete t.value;const u=t.get,E=t.set,T=r.slice(2);let m=Ce[T];m||(m=Ce[T]=j("ON_PROPERTY"+T)),t.set=function(D){let d=this;!d&&e===$&&(d=$),d&&("function"==typeof d[m]&&d.removeEventListener(T,Ye),E&&E.call(d,null),d[m]=D,"function"==typeof D&&d.addEventListener(T,Ye,!1))},t.get=function(){let D=this;if(!D&&e===$&&(D=$),!D)return null;const d=D[m];if(d)return d;if(u){let w=u.call(this);if(w)return t.set.call(this,w),"function"==typeof D[Tt]&&D.removeAttribute(r),w}return null},Ne(e,r,t),e[i]=!0}function Je(e,r,c){if(r)for(let t=0;tfunction(E,T){const m=c(E,T);return m.cbIdx>=0&&"function"==typeof T[m.cbIdx]?He(m.name,T[m.cbIdx],m,i):u.apply(E,T)})}function fe(e,r){e[j("OriginalDelegate")]=r}let Ke=!1,Ge=!1;function kt(){if(Ke)return Ge;Ke=!0;try{const e=Te.navigator.userAgent;(-1!==e.indexOf("MSIE ")||-1!==e.indexOf("Trident/")||-1!==e.indexOf("Edge/"))&&(Ge=!0)}catch{}return Ge}function Qe(e){return"function"==typeof e}function et(e){return"number"==typeof e}let ge=!1;if(typeof window<"u")try{const e=Object.defineProperty({},"passive",{get:function(){ge=!0}});window.addEventListener("test",e,e),window.removeEventListener("test",e,e)}catch{ge=!1}const vt={useG:!0},ne={},tt={},nt=new RegExp("^"+ve+"(\\w+)(true|false)$"),rt=j("propagationStopped");function ot(e,r){const c=(r?r(e):e)+le,t=(r?r(e):e)+ae,i=ve+c,u=ve+t;ne[e]={},ne[e][le]=i,ne[e][ae]=u}function bt(e,r,c,t){const i=t&&t.add||Ie,u=t&&t.rm||Me,E=t&&t.listeners||"eventListeners",T=t&&t.rmAll||"removeAllListeners",m=j(i),D="."+i+":",d="prependListener",w="."+d+":",Z=function(k,h,H){if(k.isRemoved)return;const V=k.callback;let Y;"object"==typeof V&&V.handleEvent&&(k.callback=g=>V.handleEvent(g),k.originalDelegate=V);try{k.invoke(k,h,[H])}catch(g){Y=g}const G=k.options;return G&&"object"==typeof G&&G.once&&h[u].call(h,H.type,k.originalDelegate?k.originalDelegate:k.callback,G),Y};function x(k,h,H){if(!(h=h||e.event))return;const V=k||h.target||e,Y=V[ne[h.type][H?ae:le]];if(Y){const G=[];if(1===Y.length){const g=Z(Y[0],V,h);g&&G.push(g)}else{const g=Y.slice();for(let z=0;z{throw z})}}}const U=function(k){return x(this,k,!1)},J=function(k){return x(this,k,!0)};function K(k,h){if(!k)return!1;let H=!0;h&&void 0!==h.useG&&(H=h.useG);const V=h&&h.vh;let Y=!0;h&&void 0!==h.chkDup&&(Y=h.chkDup);let G=!1;h&&void 0!==h.rt&&(G=h.rt);let g=k;for(;g&&!g.hasOwnProperty(i);)g=Le(g);if(!g&&k[i]&&(g=k),!g||g[m])return!1;const z=h&&h.eventNameToString,O={},R=g[m]=g[i],b=g[j(u)]=g[u],S=g[j(E)]=g[E],Q=g[j(T)]=g[T];let W;h&&h.prepend&&(W=g[j(h.prepend)]=g[h.prepend]);const q=H?function(s){if(!O.isExisting)return R.call(O.target,O.eventName,O.capture?J:U,O.options)}:function(s){return R.call(O.target,O.eventName,s.invoke,O.options)},A=H?function(s){if(!s.isRemoved){const l=ne[s.eventName];let v;l&&(v=l[s.capture?ae:le]);const C=v&&s.target[v];if(C)for(let y=0;yse.zone.cancelTask(se);s.call(me,"abort",ce,{once:!0}),se.removeAbortListener=()=>me.removeEventListener("abort",ce)}return O.target=null,Pe&&(Pe.taskData=null),lt&&(O.options.once=!0),!ge&&"boolean"==typeof se.options||(se.options=ie),se.target=I,se.capture=Be,se.eventName=M,B&&(se.originalDelegate=F),L?pe.unshift(se):pe.push(se),y?I:void 0}};return g[i]=a(R,D,q,A,G),W&&(g[d]=a(W,w,function(s){return W.call(O.target,O.eventName,s.invoke,O.options)},A,G,!0)),g[u]=function(){const s=this||e;let l=arguments[0];h&&h.transferEventName&&(l=h.transferEventName(l));const v=arguments[2],C=!!v&&("boolean"==typeof v||v.capture),y=arguments[1];if(!y)return b.apply(this,arguments);if(V&&!V(b,y,s,arguments))return;const L=ne[l];let I;L&&(I=L[C?ae:le]);const M=I&&s[I];if(M)for(let F=0;Ffunction(i,u){i[rt]=!0,t&&t.apply(i,u)})}const De=j("zoneTask");function ye(e,r,c,t){let i=null,u=null;c+=t;const E={};function T(D){const d=D.data;d.args[0]=function(){return D.invoke.apply(this,arguments)};const w=i.apply(e,d.args);return et(w)?d.handleId=w:(d.handle=w,d.isRefreshable=Qe(w.refresh)),D}function m(D){const{handle:d,handleId:w}=D.data;return u.call(e,d??w)}i=ue(e,r+=t,D=>function(d,w){if(Qe(w[0])){const Z={isRefreshable:!1,isPeriodic:"Interval"===t,delay:"Timeout"===t||"Interval"===t?w[1]||0:void 0,args:w},x=w[0];w[0]=function(){try{return x.apply(this,arguments)}finally{const{handle:H,handleId:V,isPeriodic:Y,isRefreshable:G}=Z;!Y&&!G&&(V?delete E[V]:H&&(H[De]=null))}};const U=He(r,w[0],Z,T,m);if(!U)return U;const{handleId:J,handle:K,isRefreshable:X,isPeriodic:k}=U.data;if(J)E[J]=U;else if(K&&(K[De]=U,X&&!k)){const h=K.refresh;K.refresh=function(){const{zone:H,state:V}=U;return"notScheduled"===V?(U._state="scheduled",H._updateTaskCount(U,1)):"running"===V&&(U._state="scheduling"),h.call(this)}}return K??J??U}return D.apply(e,w)}),u=ue(e,c,D=>function(d,w){const Z=w[0];let x;et(Z)?(x=E[Z],delete E[Z]):(x=Z?.[De],x?Z[De]=null:x=Z),x?.type?x.cancelFn&&x.zone.cancelTask(x):D.apply(e,w)})}function it(e,r,c){if(!c||0===c.length)return r;const t=c.filter(u=>u.target===e);if(!t||0===t.length)return r;const i=t[0].ignoreProperties;return r.filter(u=>-1===i.indexOf(u))}function ct(e,r,c,t){e&&Je(e,it(e,r,c),t)}function Fe(e){return Object.getOwnPropertyNames(e).filter(r=>r.startsWith("on")&&r.length>2).map(r=>r.substring(2))}function It(e,r,c,t,i){const u=Zone.__symbol__(t);if(r[u])return;const E=r[u]=r[t];r[t]=function(T,m,D){return m&&m.prototype&&i.forEach(function(d){const w=`${c}.${t}::`+d,Z=m.prototype;try{if(Z.hasOwnProperty(d)){const x=e.ObjectGetOwnPropertyDescriptor(Z,d);x&&x.value?(x.value=e.wrapWithCurrentZone(x.value,w),e._redefineProperty(m.prototype,d,x)):Z[d]&&(Z[d]=e.wrapWithCurrentZone(Z[d],w))}else Z[d]&&(Z[d]=e.wrapWithCurrentZone(Z[d],w))}catch{}}),E.call(r,T,m,D)},e.attachOriginToPatched(r[t],E)}const at=function Oe(){const e=globalThis,r=!0===e[ee("forceDuplicateZoneCheck")];if(e.Zone&&(r||"function"!=typeof e.Zone.__symbol__))throw new Error("Zone already loaded.");return e.Zone??=function ze(){const e=te.performance;function r(N){e&&e.mark&&e.mark(N)}function c(N,_){e&&e.measure&&e.measure(N,_)}r("Zone");let t=(()=>{class N{static{this.__symbol__=ee}static assertZonePatched(){if(te.Promise!==O.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")}static get root(){let n=N.current;for(;n.parent;)n=n.parent;return n}static get current(){return b.zone}static get currentTask(){return S}static __load_patch(n,o,p=!1){if(O.hasOwnProperty(n)){const P=!0===te[ee("forceDuplicateZoneCheck")];if(!p&&P)throw Error("Already loaded patch: "+n)}else if(!te["__Zone_disable_"+n]){const P="Zone:"+n;r(P),O[n]=o(te,N,R),c(P,P)}}get parent(){return this._parent}get name(){return this._name}constructor(n,o){this._parent=n,this._name=o?o.name||"unnamed":"",this._properties=o&&o.properties||{},this._zoneDelegate=new u(this,this._parent&&this._parent._zoneDelegate,o)}get(n){const o=this.getZoneWith(n);if(o)return o._properties[n]}getZoneWith(n){let o=this;for(;o;){if(o._properties.hasOwnProperty(n))return o;o=o._parent}return null}fork(n){if(!n)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,n)}wrap(n,o){if("function"!=typeof n)throw new Error("Expecting function got: "+n);const p=this._zoneDelegate.intercept(this,n,o),P=this;return function(){return P.runGuarded(p,this,arguments,o)}}run(n,o,p,P){b={parent:b,zone:this};try{return this._zoneDelegate.invoke(this,n,o,p,P)}finally{b=b.parent}}runGuarded(n,o=null,p,P){b={parent:b,zone:this};try{try{return this._zoneDelegate.invoke(this,n,o,p,P)}catch(q){if(this._zoneDelegate.handleError(this,q))throw q}}finally{b=b.parent}}runTask(n,o,p){if(n.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(n.zone||K).name+"; Execution: "+this.name+")");const P=n,{type:q,data:{isPeriodic:A=!1,isRefreshable:_e=!1}={}}=n;if(n.state===X&&(q===z||q===g))return;const he=n.state!=H;he&&P._transitionTo(H,h);const de=S;S=P,b={parent:b,zone:this};try{q==g&&n.data&&!A&&!_e&&(n.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,P,o,p)}catch(oe){if(this._zoneDelegate.handleError(this,oe))throw oe}}finally{const oe=n.state;if(oe!==X&&oe!==Y)if(q==z||A||_e&&oe===k)he&&P._transitionTo(h,H,k);else{const f=P._zoneDelegates;this._updateTaskCount(P,-1),he&&P._transitionTo(X,H,X),_e&&(P._zoneDelegates=f)}b=b.parent,S=de}}scheduleTask(n){if(n.zone&&n.zone!==this){let p=this;for(;p;){if(p===n.zone)throw Error(`can not reschedule task to ${this.name} which is descendants of the original zone ${n.zone.name}`);p=p.parent}}n._transitionTo(k,X);const o=[];n._zoneDelegates=o,n._zone=this;try{n=this._zoneDelegate.scheduleTask(this,n)}catch(p){throw n._transitionTo(Y,k,X),this._zoneDelegate.handleError(this,p),p}return n._zoneDelegates===o&&this._updateTaskCount(n,1),n.state==k&&n._transitionTo(h,k),n}scheduleMicroTask(n,o,p,P){return this.scheduleTask(new E(G,n,o,p,P,void 0))}scheduleMacroTask(n,o,p,P,q){return this.scheduleTask(new E(g,n,o,p,P,q))}scheduleEventTask(n,o,p,P,q){return this.scheduleTask(new E(z,n,o,p,P,q))}cancelTask(n){if(n.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(n.zone||K).name+"; Execution: "+this.name+")");if(n.state===h||n.state===H){n._transitionTo(V,h,H);try{this._zoneDelegate.cancelTask(this,n)}catch(o){throw n._transitionTo(Y,V),this._zoneDelegate.handleError(this,o),o}return this._updateTaskCount(n,-1),n._transitionTo(X,V),n.runCount=-1,n}}_updateTaskCount(n,o){const p=n._zoneDelegates;-1==o&&(n._zoneDelegates=null);for(let P=0;PN.hasTask(n,o),onScheduleTask:(N,_,n,o)=>N.scheduleTask(n,o),onInvokeTask:(N,_,n,o,p,P)=>N.invokeTask(n,o,p,P),onCancelTask:(N,_,n,o)=>N.cancelTask(n,o)};class u{get zone(){return this._zone}constructor(_,n,o){this._taskCounts={microTask:0,macroTask:0,eventTask:0},this._zone=_,this._parentDelegate=n,this._forkZS=o&&(o&&o.onFork?o:n._forkZS),this._forkDlgt=o&&(o.onFork?n:n._forkDlgt),this._forkCurrZone=o&&(o.onFork?this._zone:n._forkCurrZone),this._interceptZS=o&&(o.onIntercept?o:n._interceptZS),this._interceptDlgt=o&&(o.onIntercept?n:n._interceptDlgt),this._interceptCurrZone=o&&(o.onIntercept?this._zone:n._interceptCurrZone),this._invokeZS=o&&(o.onInvoke?o:n._invokeZS),this._invokeDlgt=o&&(o.onInvoke?n:n._invokeDlgt),this._invokeCurrZone=o&&(o.onInvoke?this._zone:n._invokeCurrZone),this._handleErrorZS=o&&(o.onHandleError?o:n._handleErrorZS),this._handleErrorDlgt=o&&(o.onHandleError?n:n._handleErrorDlgt),this._handleErrorCurrZone=o&&(o.onHandleError?this._zone:n._handleErrorCurrZone),this._scheduleTaskZS=o&&(o.onScheduleTask?o:n._scheduleTaskZS),this._scheduleTaskDlgt=o&&(o.onScheduleTask?n:n._scheduleTaskDlgt),this._scheduleTaskCurrZone=o&&(o.onScheduleTask?this._zone:n._scheduleTaskCurrZone),this._invokeTaskZS=o&&(o.onInvokeTask?o:n._invokeTaskZS),this._invokeTaskDlgt=o&&(o.onInvokeTask?n:n._invokeTaskDlgt),this._invokeTaskCurrZone=o&&(o.onInvokeTask?this._zone:n._invokeTaskCurrZone),this._cancelTaskZS=o&&(o.onCancelTask?o:n._cancelTaskZS),this._cancelTaskDlgt=o&&(o.onCancelTask?n:n._cancelTaskDlgt),this._cancelTaskCurrZone=o&&(o.onCancelTask?this._zone:n._cancelTaskCurrZone),this._hasTaskZS=null,this._hasTaskDlgt=null,this._hasTaskDlgtOwner=null,this._hasTaskCurrZone=null;const p=o&&o.onHasTask;(p||n&&n._hasTaskZS)&&(this._hasTaskZS=p?o:i,this._hasTaskDlgt=n,this._hasTaskDlgtOwner=this,this._hasTaskCurrZone=this._zone,o.onScheduleTask||(this._scheduleTaskZS=i,this._scheduleTaskDlgt=n,this._scheduleTaskCurrZone=this._zone),o.onInvokeTask||(this._invokeTaskZS=i,this._invokeTaskDlgt=n,this._invokeTaskCurrZone=this._zone),o.onCancelTask||(this._cancelTaskZS=i,this._cancelTaskDlgt=n,this._cancelTaskCurrZone=this._zone))}fork(_,n){return this._forkZS?this._forkZS.onFork(this._forkDlgt,this.zone,_,n):new t(_,n)}intercept(_,n,o){return this._interceptZS?this._interceptZS.onIntercept(this._interceptDlgt,this._interceptCurrZone,_,n,o):n}invoke(_,n,o,p,P){return this._invokeZS?this._invokeZS.onInvoke(this._invokeDlgt,this._invokeCurrZone,_,n,o,p,P):n.apply(o,p)}handleError(_,n){return!this._handleErrorZS||this._handleErrorZS.onHandleError(this._handleErrorDlgt,this._handleErrorCurrZone,_,n)}scheduleTask(_,n){let o=n;if(this._scheduleTaskZS)this._hasTaskZS&&o._zoneDelegates.push(this._hasTaskDlgtOwner),o=this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt,this._scheduleTaskCurrZone,_,n),o||(o=n);else if(n.scheduleFn)n.scheduleFn(n);else{if(n.type!=G)throw new Error("Task is missing scheduleFn.");U(n)}return o}invokeTask(_,n,o,p){return this._invokeTaskZS?this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt,this._invokeTaskCurrZone,_,n,o,p):n.callback.apply(o,p)}cancelTask(_,n){let o;if(this._cancelTaskZS)o=this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt,this._cancelTaskCurrZone,_,n);else{if(!n.cancelFn)throw Error("Task is not cancelable");o=n.cancelFn(n)}return o}hasTask(_,n){try{this._hasTaskZS&&this._hasTaskZS.onHasTask(this._hasTaskDlgt,this._hasTaskCurrZone,_,n)}catch(o){this.handleError(_,o)}}_updateTaskCount(_,n){const o=this._taskCounts,p=o[_],P=o[_]=p+n;if(P<0)throw new Error("More tasks executed then were scheduled.");0!=p&&0!=P||this.hasTask(this._zone,{microTask:o.microTask>0,macroTask:o.macroTask>0,eventTask:o.eventTask>0,change:_})}}class E{constructor(_,n,o,p,P,q){if(this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=_,this.source=n,this.data=p,this.scheduleFn=P,this.cancelFn=q,!o)throw new Error("callback is not defined");this.callback=o;const A=this;this.invoke=_===z&&p&&p.useG?E.invokeTask:function(){return E.invokeTask.call(te,A,this,arguments)}}static invokeTask(_,n,o){_||(_=this),Q++;try{return _.runCount++,_.zone.runTask(_,n,o)}finally{1==Q&&J(),Q--}}get zone(){return this._zone}get state(){return this._state}cancelScheduleRequest(){this._transitionTo(X,k)}_transitionTo(_,n,o){if(this._state!==n&&this._state!==o)throw new Error(`${this.type} '${this.source}': can not transition to '${_}', expecting state '${n}'${o?" or '"+o+"'":""}, was '${this._state}'.`);this._state=_,_==X&&(this._zoneDelegates=null)}toString(){return this.data&&typeof this.data.handleId<"u"?this.data.handleId.toString():Object.prototype.toString.call(this)}toJSON(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}}}const T=ee("setTimeout"),m=ee("Promise"),D=ee("then");let Z,d=[],w=!1;function x(N){if(Z||te[m]&&(Z=te[m].resolve(0)),Z){let _=Z[D];_||(_=Z.then),_.call(Z,N)}else te[T](N,0)}function U(N){0===Q&&0===d.length&&x(J),N&&d.push(N)}function J(){if(!w){for(w=!0;d.length;){const N=d;d=[];for(let _=0;_b,onUnhandledError:W,microtaskDrainDone:W,scheduleMicroTask:U,showUncaughtError:()=>!t[ee("ignoreConsoleErrorUncaughtError")],patchEventTarget:()=>[],patchOnProperties:W,patchMethod:()=>W,bindArguments:()=>[],patchThen:()=>W,patchMacroTask:()=>W,patchEventPrototype:()=>W,isIEOrEdge:()=>!1,getGlobalObjects:()=>{},ObjectDefineProperty:()=>W,ObjectGetOwnPropertyDescriptor:()=>{},ObjectCreate:()=>{},ArraySlice:()=>[],patchClass:()=>W,wrapWithCurrentZone:()=>W,filterProperties:()=>[],attachOriginToPatched:()=>W,_redefineProperty:()=>W,patchCallbacks:()=>W,nativeScheduleMicroTask:x};let b={parent:null,zone:new t(null,null)},S=null,Q=0;function W(){}return c("Zone","Zone"),t}(),e.Zone}();(function Zt(e){(function Nt(e){e.__load_patch("ZoneAwarePromise",(r,c,t)=>{const i=Object.getOwnPropertyDescriptor,u=Object.defineProperty,T=t.symbol,m=[],D=!1!==r[T("DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION")],d=T("Promise"),w=T("then"),Z="__creationTrace__";t.onUnhandledError=f=>{if(t.showUncaughtError()){const a=f&&f.rejection;a?console.error("Unhandled Promise rejection:",a instanceof Error?a.message:a,"; Zone:",f.zone.name,"; Task:",f.task&&f.task.source,"; Value:",a,a instanceof Error?a.stack:void 0):console.error(f)}},t.microtaskDrainDone=()=>{for(;m.length;){const f=m.shift();try{f.zone.runGuarded(()=>{throw f.throwOriginal?f.rejection:f})}catch(a){U(a)}}};const x=T("unhandledPromiseRejectionHandler");function U(f){t.onUnhandledError(f);try{const a=c[x];"function"==typeof a&&a.call(this,f)}catch{}}function J(f){return f&&f.then}function K(f){return f}function X(f){return A.reject(f)}const k=T("state"),h=T("value"),H=T("finally"),V=T("parentPromiseValue"),Y=T("parentPromiseState"),G="Promise.then",g=null,z=!0,O=!1,R=0;function b(f,a){return s=>{try{N(f,a,s)}catch(l){N(f,!1,l)}}}const S=function(){let f=!1;return function(s){return function(){f||(f=!0,s.apply(null,arguments))}}},Q="Promise resolved with itself",W=T("currentTaskTrace");function N(f,a,s){const l=S();if(f===s)throw new TypeError(Q);if(f[k]===g){let v=null;try{("object"==typeof s||"function"==typeof s)&&(v=s&&s.then)}catch(C){return l(()=>{N(f,!1,C)})(),f}if(a!==O&&s instanceof A&&s.hasOwnProperty(k)&&s.hasOwnProperty(h)&&s[k]!==g)n(s),N(f,s[k],s[h]);else if(a!==O&&"function"==typeof v)try{v.call(s,l(b(f,a)),l(b(f,!1)))}catch(C){l(()=>{N(f,!1,C)})()}else{f[k]=a;const C=f[h];if(f[h]=s,f[H]===H&&a===z&&(f[k]=f[Y],f[h]=f[V]),a===O&&s instanceof Error){const y=c.currentTask&&c.currentTask.data&&c.currentTask.data[Z];y&&u(s,W,{configurable:!0,enumerable:!1,writable:!0,value:y})}for(let y=0;y{try{const L=f[h],I=!!s&&H===s[H];I&&(s[V]=L,s[Y]=C);const M=a.run(y,void 0,I&&y!==X&&y!==K?[]:[L]);N(s,!0,M)}catch(L){N(s,!1,L)}},s)}const P=function(){},q=r.AggregateError;class A{static toString(){return"function ZoneAwarePromise() { [native code] }"}static resolve(a){return a instanceof A?a:N(new this(null),z,a)}static reject(a){return N(new this(null),O,a)}static withResolvers(){const a={};return a.promise=new A((s,l)=>{a.resolve=s,a.reject=l}),a}static any(a){if(!a||"function"!=typeof a[Symbol.iterator])return Promise.reject(new q([],"All promises were rejected"));const s=[];let l=0;try{for(let y of a)l++,s.push(A.resolve(y))}catch{return Promise.reject(new q([],"All promises were rejected"))}if(0===l)return Promise.reject(new q([],"All promises were rejected"));let v=!1;const C=[];return new A((y,L)=>{for(let I=0;I{v||(v=!0,y(M))},M=>{C.push(M),l--,0===l&&(v=!0,L(new q(C,"All promises were rejected")))})})}static race(a){let s,l,v=new this((L,I)=>{s=L,l=I});function C(L){s(L)}function y(L){l(L)}for(let L of a)J(L)||(L=this.resolve(L)),L.then(C,y);return v}static all(a){return A.allWithCallback(a)}static allSettled(a){return(this&&this.prototype instanceof A?this:A).allWithCallback(a,{thenCallback:l=>({status:"fulfilled",value:l}),errorCallback:l=>({status:"rejected",reason:l})})}static allWithCallback(a,s){let l,v,C=new this((M,F)=>{l=M,v=F}),y=2,L=0;const I=[];for(let M of a){J(M)||(M=this.resolve(M));const F=L;try{M.then(B=>{I[F]=s?s.thenCallback(B):B,y--,0===y&&l(I)},B=>{s?(I[F]=s.errorCallback(B),y--,0===y&&l(I)):v(B)})}catch(B){v(B)}y++,L++}return y-=2,0===y&&l(I),C}constructor(a){const s=this;if(!(s instanceof A))throw new Error("Must be an instanceof Promise.");s[k]=g,s[h]=[];try{const l=S();a&&a(l(b(s,z)),l(b(s,O)))}catch(l){N(s,!1,l)}}get[Symbol.toStringTag](){return"Promise"}get[Symbol.species](){return A}then(a,s){let l=this.constructor?.[Symbol.species];(!l||"function"!=typeof l)&&(l=this.constructor||A);const v=new l(P),C=c.current;return this[k]==g?this[h].push(C,v,a,s):o(this,C,v,a,s),v}catch(a){return this.then(null,a)}finally(a){let s=this.constructor?.[Symbol.species];(!s||"function"!=typeof s)&&(s=A);const l=new s(P);l[H]=H;const v=c.current;return this[k]==g?this[h].push(v,l,a,a):o(this,v,l,a,a),l}}A.resolve=A.resolve,A.reject=A.reject,A.race=A.race,A.all=A.all;const _e=r[d]=r.Promise;r.Promise=A;const he=T("thenPatched");function de(f){const a=f.prototype,s=i(a,"then");if(s&&(!1===s.writable||!s.configurable))return;const l=a.then;a[w]=l,f.prototype.then=function(v,C){return new A((L,I)=>{l.call(this,L,I)}).then(v,C)},f[he]=!0}return t.patchThen=de,_e&&(de(_e),ue(r,"fetch",f=>function oe(f){return function(a,s){let l=f.apply(a,s);if(l instanceof A)return l;let v=l.constructor;return v[he]||de(v),l}}(f))),Promise[c.__symbol__("uncaughtPromiseErrors")]=m,A})})(e),function Lt(e){e.__load_patch("toString",r=>{const c=Function.prototype.toString,t=j("OriginalDelegate"),i=j("Promise"),u=j("Error"),E=function(){if("function"==typeof this){const d=this[t];if(d)return"function"==typeof d?c.call(d):Object.prototype.toString.call(d);if(this===Promise){const w=r[i];if(w)return c.call(w)}if(this===Error){const w=r[u];if(w)return c.call(w)}}return c.call(this)};E[t]=c,Function.prototype.toString=E;const T=Object.prototype.toString;Object.prototype.toString=function(){return"function"==typeof Promise&&this instanceof Promise?"[object Promise]":T.call(this)}})}(e),function Mt(e){e.__load_patch("util",(r,c,t)=>{const i=Fe(r);t.patchOnProperties=Je,t.patchMethod=ue,t.bindArguments=xe,t.patchMacroTask=mt;const u=c.__symbol__("BLACK_LISTED_EVENTS"),E=c.__symbol__("UNPATCHED_EVENTS");r[E]&&(r[u]=r[E]),r[u]&&(c[u]=c[E]=r[u]),t.patchEventPrototype=Pt,t.patchEventTarget=bt,t.isIEOrEdge=kt,t.ObjectDefineProperty=Ne,t.ObjectGetOwnPropertyDescriptor=ke,t.ObjectCreate=_t,t.ArraySlice=Et,t.patchClass=be,t.wrapWithCurrentZone=je,t.filterProperties=it,t.attachOriginToPatched=fe,t._redefineProperty=Object.defineProperty,t.patchCallbacks=It,t.getGlobalObjects=()=>({globalSources:tt,zoneSymbolEventNames:ne,eventNames:i,isBrowser:Ve,isMix:Xe,isNode:Re,TRUE_STR:ae,FALSE_STR:le,ZONE_SYMBOL_PREFIX:ve,ADD_EVENT_LISTENER_STR:Ie,REMOVE_EVENT_LISTENER_STR:Me})})}(e)})(at),function Ot(e){e.__load_patch("legacy",r=>{const c=r[e.__symbol__("legacyPatch")];c&&c()}),e.__load_patch("timers",r=>{const c="set",t="clear";ye(r,c,t,"Timeout"),ye(r,c,t,"Interval"),ye(r,c,t,"Immediate")}),e.__load_patch("requestAnimationFrame",r=>{ye(r,"request","cancel","AnimationFrame"),ye(r,"mozRequest","mozCancel","AnimationFrame"),ye(r,"webkitRequest","webkitCancel","AnimationFrame")}),e.__load_patch("blocking",(r,c)=>{const t=["alert","prompt","confirm"];for(let i=0;ifunction(D,d){return c.current.run(E,r,d,m)})}),e.__load_patch("EventTarget",(r,c,t)=>{(function Dt(e,r){r.patchEventPrototype(e,r)})(r,t),function Ct(e,r){if(Zone[r.symbol("patchEventTarget")])return;const{eventNames:c,zoneSymbolEventNames:t,TRUE_STR:i,FALSE_STR:u,ZONE_SYMBOL_PREFIX:E}=r.getGlobalObjects();for(let m=0;m{be("MutationObserver"),be("WebKitMutationObserver")}),e.__load_patch("IntersectionObserver",(r,c,t)=>{be("IntersectionObserver")}),e.__load_patch("FileReader",(r,c,t)=>{be("FileReader")}),e.__load_patch("on_property",(r,c,t)=>{!function St(e,r){if(Re&&!Xe||Zone[e.symbol("patchEvents")])return;const c=r.__Zone_ignore_on_properties;let t=[];if(Ve){const i=window;t=t.concat(["Document","SVGElement","Element","HTMLElement","HTMLBodyElement","HTMLMediaElement","HTMLFrameSetElement","HTMLFrameElement","HTMLIFrameElement","HTMLMarqueeElement","Worker"]);const u=function pt(){try{const e=Te.navigator.userAgent;if(-1!==e.indexOf("MSIE ")||-1!==e.indexOf("Trident/"))return!0}catch{}return!1}()?[{target:i,ignoreProperties:["error"]}]:[];ct(i,Fe(i),c&&c.concat(u),Le(i))}t=t.concat(["XMLHttpRequest","XMLHttpRequestEventTarget","IDBIndex","IDBRequest","IDBOpenDBRequest","IDBDatabase","IDBTransaction","IDBCursor","WebSocket"]);for(let i=0;i{!function Rt(e,r){const{isBrowser:c,isMix:t}=r.getGlobalObjects();(c||t)&&e.customElements&&"customElements"in e&&r.patchCallbacks(r,e.customElements,"customElements","define",["connectedCallback","disconnectedCallback","adoptedCallback","attributeChangedCallback","formAssociatedCallback","formDisabledCallback","formResetCallback","formStateRestoreCallback"])}(r,t)}),e.__load_patch("XHR",(r,c)=>{!function D(d){const w=d.XMLHttpRequest;if(!w)return;const Z=w.prototype;let U=Z[Ze],J=Z[Ae];if(!U){const R=d.XMLHttpRequestEventTarget;if(R){const b=R.prototype;U=b[Ze],J=b[Ae]}}const K="readystatechange",X="scheduled";function k(R){const b=R.data,S=b.target;S[E]=!1,S[m]=!1;const Q=S[u];U||(U=S[Ze],J=S[Ae]),Q&&J.call(S,K,Q);const W=S[u]=()=>{if(S.readyState===S.DONE)if(!b.aborted&&S[E]&&R.state===X){const _=S[c.__symbol__("loadfalse")];if(0!==S.status&&_&&_.length>0){const n=R.invoke;R.invoke=function(){const o=S[c.__symbol__("loadfalse")];for(let p=0;pfunction(R,b){return R[i]=0==b[2],R[T]=b[1],V.apply(R,b)}),G=j("fetchTaskAborting"),g=j("fetchTaskScheduling"),z=ue(Z,"send",()=>function(R,b){if(!0===c.current[g]||R[i])return z.apply(R,b);{const S={target:R,url:R[T],isPeriodic:!1,args:b,aborted:!1},Q=He("XMLHttpRequest.send",h,S,k,H);R&&!0===R[m]&&!S.aborted&&Q.state===X&&Q.invoke()}}),O=ue(Z,"abort",()=>function(R,b){const S=function x(R){return R[t]}(R);if(S&&"string"==typeof S.type){if(null==S.cancelFn||S.data&&S.data.aborted)return;S.zone.cancelTask(S)}else if(!0===c.current[G])return O.apply(R,b)})}(r);const t=j("xhrTask"),i=j("xhrSync"),u=j("xhrListener"),E=j("xhrScheduled"),T=j("xhrURL"),m=j("xhrErrorBeforeScheduled")}),e.__load_patch("geolocation",r=>{r.navigator&&r.navigator.geolocation&&function gt(e,r){const c=e.constructor.name;for(let t=0;t{const m=function(){return T.apply(this,xe(arguments,c+"."+i))};return fe(m,T),m})(u)}}}(r.navigator.geolocation,["getCurrentPosition","watchPosition"])}),e.__load_patch("PromiseRejectionEvent",(r,c)=>{function t(i){return function(u){st(r,i).forEach(T=>{const m=r.PromiseRejectionEvent;if(m){const D=new m(i,{promise:u.promise,reason:u.rejection});T.invoke(D)}})}}r.PromiseRejectionEvent&&(c[j("unhandledPromiseRejectionHandler")]=t("unhandledrejection"),c[j("rejectionHandledHandler")]=t("rejectionhandled"))}),e.__load_patch("queueMicrotask",(r,c,t)=>{!function wt(e,r){r.patchMethod(e,"queueMicrotask",c=>function(t,i){Zone.current.scheduleMicroTask("queueMicrotask",i[0])})}(r,t)})}(at)}},te=>{te(te.s=853)}]);
\ No newline at end of file
diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts
index 899148c..e5c209b 100644
--- a/frontend/src/app/app.component.ts
+++ b/frontend/src/app/app.component.ts
@@ -20,8 +20,10 @@ import { CommonModule } from '@angular/common';
- Plataforma unificada de administración y autogestión de recursos del consorcio. Control centralizado, monitoreo en tiempo real y acceso seguro vía Active Directory.
-