# Arquitectura ## Objetivo Dejar documentada la arquitectura reusable consolidada para la vertical de drenaje NGS. ## Arquitectura final resultante Cliente final ↓ `https://.panel.mesavault.es` ↓ Grafana tenant del cliente en OVH ↓ iframe a `/control/ui` ↓ OVH VPS - Traefik - Authentik - routing `/control/*` - logout handler - Tailscale hacia `platform-40` ↓ `platform-40` - `drain_control_api` - `drain_control_scheduler` - `drain01_norm` - `drain01_pg` - `mv_postgres_hot` - `mv_mosquitto` - `cs_chirpstack` ↓ ChirpStack ↓ nodo `LSN50 + XKC` ## Decisiones estructurales correctas ### OVH es frontal público OVH aloja: - publicación web - autenticación - tenant del cliente - dashboard del cliente ### platform-40 es backend real `platform-40` aloja: - control - persistencia - lógica - telemetría - MQTT - ChirpStack core - PostgreSQL ### El dashboard del cliente no vive en platform-40 El dashboard final del cliente vive en OVH. ### La UI no se expone directamente por LAN al cliente La UI no debe darse como solución final por `192.168.40.100:8088/ui`. Se integra por frontal público en `/control/`. ## Patrón backend de control La vertical se diseñó para no hacer que Grafana mande downlinks directamente. El patrón correcto es: - una micro-API de control en `platform-40` - una tabla SQL con horarios y perfiles - un scheduler que decide `ACTIVE` o `SLEEP` - lógica de downlinks separada del `pg_sink` de telemetría ## Modelo multi-sensor La vertical no quedó diseñada para un único sensor hardcodeado. El patrón correcto es: - una fila por sensor físico en `mv_control.asset_device_map` - una fila por sensor controlable en `mv_control.drain_schedule` - resolución `asset -> dev_eui -> application_id` ## Publicación de la API En una fase del trabajo se corrigió el criterio de publicación. La API quedó publicada así: - `192.168.40.100:8088:8088` No debe usarse `0.0.0.0` como criterio por defecto si Tailscale está presente. ## Lógica de transición de perfiles Para cambiar de perfil, el scheduler debe encolar dos downlinks por transición: 1. primero `set_5vt` 2. luego `set_tdc` Esto es necesario porque el nodo es Class A y aplica los cambios en el siguiente uplink.