Volver a la wiki

Auditoría Suprema 2 · Cola racks: librería de stencils, backup/restore, plantillas y rastro de auditoría

Cuándo

04-09-2026 · commit 17879889 (PR #500, v1.109.0). Cola MEDIA/BAJA del dominio racks en la Auditoría Suprema 2 (task #286): de los 29 hallazgos MEDIA del catálogo auditoria-suprema-2/racks.json, 14 se cierran en este commit, 8 ya estaban resueltos por la Tanda 7 genérica, y 6 quedan diferidos con motivo explícito en el CHANGELOG. Los 7 hallazgos ALTA del mismo catálogo NO se tocan en este PR — ver Preventivos futuros. Implementación en Opus (worktree propio, en paralelo con los PRs de network y signage); revisión de Fable 5.1 antes de mergear. mypy limpio en racks + network/api/port_connections.py (48 ficheros).

Síntomas visibles

  1. PUT /api/racks/{id}/devices devolvía al navegador el management_config cifrado del equipo (#8).
  2. apply_template no validaba la altura del rack destino ni invalidaba la caché de roll-ups: una plantilla de 42U sobre un rack de 12U dejaba equipos en U40 (#10).
  3. Cada autosave del editor descifraba con Fernet TODOS los management_config de la organización para construir la caché de IPs, aunque el payload no trajera ninguna IP (#12).
  4. El envío a la papelera desde el editor — el camino más destructivo del dominio — no dejaba autor ni rastro de auditoría (#17).
  5. El restore extraía uploads/** del ZIP tal cual sobre un namespace plano común a todas las organizaciones: podía sobrescribir un fichero vivo de otro tenant (#22).
  6. Ni el restore completo ni el de librería tenían tope de subida, ni la descompresión del ZIP tenía techo (zip-bomb) (#23).
  7. import_image construía la ruta de disco con la category que manda el cliente: una cadena "../../.." escapaba de MEDIA_ROOT (#24).
  8. import_image guardaba un image_path de /static/ mientras escribía el fichero en MEDIA_ROOT: el stencil nacía con la miniatura rota y la API respondía 200 igualmente (#25).
  9. El backup exportaba parent_rack_id pero el restore nunca lo aplicaba: la jerarquía de racks se perdía y la verificación decía complete (#26).
  10. Nadie podaba MEDIA_ROOT/temp/: cada sesión de Visio o de librería abandonada dejaba el ZIP descomprimido en el volumen para siempre (#27).
  11. El backup completo, el restore y las mutaciones de librería no dejaban ninguna fila en el audit log (#28).
  12. create_from_device, import_visio y cleanup_session mutaban la librería del tenant sin exigir racks:admin, a diferencia de sus hermanos (#29).
  13. create_custom_stencil cargaba el fichero entero en memoria (ContentFile(read())) sin validar tipo ni tamaño (#31).
  14. La foto diaria de integridad se calculaba para TODAS las organizaciones, inactivas incluidas, y ninguna tarea purgaba las filas acumuladas (#34).
  15. Los campos de cableado no tenían max_length en el schema Ninja pero sí en la columna: un texto largo devolvía 500 en vez de 400 (#36).
  16. (Sin numerar, hallado al escribir los tests) las rutas estáticas /stencils/custom, /create_from_image y /create_from_device estaban registradas DESPUÉS de /stencils/{stencil_id}: Django Ninja resuelve por orden y POST /stencils/custom respondía 405 — endpoint muerto.

Causa raíz

Fix aplicado

Commit 17879889 (PR #500):

Lecciones

Preventivos futuros

Véase también

Subir