Saltar al contenido
verificaOTP

Capítulo 3 de 5 · 12 min de lectura

Estados del ciclo de vida

Modela la verificación como una máquina de estados y elimina los bugs de booleanos sueltos.

La mayoría de los incidentes con OTP que hemos revisado no vienen de criptografía débil, sino de estado mal modelado: un código que sigue vigente después de un acierto, un reenvío que no invalida el anterior, un contador que se reinicia con cada solicitud. La solución es tratar cada verificación como una entidad con estados explícitos.

Los estados

  • pending: emitida y enviada, esperando al usuario.
  • approved: el usuario acertó; estado terminal.
  • expired: venció el tiempo; terminal.
  • locked: se agotaron los intentos; terminal.
  • canceled: el sistema la anuló, por ejemplo al emitir un reenvío; terminal.

Solo pending acepta intentos. Todo lo demás es terminal y cualquier verify sobre un estado terminal devuelve falso sin revelar por qué al cliente; el motivo queda en tus logs.

De booleanos a estados

Refactor: de banderas sueltas a un estado único
type Verification = {
code: string;
used: boolean;
expired: boolean;
attempts: number;
};
function canVerify(v: Verification) {
return !v.used && !v.expired;
}
Mostrando: antes · haz click para alternar

Con dos booleanos tienes cuatro combinaciones, una de ellas absurda (used y expired a la vez). Con un enum, las combinaciones imposibles dejan de ser representables. Además, calcular la expiración con expiresAt en lugar de una bandera evita depender de un job que la actualice a tiempo.

Este modelo también simplifica la observabilidad: cada transición queda como un evento con timestamp, y un panel de soporte puede mostrarle al agente «emitida 10:03, reenviada 10:04 (cancela la anterior), aprobada 10:05» en vez de inferirlo desde columnas sueltas en una tabla.

En el playground de abajo simulamos justamente ese flujo: emitimos un código, lo cancelamos lógicamente reemitiendo uno nuevo (reenvío), y verificamos que solo el código vigente funcione.

Se marca completado al leer el 80%.

Comentarios (3)

Se guardan solo en tu navegador.

  • Ignacio Vera6 oct

    Aplicamos el patrón de cancelar al reenviar y los tickets de «me llegaron dos códigos y ninguno funciona» bajaron a casi cero, porque ahora el mensaje dice explícitamente que reemplaza al anterior.

  • Valentina Soto7 oct

    ¿Recomiendan guardar el historial de transiciones o basta el estado final?

    • Equipo verificaOTP7 oct

      Guarda las transiciones con timestamp. Para anti-fraude y para responder reclamos es oro.