> ## Documentation Index
> Fetch the complete documentation index at: https://alan-ramirez-dev.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 🖥️ Consola Interactiva y WAF

> Motor SQL dinámico protegido por un Web Application Firewall simulado.

Para demostrar el procesamiento de los datos ingestados, el **Pipeline** expone un endpoint que permite ejecutar sentencias SQL reales directamente contra la base de datos PostgreSQL desde una terminal interactiva.

Dado el riesgo crítico que esto representa al abrir la base de datos al exterior, el endpoint está blindado por múltiples capas de seguridad y un filtro de expresiones regulares a nivel de controlador.

## 🔌 Endpoint de Consulta Dinámica

<ParamField path="POST" type="/api/v1/etl/query">
  Ejecuta una consulta SQL de solo lectura y devuelve los resultados serializados.
</ParamField>

### 📦 Payload de la Petición

El endpoint espera un objeto JSON simple con la consulta a ejecutar:

```json theme={null}
{
  "query": "SELECT vehicle_vin, odometer_km FROM logiflow_telemetry WHERE vehicle_status = 'MOVING'"
}
```

## 🛡️ Filtro de Seguridad (WAF Simulado)

Para evitar inyecciones SQL y la ejecución de sentencias destructivas, el controlador intercepta la consulta cruda y la pasa por una serie de validaciones estrictas antes de enviarla a `JdbcTemplate`.

### 🛑 Reglas del Firewall

1. **Exclusividad de Lectura:** La sentencia debe iniciar estrictamente con la palabra clave `SELECT`.
2. **Sentencias Únicas:** Se prohíbe el apilamiento de múltiples consultas mediante el uso intermedio de punto y coma (`;`).
3. **Lista Negra de Palabras Clave:** Se escanea el texto mediante expresiones regulares contra comandos peligrosos para neutralizar la manipulación de la estructura o accesos.

```java theme={null}
// Lista de palabras prohibidas en EtlController.java
String[] forbiddenKeywords = {"INSERT", "UPDATE", "DELETE", "DROP", "ALTER", "TRUNCATE", "GRANT", "REVOKE", "COMMIT", "ROLLBACK", "EXEC", "UNION", "SLEEP", "PG_SLEEP"};
for (String keyword : forbiddenKeywords) {
    if (upperSql.matches(".*\\b" + keyword + "\\b.*")) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN)
                .body(Map.of("error", "[SECURITY ALERT] Posible inyección SQL detectada."));
    }
}
```

### 🚦 Protección contra Saturación de Red

Como última línea de defensa, la transacción a nivel de base de datos se marca como de solo lectura (`@Transactional(readOnly = true)`). Además, si la consulta original del usuario omite una cláusula de límite, el servidor inyecta automáticamente un `LIMIT 15`.

Esto evita la saturación de la red y el colapso de la memoria en el frontend en caso de que se ejecute un `SELECT *` masivo sobre una tabla con decenas de miles de registros logísticos.

```java theme={null}
// Inyección dinámica de límite en EtlController.java
if (!upperSql.contains("LIMIT")) {
    finalSql = finalSql + " LIMIT 15";
}
```
