# Arquitectura

## Estilo

Monolito modular MVC. MySQL/InnoDB es la fuente autoritativa. Los controladores coordinan casos de uso; los modelos encapsulan consultas y persistencia; los servicios contienen reglas de negocio reutilizables y comprobables sin interfaz.

## Dominios

1. Identidad, organizaciones y acceso.
2. Sedes, salas y eventos.
3. Generación e inventario de cartones.
4. Ventas, pagos manuales y asignación.
5. Sorteo y estado en vivo.
6. Reclamos, premios y pagos.
7. Reportes y auditoría.

## Identidad y autorización

El subsistema RBAC se divide en:

- `Auth`: identidad de sesión y capacidades de alto nivel.
- `AuthorizationService`: resuelve roles efectivos, herencia y permisos.
- `PermissionDecision`: regla determinista de precedencia.
- `Role`, `Permission` y `User`: persistencia y controles de jerarquía.
- middlewares `can`, `can_any` y `can_all`: autorización de rutas.
- helpers `can()`, `can_any()` y `has_role()`: visibilidad coherente en UI.

El modelo permite varios roles por usuario, un rol principal, vigencias, herencia, decisiones `allow/deny` y excepciones directas. La interfaz nunca sustituye al control server-side: toda ruta sensible exige permiso.

## Aislamiento multiempresa

- Cada usuario pertenece a una organización mediante `users.tenant_id`.
- Cada rol pertenece a una organización mediante `roles.tenant_id`.
- Una asignación sólo es válida cuando usuario y rol pertenecen al mismo tenant.
- Consultas administrativas filtran por `Auth::tenantId()`.
- El login acepta `TENANT_SLUG` para evitar ambigüedad cuando un correo existe en varias organizaciones.

## Consistencia de acceso

- La base impide más de un rol principal mediante `primary_guard` y una clave única.
- Las vigencias inválidas son rechazadas en aplicación y base de datos.
- La herencia circular se impide antes de persistir.
- La modificación de una matriz incrementa la versión de autorización de usuarios asignados y descendientes.
- Un cambio global de estado de permiso incrementa la versión de todos los usuarios.
- La sesión revalida usuario, organización, bloqueo y versión en cada solicitud.

## Consistencia operativa

- La venta bloquea el evento y las filas de cartones disponibles.
- Cada cartón sólo puede pertenecer a un `order_item`.
- Cada bola sólo puede aparecer una vez por evento.
- Cada reclamo por cartón y patrón es único.
- Cada reclamo verificado sólo puede producir un payout.
- La extracción conserva número de secuencia, hash anterior y hash actual.

## Sincronización

El tablero y el cartón consultan `/api/events/{slug}/state` cada 1.8 segundos. Para mayor escala puede sustituirse por SSE o WebSocket sin cambiar la fuente de verdad ni las tablas.

## Evolución recomendada

- Redis para caché, rate limiting distribuido y pub/sub.
- Cola para correos, PDFs, exportaciones y webhooks.
- MFA para roles privilegiados.
- Réplica MySQL para reportes.
- Storage S3 compatible para documentos.
- interfaz `PaymentGateway` para proveedores de pago.
- adaptadores de impresora, lector QR y bolillero.
- API versionada y tokens de dispositivo para POS.
