# Seguridad

## Configuración obligatoria

- Genere una `APP_KEY` aleatoria de al menos 64 caracteres hexadecimales.
- Use `APP_ENV=production`, `APP_DEBUG=false` y `SESSION_SECURE=true` bajo HTTPS.
- No publique `.env` ni exponga el directorio raíz; el DocumentRoot debe ser `public`.
- Restrinja MySQL a la red interna y utilice un usuario con privilegios mínimos.
- Cambie todas las credenciales iniciales.
- Mantenga `TENANT_SLUG` estable y no reutilice slugs entre organizaciones.

## Controles de identidad y acceso

- Contraseñas nativas con `password_hash()` y `password_verify()`.
- Contraseña temporal con cambio obligatorio.
- Bloqueo lógico de cuentas mediante `locked_until`.
- Roles aislados por organización.
- Múltiples roles, herencia y vigencia temporal.
- Mínimo privilegio: ausencia de concesión equivale a denegación.
- Denegaciones explícitas y excepciones directas justificadas.
- Protección contra autoedición y escalamiento de privilegios.
- Rol de recuperación `superadmin` protegido contra cambios estructurales.
- Revalidación de cuenta, tenant y autorización en cada solicitud.

## Protección HTTP

- CSRF en toda operación POST.
- cookies HttpOnly y SameSite Lax.
- sesión con expiración absoluta y regeneración de identificador.
- escape HTML centralizado.
- encabezados básicos de seguridad.
- rate limiting para login y reclamos.

## Auditoría

Se registran, entre otras acciones:

- inicio y cierre de sesión;
- intentos de acceso fallidos;
- creación y cambio de estado de usuarios;
- asignación de roles y excepciones;
- creación y edición de roles;
- actualización de matrices;
- creación, edición y activación de permisos;
- mutaciones operativas críticas.

La auditoría funcional no es inmutable por sí sola. En producción debe exportarse o replicarse hacia almacenamiento WORM/SIEM y protegerse con controles de retención.

## Operación

- Active MFA antes de manejar premios monetarios.
- Exija doble autorización para cambios de premios y pagos de alto valor.
- Mantenga dos cuentas de recuperación bajo custodios separados.
- Revise trimestralmente usuarios, roles, vigencias y excepciones.
- Monitoree intentos fallidos, anulaciones, reclamos y cambios de estado.
- Realice copias diarias y pruebas periódicas de restauración.
- Ejecute `php bin/doctor.php` después de cada despliegue o migración.

## Límites conocidos

- El rate limiting usa archivos locales; en varios nodos debe migrarse a Redis.
- El QR del navegador depende de una biblioteca CDN salvo que se vendorice.
- No se incluye MFA, KYC ni firma criptográfica externa certificada.
- El RNG usa el CSPRNG del sistema mediante PHP, pero no está certificado por laboratorio de juego.
- El acceso al cartón se basa en un token secreto; no sustituye una identidad verificada.

## Compra pública v2.1

- Las órdenes se consultan mediante tokens aleatorios de 256 bits.
- La idempotencia evita dobles órdenes por reenvío del formulario.
- Los cartones se reservan dentro de transacciones InnoDB con bloqueo de fila.
- Los comprobantes no se sirven desde una carpeta pública.
- Sólo caja con `public_orders.view` puede abrir evidencias.
- Sólo `public_orders.manage` puede activar o liberar cartones mediante una decisión.
- Los datos de tarjetas no se solicitan ni almacenan.
- Producción debe ejecutar el cron de expiración, HTTPS y límites de carga del servidor web/PHP.
