Skip to content
Néstor Castelblanco
Back to projects
  • In production
  • Professional
  • 2026

SIGESAC

Request tracking and audit trail for an education provider

Visit sitePrivate repository

Screenshots

sigesac.sysdatec.edu.co/radicar
SIGESAC's public form for filing an anonymous request, with type, subject, category, description and attachments.
Anonymous filing, a public page in production.
sigesac.sysdatec.edu.co/login
SIGESAC sign-in screen with links to create an account, look up a tracking number and file without signing in.
Sign-in and public entry points.
Architecture: SIGESAC
  1. Web client

    • React 18 SPAVite + Tailwind
    • React RouterRole-protected routes
    • AxiosAttaches the JWT
  2. → HTTPS · JSON · JWT
  3. REST API · Spring Boot 3

    • 12 controllers@PreAuthorize authorization
    • ServicesRules and state machine
    • VencimientoSchedulerFlags overdue by SLA
  4. → JPA / Hibernate
  5. Persistence

    • Spring Data JPA14 entities
    • PostgreSQL 16Relational store
    • FlywayVersioned migrations

Cross-cutting concerns

  • Security

    • JwtAuthenticationFilter
    • RBAC, 4 roles
  • Auditing

    • AOP @Auditable
    • Historial de negocio
  • Integrations

    • SMTP, correo HTML
    • Adjuntos validados
  • Delivery

    • GitHub Actions
    • Jenkins + SonarQube

Overview

A web platform that replaces WhatsApp, phone calls, email and spreadsheets with a single system where every request or complaint has a tracking number, an owner, a deadline and an auditable history.

Customer requests arrived through scattered channels, with no clear owner, no response-time control and no reporting.

Role
Built end to end as the sole author: domain model, REST API, frontend, security, tests, pipelines, deployment and technical documentation.
Period
2026
Status
In production
Code
Private, described with permission
  • 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

Context

Sysdatec Centro de Desarrollo Integral S.A.S. received petitions, complaints, claims, suggestions and compliments from students, applicants and the public through informal channels. There was no way to tell who was handling each case or how long it had been open.

Goals

  • A unique tracking number and a public status lookup for the requester.
  • A clear owner and a response deadline per category.
  • A complete history of actions and metrics computed from the database.

Architecture

A layered modular monolith: controller → service → repository → entity, with DTOs and mappers, plus cross-cutting modules for security, configuration, exceptions and AOP-based auditing. The frontend is a standalone SPA that talks to the API over HTTP/JSON.

I explicitly ruled out microservices and full hexagonal architecture: one team, one cohesive domain and a single database don't justify that complexity. The decision is recorded in an ADR.

Technical decisions

  • Dual auditing: a user-readable business history, kept apart from a technical log (IP, before/after JSON) that only administrators can see. A single log would have meant filtering one model for two audiences.
  • Stateless JWT authentication with method-level authorization (@PreAuthorize) for four roles.
  • Versioned Flyway migrations, applied to the test database too.
  • Attachments validated by an extension allow-list and by the file's binary signature, not just its name.

Key features

  • Request filing with attachments, including anonymous filing.
  • A lifecycle with states such as assigned, in analysis, awaiting information, resolved, response sent, closed and overdue.
  • Reassignment with automatic acceptance after 24 hours.
  • A scheduler flags overdue requests based on each category's SLA.
  • Branded HTML emails for staff and citizens, plus a metrics dashboard.

Challenges and solutions

  • Security hardening in dedicated commits: I closed a privilege escalation in public sign-up and an IDOR that exposed internal notes, masked passwords in the audit log and stopped leaking exception messages in 500 errors. The escalation is covered by a unit regression test and an integration test.
  • A requester can't read someone else's request, and neither can staff without the central-reception role. Both rules are verified end to end with the real security filters in place.
  • npm ci failed in CI on Node 20 because of how npm resolves optional binaries. I traced it to an npm version mismatch rather than a corrupt lockfile, and aligned the pipeline's Node version with development.

Quality and testing

  • Backend: JUnit 5 + Mockito for the state machine, authentication and storage, plus @SpringBootTest + MockMvc integration tests against a Flyway-migrated PostgreSQL.
  • Frontend: ESLint, Vitest + Testing Library (including the modal's focus trap) and Playwright for the main flows.
  • GitHub Actions runs mvn verify against a PostgreSQL 16 service, plus frontend lint, tests and build.
  • A Jenkins pipeline adds Selenium E2E and SonarQube static analysis.
  • A traceability matrix links each requirement to its code and its test.

Outcome

The system is in production at sigesac.sysdatec.edu.co, with public and anonymous filing, tracking-number lookup and role-based internal management.

What I learned

Writing ADRs, even retroactively, forced me to justify each choice against its alternatives. Security tests at the HTTP level caught problems that unit tests alone would have missed.

Next case studyGPE — Gestión de Prácticas EmpresarialesA production system for the full internship lifecycle