De 600 líneas de React a 40 líneas de JSON
Una pantalla de onboarding de proveedores que migramos el mes pasado tiene 37 campos, cuatro secciones condicionales, tres rutas de aprobación y un drill-through a una vista de detalle de contrato. La versión original en Oracle Forms era aproximadamente 2.400 líneas de PL/SQL y lógica de formulario. Un port manual a React resultó en 610 líneas distribuidas en seis archivos. El DEX descriptor tiene 43 líneas de JSON.
El descriptor no es más corto porque recortamos funcionalidades. Es más corto porque el runtime lleva todo lo que no cambia entre pantallas.
Qué hace realmente el runtime
El runtime es el 90% aburrido. Autenticación contra el IdP empresarial. Aplicación de RBAC en cada campo y acción. Audit logging en un formato que los auditores SOX ya saben leer. Validación de formularios con los mismos mensajes de error en el cliente y el servidor. Localización. Navegación por teclado. Actualizaciones optimistas con rollback. Exportación a Excel. Diseños de impresión. Accesibilidad hasta el anillo de enfoque.
Nada de eso pertenece a un descriptor. Ponerlo allí convertiría cada pantalla en un pasivo. El runtime lo maneja una vez, en TypeScript, en código que poseemos y probamos.
El schema del descriptor
Un descriptor tiene cinco secciones de nivel superior: data, layout, logic, integrations y access. Cada una se valida contra un JSON Schema antes de que algo se renderice. El validador se ejecuta en el navegador, en el pipeline de build y en el loop de tool-use del LLM, de modo que los descriptors malformados fallan en el mismo lugar cada vez.
La sección data nombra entidades y campos de la capa semántica. La sección layout describe regiones, no píxeles. La sección logic declara reglas — “aprobación requerida cuando el monto excede el umbral” — en lugar de código imperativo. Integrations referencia endpoints nombrados de un documento OpenAPI. Access referencia roles del sistema RBAC.
Nada en el descriptor es una cadena de texto libre que el runtime deba interpretar heurísticamente. Cada referencia resuelve a algo que el runtime ya conoce.
Por qué no construimos un editor visual primero
El producto obvio para esta arquitectura es un builder de arrastrar y soltar. Deliberadamente construimos primero el runtime y el schema del descriptor, con un editor de texto plano como única superficie de autoría, y luego agregamos generación con IA antes de agregar un editor visual.
La razón es prosaica. Un editor visual restringe lo que se puede expresar a lo que el editor puede dibujar. Un schema restringe lo que se puede expresar a lo que el runtime puede ejecutar. La segunda restricción es la que importa para sistemas en producción. Una vez que el schema está bien, el editor visual es directo. Si el schema está mal, el editor visual oculta el problema hasta que un cliente encuentra un caso límite que el editor nunca le mostró.
Puntos de extensión
Cada pantalla empresarial tiene al menos una cosa que el descriptor no puede expresar. Un cálculo personalizado. Un endpoint SOAP legacy que nadie quiere tocar. Un widget específico para regulación. El runtime maneja estos mediante puntos de extensión nombrados — módulos TypeScript que el descriptor referencia por nombre.
Esto mantiene el descriptor declarativo mientras deja válvulas de escape para la realidad. Hemos encontrado que aproximadamente el 5% de las pantallas necesitan una extensión, y las que la necesitan generalmente requieren exactamente una. El otro 95% se mantiene como JSON puro.
Lo que esto nos cuesta
Cada decisión arquitectónica tiene una factura. La nuestra es el runtime en sí. Es una pieza no trivial de TypeScript que debe mantenerse, probarse y versionarse cuidadosamente, porque cada pantalla en producción depende de él. Un error en la capa de aplicación de RBAC es un error en cada pantalla a la vez.
Tratamos el runtime como un proveedor de bases de datos trata su planificador de consultas. Releases conservadores. Suites extensas de regresión. Compatibilidad hacia atrás en el schema del descriptor medida en años, no en sprints. Ese es el precio de hacer que los descriptors sean económicos.
La conclusión
Los JSON descriptors no son un truco. Son una división del trabajo. El runtime posee las partes que deben estar bien cada vez. El descriptor posee las partes que cambian por pantalla. El LLM escribe el descriptor. El auditor lee el descriptor. El usuario ve una interfaz de producción que se comporta como software empresarial porque software empresarial es lo que el runtime fue construido para renderizar.