# Architect — CLUB-004 ## Objetivo Permitir que un socio anónimo recupere su membresía en un dispositivo nuevo usando códigos de recuperación. ## Diseño ### Flujo 1. **Alta**: al unirse al Club se generan 3 códigos (mostrados una sola vez). 2. **Generar más**: `POST /club/recovery-codes/generate` (autenticado con device token o cuenta). 3. **Listar**: `GET /club/recovery-codes` devuelve códigos activos (fingerprints, nunca plaintext). 4. **Recuperar**: `POST /club/recover` acepta `{ code, newDeviceToken }` → consume código + vincula nuevo dispositivo. ### Formato de código `XXXX-XXXX-XXXX-XXXX-XXXX-XXXX` (6 grupos de 4 chars alfanuméricos, sin I,O,0,1 para legibilidad). ~44 bits de entropía (~10⁹⁶ combinaciones). ### Almacenamiento - `code_hash = SHA-256(plaintext)` — para verificación - `code_fingerprint = SHA-256(UPPER(plaintext))[0:16]` — para lookups rápidos y dedup - `expires_at = now() + 30 días` - `used_at = NULL` initially ### Seguridad - Código hasheado, nunca se guarda plaintext - `FOR UPDATE` en la misma transacción para evitar race conditions - Valida que no esté usado ni caducado antes de vincular ### Endpoints nuevos | Método | Ruta | Auth | Descripción | |--------|------|------|-------------| | POST | `/club/recovery-codes/generate` | device token o sesión | Generar códigos | | GET | `/club/recovery-codes` | device token o sesión | Listar códigos activos | | POST | `/club/recover` | ninguno (código + token) | Recuperar con código |