# Expiración escalonada Use `ladder()` en **Expira en**, en la acción [Agregar a la lista](/es/rules/actions/add_to_list/), para mantener un valor en la lista por más tiempo con cada reincidencia. Por ejemplo, una IP bloqueada por primera vez sale de la lista en 1 hora, y una IP reincidente permanece 2 días. ## Sintaxis ``` ladder(<índice>, , , ...) ``` - **Índice**: un campo (`$intentos`) o una lectura publicada por una acción anterior (`%bloqueos.cells.ip.value`), con valor numérico. Un número fijo, como `ladder(1, 1h, 4h)`, se rechaza al guardar la regla. - **Plazos**: de 1 a 10 plazos, cada uno con un número entero seguido de `m`, `h` o `d`. Cada plazo está entre `5m` y 2 años. El índice elige el plazo por la posición, contada a partir de 0: | Índice | Plazo elegido | | :--------------------- | :----------------------------------------------- | | `0` | el primero | | `1`, `2`, ... | el plazo en esa posición | | más allá del último plazo | el último | | decimal | redondeado hacia abajo: `2,7` elige la posición 2 | | ausente o negativo | el primero | Con `ladder(%bloqueos.cells.ip.value, 1h, 4h, 16h)`, el índice 0 elige 1 hora, el índice 1 elige 4 horas y el índice 2 o mayor elige 16 horas. ## Bloqueo por reincidencia El índice suele ser el conteo de bloqueos anteriores del mismo valor. El análisis `bloqueos` tiene una [celda sin disparador](/es/rules/analyses/#sin-disparador) `ip`, que cuenta los eventos por `$ip` en 30 días. La regla registra un evento en ese análisis solo cuando la IP entra efectivamente en la lista: ``` Condición 1: "ip_velocity" in %riesgo.triggered_cells Acciones: Ejecutar análisis: bloqueos (resultado: bloqueos) Agregar a la lista → $ip en @ips_bloqueadas, expira en ladder(%bloqueos.cells.ip.value, 1h, 4h, 16h, 2d) (resultado: ip_bloqueada) Condición 2: %ip_bloqueada.added == true Acciones: Registrar análisis: bloqueos ``` El campo **Resultado** de la acción publica `%ip_bloqueada.added`. La lectura es `true` solo cuando la ejecución incluyó la IP en la lista. Mientras la IP está en la lista, los eventos siguientes leen `false` y no cuentan como un nuevo bloqueo. En una ráfaga de eventos de la misma IP, solo una ejecución lee `true`. La celda `ip` cuenta, así, los bloqueos de la IP, y no cada evento sospechoso: | Bloqueo | Conteo en la celda `ip` | Plazo en la lista | | :-------------- | :---------------------- | :---------------- | | primero | 0 | 1 hora | | segundo | 1 | 4 horas | | tercero | 2 | 16 horas | | cuarto en adelante | 3 o más | 2 días | La ventana de la celda define por cuánto tiempo un bloqueo cuenta como reincidencia. En el ejemplo, una IP sin bloqueos en 30 días vuelve al plazo de 1 hora. ## Puntos a considerar - **El plazo nunca se acorta**: si el valor ya está en la lista, la ejecución mantiene el plazo más largo entre el actual y el elegido, según [Agregar a la lista](/es/rules/actions/add_to_list/). - **La observación y la simulación no escriben en la lista**: en [observación](/es/rules/versioning/#observación) y en [simulación](/es/rules/simulation/), la acción no incluye el valor y no publica el resultado.