Saltar a contenido

Flujos de Datos y Procesos

Documentación de los flujos clave de datos y procesos en SmallCountry: autenticación, telemetría de sensores, backups y despliegue. Cada flujo está representado con un diagrama de secuencia Mermaid.


1. Flujo de autenticación

Cómo una persona accede a un servicio protegido. El camino completo desde el navegador hasta la aplicación.

sequenceDiagram
    actor Persona as 👤 Persona
    participant Caddy as 🔒 Caddy (proxy TLS)
    participant Authentik as 🛡️ Authentik (IdP)
    participant Servicio as 📦 Servicio

    Persona->>Caddy: GET https://servicio.sc
    Caddy->>Authentik: forward_auth /outpost.goauthentik.io/auth

    alt Sin sesión
        Authentik->>Caddy: 302 Redirect → /login
        Caddy->>Persona: Redirige a login.authentik.sc
        Persona->>Authentik: POST credenciales + TOTP
        Authentik->>Authentik: Valida credenciales
        Authentik->>Authentik: Valida TOTP/WebAuthn
        Authentik->>Caddy: Set-Cookie + 302 → servicio.sc
    end

    Caddy->>Authentik: Valida cookie de sesión
    Authentik->>Caddy: 200 OK + cabeceras X-Authentik-*

    alt Usuario autorizado (grupo correcto)
        Caddy->>Servicio: Proxy + cabeceras de auth
        Servicio->>Servicio: Autorización por grupo
        Servicio->>Caddy: 200 OK (contenido)
        Caddy->>Persona: Contenido del servicio
    else Usuario no autorizado
        Caddy->>Persona: 403 Forbidden
    end

Dónde ocurre: Ra, LXC caddy.sc y authentik.sc
Tiempo típico: <200ms con sesión activa, <2s con login nuevo
ADR: ADR-014 (Authentik), ADR-015 (Caddy)


2. Flujo de datos de sensor

El recorrido de un dato desde un ESP32 en el campo hasta el dashboard de Grafana que ve Melissa.

sequenceDiagram
    participant ESP32 as 📡 ESP32 (campo)
    participant Mosquitto as 📨 Mosquitto (MQTT broker)
    participant NodeRED as 🔄 Node-RED
    participant InfluxDB as 💾 InfluxDB
    participant Victoria as 📊 VictoriaMetrics
    participant Grafana as 📈 Grafana
    participant ntfy as 🔔 ntfy
    actor Melissa as 👩‍🌾 Melissa

    ESP32->>ESP32: Lectura del sensor BME280<br/>temp=34.2°C, hum=58%, peso=45.3kg
    ESP32->>Mosquitto: PUBLISH colmenas/03/sensores<br/>QoS 1, retain: true
    Mosquitto->>NodeRED: Mensaje entregado (suscriptor)

    NodeRED->>NodeRED: Transformación:<br/>extraer temp, hum, peso<br/>añadir timestamp y ubicación

    par Almacenamiento en paralelo
        NodeRED->>InfluxDB: WRITE serie temporal<br/>colmena_03, temp=34.2
        NodeRED->>Victoria: WRITE vía Prometheus remote write<br/>sc_colmena_temp{id="03"} 34.2
    end

    NodeRED->>NodeRED: Evalúa reglas de alerta:<br/>¿peso bajó >20% en 24h?

    alt Alerta detectada
        NodeRED->>ntfy: POST tópico sc-campo<br/>"⚠️ Colmena 03: pérdida de peso"
        ntfy->>Melissa: Push notification al móvil
    end

    Grafana->>Victoria: QUERY PromQL<br/>sc_colmena_temp{id="03"}[24h]
    Victoria->>Grafana: Serie temporal (8640 puntos)
    Grafana->>Melissa: Dashboard de colmenas actualizado

Dónde ocurre: ESP32 en campo → Ra (Mosquitto LXC + Node-RED LXC)
Latencia: <500ms desde lectura hasta dashboard
ADR: ADR-001 (MQTT), ADR-008 (ESP32)


3. Flujo de backup

Cómo se protegen los datos: del snapshot ZFS automático al backup offsite verificado.

sequenceDiagram
    participant ZFS as 💾 ZFS (rpool)
    participant PBS as 📦 PBS (Proxmox Backup Server)
    participant Restic as 🔐 Restic
    participant Thoth as 🗄️ Thoth (offsite)
    participant n8n as ⚙️ n8n (verificación)
    actor Mnemosine as 📋 Mnemósine

    Note over ZFS: Cada 15 minutos (automático)
    ZFS->>ZFS: zfs snapshot rpool/datos/*@auto-$(date +%H%M)

    Note over PBS: Diario 02:00
    PBS->>ZFS: Backup de todos los CT y VM
    ZFS->>PBS: Datos incrementales (solo bloques modificados)
    PBS->>PBS: Verificación de integridad SHA-256

    Note over Restic: Diario 03:00
    Restic->>ZFS: restic backup /datos/*
    ZFS->>Restic: Datos cifrados y deduplicados
    Restic->>Restic: Snapshot con ID único

    Restic->>Thoth: restic copy → repositorio remoto (NetBird)
    Thoth->>Thoth: Almacena snapshot cifrado

    Note over n8n: Semanal, domingo 02:00
    n8n->>Restic: restic check --read-data
    Restic->>Thoth: Verifica integridad de todos los blobs
    Thoth->>Restic: Checksums válidos
    Restic->>n8n: ✅ Verificación OK
    n8n->>Mnemosine: Matrix: "Backup semanal verificado correctamente"

    alt Verificación fallida
        Restic->>n8n: ❌ Corrupción detectada en blob X
        n8n->>Mnemosine: ntfy CRÍTICO: "Backup corrupto. Recuperar de snapshot anterior"
    end

Dónde ocurre: Ra (ZFS, PBS, Restic, n8n) → Thoth (offsite vía NetBird)
Estrategia: Backup 3-2-1. Tres copias, dos medios (SSD + HDD), una externa (Thoth)
ADR: ADR-006 (ZFS), ADR-016 (Backup 3-2-1)


4. Flujo de despliegue

Cómo un cambio en el código llega a producción de forma segura y automatizada.

sequenceDiagram
    actor Hefesto as 👷 Hefesto (admin)
    participant Forgejo as 🔧 Forgejo (repositorio)
    participant Actions as ⚡ Forgejo Actions (CI/CD)
    participant Lint as ✅ Lint & Test (LXC)
    participant Ansible as 📜 Ansible
    participant SSH as 🔑 SSH
    participant LXC as 📦 LXC destino
    participant Semaphore as 🎛️ Semaphore (registro)
    actor Argos as 👁️ Argos (observabilidad)

    Hefesto->>Forgejo: git push → rama main<br/>(cambio en rol Ansible de Immich)

    Forgejo->>Actions: Trigger workflow: `.forgejo/workflows/deploy.yml`

    Actions->>Lint: Job 1: Lint
    Lint->>Lint: ansible-lint, yamllint, shellcheck
    Lint->>Actions: ✅ Lint OK

    Actions->>Lint: Job 2: Test (entorno aislado)
    Lint->>Lint: ansible-playbook --check --diff
    Lint->>Actions: ✅ Test OK (dry-run sin errores)

    Actions->>Actions: Job 3: Deploy (requiere aprobación)
    Actions->>Hefesto: Solicita aprobación manual

    Hefesto->>Actions: ✅ Aprobado

    Actions->>Ansible: ansible-playbook deploy-immich.yml
    Ansible->>SSH: Conexión SSH a LXC immich (10.10.10.42)
    SSH->>LXC: Ejecuta tareas del rol:
    LXC->>LXC: 1. Backup pre-deploy (ZFS snapshot)
    LXC->>LXC: 2. docker-compose pull (nueva versión)
    LXC->>LXC: 3. docker-compose up -d
    LXC->>LXC: 4. Healthcheck: curl localhost:8080/health
    LXC->>Ansible: ✅ Deploy OK

    Ansible->>Actions: ✅ Playbook completado
    Actions->>Semaphore: Registra despliegue (auditoría)
    Actions->>Argos: Notifica por Matrix: "Immich v1.125 desplegado"

    Argos->>Argos: Verifica métricas post-deploy:<br/>sin errores 5xx, latencia normal

Dónde ocurre: Forgejo Actions → Ansible → LXC destino
Tiempo típico: <3 min desde push hasta deploy (más aprobación manual)
ADR: ADR-018 (LXC aislamiento)


Resumen de flujos

Flujo Gatillo Latencia Criticidad
Autenticación GET a servicio protegido <200ms (sesión), <2s (login) Tier A
Datos de sensor Lectura de ESP32 cada 60s <500ms extremo a extremo Tier B
Backup automático CRON (cada 15 min / diario) 5-45 min según dataset Tier A
Despliegue Push a main en Forgejo <3 min + aprobación Tier B