Author: Dominicode

  • Cómo usar Claude Code para tareas sin ser developer

    Cómo usar Claude Code para tareas sin ser developer

    Es claude code tan solo para developers ? 3 cosas que puedes hacer con claude sin ser developer

    “Tiempo estimado de lectura: 3 min”

    • Claude Code es una herramienta orientada a terminales y repos; Claude (modelo web/API) ofrece razonamiento técnico accesible sin instalar dependencias.
    • Con Claude puedes diseñar y depurar workflows en herramientas como n8n (automatización), transformar y analizar datos, y generar documentación y diagramas (Mermaid, OpenAPI).
    • La diferencia clave no es saber programar, sino estructurar problemas y validar hipótesis técnicas usando el modelo web/API.

    Introducción

    Es claude code tan solo para developers ? Si escuchaste “CLI” y cerraste la puerta, respira: la respuesta técnica es sí —pero la historia completa no es tan simple.

    Claude Code (el agente CLI de Anthropic) está pensado para terminales, repos y tareas que tocan el código. Pero Claude, el modelo, vive en la web, en APIs y en integraciones: te da razonamiento técnico sin obligarte a teclear npm install. Aquí te explico por qué importa y tres cosas concretas que puedes hacer sin ser developer.

    Resumen rápido (lectores con prisa)

    Qué es: Claude Code es un agente CLI; Claude (modelo) se accede vía web/API e integraciones.

    Cuándo usarlo: Usa Claude Code si un agente debe tocar tu repo y ejecutar tests; usa Claude Web/API para razonamiento, diseño de flujos y transformación de datos.

    Por qué importa: Permite a non-devs con criterio diseñar, validar y documentar soluciones técnicas sin convertirse en especialistas en sintaxis.

    Cómo funciona: En vez de escribir sintaxis, describes escenarios, estructuras y reglas; el modelo transforma esa descripción en snippets, esquemas y diagramas reutilizables.

    Es claude code tan solo para developers ? Lo esencial en 60 segundos

    Claude Code = herramienta para desarrolladores. Vive en la terminal. Requiere Git, variables de entorno y un repo que pueda inspeccionar y modificar.

    Claude (3.7 Sonnet y variantes) = modelo razonador accesible por web/API. No necesitas compilar nada, sí necesitas saber explicar problemas con precisión. En vez de escribir sintaxis, planteas escenarios, estructuras de datos y reglas. El peso se traslada del teclado al criterio.

    Traducción práctica: si eres product manager, automation builder o founder, puedes usar Claude como copiloto intelectual. No como quien programa, sino como quien diseña y valida soluciones.

    1) Diseñar y depurar workflows en n8n — sin tocar Node.js

    n8n es el lugar donde los flujos se vuelven reales. Pero cuando un JSON llega sucio o una API no tiene nodo nativo, la fricción aparece.

    Lo que haces con Claude:

    • Pegas el payload del webhook y pides: “Dame el fragmento JS para extraer estos campos y normalizarlos.”
    • Le pides la lógica de reintentos y manejo de errores: condiciones, backoff y notificaciones.
    • Si una API requiere HMAC o firma en cabeceras, Claude te escribe la plantilla para el nodo HTTP.

    Ejemplo (conceptual): le describes el JSON y obtienes el snippet listo para pegar en un Code Node de n8n. No tienes que memorizar async/await; solo validar la salida.

    Referencia: n8n (automatización)

    2) Transformar y analizar datos — sin pelear con hojas de cálculo eternas

    Limpiar datos es un agujero negro. Claude lo hace predecible.

    Casos concretos:

    • Generar regex para extraer emails, IDs o patrones específicos. (“Extrae solo .edu y .org que parezcan institucionales.”)
    • Convertir CSV/XML desordenados a JSON con esquema validado. Pegas 50 filas y pides el JSON-schema.
    • Redactar consultas SQL complejas: joins, ventanas, filtros por fechas. Le das la estructura de tablas y la métrica que quieres; él devuelve la query optimizada para tu caso.

    No es “codificar por ti”. Es convertir trabajo repetitivo y propenso a errores en instrucciones reproducibles.

    3) Documentación y diagramas técnicos que no te roban medio día

    El 70% del valor de una decisión técnica está en cómo se comunica. Claude entiende Mermaid.js y puede producir diagramas desde tu texto.

    Lo que recibes:

    • Código Mermaid listo para pegar en Notion o GitHub y ver el diagrama al instante.
    • Un borrador de OpenAPI a partir de la descripción de un endpoint (paths, parámetros, respuestas).
    • Un mapa de arquitectura cloud con dependencias y puntos de integración (ideal para alinear con ingeniería sin sonar inocente).

    Pequeña ventaja: llegas a la reunión con algo que se puede visualizar y discutir, no con una vaga idea.

    Docu: Mermaid (diagramas) · OpenAPI spec

    ¿Cómo decidir si usar Claude Code o Claude Web/API?

    Regla simple:

    • Si vas a dejar que un agente toque tu repo, ejecuciones y tests: Claude Code (requiere developer).
    • Si necesitas razonamiento, diseño de flujos, transformación de datos o documentación: Claude Web/API o integraciones (ideal para non-devs con criterio).

    El nuevo diferencial no es “saber programar”. Es saber estructurar problemas y validar hipótesis técnicas. Claude amplifica eso.

    Conclusión

    No conviertas la terminal en el test de tu valía. Aprende a describir problemas con precisión y tendrás una herramienta que piensa en arquitectura, no solo en sintaxis. Esto apenas comienza: la próxima ronda será cómo integrar Claude en tus procesos de despliegue y gobernanza sin romper producción.

    Fuentes útiles: Anthropic – Claude, n8n (automatización), Mermaid (diagramas), OpenAPI spec

    Para explorar implementaciones y experimentos relacionados con automatización y agentes, visita Dominicode Labs. Es una continuación lógica para quien quiere pasar del diseño a prototipos reproducibles.

    FAQ

    Respuesta: Claude Code es el agente CLI de Anthropic diseñado para operar en terminales y repos (requiere Git, variables de entorno y permisos de repo). Claude, en cambio, es el modelo accesible por web/API e integraciones y está orientado a razonamiento y generación sin necesidad de ejecutar comandos locales.

    Respuesta: No. Para acceder al razonamiento y generación de soluciones técnicas puedes usar Claude Web/API o integraciones; no necesitas ser developer, pero sí saber describir problemas con precisión.

    Respuesta: Sí. Puedes describir el payload o el problema y pedir snippets o plantillas listos para pegar en un Code Node de n8n, así evitas escribir Node.js desde cero.

    Respuesta: Generación de regex, conversión de CSV/XML a JSON con esquema validado, y redacción de consultas SQL complejas (joins, ventanas y filtros). Claude transforma tareas repetitivas en instrucciones reproducibles.

    Respuesta: Sí. Claude puede producir código Mermaid y borradores de OpenAPI que se pegan directamente en herramientas como Notion o GitHub para visualización inmediata.

    Respuesta: Elige que un agente toque tu repositorio cuando sea necesario ejecutar pruebas, aplicar cambios automáticos o inspeccionar código de forma programática. Si solo necesitas diseño, razonamiento o generación de artefactos técnicos, la web/API suele ser suficiente.

  • Implementación efectiva con Plan Mode en Claude Code

    Implementación efectiva con Plan Mode en Claude Code

    Plan Mode primero, código después: el workflow que cambia cómo trabajas con Claude Code

    Tiempo estimado de lectura: 5 min

    • Plan Mode obliga a auditar y planear antes de ejecutar cambios en código.
    • Workflow en tres fases: análisis, refinamiento y ejecución; cada fase reduce riesgo y scope de impacto.
    • Activa Plan Mode en cambios multiplataforma, código heredado o integraciones de librerías arquitectónicas.
    • Mide efectividad por integración sin rollback, estabilidad en CI y ahorro de horas en debugging.

    Plan Mode primero, código después es la regla que separa entregas limpias de correcciones interminables. Activa Plan Mode, deja que Claude analice el repositorio y produzca un plan antes de que toque una sola línea de código. Esa inversión de diez minutos evita horas de debugging por decisiones implícitas.

    Resumen rápido (lectores con prisa)

    Plan Mode obliga a auditar y planear cambios antes de codificar. Úsalo cuando el cambio implica múltiples archivos, código heredado o librerías que afectan la arquitectura. Workflow: análisis, refinamiento y ejecución. Mide por integración sin rollback y estabilidad en CI.

    Plan Mode primero, código después: qué es y por qué importa

    Plan Mode es un modo de sesión en Claude Code que obliga al agente a auditar el código existente, mapear dependencias y proponer una secuencia de cambios verificable antes de implementar. Se activa con Shift+Tab en sesiones interactivas de Claude Code; la documentación oficial lo describe como un flujo que prioriza planificación sobre ejecución (https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview y https://www.anthropic.com/claude).

    ¿Por qué importa? Porque los errores de diseño no son fallos de sintaxis: son decisiones implícitas que se propagan. Implementar primero amplifica esos errores. Planear primero los expone cuando aún cuestan cero cambios.

    Cómo funciona el workflow (práctico y repetible)

    El workflow consta de tres fases claras: análisis, refinamiento y ejecución. No son sugerencias; son pasos que los equipos efectivos repiten cuando integran agentes en su proceso.

    1) Análisis inicial (activar Plan Mode)

    Activa Plan Mode (Shift+Tab). Describe el objetivo como contrato, no como receta. Ejemplo: “Aísla la lógica de autenticación para pruebas unitarias sin DB” en vez de “usa repositorio para auth”. Deja que Claude liste archivos relevantes, dependencias directas y riesgos.

    2) Revisión y refinamiento (iterar sobre el plan)

    Lee el plan: archivos a tocar, orden propuesto, efectos secundarios y tests necesarios. Corrige límites de dominio si hace falta. Esa iteración es barata: texto, no commits. Aquí se define el alcance real y se evitan sorpresas de integración.

    3) Aprobación e implementación (ejecutar con control)

    Aprobas el plan y Claude implementa en el orden validado. Cada cambio es acotado, con tests adjuntos y notas de diseño. Si algo rompe, el impacto está limitado al módulo que se aprobó, no a toda la base de código.

    Ejemplo real de uso en migración

    Meta: migrar API REST a tRPC por módulos.

    Spec

    • Módulo A: AuthService (sin dependencias).
    • Módulo B: UserService (depende de A).
    • Módulo C: Billing (depende de B).

    Con Plan Mode, Claude devuelve: archivos a crear/modificar por módulo, tipos DTO esperados, tests unitarios y orden de merges. Implementación ocurre por sesión por módulo. Resultado: integraciones predecibles y rollback sencillo.

    Cuándo activar Plan Mode (criterio técnico)

    Activa Plan Mode cuando:

    • El cambio afecta múltiples archivos o contracts públicos.
    • Trabajas en código heredado que no conoces.
    • Vas a integrar una librería que afecta la arquitectura (auth, DB, infra).
    • La tarea es una refactorización o migración.

    No lo actives cuando:

    • El cambio es un ajuste pequeño en un único archivo.
    • Creas un archivo nuevo con una spec cerrada.
    • Resuelves un typo o validación trivial.

    El criterio es simple: a mayor riesgo arquitectónico, mayor valor del plan previo.

    Reglas prácticas para que Plan Mode funcione

    • Siempre comienza con CLAUDE.md actualizado. El agente leerá convenciones y patrones prohibidos antes de planear (si tu repo lo tiene, intégralo; si no, crea uno).
    • Exige que el plan incluya: archivos modificados, orden de cambios, tests a ejecutar y riesgos conocidos.
    • Valida el plan tú, un peer o el tech lead; las aprobaciones humanas reducen regresiones.
    • Mantén las sesiones acotadas: una sesión = un módulo. Evita planos globales indefinidos.

    Métricas que importan (no solo LOC/hora)

    Mide efectividad por:

    • Tiempo hasta integración sin rollback.
    • Número de handoffs con correcciones arquitectónicas.
    • Cobertura y estabilidad en CI tras cada merge.
    • Tiempo invertido en revisión del plan vs. horas ahorradas en debugging.

    Un plan de 10 minutos que evita 2 horas de corrección es ROI directo.

    Riesgos y límites honestos

    Plan Mode reduce errores, no elimina la necesidad de juicio humano. Si la spec es ambigua, Claude producirá una implementación ambigua más rápido. El agente no reemplaza decisiones críticas de diseño, trade-offs de rendimiento o consideraciones legales de seguridad. Su fuerza está en ejecutar lo que tú especificas mejor y antes de que toque escribir código.

    Conclusión

    Adoptar “Plan Mode primero, código después” cambia la métrica del equipo: de velocidad de salida a resiliencia de la plataforma. Si quieres que Claude Code deje de ser un generador de parches y pase a ser un colaborador técnico confiable, exige un plan. Haz que piense antes de tocar tu repo.

    Para equipos que exploran workflows, integraciones y automatización avanzada, consulta Dominicode Labs como continuación lógica del enfoque: recursos y experimentos centrados en agentes y productividad técnica.

    FAQ

    ¿Qué es Plan Mode?

    Plan Mode es un modo de sesión en Claude Code que obliga al agente a auditar el código existente, mapear dependencias y proponer una secuencia de cambios verificable antes de implementar.

    ¿Cuándo debo activarlo?

    Actívalo cuando el cambio afecta múltiples archivos, trabajas en código heredado, o integras librerías que afectan la arquitectura. Para cambios pequeños y aislados no es necesario.

    ¿Qué debe incluir un plan mínimo?

    El plan debe listar archivos a modificar, orden de cambios, tests a ejecutar y riesgos conocidos. También conviene indicar límites de dominio y criterios de aceptación.

    ¿Cómo reduce el riesgo en migraciones?

    Al definir el alcance y el orden de merge por módulo, limita el blast radius y facilita rollbacks. Permite validar la integración por partes con tests adjuntos.

    ¿Plan Mode reemplaza la revisión humana?

    No. Plan Mode reduce errores estructurales, pero las aprobaciones humanas siguen siendo necesarias para decisiones críticas y trade-offs no técnicos.

    ¿Qué métricas debe rastrear mi equipo?

    Tiempo hasta integración sin rollback, número de handoffs con correcciones arquitectónicas, cobertura y estabilidad en CI, y la relación entre tiempo de planificación y horas ahorradas en debugging.

  • Implementando Compound AI para Optimizar la Efectividad en Testing

    Implementando Compound AI para Optimizar la Efectividad en Testing

    ¿Quieres que la IA escriba código… o que lo arruine en silencio mientras nadie sabe por qué?

    Tiempo estimado de lectura: 8 min

    • Ideas clave:
    • Los LLMs no son inherentemente malos; el problema es soltarlos sin reglas ni orquestación.
    • Compound AI es orquestación: múltiples modelos, validadores, RAG y un controlador que decide.
    • Spec, Código y Tests deben mantenerse sincronizados; la trazabilidad y decisiones registradas son críticas.

    Introducción

    Poca gente lo dice claro: no es que los LLMs sean malos. Es que los estamos soltando sin reglas. Y rápido.
    Eso se nota cuando el triángulo Spec — Código — Tests se desincroniza a ritmo algorítmico. Y adivina qué aparece primero: deuda técnica.

    Claire Le Goues en CMU lo adelantó hace años. No es novedad; es evolución. Reparación automática de programas y análisis de cobertura no son juguetes académicos. Son la columna vertebral de cualquier agente que quiera escribir código que aguante en producción.

    Lo que estamos construyendo hoy se llama Compound AI. Y si lo manejas mal, es una mina.

    Resumen rápido (lectores con prisa)

    Compound AI: orquestación de múltiples modelos, validadores, bases de conocimiento (RAG) y un controlador.
    Úsalo cuando necesites código reproducible, verificable y trazable en producción.
    Importa porque reduce deuda técnica y fallos en producción al exigir specs operables, tests automatizados y decisiones registradas.
    Funciona mediante pipelines: inputs tipados, transformaciones, validación automática y decision logging.

    1) Por qué esto ya no es ML-only

    Los investigadores pueden inventar algoritmos bonitos. Pero la ingeniería de verdad exige cosas aburridas: orquestación de estado, reintentos inteligentes, persistencia de memoria, latencias aceptables y observabilidad.
    Necesitas backends robustos. PaaS. Infra que aguante agentes que lanzan 50 tareas concurrentes y esperan consistencia.

    2) DSPy y la estructuración de llamadas

    Frameworks como DSPy (o lo que quieras llamar ese nivel de orquestación) transforman llamadas LLM en flujos compilables.
    Piensa en DSLs para IA: inputs tipados, outputs comprobables, rutas deterministas. Menos “ensayo y error” y más pipelines reproducibles.

    3) Test-Time Inference y RLMs — lo que no es magia

    En vez de quemar ciclos entrenando eternamente, gastas cómputo en inferencia inteligente.
    Modelos de razonamiento (RLMs) exploran caminos, ejecutan validadores, comparan resultados y devuelven la versión que pasa las pruebas.
    Sí: eso cuesta. Sí: merece la pena cuando lo que quieres no es una demo, sino software que no explote a las 2AM.

    4) ¿Por qué necesitas ingenieros backend (con experiencia en PaaS)?

    Porque la solución no es un notebook de investigación. Es operación:

    • Orquestar estado entre modelos.
    • Persistir trazas y decisiones.
    • Manejar reintentos sin duplicar efectos.
    • Escalar validadores y tests en paralelo.
    • Aislar fallos y hacer rollback automáticos.

    Si tu equipo no tiene esto, el agente será como un aprendiz con acceso root: peligroso.

    5) El Triángulo que manda: Spec, Código, Tests

    Si uno se desincroniza, todo se va a la mierda. Punto.

    • La Spec debe ser operable. Markdown no basta. Necesitas specs con semántica, vinculadas a código y tests.
    • El Código debe exponer por qué existe. No solo el “qué”.
    • Los Tests no son opcionales. Deben ser ejecutados por el pipeline de agente antes de cualquier merge automático.

    Implementación ≠ caja negra. Implementación comunica intención. Y esa intención debe quedar como dato.

    6) Trazabilidad: la regla de oro

    Cada decisión que toma un agente necesita un artefacto: quién, cuándo, por qué, y qué alternativas se descartaron.
    Si el agente aplicó un “hack” para pasar un test, eso no puede quedar en un chat efímero. Tiene que vivir en tu repo, indexable. JSONL. PR metadata. Historia forense.

    ¿Por qué? Porque poder buscar “find all shortcuts” salva horas de debugging y evita que el mismo hack mute millón de veces.

    7) Integración práctica: stack mínimo para empezar hoy

    No necesitas toda una nave espacial. Esto es un MVP operativo:

    • Orquestador: un servicio que planifica pasos y guarda estado (puede ser una pequeña cola + DB).
    • Callers LLM: modelos rápidos (OSS) para edición y modelos potentes (RLM) para verificación.
    • RAG vector DB para contexto y specs.
    • Validadores: linters, pruebas unitarias, integración y un sandbox de ejecución.
    • Decision store: archivo versionado (.decisions.jsonl) por PR.
    • CI que no solo ejecuta tests, sino que verifica que la spec y los tests se actualizaron si el código cambió.

    8) Un flujo mínimo (ejemplo)

    1. Dev escribe o actualiza spec en formato operable.
    2. El agente genera código y propone cambios en una rama.
    3. Pipeline ejecuta tests + validadores.
    4. Agente intenta optimizar. Si aplica un atajo, registra una decisión en .jsonl. Commit falla si no hay artefacto.
    5. Reviewer aprueba la decisión o solicita cambio.
    6. Merge + sync spec/tests/código.

    Sí, agrega fricción. Es la fricción que salva producción.

    9) Herramientas y patrones recomendados

    • Esquemas validados: usa Zod o similar para validar outputs LLM cuando tocas boundaries.
    • Captura de decisiones: .jsonl con campos: id, pregunta, decisión, autor (LLM/humano), timestamp, diff link.
    • Umbrales configurables: “strict” para core, “lenient” para experiments.
    • Rollbacks automáticos: si una decisión se revoca, tus pipelines deben poder revertir o marcar la rama como needing-fix.
    • Observabilidad: traces de latencia, éxito de validadores, número de decisiones por PR.

    10) Cultura, no solo stack

    No automatices los valores. Automatiza la disciplina.
    Si el equipo ve la herramienta como un juez en lugar de asistente, la odiarán. Hazla útil. Hazla pequeña. Hazla punitiva solo cuando tenga que serlo.

    • Regla simple: cada cambio que no sea trivial necesita al menos una línea en la spec o una entrada en el decision log.
    • No más “and let it run and we go answer some email and then we come back and now I get a decision and I’m like, that’s insane. Don’t do that.” Si vas a delegar, que quede registrado.

    11) Riesgos reales y cómo mitigarlos

    • Ruido: Demasiadas decisiones pequeñas saturan. Solución: umbrales y agrupación por categoría.
    • Alucinaciones del LLM: Validadores estrictos y esquemas runtime.
    • Duplicidad de specs: Fragmenta specs por dominio y mantén ownership.
    • Ataques o leak de credenciales: todo secreto rotatable y accesible solo a procesos autorizados.

    12) Qué cambiar en GitHub (si tuvieras la varita mágica)

    • Markdown como entidad semántica. No solo texto.
    • Linkar decisiones ↔ specs ↔ tests ↔ diffs en la UI.
    • Búsqueda por “intención” (por ejemplo: “find decisions that relaxed auth checks”).
    • Hooks nativos que prevengan merges sin decision artifacts.

    13) Resultado: ¿qué ganas si lo haces bien?

    • Menos deuda acumulada.
    • Onboarding más rápido. Nuevos devs leen la historia de decisiones.
    • Automatización sin descontrol.
    • Auditoría real para compliance.
    • Velocidad que no se convierte en caos.

    14) No es sexy. Es efectivo.

    Las grandes respuestas técnicas no son flashes de genialidad. Son procesos con disciplina.
    Tenemos herramientas para bajar esa disciplina a la realidad operativa. Compound AI no es excusa para saltarse pasos. Es oportunidad para formalizarlos.

    ¿Quieres que lo vuelva práctico?
    Puedo:
    – Escribir el template de .jsonl para decisiones.
    – Diseñar el flujo de CI (GitHub Actions) que bloquee merges sin sincronía spec↔tests↔code.
    – Crear un checklist para ponerlo en marcha en 2 semanas.

    Respóndeme “Dame el template” o “Quiero la CI” y te lo entrego listo para copiar.
    Y recuerda: velocidad sin registro es solo una forma elegante de cavar tu propia trampa. Esto no acaba aquí.

    Si quieres avanzar en pipelines, validación y decision logging con ejemplos prácticos y plantillas, revisa los recursos y experimentos de Dominicode Labs. Es una continuación lógica para equipos que quieren pasar de prototipos a procesos operables. Encontrarás ejemplos de decision logs y patrones de integración que encajan con lo expuesto arriba.

    FAQ

    ¿Qué es Compound AI?

    Compound AI es la orquestación de múltiples modelos, herramientas de validación, bases de conocimiento (RAG) y un controlador que decide qué modelo o herramienta usar, cuándo y cómo, para producir resultados reproducibles y verificables.

    ¿Cuándo debo usar validadores estrictos?

    Usa validadores estrictos en componentes core que afectan seguridad, integridad de datos o disponibilidad. Para experimentos o prototipos puedes aplicar umbrales más lenient, pero documentándolo en el decision log.

    ¿Qué debe contener un decision log (.jsonl)?

    Campos mínimos: id, pregunta, decisión, autor (LLM/humano), timestamp y diff link. Debe ser indexable y versionado por PR.

    ¿Cómo evito que el agente aplique hacks sin supervisión?

    Bloquea commits sin artefacto de decisión; ejecuta validadores en CI; exige que cualquier atajo quede registrado en .jsonl y sea revisado por un humano antes del merge.

    ¿Qué cambios mínimos implemento en CI?

    1) Ejecutar tests y validadores automáticamente. 2) Comprobar que specs y tests cambien si el código cambia. 3) Fallar merges que no incluyan decision artifacts.

    ¿Cómo balancear fricción y velocidad?

    Define umbrales configurables: “strict” para core y “lenient” para experiments. Agrupa decisiones pequeñas y aplica políticas de batching para reducir ruido sin sacrificar trazabilidad.

  • Migrar de espec a producción en un día con Claude Code

    Migrar de espec a producción en un día con Claude Code

    De spec a producción en un día: migración real con Claude Code

    Tratar a Claude Code como un “programador más” es la receta para rehacer horas de trabajo. Tratarlo como un equipo paralelo que ejecuta specs precisas es la forma de pasar de spec a producción en un día: migración real con Claude Code. Aquí tienes el flujo probado, las reglas rígidas y los errores que realmente te harán perder el día.

    Resumen rápido (lectores con prisa)

    Claude Code acelera la ejecución técnica cuando recibe specs precisas y sesiones acotadas. Usa un CLAUDE.md versionado, descompone el sistema en módulos con contratos, lanza sesiones por módulo y valida cada handoff antes de integrar. El flujo minimiza errores y permite pasar de spec a producción en un día si se siguen las reglas.

    Tiempo estimado de lectura: 6 min

    • Ideas clave:
    • Claude Code funciona como un ejecutor: especifica antes de ejecutar y valida antes de integrar.
    • Divide la migración en módulos atómicos con contratos y tests incluidos.
    • Usa sesiones acotadas para evitar que el agente “invente” decisiones arquitectónicas.
    • Revisión humana en cada handoff y pipelines de CI por módulo son obligatorios.

    De spec a producción en un día: el patrón que funciona

    Referencias clave

    La diferencia entre una migración rápida y una que se desboca está en la disciplina: especificar antes de ejecutar, fragmentar antes de paralelizar y validar antes de integrar. Claude Code acelera ejecución; no reemplaza la necesidad de criterio humano para tomar decisiones arquitectónicas.

    A continuación, el flujo operativo que equipos reales usan para migrar en un día sin incendios.

    Fase 0 — Precondición: el contrato de proyecto

    Antes de cualquier línea de código, publica o actualiza un CLAUDE.md en la raíz del repo con:

    • Stack, comandos y convenciones (ej.: pnpm, TypeScript strict, patrón de servicios).
    • Patrones prohibidos y límites de seguridad.
    • Comandos de CI y thresholds de tests.

    Claude Code incorpora este archivo al contexto inicial; sin él, el agente inventa decisiones. Mantén el CLAUDE.md versiónada y sincronizado con cualquier cambio de stack.

    Fase 1 — Spec de arquitectura (1–2 horas)

    El líder técnico escribe la spec: estado actual, objetivo, invariantes y una descomposición en módulos con contratos públicos.

    Resultado concreto:

    • Lista de módulos atómicos y su orden (dependencias DAG).
    • Para cada módulo: signature, DTOs, efectos secundarios permitidos, criterios de aceptación automáticos y manuales.

    Ejemplo simple para migrar API REST a tRPC:

    • Módulo A: AuthService — createSession(userCreds): SessionDto
    • Módulo B: UserService — getUser(id): UserDto (depende de AuthService)
    • Módulo C: Billing — charge(accountId, amount): ChargeResult (depende de UserService)

    La spec es el contrato. Nada se implementa sin ella.

    Fase 2 — Implementación paralela con sesiones acotadas (3–4 horas)

    Lanza sesiones independientes de Claude Code por módulo. Cada sesión recibe:

    1. CLAUDE.md.
    2. Spec del módulo (requirements, design, tasks, acceptance).
    3. Lista de tareas atomizadas (crear tipos, implementar funciones, tests unitarios).

    Reglas de sesión:

    • Mínimo contexto: solo archivos relevantes y la spec del módulo.
    • Tasks atómicas y verificables: “añadir interfaz X” > “implementar función Y”.
    • Tests deben ser parte de la entrega. Claude produce código + tests.

    Ventaja: el agente no necesita retener todo el repo, evita “alucinaciones” arquitectónicas y produce artefactos integrables.

    Fase 3 — Handoff e integración (1–2 horas)

    Cada módulo terminado pasa por revisión humana contra la spec. Validaciones rápidas:

    • ¿Las firmas coinciden con las prometidas?
    • ¿Se respetaron patrones prohibidos del CLAUDE.md?
    • ¿Los tests pasan y la cobertura cumple el mínimo definido?

    Integración:

    • Merge secuencial según DAG de dependencias.
    • Ejecutar builds e integración continua en cada step.
    • Resolver conflictos de API con parches mínimos, volver a ejecutar tests.

    Si algo falla, el alcance de la corrección está acotado al módulo fallido. No es necesario rehelar toda la migración.

    Fase 4 — Regresión y criterios de producción (2 horas)

    Pruebas que deben pasar antes de deploy:

    • Tests unitarios y de integración: cobertura igual o superior al sistema legado por módulo.
    • Pruebas end-to-end en flujos críticos.
    • Métricas de performance (p95) dentro de los límites definidos en la spec.
    • Auditoría: sin dependencias nuevas no autorizadas, sin uso de patrones prohibidos.

    Solo cuando todo esto pasa y la revisión humana valida, se programa el deploy.

    Qué falla cuando fallas el proceso (anti-patrones)

    – Enviar una spec ambigua. Resultado: implementaciones rápidas pero inconsistentes.

    – Hacer una sesión única y global. Resultado: contexto saturado y decisiones implícitas.

    – No versionar CLAUDE.md. Resultado: el agente aplica reglas obsoletas con más fe que un humano.

    Checklist práctico para tu primer día de migración

    • [ ] CLAUDE.md actualizado y en la raíz.
    • [ ] Spec de arquitectura con módulos y contratos firmados.
    • [ ] Tasks atomizadas por módulo y asignadas a sesiones de Claude Code.
    • [ ] Validaciones automáticas y criterios de aceptación escritos en la spec.
    • [ ] Revisión humana planificada para cada handoff.
    • [ ] Pipeline de CI preparado para integración continua por módulo.

    Cierre: por qué esto no es solo “más rápido”

    La velocidad que trae Claude Code es real. Pero el verdadero valor viene de transformar la práctica: dividir el trabajo, especificar contratos y establecer handoffs claros. Si ejecutas el flujo como equipo (humano + agente), pasar de spec a producción en un día deja de ser una promesa de marketing y se convierte en un patrón repetible.

    En la próxima publicación compartiremos una plantilla de spec y un ejemplo real de CLAUDE.md listo para copiar/pegar que puedes usar en tu primer experimento de migración con Claude Code.

    FAQ

     

     

    ¿Qué es CLAUDE.md y por qué es obligatorio?

    CLAUDE.md es un archivo en la raíz del repositorio que contiene el stack, comandos, convenciones, patrones prohibidos y thresholds de CI. Es obligatorio porque Claude Code incorpora este archivo al contexto inicial; sin él, el agente puede “inventar” decisiones arquitectónicas.

    ¿Cuánto contexto debe recibir cada sesión de Claude Code?

    Cada sesión debe recibir el contexto mínimo necesario: el CLAUDE.md, la spec del módulo y solo los archivos relevantes. Reducir el contexto evita alucinaciones arquitectónicas y decisiones implícitas.

    ¿Qué deben incluir las tareas atomizadas?

    Las tareas deben ser verificables y pequeñas: crear tipos, implementar funciones concretas, añadir tests unitarios. Ejemplos: “añadir interfaz X” o “implementar función Y”.

    ¿Qué validaciones humanas son imprescindibles?

    Revisiones rápidas contra la spec: firmas de API, cumplimiento de patrones prohibidos en CLAUDE.md, que los tests pasen y que la cobertura cumpla los mínimos definidos.

    ¿Cómo se gestiona la integración cuando un módulo falla tests?

    Si un módulo falla, el alcance de corrección se acota a ese módulo. Se corrige, se vuelve a ejecutar tests y se reintegra según el DAG de dependencias, sin rehacer toda la migración.

    ¿Por qué evitar sesiones globales con el agente?

    Las sesiones globales saturan el contexto del agente y llevan a decisiones implícitas y variedad de implementaciones inconsistentes. Las sesiones acotadas garantizan consistencia y verificabilidad.

  • Cuándo usar Zod en lugar de TypeScript para validación en runtime

    Cuándo usar Zod en lugar de TypeScript para validación en runtime

    Zod vs TypeScript puro: cuándo usar validación en runtime

    ¿Confías en TypeScript para proteger tu app en producción? Deja de hacerlo. TypeScript es un analizador estático; su trabajo termina cuando el código se compila. Si quieres seguridad real en ejecución necesitas otra cosa. Aquí va la guía práctica: Zod vs TypeScript puro: cuándo usar validación en runtime.

    TypeScript ordena tu código. Zod protege tus fronteras. Úsalos juntos, no en guerra.

    Tiempo estimado de lectura: 4 min

    • TypeScript es un analizador estático: no protege en runtime.
    • Zod parsea en runtime y mantiene una sola fuente de verdad con z.infer.
    • Valida en las fronteras (endpoints, webhooks, env, uploads); confía en TypeScript dentro del dominio.
    • Mide impacto de rendimiento y evita validaciones redundantes en el core.

    ¿Confías en TypeScript para proteger tu app en producción? Deja de hacerlo. TypeScript es un analizador estático; su trabajo termina cuando el código se compila. Si quieres seguridad real en ejecución necesitas otra cosa. Aquí va la guía práctica: Zod vs TypeScript puro: cuándo usar validación en runtime.

    Resumen rápido (lectores con prisa)

    Qué es: Zod es una librería de validación y parsing en runtime; TypeScript es un sistema de tipos estático.

    Cuándo usarlo: Usa Zod en las fronteras (endpoints, webhooks, env, uploads); usa TypeScript dentro del dominio.

    Por qué importa: TypeScript sufre type erasure y no impide fallos en producción; Zod parsea y falla rápido.

    Cómo usarlo: Definir esquemas Zod, derivar tipos con z.infer y parsear payloads en los handlers.

    Por qué TypeScript no basta (y dónde duele más)

    TypeScript tiene un problema estructural: Type Erasure. Los tipos desaparecen al compilar. Eso significa que las aserciones (as T) son mentiras que el compilador acepta y la app paga en runtime.

    interface Usuario { id: number; email: string; }
    
    const datos = await respuesta.json() as Usuario;
    console.log(datos.email.toLowerCase()); // Boom si email no existe
    

    Si la API cambia, o devuelve HTML en un error 500, tu código explota. TypeScript no está ahí para detenerlo.

    Zod y el principio “Parse, don’t validate”

    Zod opera en runtime. Su filosofía es clara: no intentes “validar” por inercia; parsea y falla rápido.

    import { z } from 'zod';
    
    const UsuarioSchema = z.object({
      id: z.number(),
      email: z.string().email(),
    });
    
    type Usuario = z.infer;
    
    const res = await fetch(url);
    const raw = await res.json();
    const usuario = UsuarioSchema.parse(raw); // lanza si algo falla
    console.log(usuario.email.toLowerCase());
    

    Con z.infer mantienes una sola fuente de verdad: el esquema. Nada de duplicar interfaces y validadores.

    safeParse vs parse

    Si quieres manejo de errores controlado:

    const result = UsuarioSchema.safeParse(raw);
    if (!result.success) {
      // logging, métricas, respuesta 400 al cliente...
      throw new Error('Payload inválido');
    }
    const usuario = result.data;
    

    safeParse devuelve un objeto con success y error para flujos menos crudos.

    Dónde aplicar validación (regla práctica)

    No todo necesita Zod. La regla del arquitecto es simple:

    • Valida en runtime en las fronteras: entrada HTTP, webhooks, archivos subidos, variables de entorno, LocalStorage.
    • Confía en TypeScript dentro del dominio: funciones internas, paso de props entre componentes, mutaciones internas en stores tipados.

    Aplicar Zod en todas partes degrada rendimiento y readability. No validar en las fronteras te expone a fallos catastróficos.

    Casos prácticos y patterns

    1) Respuesta API (backend → frontend o backend → backend)

    • Parsea siempre antes de usar.
    • Registra el error y devuelve 400 o fallback claro.

    2) Webhooks / n8n / automatizaciones

    • Parsea y verifica firma si aplica.
    • Rechaza rápido para evitar procesar datos corruptos.

    3) Variables de entorno en arranque (ejemplo con Zod)

    const EnvSchema = z.object({
      DATABASE_URL: z.string().url(),
      NODE_ENV: z.enum(['development','production']),
    });
    const env = EnvSchema.parse(process.env);
    

    Arranque fallido = fallo visible y evitar estados inconsistentes.

    4) Formularios en frontend

    Integra Zod con React Hook Form para validar antes de mutar el estado o enviar al servidor.

    Coste y alternativas: cuándo preocuparse por rendimiento

    Zod añade CPU y peso al bundle. En la mayoría de apps esto es irrelevante frente a la estabilidad que gana tu producto. En sistemas de altísima demanda (millones de eventos por segundo) evalúa alternativas más ligeras o validaciones a medida.

    Alternativas emergentes existen, pero la elección debe basarse en mediciones. No te cases con una librería sin perf tests en tu caso real.

    Integración práctica: patrón recomendado

    1. Punto de entrada (API handler, webhook) → Zod parse
    2. Convertir a tipos con z.infer → pasar al core tipado con TypeScript
    3. Lógica interna → TypeScript puro, sin comprobaciones redundantes
    4. En el cliente, validar inputs críticos; en el servidor, validar todo lo externo

    Conclusión y pasos accionables

    • Zod y TypeScript no son excluyentes. TypeScript organiza tu código; Zod lo hace seguro en producción.
    • Si tienes que elegir hoy, empieza por defender las fronteras: añade validación Zod en endpoints y webhooks.
    • Usa z.infer para que el tipo estático derive del esquema y mide impacto.

    Recuerda: el compilador no vive en producción. Tú sí. Protege lo que importa.

    Prueba esto ahora: añade un esquema Zod a uno de tus endpoints y corre safeParse con un payload inesperado. Verás la diferencia. Esto no acaba aquí; la próxima nota tratará cómo estructurar esquemas Zod para versiones y migraciones sin romper consumidores.

    FAQ

    ¿TypeScript protege mi app en producción?

    No. TypeScript es un analizador estático y sus tipos desaparecen al compilar (type erasure). No impide que datos inválidos lleguen a runtime.

    ¿Qué es Zod y por qué usarlo?

    Zod es una librería de validación y parsing en runtime. Su filosofía es “parse, don’t validate”: parsea datos y falla rápido si no coinciden con el esquema, evitando errores silenciosos en producción.

    ¿Cuándo usar parse vs safeParse?

    Usa parse cuando quieras que el proceso lance inmediatamente y falle rápido. Usa safeParse para manejar errores de forma controlada (logging, métricas, respuesta 400) sin exceptions no controladas.

    ¿Dónde aplicar validación en mi arquitectura?

    Valida en las fronteras: endpoints HTTP, webhooks (p. ej. n8n), archivos subidos, variables de entorno, y LocalStorage. Dentro del dominio confía en TypeScript y evita validaciones redundantes.

    ¿Zod impacta tanto el rendimiento?

    Zod añade CPU y peso al bundle, pero en la mayoría de apps el coste es aceptable frente a la estabilidad que aporta. En sistemas de altísima demanda evalúa alternativas más ligeras y mide con perf tests.

    ¿Cómo integrar Zod con TypeScript sin duplicar tipos?

    Define esquemas Zod y deriva los tipos estáticos con z.infer. Así mantienes una sola fuente de verdad: el esquema.

  • Cómo evitar memory leaks en aplicaciones Angular

    Cómo evitar memory leaks en aplicaciones Angular

    Frontend Memory Leaks y como evitarlo en Angular

    Tiempo estimado de lectura: 3 min

    • Identifica suscripciones, listeners y timers que sobreviven a componentes.
    • Prefiere async pipe y herramientas integradas (takeUntilDestroyed) para evitar fugas.
    • Diagnostica con Chrome DevTools: heap snapshots y comparación de instancias.
    • Disciplina de equipo: code review, linters y políticas de invalidación en singletons.

    Introducción

    ¿Tu SPA se vuelve lenta sin error en consola? Frontend Memory Leaks y como evitarlo en Angular debería ser parte de tu checklist antes de enviar a producción. Si no controlas referencias, suscripciones y listeners, la app “come” memoria hasta que la pestaña muere.

    Resumen rápido (lectores con prisa)

    Qué es: Objetos no referenciados siguen vivos y el Garbage Collector no los elimina.

    Cuándo usar: Siempre que tu SPA cree y destruya componentes, gestiona suscripciones, listeners y timers.

    Por qué importa: Fugas causan degradación silenciosa de rendimiento en sesiones largas y móviles.

    Cómo funciona: Evita referencias persistentes: async pipe, takeUntilDestroyed, Renderer2 y limpieza en ngOnDestroy.

    Frontend Memory Leaks y como evitarlo en Angular: qué pasa y por qué importa

    Un memory leak ocurre cuando objetos que ya no necesitas siguen referenciados y el Garbage Collector no los elimina. En Angular esto duele más: la app vive sin recargas, los componentes se crean y destruyen, y cualquier referencia residual se acumula en el heap.

    No es magia ni culpa del navegador: es disciplina de código. Y sí, pasa en producción, en móviles y en equipos con pestañas cientos abiertas.

    Fuentes útiles:

    Vectores comunes y cómo cerrarlos

    Suscripciones RxJS sin gestionar

    • Qué pasa: .subscribe() vive más que el componente. El callback mantiene la instancia viva.
    • Soluciones: Async pipe (templates), takeUntilDestroyed() en Angular 16+, o takeUntil con un destroy$ en versiones anteriores.
    • Docs: RxJS takeUntil ; Angular rxjs-interop

    Event listeners globales

    Qué pasa: window.addEventListener('resize', fn) sin removeEventListener mantiene la referencia.

    Solución: usar Renderer2.listen() (retorna un unlisten) o guardar la referencia y llamarla en ngOnDestroy().

    Timers (setInterval, setTimeout)

    Qué pasa: un timer que cierra sobre this impide la recolección.

    Solución: almacenar el id y clearInterval/clearTimeout en ngOnDestroy().

    Servicios singleton con datos retenidos

    Qué pasa: providedIn: 'root' vive toda la sesión; si almacenas grandes estructuras sin limpieza, la memoria crece.

    Solución: políticas explícitas de invalidación / límites / weak references lógicas.

    Patrones prácticos (código)

    Async pipe — la opción más simple

    <!-- template -->
    <div *ngIf="data$ | async as data">{{ data.title }}</div>
    

    El async se suscribe y se desuscribe automáticamente cuando el componente muere.

    takeUntilDestroyed() — Angular 16+ (recomendado para TS)

    import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
    
    this.service.stream()
      .pipe(takeUntilDestroyed())
      .subscribe(x => this.handle(x));
    

    Patrón clásico (Angular <16)

    private destroy$ = new Subject<void>();
    
    ngOnInit() {
      this.service.stream()
        .pipe(takeUntil(this.destroy$))
        .subscribe(...);
    }
    
    ngOnDestroy() {
      this.destroy$.next();
      this.destroy$.complete();
    }
    

    Listeners con Renderer2

    private unlisten: () => void;
    
    ngOnInit() {
      this.unlisten = this.renderer.listen('window', 'scroll', this.onScroll.bind(this));
    }
    
    ngOnDestroy() {
      this.unlisten?.();
    }
    

    Timers

    private intervalId?: ReturnType<typeof setInterval>;
    
    ngOnInit() {
      this.intervalId = setInterval(() => this.poll(), 5000);
    }
    
    ngOnDestroy() {
      clearInterval(this.intervalId);
    }
    

    Cómo diagnosticar fugas — proceso práctico

    1. Abre Chrome DevTools → Memory (Chrome DevTools Memory).
    2. Toma Heap Snapshot.
    3. Navega al componente sospechoso, repite la interacción que crees filtra memoria.
    4. Regresa y toma otro snapshot.
    5. Compara: si ves instancias de tu componente o Detached DOM nodes, hay fuga.

    Allocation timeline te muestra crecimiento en tiempo real: una línea que solo sube y no baja es una mala señal.

    Política de equipo: lo que realmente previene fugas

    Esto no es sólo técnica, es disciplina:

    • Regla: preferir Async Pipe cuando sea posible.
    • Regla: toda suscripción en clase debe documentarse: ¿se cancela? ¿por quién?
    • Code reviews: busca .subscribe( sin takeUntil / takeUntilDestroyed o sin async.
    • Linters y tareas CI: detecta patrones peligrosos (por ejemplo .subscribe( sin unsubscribe en componentes).
    • Tests de rendimiento en CI: integra un paso de e2e que simule navegación repetida y monitorice memoria.

    Cierre: no cures síntomas, cambia hábitos

    Un memory leak no es un bug aislado; es deuda técnica que crece silenciosamente. Angular te da herramientas —async pipe, takeUntilDestroyed, Renderer2— pero depende del equipo usarlas consistentemente.

    Si quieres, en Dominicode podemos publicar una checklist de code-review y un snippet de ESLint que detecte suscripciones peligrosas. No te prometo magia: te prometo menos pestañas explotando. Apúntate y seguimos.

    FAQ

    ¿Qué es un memory leak?

    Un memory leak ocurre cuando objetos que ya no necesitas siguen referenciados y el Garbage Collector no los elimina. En una SPA esto provoca acumulación de memoria en el heap mientras la sesión continúa.

    ¿Cómo detectarlo en Angular?

    Usa Chrome DevTools → Memory: toma heap snapshots antes y después de interacciones repetidas. Busca instancias de componentes o Detached DOM nodes que no desaparecen.

    ¿Cómo manejar suscripciones RxJS?

    Prefiere async en templates, o en código use takeUntilDestroyed() (Angular 16+) o takeUntil con un destroy$ y limpieza en ngOnDestroy().

    ¿Y los listeners globales?

    No uses addEventListener sin remover. Usa Renderer2.listen() y llama al “unlisten” en ngOnDestroy().

    ¿Qué hacer con timers e intervalos?

    Guarda los ids retornados por setInterval/setTimeout y llama a clearInterval/clearTimeout en ngOnDestroy().

    ¿Los servicios singleton pueden filtrar memoria?

    Sí. Los servicios providedIn: 'root' viven toda la sesión; si almacenan grandes estructuras sin limpieza la memoria crece. Define políticas de invalidación y límites.

  • Cómo tipar correctamente una API REST en TypeScript

    Cómo tipar correctamente una API REST en TypeScript

    ¿Te fiarías de un mensaje de WhatsApp para pagar una factura importante? No. Entonces, ¿por qué confías en que la red te devuelva exactamente el JSON que tu UI necesita?

    Poca gente lo dice tan claro: la red es hostil. Los backends cambian, las APIs se versionan mal y los datos llegan raros. TypeScript te da sensaciones de seguridad en el editor. Fuera de la compilación, la realidad es JavaScript indiferente. Tipar una API REST no es cuestión de estética. Es la barrera que separa una app que sobrevive a la producción de un desastre nocturno.

    Voy a contarte cómo tipar correctamente una API REST en TypeScript sin postureo. Con ejemplos prácticos, decisiones arquitectónicas y la única verdad que importa: que tu app no rompa en prod por culpa de un campo faltante.

    Primera regla: el contrato no es el código. Es la promesa. Y debe ser verificable.

    Resumen rápido (lectores con prisa)

    Qué es: Validar y tipar el JSON recibido de la red en tiempo de ejecución usando esquemas (por ejemplo Zod) junto a tipos TypeScript.

    Cuándo usarlo: Siempre en boundaries de red; imprescindible para APIs externas o equipos distintos.

    Por qué importa: Previene errores silenciosos en producción y permite estrategias de error diferenciadas.

    Cómo funciona: Fetch/axios → recibir unknown → parse con Zod (o similar) → mapear a modelos internos.

    ¿Por qué los tipos por sí solos no bastan?

    TypeScript vive en tiempo de compilación. Cuando haces fetch o llamas a Axios, recibes JSON en tiempo de ejecución. TypeScript no inspecciona la red. Usar as T es firmar un cheque sin fondos: le estás diciendo al compilador “confía en mí”, pero nadie te va a confiar cuando el objeto tenga un null donde esperabas string.

    Eso genera errores silenciosos: undefined que se propaga, componentes que se caen sin stack trace claro, tests que pasan porque los mocks también mienten. La alternativa no es renunciar a TypeScript. Es complementarlo con validación runtime donde pinte.

    Paso 1 — Define el contrato: DTO claro y aislado

    Haz DTOs en su propio archivo. Separa lo que viene de la red de tus modelos internos.

    Ejemplo:

    // api/types.ts
    export interface UserResponse {
      id: string;
      email: string;
      full_name: string; // nota: formato snake_case típico de backend
      created_at: string;
    }
    
    export interface ApiError {
      statusCode: number;
      message: string;
      errorCode?: string;
    }
    

    ¿Por qué aislarlo?

    Porque si el backend cambia full_namefullName, no quieres que todo tu frontend explote. Cambias la capa de red y mapping. Punto.

    Paso 2 — Wrappers: encapsula fetch/axios

    No llames fetch o axios.get en mitad del componente. Haz un wrapper que:

    • haga la petición,
    • valide el payload,
    • normalice nombres,
    • lance errores tipados.

    Con fetch:

    async function fetchTyped(url: string, opts?: RequestInit): Promise {
      const res = await fetch(url, opts);
      const text = await res.text();
      let json;
      try {
        json = text ? JSON.parse(text) : {};
      } catch {
        throw new Error(`Invalid JSON from ${url}`);
      }
      if (!res.ok) throw Object.assign(new Error('HTTP error'), { status: res.status, body: json });
      return json as T; // todavía una aserción: complementa con validación runtime
    }
    

    Con Axios es más limpio:

    import axios from 'axios';
    async function get(url: string) {
      const res = await axios.get(url);
      return res.data;
    }
    

    Pero cuidado: Axios con genéricos es cómodo, no mágico. Sigue siendo una promesa de que la red devolverá lo que dijiste.

    Paso 3 — Validación runtime: Zod o similar

    Aquí se separan los novatos de los equipos que sobreviven. Zod no es moda; es la última capa de defensa. Define un esquema, parsea el JSON y obtienes tipado estático y validación a la vez.

    Ejemplo con Zod:

    import { z } from 'zod';
    
    const UserSchema = z.object({
      id: z.string(),
      email: z.string().email(),
      full_name: z.string(),
      created_at: z.string(), // luego puedes transformar a Date si quieres
    });
    
    type UserResponse = z.infer<typeof UserSchema>;
    
    async function fetchUser(id: string) {
      const raw = await fetchTyped<unknown>(`/api/users/${id}`);
      return UserSchema.parse(raw); // lanza un error si no coincide
    }
    

    Ventajas:

    • Detectas inmediatamente datos corruptos.
    • Los errores llegan con contexto (qué llave falló y por qué).
    • Puedes transformar created_at a Date de forma declarativa.

    Paso 4 — Manejo de errores tipados

    No uses catch (e) { console.error(e) }. En TS moderno el error es unknown. Te obliga a respirar antes de leer.

    Con Axios:

    try {
      const u = await get<UserResponse>('/api/users/1');
    } catch (err) {
      if (axios.isAxiosError(err)) {
        const server: ApiError | undefined = err.response?.data;
        console.error('Server:', server?.message ?? err.message);
      } else if (err instanceof z.ZodError) {
        console.error('Validation failed:', err.errors);
      } else if (err instanceof Error) {
        console.error('Network or runtime:', err.message);
      } else {
        console.error('Unknown error', err);
      }
    }
    

    ¿Por qué esto importa?

    Porque no es lo mismo que falles por validación (mal payload) que por HTTP 500 o por timeout. Cada caso requiere una estrategia distinta: retry, fallback UI, mostrar mensaje al usuario, reportar a Sentry con tags distintos.

    Paso 5 — Normaliza y mapea en la capa de red

    No dejes snake_case pululando por la app. Tradúcelo en la capa de consumo.

    function mapUser(api: UserResponse) {
      return {
        id: api.id,
        email: api.email,
        fullName: api.full_name,
        createdAt: new Date(api.created_at),
      };
    }
    

    Así tus modelos internos usan camelCase y Date real, no strings sucios.

    Decisiones arquitectónicas: cuándo validar y cuánto validar

    • Si controlas backend y frontend (monorepo o contrato firme): validación runtime puede ser ligera o incluso obviada en puntos internos. Pero en los boundaries externos, sigue validando.
    • Si consumes APIs públicas o equipos distintos: valida TODO. Sin excusas.
    • Campos opcionales: define qué hacer cuando faltan. ¿Default? ¿Error? No improvises en el handler.

    Performance y coste: ¿La validación runtime es lenta?

    Sí, agrega CPU. No, no es un killer. Para la mayoría de apps es insignificante comparado con network. Si tu app maneja miles de respuestas por segundo, shardea validaciones o valida en capas: sólo validar payloads que entren a la lógica crítica.

    Testing: no te olvides de tests de integración

    Mocks unitarios son útiles, pero añade tests e2e que disparen la API real (o un sandbox) y verifiquen que las validaciones y mappings no rompen. Testear tipado estático no te salva si la red cambia; testear contra endpoint sí.

    Checklist práctico (aplicable hoy)

    1. Centraliza DTOs en src/api/types.ts.
    2. Implementa un http wrapper (fetch/axios) que devuelva unknown.
    3. Define Zod schemas para cada DTO.
    4. Parsea el unknown con los schemas antes de castear a tipos.
    5. Mappea a modelos internos (camelCase, Date).
    6. Trata y tipa errores (Axios ZodError, Error genérico).
    7. Agrega tests e2e para validar contratos.
    8. Logea y reporta fallos con contexto (payload, endpoint, user id).

    Antipatrones que debes romper hoy

    • Usar as T en todo el código. Es la tapa del inodoro para ignorar problemas.
    • Confiar en que “el backend no cambia porque somos amigos”.
    • No versionar tus contratos. Versiona APIs y mantén backwards compatibility.
    • Manejar errores con any. Eso borra información útil para debugging.

    Metáfora que funciona: el contrato es la arquitectura del puente

    Tu frontend es el tráfico. El backend es el río. Si el puente (contrato) no es firme y verificado, los coches caen al agua. Los tipos son el plano; la validación runtime es el inspector que revisa la soldadura antes de poner el primer coche encima.

    Mini-guía de migración si tienes legado

    • Prioriza endpoints críticos: pagos, auth, guardar datos de usuario. Valida primero allí.
    • Añade schemas Zod incrementales; empieza por parse y logea sin bloquear; luego, cuando el tráfico confirme estabilidad, cambia a bloquear y fallar fast.
    • Automatiza alerts: si un endpoint empieza a fallar por validación, dispara una tarea de mesa de ayuda y un PR para el backend. No lo ignores.

    Y ahora, lo que pocas hojas blancas te dirán: la cultura importa

    La técnica sola no arregla nada. Si los desarrolladores creen que validar es “trabajo extra” y no “seguridad mínima”, la herramienta se convertirá en una carpeta más del repo. Hazlo obligatorio en el CI:

    • Test de contractos: correr zod.parse en un job.
    • Rechazar PRs si los contratos no están actualizados.
    • Mantén el mapping y los schemas en la misma PR que cambia el backend si controlas ambos.

    ¿Quieres algo listo para copiar y pegar?

    Tengo un template completo: wrapper http (fetch + manejo de errores), ejemplo de schema Zod, mapping y un job de GitHub Actions que valida contratos en CI. Lo dejo preparado para TypeScript + React (Vite) o Next.js.

    Haz esto ahora:

    1. Crea src/api/
    2. Pega el wrapper y el schema Zod del template.
    3. Añade ci/validate-contracts.yml a tu pipeline.
    4. Corre pnpm test:contracts en tu CI.

    ¿Te lo mando ya?

    Responde “Mándame el template” y te paso:

    • El wrapper http.ts listo.
    • Un user.schema.ts con Zod y z.infer.
    • Un ejemplo de fetchUser + mapping + test e2e.
    • Un workflow de GitHub Actions que bloquea merges si falla la validación.

    No es sexy. Es aburrido. Pero es lo que evita que pases la noche arreglando producción porque un created_at vino null.
    Esto no acaba aquí.

    FAQ

    ¿Por qué no son suficientes los tipos de TypeScript?

    Porque TypeScript opera en tiempo de compilación. Los datos de la red llegan en tiempo de ejecución y pueden diferir del contrato. Validar runtime evita errores silenciosos y fallos en producción.

    ¿Qué es Zod y por qué usarlo?

    Zod es una biblioteca de esquemas para validación y parsing en runtime. Proporciona validación declarativa, errores con contexto y permite inferir tipos TypeScript desde el esquema.

    ¿Dónde debo validar: en backend o frontend?

    Valida en ambos. El backend debe proteger su dominio; el frontend debe validar boundaries externos y usuarios malformados. Si controlas ambos, puedes relajar validaciones internas, pero nunca las boundaries públicas.

    ¿No hará lenta la app la validación runtime?

    Añade CPU, sí, pero para la mayoría de aplicaciones el coste es insignificante frente a la latencia de red. Para sistemas de alto rendimiento, valida selectivamente o en capas.

    ¿Cómo manejar campos opcionales o faltantes?

    Decide una política: default, error o fallback. Documenta la decisión y aplica la política consistentemente en la capa de red. No improvises en handlers dispersos.

    ¿Qué patrones debo evitar hoy mismo?

    Evita usar as T indiscriminadamente, confiar en que el backend no cambiará y manejar errores con any. También evita no versionar contratos y no tener tests contra endpoints reales.

    Tiempo estimado de lectura: 6 min

  • Cómo identificar y gestionar la deuda técnica en proyectos de software

    Cómo identificar y gestionar la deuda técnica en proyectos de software

    ¿Quieres que tu equipo deje de temer los viernes por la noche? Entonces presta atención: la deuda técnica no es un problema técnico, es un problema comercial disfrazado de código.

    Tiempo estimado de lectura: 6 min

    • Ideas clave:
    • La deuda técnica es una decisión con coste futuro; hay que tratarla como deuda comercial: medirla, priorizarla y pagarla en cuotas.
    • Las estrategias prácticas funcionan: Boy Scout, presupuesto técnico en sprints, tickets visibles, patrón Strangler y tests donde más duelen.
    • Detecta síntomas (deploys con miedo, PRs largos, regresiones) y aplica un plan de 90 días con diagnósticos y quick wins.

    Introducción

    Poca gente habla claro sobre esto. Todos hablan de “refactorizar” como si fuera una pócima mágica. Nadie te dice que hay que pagar esas facturas en cuotas, con interés, y con plan.

    Voy a contarte cómo identificarla, cuándo pagarla, cómo priorizarla y, sobre todo, cómo evitar que se convierta en una morgue de proyectos. No es teoría: es un manual de supervivencia para equipos que quieren seguir entregando valor sin enterrarse en yeso.

    Resumen rápido (lectores con prisa)

    Deuda técnica: decisión que acelera hoy y encadena mañana. Mide impacto en negocio, reserva presupuesto en cada sprint, prioriza por ROI y aplica mejoras incrementales (Boy Scout + Strangler).

    ¿Qué es la deuda técnica, de verdad?

    No es solo código feo o tests faltantes. Es cualquier decisión que acelera hoy y te encadena mañana.

    Pedir velocidad a cambio de calidad es pedir un préstamo. Si sabes que lo pides, es deuda deliberada. Si lo hiciste por ignorancia, es otra cosa — y merece formación, no romántica metáfora.

    La deuda tiene un interés: cada cambio posterior será más lento. Cada bug será más caro. Cada onboarding tomará más tiempo. Y cuando llegue la crisis, el interés se come tu ritmo de entrega.

    Cómo suena la deuda en la sala de engineering

    Frases que delatan deuda

    • “No lo toques, no vaya a romper algo” — frase clásica.
    • “Los rollouts se hacen los lunes por la mañana” — signo de miedo.
    • “Necesitamos 3 semanas para entender esto” — onboarding fallando.

    Si tu equipo dice estas frases, tienes deuda. Si además las frases salen con cara de resignación, tienes un problema estratégico.

    Tipos que importan (y cómo tratarlos)

    No todas las deudas se pagan igual.

    1) Deuda deliberada y prudente

    • Lo haces con los ojos abiertos.
    • Ejemplo: lanzar un MVP sin caché óptimo para validar mercado.
    • Cómo pagarlo: ticket en backlog, plazo definido, regla de “no crecer la superficie sin pagar”.

    2) Deuda deliberada y temeraria

    • Se hace por presión sin plan.
    • Ejemplo: copiar-pegar soluciones, no tests, no CI.
    • Cómo pagarlo: es urgente. Priorizar mitigación, pruebas, y quizá revertir la decisión de negocio si falla.

    3) Deuda inadvertida

    • Por falta de conocimiento o negligencia.
    • Ejemplo: código espagueti porque nadie revisa PRs.
    • Cómo pagarlo: formación, pair programming, código con owners claros.

    4) Deuda evolución/tecnológica

    • Dependencias sin actualizar, plataformas obsoletas.
    • Cómo pagarlo: calendarizar upgrades por riesgo, no por fecha bonita.

    Síntomas que deberían encender una alarma

    No lo adivines: mide. Estos son síntomas que indican bancarrota técnica:

    • Deployments con sudor frío y rollback semanal.
    • PRs que duran semanas por complejidad.
    • Reducción dramática de la velocidad del equipo sin razón aparente.
    • Regresiones frecuentes donde arreglas una cosa y rompes tres.
    • Tests que mienten o tardan horas en ejecutarse.

    Si ves dos o más, levanta la bandera y para la próxima feature hasta tener plan de pago.

    Estrategias que funcionan (no cuentos)

    Olvídate de “vamos a parar todo y reescribir”. Eso solo suena bien en presentaciones.

    La estrategia que funciona es incremental y política. Aquí las más efectivas:

    Regla del Boy Scout

    Deja el campamento un poco más limpio. Si tocas un archivo, arréglalo: renombra, añade un test, extrae funciones. Pequeñas mejoras constantes suman.

    Presupuesto técnico en cada sprint

    Reserva un % fijo del capacity (10–25%). Lo ideal depende de tu contexto. Si estás en hypergrowth, sube al 20%. Si estás estable, 10% puede bastar.

    Tickets visibles y priorizados

    La deuda que no está en el backlog no existe. Traduce deuda en tickets claros con impacto de negocio (tiempo de dev, riesgo, seguridad). Prioriza igual que features.

    El patrón Strangler (reconstrucción por partes)

    No reescribas el monolito. Construye nuevo alrededor y estrangula lo viejo. Migración por capas, desvío de tráfico y pruebas A/B hasta que lo antiguo deje de respirar.

    Writer único para datos críticos

    Si la deuda viene de concurrencia en escritura (bases, archivos), centraliza el writer. Evita múltiples procesos escribiendo el mismo artefacto.

    Tests donde duela

    No necesitas 100% coverage. Necesitas tests donde duele: integración crítica, pagos, seguridad y puntos con historial de fallos.

    Checklist para Tech Leads (haz que te obedezcan)

    Un listado que puedes imponer como política sin sermones:

    1. Cada PR > 200 LOC exige refactor simple o tests.
    2. Problema no documentado → no merge.
    3. Sprint: 15% de capacidad para deuda técnica.
    4. Métricas públicas: tiempo de build, tiempo de despliegue, tasa de rollback.
    5. Owners claros: cada módulo con responsable técnico.
    6. Registro de decisiones técnicas (ADR) obligatorio.

    Cómo priorizar: regla del ROI técnico

    No pagues lo que no frena tu negocio. Pregunta: ¿esta deuda impide ventas, seguridad o escalabilidad inmediata?

    Prioriza por:

    • Impacto en cliente (bugs críticos).
    • Riesgo de seguridad o cumplimiento.
    • Tiempo que retrasa nuevas features.
    • Coste de mantenimiento actual (horas/semana).

    Haz una matriz rápida: impacto vs esfuerzo. Ataca primero lo alto-impacto/bajo-esfuerzo.

    Evolución de personajes: el equipo, la feature y el legacy

    Imagina una escena: la feature (entusiasmada) quiere salir al mercado. El legacy (cansado) susurra “no me toques”. El equipo (dividido) corre para lanzar.

    Con el plan correcto, la feature sale, el equipo aprende y el legacy muere por asfixia controlada. Sin plan, la feature se convierte en otro parche que alimenta más deuda. La clave es dirigir la narrativa: que la feature evolucione, no que se enrede.

    Casos prácticos: qué hacer hoy mismo

    No necesitas permiso del CEO para estas acciones:

    1. Haz un sprint de diagnóstico (1 semana).
      • Recolecta métricas: tiempo CI, fallos, PR cycle.
      • Lista top 10 hotspots (archivos o módulos más cambiados/rotos).
    2. Empieza con 3 quick wins.
      • Añade tests en módulos críticos.
      • Elimina imports duplicados y variables globales peligrosas.
      • Automatiza un job de lint/format en CI.
    3. Define owner por módulo.
      • Asigna y documenta quien manda sobre cada componente.
    4. Programa un mes de mejoras
      • Plan de 4 semanas: cada semana 1 objetivo de deuda con entregable claro.

    Herramientas y métricas que realmente importan

    No más dashboards bonitos que no sirven.

    • MTTR (Mean Time To Recovery): si sube, hay deuda.
    • Tiempo medio de PR (days): cuando sube, complejidad.
    • Tasa de rollback: fricción operativa.
    • Coverage en paths críticos: no porcentaje general.
    • Tiempo de build y test: si CI crece, la velocidad muere.

    Cómo vender el pago de deuda al negocio (el argumento que funciona)

    No hables en técnico. Habla en riesgo, dinero y velocidad.

    • “Invertir X horas reduce tiempo de entrega de features en Y% y fallos en Z%”.
    • Muestra casos: “Reducimos rollbacks en 70% y ganamos N horas de dev/mes”.
    • Propón un plan con milestones y rollback: “Si no vemos mejora en 3 sprints, revertimos la política”.

    Cuándo sí reescribir (y cuándo no)

    Reescribir es una opción legítima. Pero sólo cuando:

    • La base de código es inentendible y ralentiza todo por encima del 50%.
    • Hay problemas legales o de seguridad que no se pueden parchear.
    • La plataforma actual impide crear valor competitivo.

    Si no, aplica strangler. Reescribir por ego o miedo es receta de desastre.

    Errores comunes que deberías evitar

    • No documentar la deuda: desaparece y vuelve peor.
    • Pay only when there are fires. (Pagar sólo cuando hay incendios.)
    • Pensar que QA soluciona deuda: QA encuentra errores, no reestructura código.
    • Ignorar la deuda cultural: sin code reviews, la deuda vuelve.

    Metáfora que pega: la deuda como jardín

    La deuda es jardín salvaje. Si lo ignoras, crece maleza y come el césped bonito. Podés dejarlo crecer por un tiempo si sólo querés probar el terreno (MVP). Pero a la larga, o contratas jardineros o el jardín se vuelve intransitable.

    Urgencia y plan de 90 días (si quieres resultados reales)

    Si te sientes valiente, este es el plan que recomiendo:

    • Día 0–7: Diagnóstico y métricas.
    • Día 8–30: Quick wins + políticas (Boy Scout + Sprint budget).
    • Día 31–60: Migraciones pequeñas (Strangler) y tests críticos.
    • Día 61–90: Medir impacto, ajustar presupuesto, presentar resultados al negocio.

    CTA directo (haz algo ahora)

    Haz esto ahora: abre tu tablero de issues, crea un epic llamado “Deuda Técnica — Sprint 0” y añade:

    • 3 métricas que vas a medir.
    • 3 hotspots para arreglar esta sprint.
    • Asignación del 15% de la capacidad.

    Respóndeme con “DEUDA YA” y te mando una plantilla de epic + checklist de 90 días que puedes pegar en tu Jira/Linear. Además te daré el mail corto y convincente para que envíes a Product/CEO y consigas el presupuesto técnico.

    Cierre — por qué esto no acaba aquí

    La deuda técnica no es un monstruo que se elimina de una vez. Es una economía: cobran intereses y cambia con el mercado. La idea no es purismo, es sostenibilidad.

    Si haces lo básico —visibilidad, presupuesto y pequeños pagos constantes— recuperarás velocidad y reducirás noches de pánico. Si no, la deuda comprará una hipoteca sobre tu tiempo de desarrollo.

    No te estoy pidiendo que seas perfecto. Te pido que seas estratégico. ¿Quieres la plantilla? Di “DEUDA YA”. Esto no acaba aquí: esto es el inicio de que tu equipo vuelva a confiar en sus despliegues.

    FAQ

    Respuesta: La deuda técnica es cualquier decisión que acelera hoy y genera coste futuro en forma de mayor complejidad, bugs o tiempo de desarrollo.

    Respuesta: Si observas dos o más síntomas (deploys con miedo, PRs largos, regresiones, subida del MTTR), detén nuevas features hasta tener un plan de pago.

    Respuesta: Reserva entre 10–25% del capacity por sprint. Ajusta según contexto: hypergrowth ≈ 20%, estable ≈ 10%.

    Respuesta: Reescribe solo si la base de código es inentendible y ralentiza más del 50%, hay problemas legales/seguridad o la plataforma impide crear valor competitivo.

    Respuesta: Publica tiempo de build, tiempo de despliegue, tasa de rollback, MTTR y tiempo medio de PR, además de coverage en paths críticos.

    Respuesta: Deuda deliberada se contrata con conocimiento y plan; inadvertida surge por falta de formación o procesos (ej.: PRs sin revisión).

    Respuesta: Traduce problemas técnicos en tickets con impacto de negocio (tiempo de dev, riesgo, seguridad), priorízalos como features y asigna owners claros.

  • Cómo Migrar a TypeScript 6.0 y Evitar Problemas

    Cómo Migrar a TypeScript 6.0 y Evitar Problemas

    ¿Listo para dejar de escribir código como si fuera 2016? TypeScript 6.0 no es un parche: es un ultimátum. Lee rápido. Haz el plan. Y no lo dejes para mañana.

    Tiempo estimado de lectura: 8 min

    • TypeScript 6.0 activa “strict” por defecto y cambia el módulo por defecto a ESM: esto exigirá limpiar deuda técnica y migrar módulos.
    • Trae soporte nativo para APIs modernas (Temporal, getOrInsert en Map) que reducen boilerplate y errores de fechas y caches.
    • Planifica la migración: branch, activar strict, clasificar errores, pruebas y CI, migración gradual a ESM y reemplazo progresivo de Date por Temporal.

    TypeScript 6.0 ya está aquí. Y no viene a hacerte la vida más fácil solo por cortesía: viene a exigir calidad. Si tu repo huele a “any” y a configuraciones por defecto, vas a ver errores. Muchos. Bienvenidos a la criba.

    Resumen rápido (lectores con prisa)

    TypeScript 6.0 activa “strict” por defecto, cambia el módulo por defecto a ESM y trae typings nativos para APIs modernas como Temporal y utilidades como getOrInsert en Map. Migrar requiere rama dedicada, pruebas y una estrategia gradual para modernizar módulos y reemplazar Date por Temporal.

    Qué cambia en TypeScript 6.0

    Primero: el golpe que no puedes ignorar — strict por defecto

    Hasta ahora, muchos iniciaban proyectos con la mínima fricción posible. Eso se acabó. TS 6.0 crea nuevos proyectos con “strict”: true por defecto. Traducción al cristiano:

    • noImplicitAny se vuelve exigente. Si algo no tiene tipo, ahora te lo va a recordar a gritos.
    • strictNullChecks hace que ignorar null y undefined sea una mala idea.
    • strictBindCallApply valida que cuando cambias el contexto de una función, lo hagas correctamente.

    Si tu código vive de aserciones (as any, as unknown, as Tipo), la migración te sacará los esqueletos del armario. Buen momento para limpiar deuda técnica, no para hacer commits de pánico.

    Ejemplo rápido: tsconfig mínimo ahora

    {
      "compilerOptions": {
        "target": "ES2022",
        "module": "esnext",
        "strict": true,
        ...
      }
    }

    Segundo: adiós CommonJS (por defecto), hola esnext

    TS 6.0 asume ESM como estándar. El valor por defecto de module pasa a esnext. Esto es intencional: el mundo ya está usando imports nativos, top-level await y bundlers modernos.

    Impactos prácticos:

    • Si aún exportas con module.exports y require(), tendrás que migrar o añadir compatibilidad.
    • Mejora el tree-shaking en bundlers modernos.
    • Usa Top-Level Await sin trucos.

    ¿Te preocupa Node legacy? Mantén compatibilidad en módulos concretos o transpila a CommonJS solo donde lo necesites. Pero el camino natural ahora es ESM.

    Tercero: nuevas API que facilitan la vida (Temporal, getOrInsert…)

    Temporal: el reemplazo sensato del desastre llamado Date

    Temporal no es una moda. Es la API de fechas que por fin piensa en zonas horarias, mutabilidad y precisión. TS 6.0 trae typings nativos para Temporal, así que puedes usarla sin depender de librerías externas.

    Ejemplo:

    import { Temporal } from '@js-temporal/polyfill'; // en runtime, o nativo en motores que lo implementen
    
    const ahora = Temporal.Now.plainDateTimeISO();
    const proximaSemana = ahora.add({ days: 7 });
    console.log(proximaSemana.toString());

    Temporal hace que calcular intervalos, convertir zonas y sumar días deje de ser una pesadilla llena de bugs.

    getOrInsert en Map: menos boilerplate, menos condiciones de carrera

    La operación de “si existe devuélvelo, si no cálcula/crea e inserta” es un patrón recurrente. Con getOrInsert (o emplace) lo tienes atómico y tipado:

    const cache = new Map();
    const user = await cache.getOrInsert(id, async () => await fetchUsuario(id));

    Esto evita el clásico:

    if (!map.has(key)) map.set(key, factory());
    const val = map.get(key);

    Menos código, menos bugs, menos gente escribiendo race conditions cuando la función es asíncrona.

    Cómo migrar sin incendiar el repo (plan paso a paso)

    Plan práctico

    • 1) No lo hagas en master. Crea un branch de migración y un plan.
    • 2) Activa strict localmente: cambia tsconfig y corre tsc. Déjalo fallar.
    • 3) Clasifica errores por impacto: trivial (añadir tipo), moderado (cambiar firmas), crítico (bibliotecas externas).
    • 4) Prioriza los puntos de entrada: handlers API, parsers de JSON, webhooks, init de app.
    • 5) Añade pruebas y CI que compile en strict. Si falla la compilación en PR, no se mergea.
    • 6) Moderniza módulos a ESM gradualmente. Empieza por paquetes que usen bundlers modernos.
    • 7) Reemplaza Date por Temporal en nuevos módulos. Hazlo con PRs pequeños.
    • 8) Introduce getOrInsert para caches y mapas concurridos.

    Checklist práctico para cada repo

    • – ¿tsconfig tiene “strict”: true? Si no, actívalo en un branch.
    • – ¿Import/Export mixto? Documenta y migra módulos uno por uno.
    • – ¿Tests unitarios? Asegúrate de que cubran la lógica de frontera (parsers, inputs externos).
    • – ¿Variables de entorno y config? Añade validación en startup (Zod o similar).
    • – ¿Dependencias nativas de Node? Verifica compatibilidad con ESM o usa interop wrappers.

    Riesgos reales y cuándo NO actualizar aún

    No es un dogma: hay casos donde deberías esperar.

    • – Repos monolíticos con mil paquetes legacy y dependencias dinámicas de require().
    • – Librerías que exponen CommonJS exclusivamente y no tienen roadmap de ESM.
    • – Pipelines que necesitan latencia ultra-baja y donde cambiar la cadena de build ahora es peligroso.

    Si estás en uno de esos escenarios, planifica una migración progresiva y una ventana de compatibilidad.

    Performance y el futuro del compilador (spoiler: se viene cambio de motor)

    TS 6.0 es la última gran versión mayor que funciona sobre el compilador escrito en JS/TS. El equipo ha dejado claro que la arquitectura actual llegó a su techo en repos masivos, y se ha hablado de explorar compiladores nativos (Go u otras tecnologías). Eso implica:

    • – Cambios en la velocidad de análisis a medio plazo.
    • – Posibles ajustes en la API del tooling.
    • – Mayor exigencia en la calidad del código para aprovechar mejoras de rendimiento.

    No lo tomes como alarma: tómalo como señal para ordenar tu base de código ahora, antes de que el motor cambie.

    Ejemplos rápidos que deberías probar hoy (copia-pega y juega)

    • 1) Activar strict y ver errores:
      npx tsc --init
      # edita tsconfig: "strict": true
      npx tsc --noEmit
    • 2) Probar Temporal (cliente o node con polyfill):
      npm i @js-temporal/polyfill
      node -e "const { Temporal } = require('@js-temporal/polyfill'); console.log(Temporal.Now.plainDateTimeISO().toString());"
    • 3) Migrar módulo a ESM:
      - cambia exports a export default / named exports
      - añade "type": "module" en package.json donde aplique

    Una metáfora rápida

    TS 6.0 es el peaje en la autopista. Si vas en coche viejo sin luces, te obliga a parar y actualizar. Si ya vas con el coche bien afinado, pasas más rápido. Y sí: pagarás por entrar, pero el viaje será más predecible.

    Cierre con plan de ataque corto (haz esto hoy)

    • 1. En un branch, activa strict y corre tsc. Mira la lista de fallos.
    • 2. Arregla los 10 errores más ruidosos. Haz PRs pequeños.
    • 3. Actualiza un paquete a ESM y lanza canary.
    • 4. Reemplaza Date por Temporal en un módulo pequeño.
    • 5. Añade validaciones de entrada (webhooks, APIs) usando Zod o tu validador favorito.

    CTA

    ¿Quieres la checklist automática para tu repo? Respóndeme con “MIGRAR MI REPO” y te envío el script que crea el branch, activa strict y lista los errores más críticos.

    FAQ

    ¿Por qué TS 6.0 activa strict por defecto?

    Porque busca elevar la calidad del código desde el inicio de nuevos proyectos. Activar strict reduce errores silenciosos relacionados con any, null y llamadas mal tipadas.

    ¿Tengo que migrar todo a ESM de inmediato?

    No. La recomendación es migrar gradualmente: empuja módulos que ya usan bundlers modernos, mantén compatibilidad para paquetes legacy y transpila a CommonJS solo donde sea imprescindible.

    ¿Cómo empiezo a usar Temporal sin romper producción?

    Introduce Temporal en módulos nuevos o en PRs pequeños. Usa el polyfill @js-temporal/polyfill en entornos que no lo soporten nativamente y añade pruebas para conversiones de zona horaria e intervalos.

    ¿Qué hago con dependencias que solo expone CommonJS?

    Mantén wrappers de interop o transpila esos paquetes en tu pipeline. Prioriza reemplazos si la dependencia es crítica y no tiene roadmap hacia ESM.

    ¿Qué pruebas debo priorizar durante la migración?

    Prioriza tests sobre parsers de entrada, handlers de API, webhooks y cualquier lógica que deserialice datos externos. Asegura que el CI falle si TypeScript en strict da errores.

    ¿Cómo evitar que un cambio de tsconfig rompa CI?

    Haz la activación de strict en un branch con su propio pipeline, clasifica errores y crea PRs pequeños que corrigen grupos de errores. No merges hasta que el build en strict pase.

  • Versiones maliciosas de Axios despliegan un troyano de acceso remoto

    Versiones maliciosas de Axios despliegan un troyano de acceso remoto

    Versiones maliciosas de Axios (1.14.1 y 0.30.4) despliegan un troyano de acceso remoto mediante un ataque de cadena de suministro

    Tiempo estimado de lectura: 5 min

    Ideas clave

    • Dos releases maliciosos: axios@1.14.1 y axios@0.30.4 publicados en npm el 2026-03-31 que introdujeron un RAT via dependencia secundaria.
    • Dependencia trampa: se añadió plain-crypto-js@4.2.1 con un script postinstall que descarga payloads desde http://sfrclak.com:8000.
    • Vector operacional: publicación manual con credenciales npm comprometidas; installs que usan latest sin lockfile pueden ejecutar código remoto.
    • Mitigación observada: detecciones automáticas (por ejemplo, Socket) y bloqueos de plataformas como Vercel ayudaron a contener la propagación.

    Tabla de contenidos

    Introducción

    El 31 de marzo de 2026 se publicaron en npm dos versiones maliciosas de Axios —1.14.1 y 0.30.4— que desplegaban un troyano de acceso remoto a través de una dependencia secundaria. Este incidente demuestra cómo una falla operacional en el ecosistema de paquetes puede convertir una librería ampliamente descargada en un vector de compromisos masivos.

    Resumen rápido (lectores con prisa)

    Qué: Axios publicó dos releases maliciosos que añadieron plain-crypto-js@4.2.1 con un postinstall que descarga y ejecuta un RAT.

    Cuándo: Publicado en npm el 2026-03-31; la dependencia trampa se subió ~18 horas antes.

    Por qué importa: installs que resuelven latest sin lockfile pueden ejecutar código remoto inmediatamente al correr npm install.

    Cómo funciona: el postinstall contacta a un C2 en http://sfrclak.com:8000 y descarga payloads por plataforma que actúan como RAT.

    Qué ocurrió, técnicamente

    Acceso y publicaciones

    Un atacante obtuvo acceso a las credenciales npm de un mantenedor principal de Axios, cambió el correo de la cuenta y publicó manualmente dos releases fuera del pipeline CI/CD y sin tags en GitHub. Las dos ramas (1.x y 0.x) fueron comprometidas con 39 minutos de diferencia.

    Dependencia trampa

    Previamente se subió la dependencia trampa plain-crypto-js@4.2.1 aproximadamente 18 horas antes de las releases. Esa dependencia definía un script postinstall que se ejecuta durante npm install y actúa como dropper.

    Impacto en installs

    Installs que resolvían latest sin un lockfile podían ejecutar código remoto tan pronto como npm install corría. Resultado: posibilidad de ejecución remota de código en entornos locales, CI y servidores de build.

    Cómo funciona el malware (anatomía técnica)

    1. Vector

    No se modificó el código funcional de Axios; se añadió una dependencia maliciosa en el árbol de dependencias.

    2. Trigger

    plain-crypto-js define un script postinstall. Npm ejecuta por defecto scripts de lifecycle en install, lo que activa la carga maliciosa.

    3. Dropper

    El postinstall contacta al servidor C2 y descarga un payload específico por plataforma (macOS, Windows, Linux). El servidor observado es http://sfrclak.com:8000.

    4. Persistencia y evasión

    El payload ejecuta acciones maliciosas, luego se autoelimina y sobrescribe su propio package.json con contenido “limpio” para dificultar auditorías forenses. Si el script se ejecutó en entornos con secretos (CI, máquinas de build, servidores), la exposición es grave.

    Diagnóstico rápido: cómo saber si te afectó

    Asume compromiso si ejecutaste npm install o instalaciones globales sin lockfile después de 2026-03-31T00:21:58Z. Búsquedas imprescindibles:

    • Revisar lockfiles y dependencias transitivas: package-lock.json / yarn.lock / pnpm-lock.yaml: busca axios@1.14.1 o axios@0.30.4.
    • Buscar en node_modules: busca plain-crypto-js.
    • Logs de red: busca conexiones a http://sfrclak.com:8000 o a sfrclak.com.
    • Sistemas CI: revisa jobs que corrieron npm install sin --ignore-scripts.

    Comandos útiles:

    grep -E "axios.*(1\.14\.1|0\.30\.4)" package-lock.json || true
    grep -r "plain-crypto-js" node_modules || true
    journalctl -u your-ci-agent.service | grep "sfrclak.com" || true

    Remediación inmediata (ordenada y práctica)

    1. Fija la versión segura en tus proyectos: axios@1.14.0 o axios@0.30.3 en package.json.
    2. Purge e instala de nuevo desde estado limpio:
      npm cache clean --force
      rm -rf node_modules
      npm install
    3. Rota TODOS los secretos de entornos que pudieron ejecutar el script: tokens CI, claves API, accesos a bases de datos y claves SSH.
    4. Redespliega desde artefactos construidos en entornos sanos.
    5. En CI, añade por defecto:
      npm ci --ignore-scripts

      Y autoriza scripts de instalación solamente de forma explícita y revisada.

    6. Audita y notifica: si detectas conexiones a http://sfrclak.com:8000, asume exfiltración y sigue el protocolo de respuesta de incidentes de tu organización.

    Medidas arquitectónicas y criterio técnico para evitarlo

    • Denegar por defecto: CI debe ejecutar --ignore-scripts y solo permitir scripts documentados y revisados.
    • Lockfiles en control de versiones: no sólo package.json; el lockfile debe revisarse y aprobarse en PR.
    • Auditoría de transitivas: integra escáneres (por ejemplo, Socket, Snyk, Dependabot) como paso obligatorio en PR y en pipelines.
    • Política de least privilege para cuentas de publish: MFA obligatorio, rotación de accesos, uso de cuentas de bot con límites.
    • Aislamiento de builders: construye artefactos en runners frescos y con secreto mínimo; evita que builders tengan credenciales de producción.
    • Monitorización post-install: alertas en EDR, inspección de conexiones salientes y huellas de procesos anómalos.

    Cierre: esto no acaba aquí

    Un mantenedor comprometido puede provocar daño a escala en minutos. La conclusión operativa es simple: reduce la superficie de ejecución de scripts, exige lockfiles revisados y trata las dependencias como parte del perímetro de seguridad. Implementa --ignore-scripts en CI, audita transitivas y rota secretos hoy mismo. Mañana publicaremos una checklist técnica para automatizar la autorización de scripts en pipelines y ejemplos de políticas IaC para entornos CI/CD.

    Dominicode Labs

    Para equipos que automatizan validaciones de seguridad en pipelines y flujos de trabajo, es recomendable integrar pasos automatizados de autorización y escaneo. Para recursos y pruebas aplicadas a pipelines, vea Dominicode Labs como continuación lógica de las medidas técnicas descritas.

    FAQ

    ¿Cómo sé si ejecuté el script malicioso?

    Asume compromiso si corriste npm install sin lockfile después de 2026-03-31T00:21:58Z. Busca la presencia de plain-crypto-js en node_modules, entradas de axios@1.14.1 o axios@0.30.4 en tus lockfiles y conexiones a http://sfrclak.com:8000 en logs de red.

    ¿Qué versiones de Axios son seguras ahora?

    Fija a axios@1.14.0 o axios@0.30.3 según la rama que uses. No uses las versiones 1.14.1 ni 0.30.4.

    ¿Debo rotar todos los secretos aunque no detecte conexiones al C2?

    Sí. Si un postinstall se ejecutó en un entorno con acceso a secretos, existe riesgo de exposición incluso sin señales evidentes de conexiones; rote tokens CI, claves API y credenciales de acceso como medida cautelar.

    ¿Por qué no basta con eliminar la dependencia maliciosa?

    El payload puede haber ejecutado acciones, creado persistencia o exfiltrado secretos antes de ser removido; además, puede haber sobrescrito artefactos y ocultado rastros. La remediación debe incluir rotación de secretos y reconstrucción desde artefactos sanos.

    ¿Qué configuraciones de CI deben cambiarse inmediatamente?

    Ejecutar por defecto npm ci --ignore-scripts, no almacenar credenciales de producción en runners que ejecutan installs, exigir revisión y aprobación del lockfile en PR y limitar cuentas con permisos de publish mediante MFA y políticas de least privilege.

    ¿Dónde puedo ver la página oficial del paquete afectado?

    La página oficial del paquete Axios en npm está disponible en página del paquete Axios en npm.