# Checklist: Lanzamiento a Producción

> Curso **Crear Páginas Web con Lógica de Negocio** · Módulo 06
> Los 35 puntos que separan "me funciona en localhost" de "está cobrando en internet". Imprímelo y táchalo punto por punto el día del lanzamiento.

---

## A. Código listo (antes de desplegar)

- [ ] 1. Búsqueda global de `localhost` en el proyecto: cero resultados en código de producción
- [ ] 2. Toda URL propia sale de `NEXT_PUBLIC_APP_URL`, no está escrita a mano
- [ ] 3. `npm run build` termina sin errores en tu máquina
- [ ] 4. `.env.local` está en `.gitignore` y **nunca** apareció en el historial de git
- [ ] 5. Cero API keys, contraseñas o secretos escritos en el código fuente
- [ ] 6. Los `console.log` de depuración con datos sensibles fueron eliminados

## B. Variables de entorno en el hosting

- [ ] 7. Inventario completo de variables cargado en Vercel (Settings → Environment Variables)
- [ ] 8. Secretos marcados como *Sensitive*
- [ ] 9. Ningún secreto de servidor lleva prefijo `NEXT_PUBLIC_`
- [ ] 10. `SUPABASE_SERVICE_ROLE_KEY` solo se usa en webhooks/crons — jamás en código de navegador
- [ ] 11. `CRON_SECRET` es aleatorio y largo (`openssl rand -hex 32`)
- [ ] 12. Proyecto de Supabase de **producción** separado del de desarrollo

## C. Base de datos

- [ ] 13. RLS activo en todas las tablas (sin alertas en el dashboard)
- [ ] 14. Políticas probadas: un cliente no puede leer citas/pagos ajenos
- [ ] 15. Restricciones (`check`, `unique`, FK) presentes en el proyecto productivo
- [ ] 16. Datos de prueba eliminados del proyecto productivo
- [ ] 17. Backups automáticos verificados en el plan de Supabase

## D. Pagos

- [ ] 18. Cuenta de pasarela aprobada para producción (papeleo del comercio completo)
- [ ] 19. Llaves productivas cargadas (`pub_prod_…`, secretos de producción)
- [ ] 20. URL del webhook actualizada al dominio real en el dashboard de la pasarela
- [ ] 21. Firma de integridad y de eventos verificadas con las llaves nuevas
- [ ] 22. Transacción real de bajo monto probada de punta a punta (y reembolsada si aplica)
- [ ] 23. La cita/pedido se confirma por el **webhook**, no por el redirect

## E. Autenticación

- [ ] 24. Site URL y Redirect URLs de Supabase apuntan al dominio real
- [ ] 25. Registro + verificación de email probados en producción
- [ ] 26. Recuperación de contraseña probada en producción
- [ ] 27. Panel admin inaccesible para cuentas cliente (probado con 2 navegadores)

## F. Dominio, HTTPS y email

- [ ] 28. Dominio conectado en Vercel; `www` y raíz resuelven
- [ ] 29. Candado HTTPS activo (certificado emitido automáticamente)
- [ ] 30. SPF y DKIM del dominio verificados en Resend
- [ ] 31. Email de confirmación llega a **bandeja de entrada** (probar Gmail y Outlook)

## G. Automatizaciones

- [ ] 32. Crons declarados en `vercel.json` y visibles en el dashboard de Vercel
- [ ] 33. Rutas de cron rechazan peticiones sin `CRON_SECRET` (probar con curl)

## H. Post-lanzamiento (primera semana)

- [ ] 34. Revisión diaria de logs (Vercel → Logs, Supabase → Logs): errores 500, webhooks fallidos, envíos caídos
- [ ] 35. Plan de incidentes escrito: qué haces si un pago se aprueba sin confirmar la cita (dónde miras, a quién contactas en la pasarela, cómo confirmas manualmente)

---

## El ciclo de humo final

Con todo tachado, ejecuta la prueba de fuego con un celular real (no el tuyo de desarrollo):

1. Registro con un email nuevo → llega la verificación
2. Reserva de una cita → el horario se bloquea
3. Pago del anticipo → checkout con candado, método local (Nequi/PSE)
4. Vuelta a la app → la cita aparece **confirmada** (lo hizo el webhook)
5. Email de confirmación en bandeja de entrada
6. Recordatorio de WhatsApp programado

Si los 6 pasos pasan: **estás en producción**. 🏁
