- En producción
- Profesional
- 2026
SIGESAC
Gestión y trazabilidad de PQRSD para una institución educativa
Capturas


Cliente web
- React 18 SPAVite + Tailwind
- React RouterRutas protegidas por rol
- AxiosAdjunta el JWT
- → HTTPS · JSON · JWT
API REST · Spring Boot 3
- 12 controllersAutorización con @PreAuthorize
- ServicesReglas y máquina de estados
- VencimientoSchedulerMarca vencidas por SLA
- → JPA / Hibernate
Persistencia
- Spring Data JPA14 entidades
- PostgreSQL 16Base relacional
- FlywayMigraciones versionadas
Componentes transversales
Seguridad
- JwtAuthenticationFilter
- RBAC, 4 roles
Auditoría
- AOP @Auditable
- Historial de negocio
Integraciones
- SMTP, correo HTML
- Adjuntos validados
Entrega
- GitHub Actions
- Jenkins + SonarQube
Resumen
Plataforma web que reemplaza WhatsApp, llamadas, correos y hojas de cálculo por un único sistema donde cada petición, queja o reclamo tiene radicado, responsable, plazo y un historial auditable.
Las solicitudes de atención al cliente llegaban por canales dispersos, sin responsable identificable, sin control de tiempos de respuesta y sin indicadores.
- Rol
- Desarrollo completo como único autor: modelo de dominio, API REST, frontend, seguridad, pruebas, pipelines, despliegue y documentación técnica.
- Periodo
- 2026
- Estado
- En producción
- Código
- Privado, descrito con autorización
- Java 17
- Spring Boot 3
- Spring Security
- JWT
- PostgreSQL
- Flyway
- React 18
- Vite
- Tailwind CSS
- JUnit 5
- Mockito
- Vitest
- Playwright
- Selenium
- GitHub Actions
- Jenkins
- SonarQube
- Docker
Contexto
Sysdatec Centro de Desarrollo Integral S.A.S. recibía peticiones, quejas, reclamos, sugerencias, denuncias y felicitaciones (PQRSD) de estudiantes, aspirantes y ciudadanos por canales informales. No había forma de saber quién atendía cada caso ni cuánto llevaba abierto.
Objetivos
- Un radicado único y una consulta pública del estado para quien radica.
- Un responsable identificable y un plazo de respuesta por categoría.
- Historial completo de actuaciones e indicadores calculados desde la base de datos.
Arquitectura
Monolito modular en capas: controller → service → repository → entity, con DTOs y mappers, y módulos transversales de seguridad, configuración, excepciones y auditoría por AOP. El frontend es una SPA independiente que consume la API por HTTP/JSON.
Descarté microservicios y arquitectura hexagonal completa de forma explícita: un equipo, un dominio cohesivo y una sola base de datos no justifican esa complejidad. La decisión quedó registrada en un ADR.
Decisiones técnicas
- Auditoría dual: un historial de negocio legible para el usuario, separado de un registro técnico (IP, antes/después en JSON) visible solo para administradores. Un único log habría obligado a filtrar un mismo modelo para dos audiencias.
- Autenticación JWT sin estado con autorización por método (@PreAuthorize) para cuatro roles.
- Migraciones versionadas con Flyway, también en la base de datos de pruebas.
- Adjuntos validados por lista blanca de extensiones y por firma binaria del archivo, no solo por el nombre.
Funcionalidades principales
- Radicación con adjuntos, incluida la radicación anónima.
- Ciclo de vida con estados como asignada, en análisis, pendiente de información, resuelta, respuesta enviada, cerrada y vencida.
- Reasignación con aceptación automática a las 24 horas.
- Un planificador marca automáticamente las solicitudes vencidas según el SLA de su categoría.
- Correos HTML institucionales para funcionarios y ciudadanos, y panel de indicadores.
Desafíos y soluciones
- Endurecimiento de seguridad en commits dedicados: cerré una escalación de privilegios en el registro público y un IDOR que exponía observaciones internas, enmascaré contraseñas en la auditoría y dejé de exponer mensajes de excepción en errores 500. La escalación quedó cubierta por una prueba unitaria de regresión y una de integración.
- Un solicitante no puede consultar la solicitud de otro, y un funcionario sin el cargo de recepción central tampoco. Ambas reglas se verifican de extremo a extremo con los filtros de seguridad reales.
- En CI,
npm cifallaba con Node 20 por la forma en que npm resuelve binarios opcionales. Lo diagnostiqué como una diferencia entre versiones de npm, no como un lockfile corrupto, y alineé la versión de Node del pipeline con la de desarrollo.
Calidad y pruebas
- Backend: JUnit 5 + Mockito para la máquina de estados, autenticación y almacenamiento, más pruebas de integración @SpringBootTest + MockMvc contra PostgreSQL migrado con Flyway.
- Frontend: ESLint, Vitest + Testing Library (incluida la trampa de foco del modal) y Playwright para los flujos principales.
- GitHub Actions ejecuta
mvn verifycon un servicio de PostgreSQL 16, y lint, pruebas y build del frontend. - Un pipeline de Jenkins añade E2E con Selenium y análisis estático con SonarQube.
- Una matriz de trazabilidad conecta cada requerimiento con su código y su prueba.
Resultados
El sistema está en producción en sigesac.sysdatec.edu.co, con radicación pública y anónima, consulta por radicado y gestión interna por roles.
Aprendizajes
Documentar decisiones con ADR, incluso de forma retroactiva, me obligó a justificar cada elección frente a sus alternativas. Las pruebas de seguridad a nivel HTTP detectaron problemas que las pruebas unitarias por sí solas no habrían encontrado.