Files
recordalexia/docker-compose.yml
Jaume Garriga Maestre 203d9b0b47 feat(saas): recuperación de contraseña, freno de fuerza bruta y hardening
Bloque A de la fase SaaS:
- Recuperación por email: código de un solo uso (solo su SHA-256 en BD),
  caducidad 30 min, emitir uno nuevo invalida los anteriores, respuesta
  idéntica exista o no la cuenta (anti-enumeración) y email asíncrono;
  restablecer cierra todas las sesiones de la familia. MailService cae a
  modo log sin SMTP configurado.
- LoginAttemptService: 5 fallos -> bloqueo con backoff exponencial (429 +
  Retry-After) en login, PIN del panel y solicitudes de reset, comprobado
  ANTES de evaluar credenciales.
- Registro exige aceptar la política de privacidad (privacy_accepted_at).
- Borrado definitivo de cuenta (RGPD) con confirmación por contraseña.
- CORS por configuración; seeder demo fail-safe (matchIfMissing=false,
  activado explícito en el compose local); application-prod.yml.
- Liquibase 005 con rollback. 44 tests verdes incl. migración en Postgres.
2026-07-13 22:07:06 +02:00

59 lines
1.8 KiB
YAML

# Stack local de recordaLexia: PostgreSQL + backend (Spring Boot) + frontend (Nginx).
# Pensado para ejecución doméstica/homelab. Las credenciales se leen de .env
# (ver .env.example); nunca van escritas aquí en texto plano.
services:
postgres:
image: postgres:16-alpine
container_name: recordalexia-postgres
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
TZ: Europe/Madrid
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
# El backend espera a que la BD esté realmente lista, no solo arrancada.
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
backend:
build:
context: ./backend
container_name: recordalexia-backend
depends_on:
postgres:
condition: service_healthy
environment:
# Conexión a la BD: host interno del servicio postgres del compose.
DB_HOST: postgres
DB_PORT: "5432"
DB_NAME: ${DB_NAME}
# Spring enlaza estas dos sobre spring.datasource.* por binding relajado.
SPRING_DATASOURCE_USERNAME: ${DB_USER}
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
# Solo en LOCAL: sembrar la familia demo. En producción no se declara
# (el seeder es fail-safe: sin la propiedad, no siembra nada).
RECORDALEXIA_SEED_ENABLED: "true"
TZ: Europe/Madrid
expose:
- "8080"
restart: unless-stopped
frontend:
build:
context: ./frontend
container_name: recordalexia-frontend
depends_on:
- backend
ports:
# Acceso a la app desde la red local del homelab (tablet en modo kiosko).
- "${WEB_PORT:-8088}:80"
restart: unless-stopped
volumes:
pgdata: