DocumentoStorage. De forma opcional, los archivos pueden replicarse o almacenarse en un servidor remoto via SFTP usando sftpClientService. Ambas capas son independientes: el almacenamiento local siempre está disponible, mientras que el SFTP se activa únicamente si SFTP_HOST está configurado.
Variables de Almacenamiento
Las rutas de almacenamiento se definen mediante variables de entorno y se exponen en el servidor a través deruntimeConfig.storage:
Si las variables de entorno no están definidas, las tres rutas apuntan por defecto al directorio
storage/ en la raíz del proyecto. En producción se recomienda apuntar a rutas absolutas fuera del directorio de la aplicación para evitar que se sobreescriban en cada despliegue.Servicio de Documentos
DocumentoStorage es una clase que gestiona la lectura y escritura de PDFs en el almacenamiento local. Se exporta como singleton (documentoStorage) para reutilizar la misma instancia en toda la aplicación.
obtenerContenidoDesdePdfGenerado(pdfGenerado) soporta tres formatos de entrada para máxima compatibilidad con los distintos proveedores de PDF:
Servicio SFTP
sftpClientService es una función factoría que encapsula el cliente ssh2-sftp-client. Mantiene una conexión singleton por instancia y comparte la misma promesa de conexión entre llamadas concurrentes para evitar handshakes duplicados.
Configuración de conexión
Prioridad de autenticación
SFTP_PRIVATE_KEY_BASE64 está presente, la clave se decodifica con Buffer.from(raw, "base64") y tiene prioridad sobre la contraseña. Si la cadena no puede decodificarse como base64, se interpreta como texto plano (compatibilidad con claves sin codificar).
Métodos disponibles
Rutas de API para Documentos
Todas las rutas bajo/api/solicitudes/:id/documentos requieren autenticación y que el usuario sea el propietario de la solicitud o tenga el rol administrator.
Modelo de Base de Datos
Los metadatos de cada documento subido se persisten en la tabladocumentos_postulantes:
activo implementa un borrado lógico: los documentos eliminados por el usuario se marcan como activo = false pero no se eliminan físicamente del disco de forma inmediata, lo que permite auditoría y recuperación posterior.
Los campos api_path y api_filename se populan cuando el documento se replica en el servidor SFTP remoto, permitiendo saber en todo momento dónde reside cada copia del archivo.