Files
2026-06-09 21:18:13 -03:00

33 KiB

TIP — Threat Intelligence Platform

Plataforma centralizada de monitoreo e inteligencia de amenazas sobre Telegram.


Tabla de Contenidos

  1. Descripción General
  2. Arquitectura del Sistema
  3. Microservicios
  4. Flujo del Alimentador
  5. Requisitos Previos
  6. Instalación y Configuración
  7. Gestión de Backups
  8. Troubleshooting

Descripción General

TIP (Threat Intelligence Platform) es una plataforma de monitoreo en tiempo real diseñada para capturar, analizar y gestionar mensajes de grupos y canales de Telegram. Mediante reglas configurables basadas en expresiones regulares, el sistema detecta patrones sospechosos, genera alertas automáticas y mantiene un registro auditable de todas las operaciones.

Características Principales

  • Monitoreo en tiempo real: Captura automática de mensajes desde grupos y canales de Telegram
  • Detección basada en reglas: Expresiones regulares configurables para identificar patrones de interés
  • Gestión de alertas: Ciclo de vida completo — Pendiente → En Curso → Resuelta — con historial de notas
  • Auditoría integral: Registro de IP, usuario y timestamp en cada operación del sistema
  • Exportación de reportes: Generación de PDFs con trazabilidad completa al cerrar una alerta
  • Estadísticas en tiempo real: Dashboards con métricas, heatmaps y análisis de actividad
  • Control de acceso por roles: Administradores y Operadores con permisos diferenciados
  • Sistema de backups: Exportación e importación de bases de datos, configuración y sesiones de Telegram

Arquitectura del Sistema

TIP está compuesto por 4 microservicios y 2 bases de datos independientes, orquestados con Docker Compose y expuestos a través de un proxy NGINX con SSL.

╔══════════════════════════════════════════════════════════════════════════════════╗
║                                   INTERNET                                       ║
╚══════════════════════════════════════════════╦═══════════════════════════════════╝
                                               ║ HTTPS :443 / HTTP :80
                              ╔════════════════╩════════════════╗
                              ║           NGINX Proxy           ║
                              ║     Terminación SSL · Routing   ║
                              ╚══════╦══════════╦═══════╦═══════╝
                                     ║          ║       ║
                      ╔══════════════╝    ╔═════╝   ╔══=╩═════════════╗
                      ▼                   ▼         ▼                 ▼
             ╔════════════════╗  ╔══════════════╗  ╔══════════════╗  ╔═══════════════╗
             ║    Frontend    ║  ║  API Feeder  ║  ║  API Users   ║  ║Backup Service ║
             ║   Streamlit    ║  ║   FastAPI    ║  ║   FastAPI    ║  ║   FastAPI     ║
             ║   Python 3.11  ║  ║  Python 3.11 ║  ║  Python 3.11 ║  ║  Python 3.11  ║
             ║    :8501       ║  ║    :8000     ║  ║    :8090     ║  ║    :8099      ║
             ╚═══════╦════════╝  ╚══════╦═══════╝  ╚══════╦═══════╝  ╚═══════╦═══════╝
                     ║                  ║                  ║                  ║
              HTTP   ║         ╔════════╩══════╗           ║                  ║
              REST   ╠         ║   Telegram    ║           ║                  ║
                     ║         ║  API (MTProto)║           ║                  ║
                     ║         ╚═══════════════╝           ║                  ║
                     ║                  ║                  ║          ╔═══════╩══════╗
                     ║         ╔════════╩═══════╗  ╔═══════╩══════╗   ║  /config/... ║
                     ╚═════════║  MariaDB :3306 ║  ║MariaDB :3307 ║   ║   (volumes)  ║
                               ║  DB: feeder    ║  ║  DB: users   ║   ╚══════════════╝
                               ╚════════════════╝  ╚══════════════╝

Comunicación entre Servicios

Origen Destino Protocolo Propósito
Frontend API Feeder HTTP/REST Alertas, mensajes, reglas, grupos, estadísticas
Frontend API Users HTTP/REST Login, gestión de usuarios
Frontend Backup Service HTTP/REST Estado y descarga de backups
API Feeder Telegram MTProto (Telethon) Captura de mensajes y adjuntos
API Feeder API Feeder (interno) HTTP/REST Persistencia de mensajes vía api_implementations.py
Backup Service MariaDB Feeder TCP/MySQL mysqldump para backup
Backup Service MariaDB Users TCP/MySQL mysqldump para backup
NGINX Todos los servicios HTTP (reverse proxy) Enrutamiento y terminación SSL

Seguridad

  • JWT compartido: Todos los microservicios validan tokens con la misma SECRET_KEY
  • Roles: admin y operator con controles en cada endpoint
  • Rate limiting: Registro público limitado a 5 peticiones/minuto (SlowAPI)
  • HTTPS: Terminación SSL en NGINX con soporte TLSv1.2 y TLSv1.3

Microservicios

1. Frontend — Streamlit

Propósito: Interfaz de usuario para el monitoreo y gestión de la plataforma.

Lenguaje: Python 3.11

Ubicación: /frontend

Librería Versión Propósito
Streamlit ≥ 1.28.0 Framework web reactivo
Requests ≥ 2.31.0 Cliente HTTP hacia las APIs
Pandas ≥ 2.0.0 Manipulación de datos en dashboards
ReportLab ≥ 3.6.0 Generación de reportes PDF
Matplotlib ≥ 3.7.0 Gráficos estáticos auxiliares

Funcionalidades:

  • Panel de inicio con métricas y estado del alimentador
  • Gestión de alertas con notas, cambio de estado y exportación PDF
  • Búsqueda avanzada de mensajes con filtros por texto, grupo, remitente y fecha
  • Descarga de adjuntos directamente desde Telegram
  • Exploración de remitentes con historial de mensajes
  • Estadísticas con gráficos de línea, barras, heatmaps y ranking de senders
  • Panel de administración para gestión de usuarios, auditoría y backups

2. API Feeder — FastAPI

Propósito: Backend principal. Captura mensajes de Telegram, evalúa reglas y sirve los datos al Frontend.

Lenguaje: Python 3.11

Ubicación: /app

Librería Versión Propósito
FastAPI 0.104.1 Framework REST asíncrono
Uvicorn 0.24.0 Servidor ASGI
Telethon 1.28.5 Cliente MTProto para Telegram
SQLAlchemy 2.0.23 ORM
PyMySQL 1.1.0 Driver MySQL/MariaDB
Pydantic 2.11.9 Validación y serialización
Alembic 1.11.1 Migraciones de base de datos
python-jose 3.3.0 Generación y validación de JWT
python-dotenv 1.0.0 Gestión de variables de entorno
httpx latest Cliente HTTP asíncrono
aiofiles 23.2.1 I/O asíncrono de archivos
Requests 2.32.5 Cliente HTTP síncrono (integraciones internas)

Endpoints principales:

Grupo Método Ruta Descripción
Messages POST /messages/ Crear mensaje + evaluar reglas
Messages GET /messages/search/ Búsqueda con filtros
Alerts GET /alerts/ Listar con filtros
Alerts POST /alerts/{id}/resolve Cerrar alerta
Alerts POST /alerts/{id}/in-progress Marcar en curso
Rules POST /rules/ Crear regla (con apply_to_history)
Groups PATCH /groups/{id}/update-position Actualizar cursor de mensajes
Attachments GET /attachments/{id}/download Descargar adjunto desde Telegram
Audit GET /audit/ Consultar logs de auditoría
Stats GET /stats/ Métricas y estadísticas agregadas
Manage POST /manage/ Agregar grupo/canal de Telegram
Manage GET /manage/init-session Iniciar autenticación Telegram
Manage POST /manage/verify-code Verificar código de autenticación

3. API Users — FastAPI

Propósito: Gestión de usuarios, autenticación y auditoría de cambios de permisos.

Lenguaje: Python 3.11

Ubicación: /usuarios

Librería Versión Propósito
FastAPI 0.104.1 Framework REST
Uvicorn 0.24.0 Servidor ASGI
SQLAlchemy 2.0.23 ORM
PyMySQL 1.1.2 Driver MySQL/MariaDB
Pydantic 2.5.0 Validación de datos
passlib[bcrypt] 1.7.4 Hash seguro de contraseñas
bcrypt 4.0.1 Backend de hashing
python-jose 3.3.0 JWT
SlowAPI latest Rate limiting en endpoints públicos
python-multipart 0.0.6 Formularios multipart

Endpoints principales:

Método Ruta Descripción
POST /api/v1/login Autenticación — devuelve JWT
GET /api/v1/users/ Listar usuarios (admin)
GET /api/v1/users/pending Usuarios pendientes de aprobación
POST /api/v1/users/common Registro público (rate-limited)
PUT /api/v1/users/{id} Actualizar datos
PATCH /api/v1/users/{id}/role Cambiar rol
POST /api/v1/users/{id}/activate Activar usuario
GET /api/v1/logs/users Historial de modificaciones

4. Backup Service — FastAPI

Propósito: Centraliza la generación y verificación de backups del sistema completo.

Lenguaje: Python 3.11

Ubicación: /backup_service

Librería Versión Propósito
FastAPI 0.104.1 Framework REST
Uvicorn 0.24.0 Servidor ASGI
python-jose 3.3.0 Validación JWT (mismo SECRET_KEY)
mysqldump / mysqladmin sistema Dump de bases de datos (instalados en Dockerfile)

Endpoints:

Método Ruta Descripción
GET /backup Genera y descarga ZIP con los componentes seleccionados
GET /backup/status Estado de cada componente sin generar backup
GET /health Verificación de salud del servicio

Componentes exportables:

  • databases/ — mysqldump de las bases de datos Feeder y Users
  • config/ — nginx.conf y docker-compose.yml
  • ssl/ — Certificados SSL
  • telegram_sessions/ — Archivos .session de autenticación de Telegram

Flujo del Alimentador

El Feeder (alimentador) es el núcleo de captura del sistema. Se ejecuta en un hilo de fondo independiente al inicio de la API y opera en ciclos continuos.

┌─────────────────────────────────────────────────────────────────────────┐
│  INICIO DE LA API (startup_event)                                        │
│  └─► Lanza run_sync_scraper() en thread separado via asyncio.to_thread  │
└──────────────────────────────┬──────────────────────────────────────────┘
                               │
                               ▼
┌──────────────────────────────────────────────────────────────────────────┐
│  CICLO PRINCIPAL (run_sync_scraper)                                       │
│                                                                           │
│  ┌─ INICIO DEL CICLO ──────────────────────────────────────────────────┐ │
│  │                                                                     │ │
│  │  1. TelegramChatSingleton.get_scraper()                             │ │
│  │     └─► ¿Existe instancia singleton?                                │ │
│  │           ├─ NO → TelegramClientManager.connect()                  │ │
│  │           │        └─► Busca session_*.session en /telegram_sessions│ │
│  │           │             Autentica con Telethon (MTProto)            │ │
│  │           └─ SÍ → Reutiliza cliente existente                      │ │
│  │                                                                     │ │
│  │  2. scraper.add_chats()                                             │ │
│  │     └─► GET /groups/ → obtiene todos los grupos activos             │ │
│  │          Para cada grupo:                                           │ │
│  │           └─► Consulta Telegram con get_entity(id)                 │ │
│  │                Actualiza nombre, tipo y descripción en la DB        │ │
│  │                                                                     │ │
│  │  3. scraper.feeder_loop()                                           │ │
│  │     └─► Para cada grupo en la DB:                                   │ │
│  │                                                                     │ │
│  │          a) set_chat_id(group_id)                                   │ │
│  │             └─► Configura el canal objetivo en Telethon             │ │
│  │                                                                     │ │
│  │          b) self.first_id = group.message_position                  │ │
│  │             └─► Lee el cursor del último mensaje procesado          │ │
│  │                                                                     │ │
│  │          c) refresh_chat()                                          │ │
│  │             └─► GetHistoryRequest(min_id=first_id)                  │ │
│  │                  Descarga en lotes de 100 solo mensajes nuevos      │ │
│  │                                                                     │ │
│  │          d) get_and_post_message_info()                             │ │
│  │             │                                                       │ │
│  │             ├─► _preload_senders()                                  │ │
│  │             │    └─► Para cada sender_id único:                     │ │
│  │             │          GET /senders/{id} → ¿existe?                 │ │
│  │             │          NO → get_entity(id) en Telegram              │ │
│  │             │               POST /senders/ → crea el remitente      │ │
│  │             │                                                       │ │
│  │             └─► Para cada mensaje descargado:                       │ │
│  │                  │                                                  │ │
│  │                  ├─► Extrae: id, content, date, sender_id,          │ │
│  │                  │   group_id, media (adjunto si existe)            │ │
│  │                  │                                                  │ │
│  │                  ├─► POST /messages/ (API interna)                  │ │
│  │                  │    │                                             │ │
│  │                  │    └─► Endpoint crea el mensaje y:               │ │
│  │                  │         Para cada regla activa:                  │ │
│  │                  │          └─► re.search(regex, content)           │ │
│  │                  │               ¿Coincide? → crea Alert(status=open)│ │
│  │                  │                                                  │ │
│  │                  └─► Si tiene adjunto → POST /attachments/          │ │
│  │                                                                     │ │
│  │          e) act_message_position(group_id, last_message_id)        │ │
│  │             └─► PATCH /groups/{id}/update-position                  │ │
│  │                  Actualiza el cursor para el próximo ciclo          │ │
│  │                                                                     │ │
│  │  4. Fin del ciclo → sleep(200 segundos)                             │ │
│  └─────────────────────────────────────────────────────────────────────┘ │
│                                                                           │
│  ⚠️  Si ocurre una excepción en cualquier punto:                          │
│       └─► scraper_status["last_error"] = str(e)                          │
│            sleep(60 segundos)                                             │
│            El singleton mantiene el cliente → intento de reconexión       │
└──────────────────────────────────────────────────────────────────────────┘

Descarga de Adjuntos (bajo demanda)

Cuando un usuario descarga un adjunto desde la UI, se sigue un flujo independiente para no interferir con el ciclo del Feeder:

Frontend
  └─► GET /attachments/{id}/download
        │
        ├─► Obtiene metadata del adjunto (group_id, message_id)
        │
        ├─► TelegramChatSingleton.get_tmp_scraper()
        │    └─► Crea un TelegramClientManager temporal
        │         Copia el .session file a un archivo temporal
        │         Lanza un thread dedicado con su propio event loop
        │
        └─► download_attachment_to_buffer(group_id, message_id)
             └─► client.get_messages(group_id, ids=message_id)
                  client.download_media(message, file=BytesIO())
                  Devuelve los bytes → StreamingResponse al Frontend
                  Elimina la sesión temporal al finalizar

Configuración del Ciclo

Los parámetros del ciclo se pueden ajustar directamente en app/main.py:

scraper_config = {
    "cicle_time": 200,   # segundos entre ciclos (recomendado ≥ 200 para evitar flood)
    "error_delay": 60,   # segundos de espera tras un error antes de reintentar
}

Requisitos Previos

Hardware Mínimo

Recurso Mínimo Recomendado
CPU 2 núcleos 4 núcleos
RAM 4 GB 8 GB
Almacenamiento 20 GB 50 GB+

Software Requerido

Componente Versión Mínima Instalación
Docker 20.10+ https://docs.docker.com/engine/install/
Docker Compose 1.29+ Incluido en Docker Desktop
Git 2.20+ https://git-scm.com/downloads
jq (solo Linux/macOS) 1.6+ sudo apt install jq o brew install jq

Nota sobre Python: El proyecto utiliza Python 3.11 en todos los microservicios. La versión está declarada en cada Dockerfile (FROM python:3.11-slim). No es necesario tener Python instalado localmente; Docker lo gestiona de forma aislada.

Credenciales Necesarias

  • Telegram API ID y API Hash: Obtener en https://my.telegram.org/apps con la cuenta que se usará para el monitoreo
  • Número de teléfono de esa cuenta (formato internacional, ej: +5491112345678)
  • Acceso a los grupos/canales de Telegram que se desean monitorear

Instalación y Configuración

Paso 1 — Clonar el Repositorio

git clone https://github.com/tu-usuario/tip.git
cd tip

Paso 2 — Crear el Archivo .env

cp .env.example .env

Edita .env con tus valores reales:

# ── TELEGRAM ────────────────────────────────────────────────────────────
# Obtener en https://my.telegram.org/apps
TELEGRAM_API_ID=123456789
TELEGRAM_API_HASH=abcdef0123456789abcdef0123456789
TELEGRAM_TELEPHONE=+5491112345678

# ── SEGURIDAD ────────────────────────────────────────────────────────────
# Clave compartida entre todos los microservicios (mínimo 20 caracteres)
# Generar con: openssl rand -hex 32
SECRET_KEY=reemplazar_con_clave_secreta_minimo_32_chars

# ── BASES DE DATOS ───────────────────────────────────────────────────────
DB_ROOT_PASS_FEEDER=password_feeder
DB_ROOT_PASS_USERS=password_users

# ── ADMIN (creado automáticamente en el primer inicio) ──────────────────
ADMIN_EMAIL=admin@tudominio.com
ADMIN_PASSWORD=contraseña_admin_segura

Paso 3 — Configurar docker-compose.yml

cp docker-compose_example.yml docker-compose.yml

Reemplaza los valores marcados con YOUR-*:

# Contraseñas de bases de datos
database:
  environment:
    MYSQL_ROOT_PASSWORD: password_feeder       # ← cambiar

database_users:
  environment:
    MYSQL_ROOT_PASSWORD: password_users        # ← cambiar

# URLs de conexión a las bases de datos
api:
  environment:
    DATABASE_URL: mariadb+pymysql://root:password_feeder@database:3306/feeder
    TELEGRAM_API_ID: TU_API_ID
    TELEGRAM_API_HASH: TU_API_HASH
    TELEGRAM_TELEPHONE: TU_TELEFONO
    SECRET_KEY: TU_SECRET_KEY

api_users:
  environment:
    DATABASE_URL: mariadb+pymysql://root:password_users@database_users:3307/users
    SECRET_KEY: TU_SECRET_KEY       # ← debe ser la misma que api
    ADMIN_EMAIL: admin@tudominio.com
    ADMIN_PASSWORD: contraseña_admin

# URLs para el backup service
backup:
  environment:
    FEEDER_DATABASE_URL: mariadb+pymysql://root:password_feeder@database:3306/feeder
    USERS_DATABASE_URL: mariadb+pymysql://root:password_users@database_users:3307/users
    SECRET_KEY: TU_SECRET_KEY

Paso 4 — Configurar NGINX

mkdir -p nginx/ssl
cp nginx/nginx.conf_example nginx/nginx.conf

Edita nginx/nginx.conf y reemplaza localhost con tu dominio:

server_name tu_dominio.com;

Para desarrollo local sin SSL, comenta el bloque HTTPS y usa solo el bloque HTTP.

Para producción con Let's Encrypt:

# Instalar certbot (fuera de Docker)
sudo apt install certbot

# Generar certificados
sudo certbot certonly --standalone -d tu_dominio.com

# Copiar al directorio del proyecto
sudo cp /etc/letsencrypt/live/tu_dominio.com/fullchain.pem ./nginx/ssl/
sudo cp /etc/letsencrypt/live/tu_dominio.com/privkey.pem   ./nginx/ssl/
sudo chown $(whoami):$(whoami) ./nginx/ssl/*

Paso 5 — Iniciar los Contenedores

# Construir imágenes e iniciar todos los servicios
docker compose up -d --build

# Verificar que todos estén corriendo
docker compose ps

Resultado esperado:

NAME            SERVICE         STATUS
feeder_api      api             running
users_api       api_users       running
frontend        frontend        running
backup_service  backup          running
feeder_db       database        running (healthy)
users_db        database_users  running (healthy)
nginx_proxy     nginx           running
# Ver logs en tiempo real
docker compose logs -f api api_users

Paso 6 — Autenticar la Sesión de Telegram

La primera vez (o tras reinstalación) es necesario autenticar el cliente de Telegram:

  1. Accede a la UI como admin: https://tu_dominio.com
  2. Ve a Panel de AdministraciónSistemaAlimentador
  3. Haz clic en Iniciar Nueva Sesión
  4. Revisa el código de verificación que llegó a tu cuenta de Telegram
  5. Ingrésalo en el campo correspondiente (más la contraseña 2FA si aplica)
  6. El alimentador se activará automáticamente

Paso 7 — Agregar Grupos a Monitorear

  1. Ve a Grupos y CanalesAgregar grupo
  2. Abre el grupo en Telegram Web (web.telegram.org)
  3. Copia la URL completa (contiene el ID: .../#-100XXXXXXXXX)
  4. Pégala en el campo y haz clic en Agregar Grupo
  5. El sistema valida el acceso contra Telegram y lo registra

Gestión de Backups

Generar un Backup

Desde la UI

  1. Accede como admin
  2. Ve a Panel de AdministraciónSistemaBackup del Sistema
  3. Selecciona los componentes a incluir
  4. Haz clic en ⬇️ Generar y Descargar Backup
  5. Guarda el archivo tip_backup_YYYYMMDD_HHMMSS.zip en lugar seguro

Desde la línea de comandos

# Primero, obtener un token JWT (reemplazar por tus credenciales)
TOKEN=$(curl -s -X POST http://localhost:8090/api/v1/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@tudominio.com","password":"tu_password"}' \
  | jq -r '.access_token')

# Solicitar el backup
curl -X GET \
  "http://localhost:8099/backup?include_db=true&include_config=true&include_ssl=true&include_sessions=true" \
  -H "Authorization: Bearer $TOKEN" \
  -o "tip_backup_$(date +%Y%m%d_%H%M%S).zip"

Restaurar un Backup

⚠️ ADVERTENCIA: La restauración sobrescribe datos existentes. Asegúrate de que es lo que necesitas antes de continuar.

Windows (PowerShell)

# 1. Coloca el archivo tip_backup_*.zip en la raíz del proyecto
# 2. Abre PowerShell como Administrador y navega al directorio
cd C:\ruta\al\proyecto

# 3. Habilitar ejecución de scripts (si no está habilitado)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

# 4. Ejecutar el script
.\restore_backup.ps1

Linux / macOS (Bash)

# 1. Coloca el archivo tip_backup_*.zip en la raíz del proyecto
# 2. Dar permisos de ejecución al script
chmod +x restore_backup.sh

# 3. Ejecutar el script
./restore_backup.sh

¿Qué hace el script de restauración?

INICIO
  │
  ├─ 1. Solicita confirmación al usuario
  │
  ├─ 2. Localiza el tip_backup_*.zip más reciente en el directorio actual
  │
  ├─ 3. Extrae el contenido en ./temp_restore/
  │
  ├─ 4. Lee manifest.json → identifica componentes incluidos y advertencias
  │
  ├─ 5. Obtiene credenciales de las bases de datos desde docker-compose.yml
  │
  ├─ 6. Por cada componente en el manifiesto:
  │     ├─ database:feeder  → levanta feeder_db y restaura el .sql
  │     ├─ database:users   → levanta users_db y restaura el .sql
  │     ├─ config:*         → copia nginx.conf y/o docker-compose.yml
  │     ├─ ssl              → copia certificados a ./nginx/ssl/
  │     └─ telegram_sessions → copia .session a ./app/telegram_sessions/
  │
  ├─ 7. Muestra las advertencias registradas en el manifiesto
  │
  ├─ 8. Elimina ./temp_restore/
  │
  └─ 9. Pregunta si desea reiniciar los contenedores (docker compose down && up)

Dependencias del Script

Dependencia Windows Linux/macOS
Docker + Docker Compose Requerido Requerido
jq No requerido (usa PowerShell nativo) sudo apt install jq

Buenas Prácticas de Backup

  • Frecuencia: Realiza backups diarios en producción, especialmente antes de actualizaciones
  • Validación: Prueba la restauración en un entorno de prueba periódicamente
  • Almacenamiento externo: Guarda copias en un servidor remoto o servicio de almacenamiento (S3, OneDrive, etc.)
  • Encriptación: Si el backup contiene sesiones o datos sensibles, encríptalo antes de transferirlo:
    # Linux/macOS
    openssl enc -aes-256-cbc -salt -in tip_backup_*.zip -out tip_backup_encrypted.zip
    
    # Descifrar
    openssl enc -d -aes-256-cbc -in tip_backup_encrypted.zip -out tip_backup_restored.zip
    

Troubleshooting

Los contenedores no inician

# Ver logs completos de todos los servicios
docker compose logs

# Ver logs de un servicio en particular
docker compose logs api
docker compose logs database

# Reconstruir imágenes sin caché
docker compose down
docker compose up -d --build --force-recreate

Error de conexión a la base de datos

# Verificar que MariaDB está aceptando conexiones
docker compose exec database mysql -u root -p -e "SELECT 1;"

# Verificar conectividad entre contenedores
docker compose exec api ping database

El alimentador aparece como inactivo

# Verificar si hay archivos de sesión de Telegram
docker compose exec api ls -la /app/telegram_sessions/

# Si no hay sesión o está corrupta, eliminarla y autenticar de nuevo desde la UI
docker compose exec api rm -f /app/telegram_sessions/session_*
# Luego: Panel de Administración → Sistema → Iniciar Nueva Sesión

NGINX devuelve 502 Bad Gateway

# Verificar que los servicios upstream estén corriendo
docker compose ps

# Validar la configuración de NGINX
docker compose exec nginx nginx -t

# Ver logs de NGINX
docker compose logs nginx

Las alertas no se generan automáticamente

# Verificar que existen reglas activas
curl -H "Authorization: Bearer $TOKEN" http://localhost:8000/rules/

# Verificar que el feeder está capturando mensajes
docker compose logs api | grep -E "Feeding|Cycle|feeder_loop"

# Verificar que no hay errores de regex en las reglas
docker compose logs api | grep -i "regex\|WARN"

Estructura del Proyecto

tip/
├── app/                        # API Feeder
│   ├── alembic/                # Migraciones de base de datos
│   ├── integrations/           # Cliente Telegram (chats.py, api_implementations.py)
│   ├── routers/                # Endpoints REST
│   ├── main.py                 # Entry point + scraper loop
│   ├── models.py               # Modelos SQLAlchemy
│   ├── schemas.py              # Schemas Pydantic
│   ├── auth.py                 # JWT helpers
│   └── audit.py                # Logger de auditoría
├── usuarios/                   # API Users
│   ├── main.py
│   ├── models.py
│   ├── schemas.py
│   ├── crud.py
│   ├── services.py
│   └── dependencies.py
├── frontend/                   # UI Streamlit
│   ├── app.py
│   ├── src/
│   │   ├── api.py              # Cliente HTTP hacia las APIs
│   │   ├── auth.py             # Login / sesión
│   │   └── pages/
│   │       ├── dashboard.py
│   │       └── views/          # alerts, messages, rules, groups, stats, ...
│   └── .streamlit/
│       ├── config.toml         # Tema visual
│       └── secrets.toml
├── backup_service/             # Backup Service
│   ├── main.py
│   ├── requirements.txt
│   └── Dockerfile
├── nginx/
│   ├── nginx.conf              # Configuración del proxy (generada desde el ejemplo)
│   └── ssl/                    # Certificados SSL (excluidos del repo)
├── Dockerfile                  # Imagen API Feeder
├── Dockerfile_users            # Imagen API Users
├── Dockerfile_frontend         # Imagen Frontend
├── docker-compose.yml          # Orquestación (generado desde el ejemplo)
├── docker-compose_example.yml  # Plantilla de configuración
├── entrypoint.sh               # Ejecuta migraciones Alembic antes de iniciar la API
├── restore_backup.sh           # Script de restauración (Linux/macOS)
├── restore_backup.ps1          # Script de restauración (Windows)
├── requirements.txt            # Dependencias API Feeder
├── requirements_users.txt      # Dependencias API Users
├── requirements_frontend.txt   # Dependencias Frontend
└── .gitignore

Plataforma desarrollada para uso interno — Municipio de Paraná.