PROJECT_02
Biblioteca Maxipet
Corporate platform migrated from Flask to Spring Boot 3 (Java 17) keeping the database intact: document management, KPIs, complaints, corrective actions, safety alerts, questionnaires and audit log.
- TYPE
- Migration · Spring Boot
- STATUS
- IN PRODUCTION
CONTEXT
A platform already in production that had to be modernized without stopping operations or touching the existing data: same PostgreSQL, same users, new backend.
WHAT IT COVERS
- Document management by category: documents, manuals, courses, lessons, bulletin and warehouses.
- KPIs and objectives, complaints with evidence, and corrective actions with activities tracked by reference number.
- Safety alerts, questionnaires with one answer per user, audit log and staff directory.
- Five roles with different permissions, including two specific to warehouse management.
THE MIGRATION
- Flask → Spring Boot 3.5 on Java 17, keeping the existing PostgreSQL schema.
- Flyway takes over the schema with versioned migrations; Hibernate only validates, never modifies.
- Separate dev and prod profiles: in prod the application refuses to start if the secrets are still the development values.
- Removed the initializer that created an admin user with a known password on any empty database.
SECURITY
- 15-minute access token and 7-day rotating refresh in an httpOnly cookie; only its SHA-256 hash is stored in the database.
- Reuse detection: if an already-rotated refresh arrives, the entire token family for that user is revoked.
- Changing the password invalidates previous tokens by comparing the iat claim against the change timestamp.
- TOTP 2FA (RFC 6238) with QR setup, and the secret encrypted in the database with AES-256-GCM.
- Rate limiting with Bucket4j on login, 2FA verification and registration; in memory by default, or Redis for multiple instances.
- Files validated by extension and magic bytes with path-traversal protection: an .exe renamed to .pdf is rejected.
OPERATIONS
- Docker Compose with a non-root user and a persistent volume for uploaded files.
- Nginx and Cloudflare Tunnel in front; the origin exposes no ports.
- Micrometer metrics and JSON logs with a request id; the Prometheus endpoint is deliberately kept off the public network.
- React 18 + Vite frontend on Vercel, with transparent session refresh in the axios interceptor.