# Manual técnico — FLEXI Platform

## Arquitectura

Laravel 12/PHP 8.2, Blade, CSS propio y JavaScript vanilla. MySQL/MariaDB en producción; SQLite en desarrollo. Eloquent persiste; Form Requests validan; middleware aplica sesión/roles/cabeceras; Policies protegen usuarios; servicios encapsulan amortización, pagos, notificación y auditoría.

```mermaid
flowchart TB
 Request --> Routes --> Middleware --> Controller
 Controller --> FormRequest
 Controller --> Service
 Service --> Model --> DB[(MySQL)]
 Service --> Mail
 Blade --> Assets
```

## Directorios

| Ruta | Responsabilidad |
|---|---|
| `app/` | Controladores, modelos, políticas, servicios y correo propios |
| `bootstrap/` | Arranque y aliases middleware |
| `config/` | Configuración sin secretos |
| `database/` | Migraciones, factories y seeders solo local/testing |
| `public/` | único Document Root; assets y front controller |
| `resources/` | Blade y fuentes front-end |
| `routes/` | rutas públicas y manager nombradas |
| `storage/` | logs/cache/sesiones; escritura requerida |
| `tests/` | pruebas feature/unit |

## Datos propios

| Tabla | Propósito y relaciones | Datos sensibles / índices |
|---|---|---|
| `users` | personal interno; creador autorreferente | password hash oculto; email/public_id únicos; role/status |
| `clients` | maestro cliente 1:N solicitudes/préstamos | cédula cifrada; HMAC único; public_id único |
| `loan_requests` | solicitud pública auditable, cliente nullable | cédula cifrada, token/request_number/public_id únicos; estados/fecha |
| `loan_request_notes` | notas internas por autor | texto escapado; FK solicitud/usuario |
| `loan_request_status_history` | transición, autor y nota | historial append-only |
| `loan_communications` | email, destinatario, asunto, intentos | sin cuerpo/nota interna; public_id/estado |
| `panel_notifications` | campana por usuario | no contiene cédula; usuario/leída |
| `loans` | snapshot de términos | DECIMAL; public_id/estado; relaciones |
| `loan_installments` | amortización y pago | DECIMAL; loan+number único; fecha/estado |
| `payments` | pago operacional | DECIMAL; public_id; relaciones |
| `audit_logs` | eventos operativos/seguridad | metadata minimizada; acción/entidad |
| `user_invitations` | activación temporal | SHA-256 del token, expiración/uso |
| `contact_messages` | contacto público | PII mínima; fecha |
| framework | sesiones, reset, caché y jobs | acceso DB restringido |

## Rutas y autorización

`MANAGEMENT_ROUTE_PREFIX` determina el prefijo opaco; Blade usa `route('manager...')`. Setup usa otro prefijo. Cambiarlo exige limpiar caché. ULID/public_id alimenta route model binding. `auth`, `active.session`, `role` y `UserPolicy` impiden IDOR; ocultar la URL no es control suficiente.

## Servicios

- `AmortizationCalculator`: cuota nivelada/saldo decreciente, BCMath, centavos y balance final 0.00.
- `LoanCreationService`: transacción y snapshot préstamo/cuotas.
- `PaymentAllocationService`: política provisional FIFO aislada.
- `LoanNotificationService`: historial y entrega interna/cliente/estado; captura SMTP.
- `PanelNotificationService`: notificación persistente por solicitud.
- `IdentityLookup`: HMAC de identidad normalizada con `APP_KEY`.
- `AuditService`: evento y metadata segura.

## Seguridad, correo y finanzas

Password hash no reversible; cifrado Laravel para cédulas; CSRF; CSP; rate limit; honeypot; mass assignment; escape Blade; sesiones por versión. El orden de solicitud es commit DB → panel → email corporativo → confirmación. Fallar SMTP no revierte DB. Dinero usa DECIMAL/string BCMath, nunca float. La tasa nominal anual se divide entre 12 mensual o 24 quincenal; el ajuste final lleva el cierre a 0.00.

