> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Cuarentenas

> Reglas anti-duplicado que limitan cuántas veces un respondente puede enviar el mismo formulario dentro de una ventana de tiempo

<Info>
  **Disponible en el plan Corporate.** Esta funcionalidad forma parte de las capacidades empresariales de woku. [Conversa con nuestro equipo comercial](https://woku.app/pricing).
</Info>

Una **cuarentena** es una regla por empresa que limita cuántas
respuestas puede enviar el mismo respondente (identificado por correo
o teléfono) dentro de una ventana de tiempo deslizante. Cuando se
supera el límite, la API responde con `429` y la pantalla pública del
formulario muestra un mensaje específico, sin revelar la regla.

Usos típicos:

* Anti-spam: bloquear el mismo correo intentando dejar varias reseñas
  seguidas para inflar puntuación.
* Anti-fraude liviano: limitar 1 respuesta por empleado por mes por
  programa.
* Calidad de datos: evitar que un mismo cliente cargue dos veces el
  mismo formulario por error.

## Modelo

Cada cuarentena pertenece a una empresa y define:

| Campo                       | Tipo                                            | Descripción                                                                                          |
| --------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `name`                      | string                                          | Nombre visible en el panel.                                                                          |
| `description`               | string opcional                                 | Para qué sirve la regla.                                                                             |
| `respondentIdentifier`      | `'email' \| 'phone'`                            | Qué campo del envío identifica al respondente.                                                       |
| `windowDurationMin`         | número                                          | Ventana en minutos dentro de la cual se cuentan envíos previos.                                      |
| `maxResponsesPerRespondent` | número                                          | Cantidad permitida antes de bloquear.                                                                |
| `enabled`                   | booleano                                        | Si está activa.                                                                                      |
| `priority`                  | número                                          | Orden de evaluación. Menor valor evalúa primero; la primera regla que bloquea detiene la evaluación. |
| `metrics`                   | `{ totalBlocked, totalAllowed, lastBlockedAt }` | Contadores en vivo, sin agregaciones extra.                                                          |

La identificación por correo se hace contra el **hash SHA-256** del
correo, nunca contra el correo en claro: el evaluador no descifra
datos en la ruta crítica.

## Activar una cuarentena

1. Ve a **Cuarentenas** en el menú lateral.
2. Click en **Nueva cuarentena**.
3. Completa nombre, identificador, ventana en minutos y límite.
4. Guarda.

> El backend exige nombre, identificador, ventana ≥ 1 y límite ≥ 1.

## Cómo se evalúa

Para cada envío de formulario entrante:

1. El evaluador carga las cuarentenas activas de la empresa,
   ordenadas por `priority` ASC.

2. Para cada regla, calcula el valor del respondente (email
   normalizado y hasheado, o teléfono tal cual), cuenta los envíos
   previos con el mismo identificador dentro de la ventana, y
   compara contra `maxResponsesPerRespondent`.

3. Si una regla bloquea, la evaluación se detiene y el backend lanza
   `HTTP 429` con el siguiente cuerpo:

   ```json theme={null}
   {
     "code": "QUARANTINE_BLOCKED",
     "quarantineId": "65f...",
     "remainingMinutes": 45
   }
   ```

4. Si ninguna regla bloquea, los contadores `totalAllowed` se
   incrementan y el envío sigue su flujo normal.

El campo `remainingMinutes` indica la duración de la ventana, no el
tiempo exacto hasta que la próxima respuesta sea aceptada (es una
ventana deslizante).

## Simulador

El builder incluye un panel **Simulador** que ejecuta la lógica real
contra un correo o teléfono de prueba, pero con `dryRun: true`,
**no incrementa los contadores ni persiste nada**. Útil para validar
una regla recién creada antes de exponerla a tráfico real.

## Lo que ve el respondente

En `review.woku.app` (y en cualquier SDK que consuma la API), un
`429 QUARANTINE_BLOCKED` se traduce en una pantalla genérica:

> Ya nos enviaste esta respuesta hace poco. Vuelve a intentarlo en
> aproximadamente N minutos.

Intencionalmente **no revelamos el nombre de la regla ni el
identificador** que la disparó, para no entregar pistas a un atacante
que pretenda enumerar las reglas activas.

## Garantías

* **Privacidad**: el evaluador trabaja con el hash de búsqueda del
  correo, nunca con el correo en texto claro.
* **Atómico**: los contadores `totalBlocked` y `totalAllowed` se
  actualizan con `$inc` de MongoDB; los envíos concurrentes no pueden
  perder updates.
* **Sin impacto si no hay reglas**: la query inicial está respaldada
  por el índice `{ companyId, enabled, priority }` y devuelve vacío
  en microsegundos cuando no hay cuarentenas activas para la empresa.
* **Auditable**: cada bloqueo se registra en el [audit
  log](/seguridad/audit-log) como `quarantine.create`,
  `quarantine.update`, etc., los bloqueos individuales no se
  registran como entradas separadas para no saturar el log; los
  contadores en vivo son la fuente.

## Limitaciones conocidas (V1)

* `respondentIdentifier` solo soporta `email` o `phone`. Identificadores
  custom (campo de `customFields`) y `deviceId` quedan para V2.
* La cuarentena por `wokuId`/`formId` no se aplica todavía: la regla
  es global a la empresa. Cuando el envío empiece a llevar `formId`,
  el filtro por formulario se activa sin migración de datos.
* El identificador por teléfono compara el valor tal como llega
  (sin normalización E.164). Recomendamos al cliente normalizar
  antes de enviar.

## Pérdida de acceso

Si todos los miembros de la empresa quedan bloqueados por error
(por ejemplo una regla con `maxResponsesPerRespondent: 0`), un
admin puede desactivar la cuarentena desde el panel, los envíos
nuevos pasan inmediatamente. Las métricas previas se conservan.
