# AGENTS.md - Guía para Agentes de Codificación IA

## Arquitectura General
Este proyecto es una API REST modular en Node.js/TypeScript para gestión de solicitudes de recursos en UNAULA. Usa Express.js con MySQL, autenticación JWT, subida de archivos y envío de correos vía Microsoft Graph.

**Estructura modular clave:**
- Cada módulo (`src/modulos/`) contiene: `.ruta.ts` (rutas), `.controlador.ts` (HTTP), `.servicio.ts` (lógica negocio), `.repositorio.ts` (SQL), `.interface.ts` (tipos).
- `src/app.rutas.ts` agrupa los routers reales: `/solicitud-recurso`, `/usuarios`, `/autenticacion`, `/dependencia`, `/cargo`, `/dependencia-cargo`, `/tipo-recurso`, `/accion-mejora`, `/proposito`, `/instrumento`, `/informes`, `/asignar`, `/config-sistema` y `/flujo-solicitud`. `historial-solicitud` existe como soporte interno de auditoría y no expone router público.
- **Módulo `dependencia-cargo`:** Gestiona la relación muchos-a-muchos entre dependencias y cargos. Endpoint clave: `GET /cargos-por-dependencia/:idDependencia` para cargar dinámicamente en el frontend.
- **Módulo `flujo_solicitud`:** expone el CRUD de flujos de solicitud por tipo de recurso en `/flujo-solicitud` (`/crear`, `/listar`, `/detalle/:id`, `/actualizar/:id`, `/cambiar-estado/:id`). El módulo `paso-flujo` modela los pasos del flujo y permite consultar pasos por flujo con `GET /flujo/:id_flujo`; está montado públicamente en `src/app.rutas.ts` en el prefijo `/paso-flujo`.
- Controladores delegan a servicios; servicios usan repositorios para DB, servicios compartidos (correo, etc.) y, cuando necesitan atomicidad, abren transacciones con `pool.getConnection()`.
- Ejemplo: `src/modulos/solicitud-recurso/solicitud.controlador.ts` maneja requests, delega a `SolicitudServicio.crearSolicitud()`.

**Flujo de datos:** HTTP → Controlador → Servicio → Repositorio → MySQL. Servicios disparan correos, manejan historial y, en operaciones críticas, controlan `beginTransaction/commit/rollback/release`.

**Tablas principales:**
- `solicitud_recurso` - Solicitudes de recursos (FK a dependencia, cargo, tipo_recurso, estado_solicitud, accion_mejora, proposito, instrumento, usuario)
- `usuario` - Usuarios del sistema (FK a rol_usuario, estado_usuario)
- `dependencia` - Dependencias de la institución
- `cargo` - Cargos institucionales
- **`dependencia_cargo`** - Tabla de unión que asigna cargos a dependencias (clave compuesta: id_dependencia + id_cargo)
- `flujo_solicitud` - Flujos de solicitud por tipo de recurso
- `paso_flujo` - Pasos de un flujo (con estados y responsables)
- `archivo_solicitud` - Archivos adjuntos a solicitudes
- `asignacion_solicitud_recurso` - Asignaciones de solicitudes a usuarios responsables
- `historia_acciones` - Auditoría de cambios en solicitudes
- `estado_solicitud` - Estados posibles de una solicitud
- `estado_usuario` - Estados posibles de un usuario
- `rol_usuario` - Roles del sistema
- `logs_sistema` - Registro de eventos del sistema

## Workflows Críticos
- **Desarrollo:** `npm run dev` (nodemon + ts-node desde `src/server.ts`).
- **Build:** `npm run build` (compila TS a `dist/`).
- **Watch:** `npm run build:watch` (TypeScript en modo observación).
- **Producción:** `npm start` (node `dist/server.js`).
- **Puerto por defecto:** `src/server.ts` usa `PUERTO=3001` si no se define la variable de entorno; el arranque sigue validando MySQL con `pool.getConnection()` antes de escuchar.
- **DB:** `src/server.ts` prueba la conexión con `pool.getConnection()` antes de arrancar; el pool usa `mysql2/promise` y lee `SERVIDOR_BD`, `NOMBRE_BD`, `USUARIO_BD` y `CLAVE_BD`.
- **Archivos:** Subidas a `archivos_subidos/` con nombres únicos (timestamp-random). Servidos en `/solicitud-recurso-api/archivos_subidos` y `/archivos_subidos` desde `src/app.ts`.

## Convenciones Específicas
- **Nombres en español:** Variables, funciones, comentarios (ej: `nombres_solicitante`, `crearSolicitud`).
- **Inyección de dependencias:** Constructores inyectan servicios/repos (ej: `constructor(servicio?: MiServicio)`).
- **Manejo errores:** Try-catch en controladores; respuestas JSON con `cod_estado` y `mensaje`.
- **SQL puro en repos:** La persistencia principal vive en repositorios, pero los servicios pueden abrir conexiones para transacciones y consultas auxiliares; si una operación debe ser atómica, pasa la conexión al repositorio.
- **Correos:** Usa `CorreoServicio.enviarCorreo()` con plantillas HTML en `src/compartido/correo/plantillasCorreo.ts` (ej: `plantillaCorreoCreacionSolicitud` y `plantillaCorreoNuevaAsignacion`).
- **Rutas:** Prefijo base `/solicitud-recurso-api/` + módulo; verifica los nombres exactos en `src/app.rutas.ts` y `GUIA_ENDPOINTS.md` (por ejemplo, asignación se monta en `/asignar`).
- **Archivos estáticos:** Configurados en `app.ts` con `express.static()` para `archivos_subidos`.
- **Seguridad:** `helmet` con CSP permitiendo `https://servicios.unaula.edu.co`; `cors` y `morgan` activos, además de `express.json()` y `express.urlencoded()`.

## Integraciones
- **DB:** MySQL via `mysql2/promise` pool. Queries con `pool.query()`.
- **Auth:** JWT en `src/compartido/utilidades/jwt.ts` y validación de tokens en `src/compartido/seguridad/validar-token.servicio.ts`; claves con `bcryptjs` en `src/compartido/utilidades/bcrypt.ts`.
- **Correos:** Microsoft Graph API; token obtenido via `obtenerTokenGraph()` con `axios`.
- **Uploads:** Multer con límites de 5MB por archivo, máximo 5 archivos y extensiones permitidas `pdf`, `docx`, `xlsx`, `jpg`, `jpeg` y `png`.
- **Sockets:** Se crea `http.createServer(app)` en `src/server.ts`, pero no hay `socket.io` enlazado actualmente.

## Ejemplos
- **Crear endpoint:** En `solicitud.ruta.ts`, añade `enrutador.post('/crear-solicitud-recurso', manejarErrorMulter, (req, res) => solicitudControlador.registrarSolicitudRecurso(req, res))`.
- **Lógica negocio:** En servicio, valida datos, llama `repositorio.insertar()`, registra historial y envía correo.
- **Query DB:** En repo, `const [result] = await pool.query('INSERT INTO tabla SET ?', [objeto])`.
- **Manejo archivos:** Usa `subirArchivos.array('archivos', 5)` en `solicitud.ruta.ts`; maneja `LIMIT_FILE_SIZE` y `LIMIT_FILE_COUNT` en la ruta.
