El panel de administración personalizado que construimos en la sesión 020 funcionaba. Tenía rutas UUID, autenticación JWT y jerarquía de roles. Pero también tenía un problema: era una aplicación frontend completamente separada que necesitaba mantenimiento junto con el panel SolidJS principal y el sitio de marketing. Tres aplicaciones frontend para una plataforma eran dos de más.
En sesiones posteriores, tomamos la decisión de retirar el admin SolidJS personalizado y reemplazarlo con SQLAdmin -- una biblioteca Python que genera una interfaz de administración directamente desde modelos ORM de SQLAlchemy. La migración tocó 12 archivos de modelos ORM, creó 16 modelos SQLAlchemy, construyó 12 vistas de administración y eliminó miles de líneas de código frontend personalizado.
¿Por qué SQLAdmin?
| Característica | Admin SolidJS personalizado | SQLAdmin |
|---|---|---|
| Carga de mantenimiento | Alta (app separada) | Baja (auto-generado desde modelos) |
| Pipeline de build | Vite + SolidJS | Ninguno (renderizado en servidor) |
| Soporte de nuevo modelo | Escribir frontend + API | Añadir una clase de vista admin |
| Búsqueda/filtro | Implementación personalizada | Incorporado |
| Despliegue | Servicio separado | Mismo proceso del backend |
La compensación fue clara. Perdimos control de diseño píxel por píxel, pero ganamos cero sobrecarga de mantenimiento para operaciones CRUD de admin. Para una herramienta interna usada por una persona (Thales), esa compensación fue fácil de hacer.
Los 16 modelos SQLAlchemy
La migración requirió convertir cada tabla de base de datos a un modelo ORM de SQLAlchemy apropiado: User, App, Transaction, Provider, AppProvider, PaymentMethod, Webhook, WebhookDelivery, Invoice, Coupon, CouponUsage, ApiKey, FeatureRequest, FeatureUpvote, FeatureComment y AuditLog.
El problema del nombre de columna reservado: metadata a meta
metadata es un atributo reservado en la base declarativa de SQLAlchemy. Definir una columna con ese nombre oculta el atributo interno y causa errores crípticos. El renombrado a meta se propagó a través de cada modelo, endpoint API, SDK y la migración de base de datos misma.
Las 12 vistas de administración
Las transacciones son solo lectura (can_create = False, can_edit = False, can_delete = False) -- en una plataforma de pagos, nunca modificas un registro de transacción después de la creación. Esto es un principio fundamental de auditoría financiera: el libro mayor es solo de adición.
SessionMiddleware para autenticación por cookie
SQLAdmin usa sesiones basadas en cookies para autenticación. El panel ahora vive en /thales -- una ruta significativa para Thales (el CEO y único admin) mientras sigue siendo no obvia para escáneres automatizados.
La corrección de compatibilidad de column_filters
Encontramos errores 500 al usar filtros de columna en SQLAdmin. La corrección requirió especificar filtros como cadenas en lugar de atributos del modelo.
Lo que eliminó la migración
~3.000 líneas de código admin SolidJS, 7 endpoints API personalizados, un pipeline de build separado, configuración de despliegue específica del admin y enrutamiento frontend para admin.
Lecciones de la migración
Empieza con SQLAdmin si eres un equipo pequeño. El nombre de columna metadata te morderá. Las vistas de solo lectura son una funcionalidad, no una limitación. Las sesiones de cookies están bien para configuraciones de un solo admin.
Este artículo es parte de la serie "Cómo construimos 0fee.dev". 0fee.dev es un orquestador de pagos que cubre más de 53 proveedores en más de 200 países, construido por Juste A. GNIMAVO y Claude desde Abiyán sin ingenieros humanos. Sigue la serie para conocer la historia completa de la construcción.