Metadata-Version: 2.5
Name: vigia-nids
Version: 0.2.0
Summary: Control de calidad continuo para los datos de modelos de ciberseguridad
Project-URL: Homepage, https://github.com/Joshua203-byte/Data
Project-URL: Documentation, https://github.com/Joshua203-byte/Data/tree/main/vigia/docs
Project-URL: Issues, https://github.com/Joshua203-byte/Data/issues
Project-URL: Changelog, https://github.com/Joshua203-byte/Data/blob/main/vigia/CHANGELOG.md
Author: Joshua
License: Apache-2.0
License-File: LICENSE
Keywords: data-quality,dataset,machine-learning,nids,security
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Requires-Python: >=3.11
Requires-Dist: polars>=1.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.12
Provides-Extra: api
Requires-Dist: fastapi>=0.110; extra == 'api'
Requires-Dist: python-multipart>=0.0.9; extra == 'api'
Requires-Dist: uvicorn[standard]>=0.29; extra == 'api'
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: psutil>=5.9; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Provides-Extra: ml
Requires-Dist: cleanlab>=2.6; extra == 'ml'
Requires-Dist: datasketch>=2.0; extra == 'ml'
Requires-Dist: lightgbm>=4.0; extra == 'ml'
Requires-Dist: numpy>=1.26; extra == 'ml'
Requires-Dist: scikit-learn>=1.4; extra == 'ml'
Provides-Extra: parquet
Requires-Dist: pyarrow>=15.0; extra == 'parquet'
Provides-Extra: pcap
Requires-Dist: nfstream>=6.5; extra == 'pcap'
Requires-Dist: pandas>=2.0; extra == 'pcap'
Description-Content-Type: text/markdown

# Vigía

**Control de calidad continuo para los datos de modelos de ciberseguridad.**

Vigía revisa los datasets con los que se entrenan los detectores de intrusiones y
responde una pregunta incómoda: *¿este 0.99 de F1 es real, o es un artefacto de
los datos?*

La investigación sobre los datasets más usados del área (CIC-IDS2017,
CSE-CIC-IDS2018, UGR'16) documenta duplicados masivos, etiquetas incorrectas,
fugas entre entrenamiento y prueba, y columnas que le delatan la respuesta al
modelo. El resultado es siempre el mismo: **el modelo parece excelente en el
laboratorio y falla en una red real.**

> Estado: **v0.2.0 — los tres módulos implementados y validados contra datos
> reales.** El auditor cubre los diez requisitos P0, más los lectores de Zeek,
> Suricata EVE y PCAP (R13 y R14). El monitor de deriva está medido sobre los
> cinco días de CIC-IDS2017, y los detectores de envenenamiento sobre ataques
> inyectados en ese mismo tráfico y sobre el ruido de etiqueta que documentaron
> Engelen et al. Los números están en
> [`benchmarks/RESULTADOS.md`](benchmarks/RESULTADOS.md), incluidos los casos
> donde el rendimiento es pobre.

## Los tres módulos

| Módulo | Comando | Qué responde |
|---|---|---|
| **1. Auditor** | `vigia audit` | ¿Este dataset tiene defectos que inflen las métricas? |
| **2. Envenenamiento** | `vigia poison` | ¿Alguien insertó registros para manipular el modelo? |
| **3. Deriva** | `vigia drift` | ¿El tráfico de hoy sigue pareciéndose al de entrenamiento? |

24 checks, 8 correcciones automáticas y la comparación de rendimiento
antes/después.

## Instalación

```bash
pip install -e ".[dev]"      # desde el repositorio
vigia --help
```

Requiere Python 3.11 o superior.

## Uso

```bash
# Auditar un dataset (las columnas se detectan solas por nombre)
vigia audit data/flows.csv --report out/

# Indicar las columnas explícitamente
vigia audit data/flows.parquet \
  --label-col Label --split-col split --time-col Timestamp \
  --report out/

# Correr solo una categoría de checks
vigia audit data/flows.csv --checks leak,dup

# En CI: salir con código 1 si hay hallazgos críticos
vigia audit data/train.csv --fail-on critical

# Listar los checks disponibles
vigia checks
```

Desde Python:

```python
import vigia

ctx = vigia.load("data/flows.parquet", label_col="Label", split_col="split")
report = vigia.audit(ctx)

print(report.traffic_light())  # 'rojo' | 'amarillo' | 'verde' | 'gris'
print(report.counts())  # {'critical': 2, 'high': 1, ...}

from vigia.report import write_report

write_report(report, "out/")  # report.html + report.json
```

## Qué revisa hoy

| Check | Qué encuentra |
|---|---|
| `dup.exact` | Filas idénticas: el modelo se evalúa con ejemplos que ya vio |
| `dup.class_ratio` | Clases formadas mayoritariamente por duplicados |
| `dup.cross_split` | **Crítico.** La misma fila en entrenamiento y en prueba |
| `leak.temporal` | El conjunto de prueba se solapa con el de entrenamiento en el tiempo |
| `leak.host` | El mismo host atacante en ambos splits: el modelo memoriza la IP |
| `shortcut.single_feature` | Una sola columna predice la etiqueta demasiado bien |
| `shortcut.identifier` | IPs, IDs de flujo o timestamps usados como características |
| `validity.nan_inf` | NaN e infinitos (CIC-IDS2017 los tiene en las columnas de tasas) |
| `validity.constant` | Columnas con un solo valor |
| `validity.impossible` | Puertos > 65535, duraciones negativas, bytes negativos |
| `validity.column_names` | Nombres con espacios (`" Destination Port"`) o ambiguos |
| `leak.session` | Flujos de la misma conexión repartidos entre splits |
| `labels.conflict` | Filas idénticas con etiquetas distintas |
| `labels.noise` | Etiquetas que contradicen al resto del dataset (cleanlab) |
| `labels.taxonomy` | La misma clase escrita de varias formas |
| `labels.imbalance` | Clases con tan pocos ejemplos que su métrica no dice nada |

Cada hallazgo trae severidad, métrica, filas afectadas, ejemplos concretos y una
recomendación. Un check que no puede correr (falta la columna de split, por
ejemplo) no falla en silencio: aparece en la sección "checks no ejecutados" del
reporte.

### El semáforo

| Color | Significa |
|---|---|
| **rojo** | Hay hallazgos críticos o altos |
| **amarillo** | Hay hallazgos medios o bajos |
| **verde** | Sin hallazgos y todos los checks se ejecutaron |
| **gris** | Sin hallazgos, pero algunos checks no se ejecutaron |

El gris existe porque "no encontré nada" y "está limpio" no son lo mismo. Si la
columna de etiqueta o la de split no se detectan, los checks que se saltan son
justamente los que buscan fuga y duplicados entre conjuntos: dar verde ahí sería
confirmar que el dataset está bien cuando en realidad casi no se lo revisó. Si el
semáforo da gris, especificá las columnas a mano con `--label-col` y `--split-col`.

## Corregir

Los hallazgos nombran su corrección. `vigia fix` las aplica:

```bash
# Ver las disponibles
vigia fixes

# Aplicarlas en cadena; el archivo original nunca se toca
vigia fix data/flows.csv \
  --apply drop_duplicates,drop_constant,drop_identifiers \
  --out data/flows_corregido.parquet
```

Las filas con etiqueta dudosa **nunca se borran**: `quarantine_noise` las deja
en un archivo aparte para que una persona las revise.

## Medir cuánto del rendimiento era real

```python
from vigia.benchmark import compare

c = compare(ctx, ["drop_identifiers"])
print(c.summary())
print(c.after.per_class_recall)
```

Entrena el mismo modelo antes y después de corregir. Una caída no significa
que las correcciones empeoraron el modelo: significa que el número original
estaba inflado. Sobre CIC-IDS2017, cambiar un split aleatorio por uno temporal
lleva el recall de DoS Hulk, PortScan y DDoS de ~0,95 a **0,00** — ver
[`benchmarks/RESULTADOS.md`](benchmarks/RESULTADOS.md).

## Formatos de entrada

| Formato | Extensión | Notas |
|---|---|---|
| CSV | `.csv`, `.txt` | Reintenta en cp1252 si no es UTF-8 |
| Parquet | `.parquet`, `.pq` | Conserva los tipos |
| Zeek | `.log` | TSV con cabecera o JSON Lines |
| Suricata EVE | `.json`, `.eve` | `--event-type` elige flujos o alertas |
| PCAP | `.pcap`, `.pcapng`, `.cap` | Con `pip install 'vigia-nids[pcap]'` |

Archivo suelto o carpeta completa: los datasets CIC vienen partidos en un
archivo por día, Vigía los concatena y conserva la procedencia en
`__source_file`. Los PCAP se leen de a uno, porque extraer flujos tarda minutos.

Detalles de cada formato en [`docs/USO.md`](docs/USO.md#formatos-de-entrada).

## Desarrollo

```bash
pip install -e ".[dev,ml]"

pytest                 # pruebas
ruff check src tests   # lint
ruff format src tests  # formato
mypy src               # tipos
```

Agregar un check nuevo es una clase con cuatro atributos y un método. El
registro es automático al importarse el módulo desde `vigia/checks/__init__.py`.
Los detalles están en [`docs/ARQUITECTURA.md`](docs/ARQUITECTURA.md).

## Documentación

| Documento | Para qué |
|---|---|
| [`docs/CHECKS.md`](docs/CHECKS.md) | Qué significa cada hallazgo del auditor y qué hacer |
| [`docs/ENVENENAMIENTO.md`](docs/ENVENENAMIENTO.md) | Módulo 2: los detectores, el simulador y qué tan bien funcionan |
| [`docs/DERIVA.md`](docs/DERIVA.md) | Módulo 3: los checks, las métricas y cómo leerlos |
| [`docs/USO.md`](docs/USO.md) | Referencia de la CLI, del SDK y del formato JSON |
| [`docs/ARQUITECTURA.md`](docs/ARQUITECTURA.md) | Cómo está armado por dentro; cómo agregar un check |
| [`benchmarks/RESULTADOS.md`](benchmarks/RESULTADOS.md) | Resultados verificados sobre NSL-KDD y CIC-IDS2017 |
| [`docs/PLAN.md`](docs/PLAN.md) | Qué falta hasta la 1.0, en qué orden y cómo |

## Documento de diseño

El diseño completo — los tres módulos (auditor, envenenamiento, deriva), la
arquitectura, el plan por fases y las referencias académicas — está en
[`vigia.md`](../vigia.md).

## Licencia

Apache 2.0.
