Módulo 6: Rollback And Safety Nets

5. ¿Un pipeline hubiera detenido el incidente de Claude Code?

Descripción

El Módulo 1 (lección 2) nombró el incidente de terraform destroy que un agente de IA corrió contra la infraestructura de producción de DataTalks.Club, y dejó una respuesta preliminar: un pipeline no evita la negligencia, pero deja un registro auditable que el incidente real no tuvo. Esta lección vuelve a la misma pregunta, ahora con todas las piezas del pipeline completo en la mano —revisión obligatoria (Módulo 3), aplicación automática (Módulo 5), rollback (lecciones 2-3), branch protection (lección 4)— y con una pieza más, todavía sin construir del todo: el guardrail de las lecciones 6-7. La respuesta, con esta profundidad, tiene un matiz que el Módulo 1 no podía dar todavía.

Conexión con el módulo

Esta lección conecta directamente las lecciones 2, 3 y 4 de este módulo con el incidente ya nombrado en el Módulo 1. No introduce ningún mecanismo técnico nuevo — es, deliberadamente, una lección de análisis, que usa todo lo que ya construiste para responder una pregunta concreta con la mayor honestidad posible. La lección 6 nombra la pieza que todavía falta para cerrar el análisis por completo: un guardrail automatizado, que la lección 7 construye de verdad.


El incidente, otra vez, con los hechos exactos

En marzo de 2026, Claude Code —un agente de IA operando con acceso a una cuenta de AWS real— corrió terraform destroy contra la infraestructura de producción de DataTalks.Club (Alexey Grigorev), después de que el propio agente reemplazara, sin querer, el state activo por una copia vieja archivada en un .zip. El destroy borró la VPC, el clúster ECS, los balanceadores de carga, el bastion host, la base de datos RDS y sus snapshots automáticos: cerca de 1.943.200 filas y 2,5 años de historial de un curso completo, con aproximadamente 24 horas de recuperación, posible únicamente vía soporte directo de AWS (Alexey Grigorev — How I Dropped Our Production Database · Hacker News #47278720 · incidentdatabase.ai — Incident 1424).

El detalle que hace de este incidente algo más que una anécdota de terror, y que ya nombró el Módulo 1: el agente había señalado el riesgo antes de ejecutar el destroy, y el humano que supervisaba la sesión aprobó de todas formas. No fue un destroy corrido a ciegas — hubo una advertencia visible, y hubo una aprobación explícita que la pasó por alto.


Corriendo el incidente, paso a paso, a través de cada capa que construiste

Esta vez, en vez de responder en abstracto, sigue el incidente a través de cada control específico de este módulo, uno por uno, y pregúntate honestamente si lo habría detenido.

   ①  El agente reemplaza el state activo por uno viejo (error de origen)
            │
            ▼
   ②  El agente propone terraform destroy, señalando el riesgo
            │
            ▼
   ③  El humano supervisor aprueba de todas formas
            │
            ▼
   ④  destroy corre contra producción real: VPC, ECS, RDS, snapshots
            │
            ▼
   ⑤  ~24h de recuperación vía soporte de AWS

Paso ①, el reemplazo del state. Ninguna pieza de este módulo lo hubiera evitado directamente — no es un problema de revisión de cambios, es un problema de manejo del propio state (el tipo de riesgo que terraform-and-iac-guide, Módulo 4, ya cubrió con locking y backends remotos, fuera del alcance de esta guía). Vale la pena nombrarlo con honestidad: este módulo no resuelve todos los riesgos de un pipeline de infraestructura, solo los que están dentro de su alcance declarado.

Paso ②, la propuesta con el riesgo señalado. Aquí es donde el patrón HashiCorp/GitHub del Módulo 3 sí cambia algo, aunque no de la forma que uno esperaría al principio: si ese destroy hubiera tenido que pasar por un ci.yml real, con el plan publicado como evidencia (Módulo 3, lección 7) y branch protection exigiendo que un PR pase por revisión antes de fusionarse (lección 4 de este módulo), el riesgo señalado por el agente habría quedado escrito, en un lugar público y persistente —no solo visible en una sesión de terminal que nadie más ve—. Eso no impide la aprobación equivocada, pero cambia radicalmente quién puede verla, y cuándo.

Paso ③, la aprobación equivocada. Este es el paso donde hay que ser más honesto, sin adornar la respuesta: nada de lo que construiste en este módulo impide que un humano apruebe algo peligroso después de haber visto la advertencia. Un Environment de producción con aprobación requerida (Módulo 4 de esta guía) no habría cambiado el resultado si la misma persona, viendo el mismo plan con la misma advertencia, hubiera aprobado igual. Branch protection tampoco — exige que algo apruebe, no que la aprobación sea correcta. Este es, con precisión, el límite real de todo lo enseñado hasta ahora: automatiza el proceso alrededor de una decisión humana, no la calidad de esa decisión.

Paso ④, la ejecución del destroy. Aquí es donde aparece el matiz que el Módulo 1 todavía no podía dar, porque el guardrail de las lecciones 6-7 de este módulo todavía no existía en ese punto de la guía. Un guardrail automatizado que revisa el plan en JSON y bloquea cualquier acción de destrucción sobre un recurso protegido —el mecanismo exacto que construyes en la lección 7— no depende del juicio humano en absoluto. No importa si el humano que aprueba está cansado, apurado, o simplemente confía demasiado en el agente que se lo pide: si el plan contiene una acción delete sobre un recurso marcado como protegido, el job falla, automáticamente, antes de que apply.yml tenga la oportunidad de ejecutar nada. Esta es la primera capa de todo este módulo que actúa sin necesitar que nadie tome la decisión correcta en el momento — la lección 7 la construye de verdad, no solo la nombra.

Paso ⑤, la recuperación de 24 horas. Fuera del alcance de cualquier pieza de este módulo — recuperación de desastres, backups, snapshots automáticos, es el terreno de sre-and-incident-response-guide, no de esta guía.


La respuesta completa, sin adornos

Juntando los cinco pasos:

Un pipeline completo —revisión, aplicación automática, rollback, branch protection— no hubiera evitado que el humano aprobara el destroy después de ver la advertencia. Esa es la parte incómoda, y repetirla con la misma honestidad del Módulo 1 importa: automatizar el proceso alrededor de una decisión no cambia la decisión misma.

Pero un guardrail automatizado, del tipo que construyes en la lección 7, sí hubiera cambiado el resultado —no porque hiciera al humano más cuidadoso, sino porque no necesita que el humano sea cuidadoso en absoluto. Si la tabla Shipments de Andes Cargo (o, en el incidente real, la base RDS de DataTalks.Club) estuviera marcada como un recurso protegido por un guardrail que bloquea cualquier delete sobre ella, el job de CI fallaría automáticamente al calcular el plan —mucho antes de que cualquier humano tuviera la oportunidad de aprobar o rechazar nada—. Esta es la diferencia real entre "dejar un registro de la mala decisión" (lo que ya viste en el Módulo 1) y "hacer la mala decisión técnicamente imposible de ejecutar para un recurso específico marcado como crítico" (lo que las lecciones 6-7 de este módulo agregan).

Con esto, la tesis completa de este módulo, en una frase: branch protection y la revisión humana hacen auditable la mala decisión; un guardrail automatizado, sobre un recurso específico, hace algunas malas decisiones imposibles de ejecutar, sin depender de que nadie las note a tiempo. Ninguna de las dos capas es "la solución completa" por sí sola — juntas, son lo más cerca que este módulo llega de una respuesta honesta a la pregunta de su título.


Errores comunes

Concluir que el guardrail de la lección 7 "resuelve" el incidente por completo (de expectativa, el error más importante de esta lección). Qué pasa: alguien, después de leer sobre el guardrail, piensa que este módulo demuestra que el incidente de Claude Code "ya no podría pasar" en un pipeline moderno. Cómo detectarlo: si tu resumen de esta lección es "con un guardrail, esto nunca pasaría" en vez de "con un guardrail sobre ESTE recurso específico, ESTA acción específica se hubiera bloqueado". Cómo corregirlo: el guardrail de la lección 7 protege un recurso concreto, marcado explícitamente de antemano (Shipments, en el caso de Andes Cargo). Un incidente real puede tocar cualquier recurso — el guardrail solo protege los que alguien pensó, con anticipación, en proteger. Un sistema de políticas completo (conftest, nombrado en la lección 6) escala esa protección a reglas más generales, pero tampoco es infalible: sigue dependiendo de que alguien escriba la regla correcta antes de que el incidente ocurra.

Pensar que esta lección contradice al Módulo 1 (conceptual). Qué pasa: alguien nota que el Módulo 1 dijo "un pipeline no evita la negligencia" y esta lección parece decir algo distinto sobre el guardrail. Cómo corregirlo: no hay contradicción — el Módulo 1 analizaba el pipeline sin un guardrail de contenido (todo lo que existía en ese punto de la guía era revisión y aprobación, ambas humanas). Esta lección agrega una pieza que el Módulo 1 todavía no había construido: un control que no depende del juicio humano en absoluto. Las dos lecciones son consistentes; esta simplemente tiene una pieza más para trabajar.

Asumir que el guardrail hubiera evitado el error de origen (paso ① del incidente) (de alcance). Qué pasa: alguien piensa que el guardrail de la lección 7 también hubiera evitado que el state se reemplazara por una copia vieja. Cómo corregirlo: el guardrail actúa sobre el contenido del plan, calculado después de que el state ya está en la posición que sea — no puede detectar ni evitar que el state mismo se haya corrompido antes de esa comparación. Ese riesgo específico vive en el manejo del state (locking, backends remotos), un tema de terraform-and-iac-guide, no de este módulo.


Ejercicios

Ejercicio 1 — Traza el incidente a través de las cinco capas, sin mirar esta lección. Para cada uno de los cinco pasos del incidente (reemplazo del state, propuesta con riesgo señalado, aprobación, ejecución, recuperación), decide si alguna pieza de este módulo lo habría cambiado, y cuál.

Ver solución

Ninguna pieza de este módulo — es un problema de manejo del state, fuera de este alcance. El patrón plan en PR + branch protection hace que la advertencia del agente quede escrita en un lugar público y persistente, en vez de perderse en una sesión de terminal. Ninguna pieza de este módulo cambia la decisión humana en sí — ni branch protection ni un Environment de aprobación garantizan que la aprobación sea correcta. El guardrail de la lección 7, si el recurso destruido estuviera marcado como protegido, hubiera bloqueado el apply automáticamente, sin depender de ningún humano. Ninguna pieza de este módulo — recuperación de desastres es terreno de sre-and-incident-response-guide.

Ejercicio 2 — Responde al colega escéptico del Módulo 1, ahora con la pieza nueva. El mismo colega del Ejercicio 2 del Módulo 1 (lección 2) insiste: "si un humano puede aprobar algo peligroso de todas formas, ningún pipeline sirve de nada". Respóndele, incorporando lo que aprendiste en esta lección.

Ver solución

Una respuesta completa suena, más o menos, así: "Tienes razón en que ningún pipeline cambia la decisión de un humano que aprueba algo peligroso habiendo visto la advertencia — eso ya lo reconocimos desde el Módulo 1. Pero eso no significa que un pipeline 'no sirva de nada': un guardrail automatizado, sobre un recurso específico marcado como crítico, no le pide a nadie que tome la decisión correcta — simplemente hace esa acción técnicamente imposible de ejecutar, sin importar quién la apruebe. No es una solución universal (solo protege lo que alguien pensó en proteger de antemano), pero para los recursos que sí están protegidos, elimina por completo la dependencia del buen juicio humano en ese momento específico."

Ejercicio 3 — Diseña la protección que Andes Cargo necesitaría, más allá de Shipments. Basándote en los cuatro recursos canónicos de Andes Cargo (el bucket, la tabla, los dos roles IAM), ¿cuáles otros crees que merecerían un guardrail similar al de la lección 7, y por qué la tabla Shipments es la elección correcta para esta guía?

Ver solución

Una respuesta razonable: el bucket andes-cargo-shipment-docs también podría merecer un guardrail (contiene documentos de envío, similar en criticidad a los registros de la tabla), y los roles IAM podrían merecer uno distinto —no contra destrucción, sino contra cambios que amplíen permisos de forma peligrosa—. La tabla Shipments es la elección de esta guía porque es el ejemplo más claro y menos ambiguo de "dato que, una vez destruido, no se puede reconstruir desde el HCL" —a diferencia de un rol IAM, cuya definición completa vive en el propio código y podría recrearse sin pérdida de información—, el mismo tipo de razonamiento que hizo que la base de datos RDS fuera la pérdida más grave del incidente real, no la VPC o los balanceadores (que sí se recrean idénticos desde el HCL).


Resumen y siguiente paso

En esta lección volviste al incidente de Claude Code con las cuatro piezas de este módulo en la mano —rollback, branch protection, y el guardrail todavía por construir— y trazaste, paso a paso, cuál de ellas habría cambiado qué parte del incidente real. La respuesta completa tiene dos partes honestas: ningún control de proceso cambia una mala decisión humana tomada con la información correcta ya visible; pero un guardrail automatizado, sobre un recurso específico marcado como crítico, elimina la dependencia de esa decisión por completo, para ese recurso.

Antes de avanzar deberías poder: trazar el incidente completo a través de las cinco capas de esta lección; explicar con precisión la diferencia entre "dejar un registro auditable" y "hacer una acción técnicamente imposible"; y anticipar, sin haberlo visto todavía, qué tipo de mecanismo construyen las lecciones 6 y 7.

La lección 6 nombra el sistema completo de guardrails automatizados —conftest, policy-as-code— como el siguiente paso más allá de lo que esta guía construye. La lección 7 construye, de verdad, la versión mínima y honesta de ese mecanismo: el guardrail concreto que esta lección ya anticipó.

Recursos

  1. Hacker News — discusión del incidente #47278720 — el hilo original del incidente de destroy, ya citado en el Módulo 1.
  2. incidentdatabase.ai — Incident 1424 — el registro estructurado del incidente en la base de datos pública de incidentes de IA.
  3. Módulo 1 de esta guía (02-the-trouble-with-manual-apply.md) — el primer análisis del incidente, la base directa de esta lección.
  4. terraform-and-iac-guide, Módulo 8, lección 5 — la fuente técnica completa del incidente, incluido cómo se reemplazó el state.