PR #47 — NutriTrack SaaS · Revisado por revisor-codigo-django v1.0 · 2026-06-18
DEBUG = True en producción expone stack traces completos a usuarios anónimos, incluyendo variables locales, rutas del servidor y fragmentos de código fuente. Combinado con ALLOWED_HOSTS = ['*'], cualquier host externo puede explotar esta filtración de información.
Definir DEBUG = False. Leer SECRET_KEY desde variable de entorno: os.environ['DJANGO_SECRET_KEY']. Listar explícitamente los hosts permitidos. Rotar el SECRET_KEY actual ya que ha sido comprometido en el repositorio.
La SECRET_KEY está en texto plano en el repositorio. Cualquier persona con acceso al repo puede falsificar sesiones, tokens CSRF y signed cookies. Además el prefijo django-insecure- confirma que no fue generada correctamente.
Rotar inmediatamente el SECRET_KEY actual. Añadir al .gitignore. Auditar el historial de git para eliminar la clave comprometida (git-filter-repo).
OrderCreateView no declara permission_classes. Con la configuración por defecto de DRF (IsAuthenticated), esto depende de la configuración global, que en muchos proyectos está en AllowAny. Cualquier usuario anónimo podría crear órdenes de suplementos clínicos a nombre de pacientes reales.
Añadir permission_classes explícito a todas las vistas. En un SaaS médico, el principio de mínimo privilegio es crítico por normativa HIPAA/RGPD.
La migración elimina directamente ssn (número de seguro social) en una sola operación. Si el deploy de código y la migración no son simultáneos, habrá una ventana donde el código viejo intenta leer una columna inexistente, causando 500 en toda la app de pacientes.
Separar en dos deployments independientes. En BBDD de producción con millones de registros de pacientes, esta migración bloquea la tabla completa durante el ALTER TABLE.
El loop en clinic_dashboard ejecuta una query extra por cada orden para obtener el paciente (order.patient.full_name) y otra para contar sus órdenes. Con 1.000 órdenes en DB = 2.001 queries por carga de página.
Se crea Order y luego múltiples OrderItem sin transacción atómica. Si falla la creación de un item (e.g., supplement_id inválido), la Order queda en DB sin items y sin rollback — estado corrupto en datos clínicos.
Tanto OrderItemSerializer como OrderSerializer usan fields = '__all__'. Esto expone en la API todos los campos del modelo, incluyendo items_cache (caché interna), IDs internos, y campos de auditoría — violación de principio de mínima exposición en datos médicos.
Si patient_id no existe en DB, Django lanza Patient.DoesNotExist sin capturar, resultando en un 500 en lugar de un 404 correcto. En prod con Sentry activo, esto genera alertas falsas y expone el stack trace.
items_cache = models.JSONField(default={}) — el dict {} es evaluado una sola vez en tiempo de carga del módulo y compartido por todas las instancias. Mutaciones en un objeto afectan a otros objetos no guardados.
La creación de Order + OrderItems es lógica de dominio. Debe extraerse a apps/orders/services.py para facilitar testing, reutilización desde Celery tasks y trazabilidad.
Los modelos carecen de __str__. El Django Admin mostrará Order object (1) en lugar de información útil. Imprescindible para diagnóstico de soporte clínico.
Los FK sin related_name generan accesores automáticos como order_set que son ambiguos y difíciles de mantener. Definir explícitamente: related_name='orders', related_name='items'.
Se encontraron 4 issues CRÍTICOS y 5 issues ALTOS que impiden el merge a producción. La combinación de credenciales comprometidas, endpoint sin autenticación y migración destructiva representa un riesgo inaceptable para un SaaS de datos médicos bajo normativa RGPD.