services/api/src/modules/auth/phone-verification.client.js

Overview

Este módulo encapsula la integración con Twilio Verify para verificación telefónica por SMS. Es la única capa del módulo auth que importa el SDK de Twilio, y el servicio de dominio no habla con ese SDK directamente.

Su responsabilidad es iniciar y comprobar verificaciones sin exponer objetos crudos del proveedor. También incluye un mecanismo de sustitución para tests, para evitar llamadas reales a Twilio. fileciteturn0file1turn0file7

[!NOTE] El módulo depende de cuatro variables de entorno de Twilio. Si faltan, responde con 503 y PHONE_VERIFICATION_NOT_CONFIGURED.

How it works

El flujo es pequeño y determinista. Primero revisa si existe un proveedor de prueba. Si no existe, valida la configuración y usa un cliente Twilio cacheado. Después, traduce errores del SDK a ApiError propios del sistema. fileciteturn0file1turn0file4

flowchart TD
    Start[startPhoneVerification]
    Check[checkPhoneVerification]
    Override[providerOverride]
    Config[Twilio env config]
    Client[getClient]
    Twilio[Twilio Verify SDK]
    Error[ApiError]
    TestSet[setPhoneVerificationProviderForTests]
    TestReset[resetPhoneVerificationProviderForTests]

    TestSet --> Override
    TestReset --> Override

    Start -->|override| Override
    Check -->|override| Override

    Start -->|needs config| Config
    Check -->|needs config| Config
    Config --> Client
    Client --> Twilio

    Start -->|send SMS| Twilio
    Check -->|verify code| Twilio

    Twilio -->|send failure| Error
    Twilio -->|check failure| Error

startPhoneVerification crea una verificación SMS para el teléfono ya normalizado por el caller. checkPhoneVerification consulta el estado del código y devuelve solo el status normalizado. Ninguna de las dos funciones devuelve el objeto completo de Twilio. fileciteturn0file4turn0file1

Key components

Estos son los símbolos importantes que exporta el archivo. Cada uno forma parte del borde entre el dominio de autenticación y Twilio.

{
    "title": "setPhoneVerificationProviderForTests",
    "content": "[badge:public] Sustituye el proveedor real por un doble de pruebas. Solo funciona en NODE_ENV test.",
    "type": "function",
    "filePath": "services/api/src/modules/auth/phone-verification.client.js",
    "badges": [
        "public"
    ]
}
{
    "title": "resetPhoneVerificationProviderForTests",
    "content": "[badge:public] Limpia el proveedor de pruebas cuando el entorno actual es test.",
    "type": "function",
    "filePath": "services/api/src/modules/auth/phone-verification.client.js",
    "badges": [
        "public"
    ]
}
{
    "title": "startPhoneVerification",
    "content": "[badge:public] Inicia una verificaci\u00f3n Twilio Verify por SMS para un tel\u00e9fono normalizado. No devuelve el SID ni el OTP.",
    "type": "function",
    "filePath": "services/api/src/modules/auth/phone-verification.client.js",
    "badges": [
        "public"
    ]
}
{
    "title": "checkPhoneVerification",
    "content": "[badge:public] Comprueba un c\u00f3digo SMS contra Twilio Verify y devuelve solo el estado normalizado de la verificaci\u00f3n.",
    "type": "function",
    "filePath": "services/api/src/modules/auth/phone-verification.client.js",
    "badges": [
        "public"
    ]
}

Data & fields

El archivo mantiene dos piezas de estado interno. Ambas viven en memoria del proceso y no se exponen fuera del módulo.

  • client [badge:read-only] Twilio client | null — instancia cacheada del SDK de Twilio.
  • providerOverride [badge:optional] object | undefined — proveedor alternativo usado solo en tests.

El módulo considera configurado el entorno solo si existen estas cuatro variables.

  • env.twilioAccountSid [badge:required] string — Account SID usado al construir el cliente.
  • env.twilioApiKeySid [badge:required] string — SID de la API Key restringida.
  • env.twilioApiKeySecret [badge:required] string — secreto de la API Key restringida.
  • env.twilioVerifyServiceSid [badge:required] string — identificador del Verify Service.

Behaviors

El archivo combina helpers internos y funciones exportadas. Los helpers manejan configuración, cache y errores. Las funciones exportadas ejecutan el flujo de negocio de verificación. fileciteturn0file1turn0file4

  • isConfigured — devuelve true solo si existen todas las credenciales de Twilio requeridas.
  • getClient — crea el cliente Twilio una sola vez y luego reutiliza la instancia.
  • notConfiguredError — construye un ApiError 503 con código PHONE_VERIFICATION_NOT_CONFIGURED.
  • setPhoneVerificationProviderForTests — registra un proveedor falso, pero solo en entorno de test.
  • resetPhoneVerificationProviderForTests — elimina el proveedor falso, pero solo en entorno de test.
  • startPhoneVerification(phone) — inicia una verificación SMS y no devuelve valor útil.
  • checkPhoneVerification(phone, code) — verifica el código y devuelve { status }.

setPhoneVerificationProviderForTests

Esta función existe para tests deterministas. Si NODE_ENV no es test, lanza un error inmediato. El comentario del archivo indica que evita depender de Twilio real. fileciteturn0file1turn0file7

resetPhoneVerificationProviderForTests

Esta función limpia el override únicamente en test. En otros entornos no modifica el estado.

startPhoneVerification

Esta función aplica este orden:

  1. Usa providerOverride.start(phone) si existe.
  2. Comprueba si el entorno está configurado.
  3. Crea una verificación SMS con Twilio Verify.
  4. Convierte cualquier fallo del SDK en un ApiError 502. fileciteturn0file1turn0file4

No persiste el OTP. Tampoco conserva el SID de la verificación. El comentario del archivo dice que Twilio resuelve la comprobación por to, no por SID.

checkPhoneVerification

Esta función sigue el mismo patrón:

  1. Usa providerOverride.check(phone, code) si existe.
  2. Comprueba la configuración.
  3. Llama a verificationChecks.create.
  4. Devuelve { status: result.status }. fileciteturn0file1turn0file4

Si Twilio responde 404, la función normaliza el caso a { status: 'not_found' }. Ese caso representa una verificación inexistente, expirada o ya aprobada.

[!IMPORTANT] El módulo nunca reexpone mensajes crudos del SDK. Los errores se colapsan en ApiError genéricos para evitar fugas de datos del proveedor.

Gotchas & edge cases

[!WARNING] El override de proveedor solo está disponible en tests. En ejecución normal, setPhoneVerificationProviderForTests lanza un error.

[!WARNING] Si faltan credenciales, startPhoneVerification y checkPhoneVerification no intentan contactar Twilio. Ambas fallan con 503 por configuración incompleta.

[!CAUTION] Un 404 de Twilio en checkPhoneVerification no se trata como error técnico. Se traduce a not_found, y el caller debe tratarlo como verificación no aprobada.

[!NOTE] El archivo está alineado con el patrón de otros clientes del módulo auth. Los comentarios lo comparan con google-identity.client.js y notification.client.js. fileciteturn0file1turn0file8

Este archivo se conecta con piezas cercanas del módulo auth. Las relaciones visibles en el código ayudan a entender su lugar en la arquitectura. fileciteturn0file0turn0file2turn0file18

  • services/api/src/modules/auth/phone-verification.service.js usa startPhoneVerification y checkPhoneVerification como capa de dominio.
  • services/api/src/modules/auth/phone-verification.controller.js llama al servicio y no al SDK de Twilio.
  • services/api/src/modules/auth/auth.validation.js valida el cuerpo de las solicitudes de inicio y comprobación.
  • services/api/src/config/env.js provee las credenciales que este módulo lee.
  • services/api/src/utils/apiError.js define el tipo de error usado aquí para fallos de configuración y proveedor.

[!TIP] La separación es estricta: este archivo conoce a Twilio, pero el servicio de dominio no. Esa división aparece explícitamente en los comentarios del código. fileciteturn0file1turn0file0