Screen · Recuperar contraseña

Recuperar contraseña — flujo de 3 pasos

Entrada desde el link ¿Olvidaste tu clave? del login (A2). Tres pasos: solicitud (celular) → verificación (OTP 6 dígitos, reuso de components-otp-input) → nueva clave (con confirmación y requisitos visibles). El copy de solicitud es anti-enumeración: nunca confirma que la cuenta exista. La pantalla de éxito comunica la consecuencia de seguridad del vault: se cierran las otras sesiones del titular — tono informativo, no punitivo.

/password-recovery 3 pasos · stepper anti-enumeración cierre de otras sesiones post-reset forgot / reset-password
Layout anotado · paso 1 · solicitud

Mismo input de celular que el login (+57 readonly, 10 dígitos). El copy promete el condicional, no el hecho: "si existe una cuenta…" — así la respuesta es idéntica exista o no.

back + stepper 1/3
copy condicional · anti-enum
input celular · reuso A2
CTA · habilita con 10 dígitos
9:41
1 / 3

Recupera tu clave

Si existe una cuenta con este celular, te enviaremos un código de verificación por SMS.

Celular
🇨🇴 +57 312 456 7890
Enviar código

Composición

  1. Stepper 1/3Indicador mono discreto en el app bar (reuso de components-stepper compacto). El back del paso 1 vuelve al login.
  2. Copy condicional"Si existe una cuenta con este celular…" — la pantalla siguiente es la misma exista o no la cuenta. Nunca "no encontramos este número".
  3. Input celular · reusoMismo componente de A2: prefijo +57 readonly, 10 dígitos que empiezan por 3, teclado numérico, CTA disabled hasta válido.
  4. Tras enviarAvanza siempre al paso 2 con el mismo copy — si la cuenta no existe, el SMS simplemente no llega. Rate limit por IP y por número en backend.
Pasos 2 y 3 · OTP y nueva clave

El OTP reusa components-otp-input tal cual (6 cajas, auto-avance, reenvío con countdown). La nueva clave muestra sus requisitos siempre visibles, validados en vivo.

Paso 2 · verificación OTP
9:41
2 / 3

Ingresa el código

Enviamos un código de 6 dígitos por SMS al +57 ******7890.

482
Verificar
Paso 3 · nueva clave
9:41
3 / 3

Crea una clave nueva

La usarás para entrar a MiCapi. Que no sea la de otro servicio.

Nueva clave
••••••••••
Mínimo 8 caracteres
Una mayúscula y una minúscula
Un número
No contiene tu celular
Confirma la clave
••••••
Guardar clave
Éxito · con aviso de seguridad
9:41
Clave actualizada
Ya puedes iniciar sesión con tu clave nueva.

Por tu seguridad, cerramos tus otras sesiones al cambiar la clave. Todo lo demás funciona normal: puedes comprar, vender y recibir.

Iniciar sesión

Regla del vault — aviso de consecuencia de seguridad. El aviso es obligatorio en la pantalla de éxito y se repite en una notificación (centro A-previo). Tono informativo, no punitivo: se explica como protección ("por tu seguridad") y se acota el alcance. Corregido a mano el 2026-08-11 (decisión de William) — mantener en el próximo re-export de Claude Design: el aviso decía «los retiros quedan pausados durante 48 horas», una pausa que no existía en ninguna capa (fichas BE-AUTH-0101 / APP-AUTH-0201) — afirmar en pantalla un control inexistente es información engañosa (Ley 1480 arts. 23-24). No se construyó porque la operación que pausaba (retiro on-chain, F5) no existe, y porque en el riel bancario el control correcto es la titularidad verificada del destino (BE-BANKING-0104), no una pausa. El candado sí está construido en el backend (columna withdrawals_locked_until, sello atómico en el reset, ventana de 48 h) con un centinela que pone el gate en rojo si alguien rutea el retiro sin imponerlo: el aviso de 48 h se restituye junto con F5, y ahí vuelve el contador con su fecha de fin.

Estados · error de OTP y offline
OTP incorrecto
9:41
2 / 3

Ingresa el código

Enviamos un código de 6 dígitos por SMS al +57 ******7890.

482917
Código incorrecto. Te quedan 2 intentos.
Offline · paso 1
9:41
1 / 3
Sin conexión. Intenta cuando vuelva la señal.

Recupera tu clave

Si existe una cuenta con este celular, te enviaremos un código por SMS.

Enviar código

Reglas de estado

  1. OTP · intentos y expiración3 intentos por código; contador visible desde el segundo fallo. Código expira a los 10 min → "Este código expiró. Pide uno nuevo." Reenvío con countdown 60s (reuso components-otp-input).
  2. Anti-enumeración en paso 2Se llega al OTP aunque la cuenta no exista (el SMS no llega). "Reenviar" responde igual en ambos casos.
  3. Requisitos en vivoChecklist valida al escribir: check verde al cumplir, círculo neutro pendiente. La confirmación solo valida al perder foco → "Las claves no coinciden."
  4. LoadingCTAs con spinner inline + "Procesando…". El OTP verifica automáticamente al completar el sexto dígito.
Dark · 360dp
Dark · paso 3
9:41
3 / 3

Crea una clave nueva

La usarás para entrar a MiCapi. Que no sea la de otro servicio.

Nueva clave
••••••••••
Mínimo 8 caracteres
Una mayúscula y una minúscula
Un número
No contiene tu celular
Confirma la clave
••••••
Guardar clave
Dark · éxito
9:41
Clave actualizada
Ya puedes iniciar sesión con tu clave nueva.

Por tu seguridad, cerramos tus otras sesiones al cambiar la clave. Todo lo demás funciona normal: puedes comprar, vender y recibir.

Iniciar sesión
Notas de implementación · Flutter

Flujo forgot / reset + candado de retiros (espera F5)

Endpoints

POST /v1/auth/forgot-password {phone} → 200 siempre (exista o no). POST /v1/auth/reset-password {phone, otp, new_password} → 200 + side-effect: withdrawals_locked_until = now + 48h.

OTP · reuso

Widget de components-otp-input: 6 cajas, auto-focus siguiente, pegar desde SMS (sms_autofill / user consent API en Android), verificación automática al sexto dígito.

Éxito · check dibujado

Check con stroke-dashoffset 420ms ease-standard (canon §4.18); con reduced-motion aparece dibujado. Sin confeti.

Candado de 48 h — construido, sin puerta todavía

El backend sella withdrawals_locked_until y lo expone en /v1/me, pero hoy ninguna operación lo consume: el retiro on-chain (POST /v1/withdrawals/crypto) está en el contrato con x-phase: F5 y no está ruteado. Por eso esta pantalla ya no anuncia la pausa (ver §redline). Cuando F5 exista, el flujo de retiro consume el campo y muestra la hora exacta de desbloqueo, y el aviso vuelve acá. Un centinela del backend pone el gate en rojo si alguien rutea el carril sin imponer el candado.

Sesiones

El reset revoca todas las sesiones activas (visible en A5). El copy de éxito no lo dice aquí para no sobrecargar; se comunica en la notificación de seguridad.

Anti-enumeración

Respuestas uniformes, mismos tiempos (el backend añade jitter). La UI nunca ramifica por existencia de cuenta. Rate limit: 3 solicitudes/hora por número.