Saltar al contenido principal

Ola de mejoras internas: seguridad, rendimiento y resiliencia

Producto y plataforma

Esta semana ha sido más de quitar deuda que de añadir cosas nuevas, pero el resultado es que la app se siente más sólida. Resumen para que sepas dónde mejoró aunque no lo viera el ojo.

Seguridad

  • Escapado de JSON-LD en la carta pública para evitar inyecciones desde nombres de plato exóticos.
  • Validación de URLs externas antes de mostrarlas en públicas.
  • Subida de imágenes ahora rechaza SVGs y limita tamaño a 5 MB. Antes se podía colar un SVG con script.
  • Token de edición pública firmado con HMAC: nadie puede editar la reserva de otro aunque adivine el ID.
  • Webhook de Stripe idempotente: si el mismo evento llega dos veces (Stripe a veces reintenta), solo se aplica una vez.
  • Rate-limit y access guard en seis funciones de Gemini para que no se abuse del coste.
  • Roles: workspace-member-upsert ya no permite escalar a owner desde un rol inferior.

Rendimiento

  • Admin overview dejó de hacer N+1 al listar restaurantes (era una query por cada uno; ahora una sola).
  • Sentry lazy-loaded: solo se carga cuando hace falta, no en cada visita a la home pública.
  • date-fns por bundle pequeño en lugar del paquete entero, ahorra ~80KB en cada carga.

Resiliencia

  • Auto-reload del frontend si falla el preload de un chunk tras un deploy: el usuario no ve pantalla rota, recarga sola.
  • Snapshot de dist/ y script de rollback rápido a la versión anterior si un deploy mete la pata.
  • Recordatorios ahora respetan la zona horaria del restaurante (antes se enviaban en UTC y a veces se adelantaban una hora).
  • Cron de stats públicas reagendado para no pisarse con backups.

Si algo iba lento o raro y notas que ya no, era esto.

ESENCA