


Cambiar una API en Go y una SPA en React editando primero la especificación OpenAPI
Para repositorios donde un backend en Go y una SPA en React comparten una especificación OpenAPI. Cambia la especificación y regenera el código sin tocar lo generado, sigue reglas para ajustes, errores, sesiones, descargas y actualizaciones, y prueba antes de informar.
Para usar estas reglas de IA
## Tomar la especificación OpenAPI como fuente de verdad y separar el trabajo de cada capa
- Trata la especificación OpenAPI como fuente de verdad para rutas, esquemas de request y response, y modelos compartidos.
- Mantén el backend en Go y la SPA en React compilables de forma independiente durante el desarrollo.
- En producción, prefiere incrustar la SPA compilada en el binario del backend y servir la API y la UI desde el mismo origen.
- Usa el servidor de desarrollo solo como comodidad de proxy; no permitas que puertos o hosts exclusivos del desarrollo se filtren al código de producción.
- Conserva una propiedad clara: la capa de API posee el transporte, los servicios el comportamiento del dominio, los almacenes la persistencia y el frontend la presentación.
- Amplía los contratos existentes antes de inventar rutas, almacenes de configuración, canales de eventos o modelos de estado paralelos.
- No añadas subsistemas aplazados explícitamente sin un requisito delimitado y una decisión arquitectónica.
- Cuando la documentación y la implementación discrepen, detén el cambio afectado y resuelve primero el conflicto entre fuentes de verdad.
## Editar la especificación y regenerar el código en vez de tocar archivos generados
1. Inspecciona la especificación, las interfaces generadas, la implementación, las pruebas y la documentación operativa pertinente.
2. Edita la fuente autoritativa: los archivos OpenAPI para la forma de la API, las estructuras de configuración para los ajustes y los catálogos de mensajes para el texto de la UI.
3. Regenera los artefactos del backend y del frontend con los comandos del repositorio.
4. Implementa la interfaz generada y actualiza solo los servicios y wrappers de UI directamente afectados.
5. Ejecuta el formateo, el análisis estático, pruebas enfocadas y la menor comprobación de ejecución pertinente.
6. Revisa los diffs generados para confirmar que la especificación produjo el contrato previsto.
- Nunca edites manualmente archivos generados; corrige la especificación o la configuración del generador.
- Nunca registres una ruta improvisada que eluda la interfaz de servidor generada.
- Mantén los identificadores de operación únicos y estables porque se convierten en nombres de métodos generados.
## Reunir los esquemas compartidos en un solo lugar y mantener los tipos generados iguales a la API
- Divide las definiciones de rutas por dominio y conserva los esquemas, parámetros y responses compartidos en una única sección canónica de components.
- Reutiliza referencias compartidas en lugar de duplicar esquemas casi idénticos entre archivos de rutas.
- Conserva los mapeos de importación y los controles de poda específicos del generador que requieran las referencias entre archivos.
- Cuando un esquema refleje un tipo de una biblioteca upstream, mantén sincronizados el mapeo de máquina y las propiedades JSON.
- Declara todos los campos serializados y marca como required cada campo siempre presente para consumidores que no sean Go.
- Representa las referencias nullable con la forma exigida por la versión de OpenAPI y el generador; prueba el resultado generado.
- Genera los tipos del frontend a partir del documento de API que realmente sirve el backend cuando importe la fidelidad de ejecución.
- Haz commit de los tipos de API generados cuando la política del repositorio use sus diffs como evidencia de revisión del contrato.
- Mantén los clientes de API detrás de wrappers de dominio para que los componentes no dependan de detalles del transporte.
## Devolver errores estructurados sin filtrar el texto de errores internos
- Implementa los endpoints mediante la interfaz de servidor generada y agrupa los métodos de handler por dominio.
- Usa un solo helper compartido para responses JSON y un clasificador central de errores.
- Devuelve errores estructurados con códigos de máquina estables, una clase de representación, campos opcionales seguros y un identificador de request.
- Nunca copies texto de error interno o upstream sin procesar en una response para el cliente.
- Coloca los detalles de validación de campos en un map dedicado y reserva una clave general para fallos que no pertenezcan a un campo.
- Convierte los fallos upstream en identificadores de motivo estables; conserva los bodies sin procesar solo en logs protegidos.
- Usa errores tipados visibles para el usuario únicamente cuando el texto dinámico sea deliberadamente seguro para mostrar.
- No construyas envelopes de error del protocolo fuera del clasificador.
- Devuelve códigos de estado y errores JSON en lugar de usar panics para controlar el flujo.
- Trata la recuperación de panics como una red de seguridad estructurada y registrada, no como comportamiento normal.
## Definir cada ajuste una sola vez y marcar los que requieren reinicio
- Define los ajustes una sola vez en estructuras de configuración tipadas; deriva de ellas valores predeterminados, validación, metadatos del esquema y claves de entorno.
- Aplica siempre la misma precedencia: valores predeterminados, archivo de ajustes y overrides del entorno.
- Persiste solo los valores que difieran de los predeterminados integrados.
- Para cada ajuste nuevo, define su valor predeterminado, validación, categoría de UI, sensibilidad, visibilidad y comportamiento de reinicio.
- Un ajuste con recarga en caliente debe tener un consumidor activo o un hook de recarga; de lo contrario, márcalo como sujeto a reinicio.
- Los valores sujetos a reinicio pueden persistirse de inmediato, pero deben quedar fijados en la vista efectiva de ejecución hasta el reinicio.
- Enmascara los valores sensibles en las responses de la API y trata los placeholders ocultos como no-op durante la actualización.
- Mantén los ajustes exclusivos del programa como read-only mediante la API de ejecución y excluye los ajustes ocultos del esquema reflejado de la UI.
- Ejecuta los mismos validadores al iniciar y antes de persistir para que una configuración guardada no rompa el siguiente arranque.
- Escribe los ajustes de forma atómica y ancla las rutas relativas gestionadas a una raíz de datos estable, no al directorio de inicio.
## Usar un solo formato de logs y apagar el servidor sin dejar trabajo pendiente
- Usa logging estructurado con un único esquema para requests HTTP, eventos del ciclo de vida y workers en segundo plano.
- Adjunta los campos y errores del handler al log de la request actual en lugar de emitir eventos duplicados por request.
- Mantén los logs del backend en un único idioma operativo; la localización de la UI pertenece al frontend.
- Conserva el orden del middleware cuando dependan de él los ID de request, las direcciones reales de clientes, el logging de requests y la recuperación de panics.
- Coloca el middleware nuevo dentro del límite de recuperación salvo que deba modificar campos antes de que empiece el logging de requests.
- Al cerrar, desconecta los suscriptores de eventos persistentes antes de drenar el servidor HTTP.
- Establece un plazo acotado de drenaje para las requests en curso y define el comportamiento explícito cuando venza.
- Para reiniciar, completa la limpieza de servicios antes de sustituir o generar el proceso.
- Haz que los handlers de streaming regresen al cerrar el hub o cancelar la request.
- Registra cada worker en segundo plano en la misma secuencia de cierre para no abandonar trabajo.
## Usar claves de consulta estables y vaciar la caché cuando cambia el usuario
- Explicita el orden de providers cuando los posteriores dependan de contextos de query, locale, autenticación o eventos.
- Expón factories de opciones de query desde módulos de features y conserva las llamadas directas a la API dentro de wrappers de dominio.
- Usa claves de query estables que incluyan todos los parámetros que cambien la identidad.
- Conserva los datos de la lista anterior solo para transiciones reales de página; descártalos cuando cambien los filtros, usuarios, tabs o la identidad de búsqueda.
- Limpia las cachés del ámbito de la cuenta cuando cambie la sesión autenticada.
- Centraliza las actualizaciones optimistas, las snapshots de rollback y la invalidación para mantener coherente cada copia en caché de una entidad.
- Trata los eventos del servidor como indicios de refresh; el estado autoritativo sigue procediendo de queries o endpoints de estado.
- Lee las funciones de mensajes localizados mediante un contexto reactivo dentro de las rutas de renderizado.
- Mapea las claves dinámicas de traducción mediante resolvers estáticos explícitos y conserva formas de placeholder idénticas entre locales.
- Mantén las etiquetas de configuración legibles para humanos en catálogos del frontend, no en esquemas del backend.
## Guardar la sesión aparte y no cerrarla por fallos temporales
- Guarda las credenciales de sesión en un único archivo de estado dedicado con permisos restrictivos; nunca las mezcles con los ajustes generales.
- Trata la credencial de refresh como autoridad de sesión y las credenciales de acceso de corta duración como sustituibles.
- Renueva proactivamente cerca del vencimiento y de forma reactiva una vez después de un fallo de autenticación, con coordinación single-flight.
- Conserva la sesión ante fallos transitorios; límpiala solo después de confirmar un rechazo permanente.
- Mantén los verificadores de autorización con vida corta, capacidad limitada y un solo uso.
- Valida los valores de callback pegados antes de enviarlos upstream y devuelve errores localizados y accionables.
- Retira las credenciales de los resultados de detección de proxy y mantén la detección como read-only.
- Protege las escrituras de onboarding no autenticado para que no puedan modificar ajustes después del login.
- Protege los endpoints de mutación sensibles con autenticación y un header CSRF específico de la aplicación.
- Nunca expongas al cliente bodies de autenticación upstream, credenciales ni errores de paquetes internos.
## Guardar descargas mediante archivos temporales y no borrar archivos que la app no creó
- Convierte el job en límite de la transacción y persiste atómicamente cada transición de estado significativa.
- Envía el progreso de alta frecuencia mediante eventos en lugar de reescribir el estado persistente en cada tick.
- Escribe los payloads en archivos temporales con nombres únicos y renómbralos solo tras el éxito; elimina los parciales al cancelar o fallar.
- Reintenta únicamente los fallos reintentables con backoff exponencial acotado.
- Registra si la aplicación creó cada archivo final antes de limpiar; nunca elimines una ruta basándote solo en su nombre esperado.
- Resuelve las colisiones contra el contenido del disco y las reservas en curso, con una estrategia de fallback acotada.
- Vuelve a resolver las rutas durante la recuperación tras un reinicio salvo que un payload terminado ya sea propietario de su destino.
- Analiza las plantillas de rutas al arrancar y vuelve a validarlas antes de aceptar cambios de configuración.
- Sanea cada segmento de ruta, conserva las raíces explícitas, limita los nombres de archivo por bytes y cuenta por caracteres el truncado visible para el usuario.
- Fija las decisiones de conversión y nombres por job para que los ajustes recargados en caliente no cambien trabajo en curso.
## Reenviar los eventos perdidos al reconectar y resincronizar si no es posible
- Mantén el estado persistente como autoritativo y trata los eventos como una optimización.
- Asigna a los eventos ID, timestamps, topics, tipos y payloads reconstruibles estables.
- Al reconectar, reproduce los eventos posteriores al último ID conocido por el cliente si el buffer aún los conserva.
- Si no es posible reproducirlos, emite un solo evento de resincronización y exige que los clientes vuelvan a obtener el estado autoritativo.
- Usa keepalives para impedir que los intermediarios cierren silenciosamente streams inactivos.
- Permite que solo los eventos de nivel de job establezcan el estado agregado del job; los eventos de task actualizan la task sin recalcular reglas propiedad del servidor.
- Actualiza las vistas afectadas tras reconectar y después de una señal de resincronización.
- Limita la frecuencia de las notificaciones de progreso, pero evita esa limitación para las transiciones terminales y la actualización final de progreso.
- Mantén el transporte de eventos independiente de los gestores de dominio mediante una interfaz publisher pequeña.
## Limitar los destinos del proxy y verificar la firma antes de actualizar la app
- Permite objetivos de proxy según una política exacta de hosts y vuelve a comprobar cada redirección para impedir falsificación de requests del lado del servidor.
- Comparte los fallos simultáneos de caché para el mismo recurso y rechaza bodies demasiado grandes antes de almacenarlos.
- Trata el sistema de archivos como verdad de la caché; reconcilia su tamaño periódicamente y después de escribir, expulsando primero lo menos recientemente accedido.
- Mantén el almacenamiento de caché reubicable y separado del estado de usuario duradero.
- Inyecta las ubicaciones del feed de actualizaciones y las claves de firma confiables durante el build de release; falla de forma cerrada si falta material de confianza.
- Verifica un manifest firmado antes de confiar en cualquier versión, URL, checksum o campo de notas de release.
- Verifica el archivo descargado contra el manifest firmado antes de sustituir un binario.
- Ejecuta la aplicación de actualizaciones en single-flight, recházala en builds de desarrollo y exige autenticación junto con protección CSRF.
- Resuelve el ejecutable de sustitución de forma determinista y rechaza archivos ambiguos.
- Drena los servicios y reinicia solo después de preparar el reemplazo verificado.
## Probar la app en ejecución y detenerse antes de publicar o cambiar producción
- Completa la generación, implementación, pruebas enfocadas y verificación directa de ejecución sin omitir pasos fallidos.
- Verifica el endpoint de salud, el documento OpenAPI servido, el comportamiento de la API afectada y la ruta de UI directamente afectada.
- Ejecuta formateo, análisis estático, pruebas de backend sensibles a condiciones de carrera, comprobaciones de frontend y builds de producción cuando el cambio los afecte.
- Confirma con pruebas enfocadas la persistencia atómica, la semántica de reinicio, el enmascaramiento de secretos y la no divulgación de errores.
- Para trabajo de release, valida versionado semántico estricto, continuidad del feed firmado, checksums y resolución de archivos por plataforma.
- Mantén aplazadas las features aplazadas salvo que el requisito actual las incluya explícitamente en el alcance.
- Evita refactorizaciones no relacionadas, almacenes de estado paralelos, sistemas de errores duplicados e infraestructura especulativa.
- Detente antes de una release externa, migración destructiva, cambio de credenciales o mutación de producción salvo autorización explícita.
- Informa qué cambió, qué se verificó, qué queda fuera del alcance y cualquier conflicto de contrato sin resolver.
