ontoref/assets/presentation/talk-structure.md
Jesús Pérez d59644b96f
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
  --gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00

28 KiB
Raw Blame History

Talk Structure: Why I Needed Rust

Orientado a: abstract_en.md Fuente: 2026-02-17-notas_voz.md


Sistema de Medidores (elemento visual persistente)

Tres barras que aparecen en esquina de cada slide de transición. Escala 05. Se actualizan en cada etapa clave.

🛡 Confianza   ●●●●● = máxima certeza sobre el sistema
😴 Descanso    ●●●●● = puedes dormir tranquilo
🔥 Estrés      ●●●●● = alarma permanente, pesadillas

Estado inicial (apertura)

🛡 ●●●○○   😴 ●●●○○   🔥 ●○○○○

Se presenta como "¿Reconoces estos números? Sigamos..."

Progresión a lo largo de la charla:

Momento 🛡 Confianza 😴 Descanso 🔥 Estrés
Etapa 1 — Local ●●●●○ ●●●●○ ●○○○○
Etapa 2 — Redes ●●●○○ ●●●○○ ●●○○○
Etapa 3 — Cloud/CI-CD ●●○○○ ●○○○○ ●●●●○
YAML hell / peak pain ●○○○○ ○○○○○ ●●●●●
Rust — compilador ●●●○○ ●●○○○ ●●●○○
Rust — tipos + traits ●●●●○ ●●●●○ ●●○○○
Cierre ●●●●● ●●●●● ●○○○○

El título de la charla ES el último estado del medidor de sueño.


0. Hook de apertura

Pregunta de apertura al público (manos arriba):

"¿Quién ha sido despertado a las 3am por un fallo de infraestructura?"

Pausa. Mirar la sala. Asentir.

"Esto es para vosotros."


Imagen concreta: definir un host, un nodo, un puerto.

  • Eso es todo. Queremos que algo corra en algún sitio y que algo pueda hablar con él.
  • ¿Cómo de difícil puede ser?

38 años de infraestructura. 19872025.

  • Perl (90s) → Python (2000s) → Bash → Chef → Ansible → Terraform → Go → ???
  • Cada vez pensé que tenía la respuesta.
  • Cada vez la realidad me demostró que no.

Promesa: vamos a ver por qué eso, durante décadas, nos ha dado pesadillas. Y por qué Rust cambió eso.

→ Mostrar medidores en interrogante o en estado inicial neutro


1. Evolución de los desafíos en infraestructura (2013-2025)

Abstract: "The evolution of infrastructure challenges (2013-2025)"

Etapa 1 — Local (finales 80s / primeros 90s)

  • Terminales tontos, desarrollo local
  • Ciclos de despliegue largos, baja urgencia
  • Un solo estado, fácil de observar y controlar
  • IaC: scripts procedurales, lógica oculta en comandos o en la aplicación
  • La era Perl: podíamos hacer cualquier cosa. También podíamos romper cualquier cosa.
    • Metaprogramming bello y aterrador. Sin red de seguridad. Fallos silenciosos a las 3am.
    • Lección: poder sin seguridad es un desastre.

Medidores fin Etapa 1: 🛡 ●●●●○ 😴 ●●●●○ 🔥 ●○○○○ "Tienes un servidor. Sabes lo que tiene. Puedes dormir."

Etapa 2 — Conectividad en red / Internet

  • Los sistemas están cada vez más lejos — acceso remoto, redes distantes
  • Seguridad empieza a importar; procesos críticos, coste de caída sube
  • Más agentes participando (dev, ops, seguridad) — hay que armonizar
  • Armonizar: instalación de paquetes, configuración de recursos, actualizaciones en paralelo
  • IaC: procesos automatizables y reproducibles, primeros intentos declarativos, config-driven model
  • La era Python: desarrollo rápido, gran comunidad. Pero nada te impedía estar equivocado.
    • Type hints llegaron tarde, y opcionales. Errores en runtime > errores en compilación.
    • Lección: pragmatismo sin garantías es frágil.

Medidores fin Etapa 2: 🛡 ●●●○○ 😴 ●●●○○ 🔥 ●●○○○ "Más piezas. Más personas. Empieza a ponerse interesante."

Etapa 3 — Contenedores / Cloud / CI-CD

  • Monolítico → distribuido, 24×7×365, alta disponibilidad
  • Cloud, híbrido, multi-cloud, on-prem — todo a la vez
  • Rollback y rollforward: como transacciones de BD, pero en infraestructura
  • Escalado horizontal y vertical, también desescalado — en ambas direcciones
  • CI/CD continuo, ciclos cortos — nuevas funcionalidades, nuevos despliegues, permanente
  • IaC: Helm, Ansible, Terraform — más herramientas, más complejidad
  • Múltiples versiones de "lo que creemos que es válido" — la fuente de verdad se fragmenta
  • La era Cloud/IaC: Ansible, Terraform, Chef, Puppet. ¿Qué cambió? La sintaxis.
    • Seguimos peleando con type safety. Seguimos descubriendo errores en producción.
    • Lección: más herramientas no resuelven problemas de paradigma.
  • Resultado: estados de alarma como norma, no como excepción

Medidores fin Etapa 3: 🛡 ●●○○○ 😴 ●○○○○ 🔥 ●●●●○

"¿Hemos aumentado la productividad? Sí.
¿Hemos aumentado el estrés? Sí.
¿Hemos aumentado las posibilidades de tener problemas? También.
¿Tenemos más control y seguridad? No."


┌─────────────────────────────────────────────┐
│  SLIDE STANDALONE — The Breaking Point      │
│                                             │
│  Podía automatizar infraestructura.         │
│                                             │
│  No podía hacerla fiable.                   │
│                                             │
│  No podía prevenir los errores.             │
│                                             │
│  No podía dormir.                           │
└─────────────────────────────────────────────┘

Medidores: 🛡 ●○○○○ 😴 ○○○○○ 🔥 ●●●●● Tono: sin ironía. Personal. Pausa larga. Dejar que aterrice. Lo que no se puede medir: el miedo.


2. Por qué el IaC tradicional falla a escala

Abstract: "Why traditional approaches to IaC fall short at scale"

La analogía del restaurante (hilo conductor de toda la charla)

Un restaurante tiene tres actores: comensal (mesa), camarero (servicio), cocina.

Restaurante Infraestructura
Comensal declara lo que quiere Config declarativa (YAML, HCL, Helm)
Camarero valida y transmite Orchestrator (K8s, Ansible, Terraform)
Cocina ejecuta y entrega Runtime / provisioning
El plato llega — o no Deployment exitoso — o no

Lo que hace que funcione — o no:

  • El comensal declara, no implementa: no dice cómo cocinar, dice qué quiere
  • El camarero debe saber qué es posible y validar antes de ir a cocina
  • "Quiero X" → camarero va a cocina → "X no hay, ¿por qué está en la carta?" → vuelve a mesa
  • Equivalente: configuré un host con el puerto 8443 → ese puerto no está permitido → hay que reconfigurar desde cero

La verdad que muta — y el problema de estado

  • La "verdad" no es estática. Muta en cada paso de la cadena:
    • Comensal: su petición oral
    • Camarero: la nota que toma
    • Cocina: las marcas sobre lo que ya está hecho o no
    • Caja: el ticket de pago
  • Cada actor ve una parte de la verdad, relevante para él en ese momento
  • Como en un sistema neuronal: hay eventos que no activan ciertas neuronas porque no son relevantes para ellas
  • El camarero conoce al cliente habitual ("siempre sin sal") — la cocina, no. ¿Está ese contexto explícito en el pedido, o asumido?
  • Si el camarero cambia, o si interviene otra estación de cocina → el estado implícito se pierde

El coste del fallo depende de dónde ocurre

  • Fallo en mesa al pedir (pedido imposible): barato — se corrige antes de llegar a cocina
  • Fallo en cocina al elaborar (ingrediente no disponible): medio — hay que volver a mesa y renegociar
  • Fallo al entregar (plato se cae): caro — hay que rehacer desde cero
  • Fallo cuando llega el plato y no es lo que se pidió: muy caro — experiencia destruida + tiempo perdido
  • Fail early = fail cheap. Fail in production = nightmare.

La renegociación: "no tengo champiñón"

  • Un actor en la cadena descubre que no puede cumplir parte del pedido
  • Debe volver atrás y validar con el comensal: "¿te pongo verduras?"
  • Esto requiere que el cambio sea explícito, trazado, y re-autorizado — no silencioso
  • Equivalente en infra: configuration drift, estado divergente sin notificación

El ciclo de la config: cómo llegamos hasta aquí

  1. Hardcoded — dependencias, rutas, puertos dentro del binario. Control total, cero flexibilidad
  2. Config externa (JSON) — funciona bien entre máquinas, ilegible para humanos a escala
  3. YAML / TOML — más legible, pero sintaxis frágil: indentación, tipos implícitos, errores silenciosos
  4. YAML + Serde — cargamos la config con Serde, que valida la estructura:
    • ¿Existe el campo? ¿Es del tipo correcto?
    • ¿Aceptamos "elefante" como animal de compañía? Depende del tipo. Pero si el tipo es String... sí.
    • Serde valida forma. No valida significado.
  5. Helm / Jinja templates — escribimos YAML a partir de variables (en YAML o JSON)
    • El template genera el YAML final que consume la aplicación
    • ¿Valida el contenido del YAML generado? No. En absoluto.
    • Como usar un LLM con un markdown de referencia: el formato está, pero ¿el contenido es correcto? Eso no lo garantiza nadie.
  6. Resultado: CI/CD continuo + config sin validación semántica = esperanza continua

"Lo que hacemos es escribir lo que queremos, como una carta a los Reyes Magos. Y cruzamos los dedos."


┌─────────────────────────────────────────────┐
│  SLIDE STANDALONE — Esperanza continua      │
│                                             │
│  CI/CD continuo.                            │
│  Sin validación semántica.                  │
│                                             │
│  Esperanza continua.                        │
│                                             │
│  (cruzamos los dedos en producción)         │
└─────────────────────────────────────────────┘

Medidores: 🛡 ●○○○○ 😴 ○○○○○ 🔥 ●●●●● Tono: irónico, de reconocimiento. La audiencia asiente.


Las tres preguntas sin respuesta

Pregunta 1 — ¿Por qué esperamos a que se rompa?

  • "In my machine it works" — en producción, no lo sé
  • Fail late = coste máximo
  • Queremos: fail fast, fail cheap — cuanto antes, menor el coste

Pregunta 2 — ¿Tenemos claro lo que queremos?

  • ¿La declaración es suficiente y consistente con lo que es posible?
  • ¿Respeta los límites del sistema? ¿Cuáles son esos límites — estáticos o dinámicos?
  • ¿Cuál es la fuente de verdad? ¿Y cuándo y cómo muta?

Pregunta 3 — ¿Podemos garantizar determinismo?

  • ¿Tenemos herramientas que usen nuestras definiciones para operar automáticamente en el ciclo de vida?
  • ¿Podemos tener certeza de que obtendremos lo que formulamos — no de forma aleatoria?
  • No "en mi máquina funciona". Siempre. En cualquier máquina. En cualquier momento.

En realidad no estamos inventando nada. Todo ya existe. El problema es si lo estamos gestionando adecuadamente.


┌─────────────────────────────────────────────┐
│  SLIDE STANDALONE — El paradigma            │
│                                             │
│  Las herramientas no eran el problema.      │
│                                             │
│  Los lenguajes no eran el problema.         │
│                                             │
│  El paradigma era el problema.              │
└─────────────────────────────────────────────┘

Tono: claridad repentina. El momento en que todo encaja. Necesitaba algo que forzara claridad — no que habilitara el caos. Que previniera errores — antes de producción. Que hiciera las asunciones explícitas — no ocultas.


┌─────────────────────────────────────────────┐
│  SLIDE STANDALONE — Pesadilla continua      │
│                                             │
│  Sistemas que no sabemos cómo controlar.    │
│  Esperamos que funcionen.                   │
│  Cuando no funcionan, los arreglamos.       │
│                                             │
│  Pesadilla continua.                        │
│                                             │
│  (el estado de alarma es lo normal)         │
└─────────────────────────────────────────────┘

Medidores: 🛡 ●○○○○ 😴 ○○○○○ 🔥 ●●●●● Tono: oscuro, sin ironía. El suelo emocional de la charla. Pausa aquí.


3. Type safety y memory safety como fiabilidad en producción

Abstract: "Type safety and memory safety as production reliability"

El puente: de YAML+Serde a tipos Rust

Serde carga config estructuralmente válida. Pero "elefante" como valor de animal_companía: String compila. La respuesta de Rust: no uses String. Usa un tipo.

enum Animal { Perro, Gato, Conejo }  // "elefante" no compila

Eso es lo que cambia. No el formato de la config. El modelo de qué puede contener.


Lo que Rust introduce — respuesta a las tres preguntas

Tipado estático estricto (responde: "¿tenemos claro lo que queremos?")

  • Un número no es un string. Un puerto no es cualquier entero.
  • Los tipos son la declaración de intenciones — sin ambigüedad, sin equívocos
  • Las conversiones (cast) son explícitas, no implícitas
  • Tipos primarios ricos + structs, enums, tuplas, newtypes

Inmutabilidad por defecto (responde: "¿qué puede cambiar?")

  • "Quiero tomate. Puedes inventarte lo que quieras, pero sin tomate no es el plato que pedí."
  • let es inmutable. let mut es explícito y deliberado.
  • Los invariantes son invariantes — no silenciosamente mutados en runtime

Option<T>, no nulos (responde: "¿qué es opcional y qué es obligatorio?")

  • No null, no "asume que está si no se especifica"
  • Option<T>: o está (Some) o no está (None) — y ambos casos se manejan explícitamente
  • Restaurante: "champiñón opcional. Si no está, lo sé. Lo decido. Lo gestiono."
  • El camarero no puede ignorar que no hay champiñón — el compilador no le deja

Enums como dominio cerrado (responde: "¿cuáles son los valores válidos?")

  • Un cloud provider es enum Provider { AWS, GCP, Azure, OnPrem } — no un String libre
  • Un puerto es un u16 con rango validado — no cualquier entero
  • Las restricciones están en el tipo, no en comentarios, no en documentación, no en la memoria del equipo

Traits como contratos entre actores (responde: "¿pueden los actores de la cadena cambiar?")

  • Composición en vez de herencia rígida
  • Cada "actor" de la cadena (AWS provider, K8s, on-prem) implementa el mismo trait
  • La cadena funciona con cualquier implementación que cumpla el contrato
  • Como el restaurante: el camarero puede cambiar — si conoce el protocolo, el proceso es el mismo

El compilador como el camarero que valida (responde: "¿cuándo detectamos el fallo?")

  • Valida antes de construir el binario — no en runtime, no en producción
  • No cuando lleva horas ejecutándose. No cuando se llama a una función que nadie tocaba hace meses.
  • Fail early. Fail cheap. En compilación, no en el 2am del domingo.
  • Binarios predecibles: comportamiento de memoria, recursos y flujos deterministas

"El compilador es el camarero que valida el pedido antes de que llegue a cocina. Antes de que el cliente espere. Antes de que el ingrediente no esté."


El impacto humano — cuando el sistema es fiable

Esto no es solo técnico. Cuando la infraestructura es predecible:

  • El sueño vuelve
  • La confianza vuelve
  • El equipo confía en la automatización
  • El estrés baja
  • Puedes descansar de verdad

"Lo que no se puede medir: el miedo. Lo que sí se mide: el MTTR. Antes > 30min. Ahora < 5min."

Medidores — compilador activo: 🛡 ●●●○○ 😴 ●●○○○ 🔥 ●●●○○ Medidores — tipos + traits + options: 🛡 ●●●●○ 😴 ●●●●○ 🔥 ●●○○○ Medidores — Rust completo en producción: 🛡 ●●●●● 😴 ●●●●● 🔥 ●○○○○


┌─────────────────────────────────────────────┐
│  SLIDE STANDALONE — Certeza continua        │
│                                             │
│  El compilador valida antes del binario.    │
│  Los tipos definen lo que es posible.       │
│  El contrato se cumple — o no compila.      │
│                                             │
│  Certeza continua.                          │
│                                             │
│  (para continuar durmiendo bien)            │
└─────────────────────────────────────────────┘

Medidores: 🛡 ●●●●● 😴 ●●●●● 🔥 ●○○○○ Tono: resolución. El arco cierra. El título de la charla, demostrado.


4. Orquestación segura multi-cloud y on-prem

Abstract: "Building safe orchestration across multi-cloud and on-prem environments"

De la teoría al sistema real

Todo lo anterior no es hipotético. Es la arquitectura de Provisioning — un sistema de orquestación de infraestructura en producción, escrito en Rust, que gestiona despliegues en AWS, UpCloud y on-prem desde una sola base de código.

La pregunta es: ¿cómo se traduce "tipos y traits" a un sistema que maneja multi-cloud real?


Nickel como source of truth tipado (ADR-003)

YAML fue rechazado explícitamente. TOML fue rechazado. La razón: sin type safety.

Nickel — un lenguaje de configuración funcional con sistema de tipos — reemplaza YAML:

{
  infrastructure = {
    compute | {
      region      | String,
      count       | Number & (> 0),
      auto_scaling | {
        min | Number & (> 0),
        max | Number & (>= min),  -- el compilador verifica esto
      }
    }
  }
}
  • Validación en tiempo de compilación de la config — no en runtime, no en producción
  • Merging jerárquico tipado: defaults → workspace → profile → environment → runtime
  • Resultado (ADR-003): zero configuration type errors en producción
  • Alternativas rechazadas explícitamente: TOML (no type safety), KCL, YAML+validación híbrida

"Serde valida forma. Nickel valida significado. El compilador valida antes del despliegue."


Traits como contratos de provider (el restaurante, resuelto)

El problema del restaurante: la cocina puede cambiar. AWS no es UpCloud no es bare metal. La solución Rust: todos implementan el mismo trait.

// El trait es el menú. Los providers son las cocinas.
#[async_trait]
pub trait TaskStorage: Send + Sync {
    async fn create_task(&self, task: WorkflowTask) -> StorageResult<WorkflowTask>;
    async fn update_task(&self, id: &str, status: TaskStatus) -> StorageResult<()>;
    async fn list_tasks(&self, filter: TaskFilter) -> StorageResult<Vec<WorkflowTask>>;
    async fn audit_operation(&self, op: AuditEntry) -> StorageResult<()>;
}

// Implementaciones: FilesystemStorage, SurrealDbStorage, MemoryStorage
// El orchestrator no sabe cuál usa. El compilador garantiza que todas cumplen.
// Dominios cerrados — no strings libres
enum RollbackStrategy { ConfigDriven, Conservative, Aggressive, Custom { operations: Vec<String> } }
enum DependencyType  { Hard, Soft, Optional }
enum TaskStatus      { Pending, Running, Completed, Failed, Cancelled }
enum ProviderType    { UpCloud, AWS, Local }

Cuando se añade un nuevo provider: implementa el trait o no compila. No hay forma de olvidarse de un caso.


Orquestación con grafo de dependencias

El orchestrator construye un DAG (grafo acíclico dirigido) de tareas con detección de ciclos en tiempo de compilación del workflow.

pub struct WorkflowConfig {
    pub max_parallel_tasks:        usize,
    pub task_timeout_seconds:      u64,
    pub fail_fast:                 bool,    // falla rápido, falla barato
    pub checkpoint_interval_seconds: u64,
}

Instalación de Kubernetes como ejemplo — el orchestrator resuelve:

containerd (Hard) → etcd (Hard) → kubernetes → cilium (requires kubernetes) → rook-ceph

No se puede instalar kubernetes si containerd falla. El tipo DependencyType::Hard lo garantiza. El compilador detecta dependencias circulares. No el operador de guardia a las 3am.


El estado explícito elimina el drift

El problema de configuration drift: el sistema real diverge silenciosamente del estado deseado.

Rust obliga a que toda mutación sea explícita (let mut). El sistema de estado del orchestrator hace lo mismo a nivel de infraestructura:

pub struct WorkflowExecutionState {
    pub status:         WorkflowStatus,
    pub task_states:    HashMap<String, TaskExecutionState>,
    pub checkpoints:    Vec<WorkflowCheckpoint>,  // qué se hizo y cuándo
    pub statistics:     WorkflowStatistics,
}
  • Checkpoints cada 5 minutos (configurable)
  • Hasta 50 checkpoints retenidos
  • Cada estado de provider capturado en HashMap<String, ProviderState>
  • Sin estado implícito. Sin "el camarero recuerda que el cliente no quiere sal". Está en el pedido.

Medidores — sección 4: 🛡 ●●●●● 😴 ●●●●● 🔥 ●○○○○


5. Aplicaciones reales

Abstract: "Real applications: Kubernetes, blockchain validators, disaster recovery"

Kubernetes — despliegue con tipos

El orchestrator se despliega en Kubernetes. 3 réplicas, rolling update, anti-affinity entre nodos. Pero lo relevante no es que corre en Kubernetes — es cómo se gestiona Kubernetes como target.

El orchestrator provisiona los componentes del cluster como workflow tipado:

containerd → etcd → kubernetes control plane
                  → kubelet (workers)
                  → CoreDNS
                  → Cilium (CNI, requires kubernetes)
                  → Rook-Ceph (storage, requires kubernetes + Cilium)

Cada componente es un tipo. Cada dependencia es un DependencyType. El compiler detecta si intentas instalar Cilium sin Kubernetes. No el CI a las 2am.

Los health probes del orchestrator en K8s — /health cada 10 segundos — no son decoración. Son parte del contrato: el sistema sabe cuándo está sano. Lo sabe antes de que falle el cliente.


Blockchain validators — disponibilidad como tipo

Los validators de blockchain (Polkadot, Ethereum) tienen un requisito brutal: uptime o slashing. Un validator que falla pierde fondos. No hay margen para "en mi máquina funciona".

Lo que Rust + este sistema aporta:

Secretos con post-quantum cryptography (ADR-006)

  • CRYSTALS-Kyber (KEM) + Falcon (signatures) + AES-256-GCM (hybrid)
  • Las claves del validator no pueden ser comprometidas por computación cuántica futura
  • La rotación de claves es automática, trazada, con audit log

SLOs con error budgets reales (ADR-009)

Tier 1 — Critical: 99.99% uptime = 52.6 minutos de downtime/año

Esto no es un número de marketing. Es un Prometheus rule que dispara alertas y bloquea deploys cuando el burn rate supera el presupuesto.

Configuración determinista

  • Los parámetros del validator son tipos, no strings: no puede entrar un valor de bond_amount que no sea un u128 validado
  • La config del validator es reproducible bit-a-bit en cualquier nodo — mismo Nickel schema, mismo resultado

Disaster recovery — rollback como tipo, no como procedimiento

El problema clásico de DR: el runbook existe, pero no se ejecutó correctamente, o el estado en DR no coincide con el de producción.

Checkpoints como snapshots de estado completo

pub struct Checkpoint {
    pub workflow_state:  Option<WorkflowExecutionState>,
    pub resources:       Vec<ResourceSnapshot>,
    pub provider_states: HashMap<String, ProviderState>,
}

No es "vuelve al commit anterior". Es el estado completo del sistema: qué estaba corriendo, en qué provider, con qué configuración, en qué momento.

Rollback como estrategia tipada

enum RollbackStrategy {
    ConfigDriven,                           // lo que diga la config
    Conservative,                           // preserva todo salvo lo marcado
    Aggressive,                             // revierte todo
    Custom { operations: Vec<String> },     // playbook explícito
}

No hay forma de hacer rollback sin elegir una estrategia. El compilador no te deja ignorar el caso.

Self-healing automatizado (ADR-010)

┌─────────────────────────────────────────────┐
│  SLIDE STANDALONE — MTTR                    │
│                                             │
│  Sin tipos. Sin compilador. Sin estado.     │
│                                             │
│  MTTR > 30 minutos.                         │ 
│                                             │
│ (a las ??, apagar el fuego) Alarma pesadilla│
│  ────────────────────────────────           │
│                                             │
│  Rust. Tipos. Estado explícito.             │
│  Automated response.                        │
│                                             │
│  MTTR < 5 minutos.                          │
│                                             │
│ (a las 3am, sin ti)  Descanso en paz mental │
└─────────────────────────────────────────────┘

Medidores: 🛡 ●●●●● 😴 ●●●●● 🔥 ●○○○○ Tono: cifras reales, no promesas. Pausa después de "sin ti".

El RemediationEngine ejecuta playbooks tipados: ScaleService, FailoverService, RestartService, ClearCache. Si el remedio falla 3 veces, escala a humano. No itera indefinidamente.

Multi-backend backup tipado

  • restic, borg, tar, rsync — todos como variantes de un enum
  • El backup de producción y el restore en DR usan el mismo tipo, el mismo schema
  • "Funciona en prod pero no en DR" no puede ocurrir si el estado es el mismo tipo

"No estamos cruzando los dedos. Tenemos el estado. Tenemos el tipo. Tenemos el rollback. Dormimos."

Medidores — sección 5: 🛡 ●●●●● 😴 ●●●●● 🔥 ●○○○○


Cierre

Para los veterans de infraestructura

Si has vivido lo que yo he vivido:

  • Rust resuelve los problemas que ya conoces — no problemas hipotéticos
  • No es hype. Llevo décadas viendo tecnologías venir y irse.
  • Dale una oportunidad real. Tu sueño te lo agradecerá.

Para los engineers más jóvenes

Aprende de alguien que lo intentó todo:

  • No malgastes décadas en infraestructura frágil
  • Empieza con type safety desde el principio
  • Constrúyelo fiable desde el día uno

La perspectiva

"A mi edad, tengo perspectiva. He visto tecnologías venir y irse. Rust no es hype. Resuelve problemas reales que he tenido durante décadas. Tener más años no es una limitación. Es una ventaja."


  • No hemos inventado nada nuevo. Los problemas siempre han existido.
  • Rust los reúne y los resuelve: tipos, traits, compiler, memory safety.
  • El resultado: infraestructura predecible. Deployments sin pesadillas.
  • Duermes bien.

Medidores — cierre: 🛡 ●●●●● 😴 ●●●●● 🔥 ●○○○○

Slide final: los tres medidores en verde. Título de la charla. Fin.