# CHANGELOG

## [Fase 2.5] — Fortalecimiento del Core — 2026-07-15

Fase de arquitectura pura: **cero cambios de funcionalidad visible**. Todo lo
que funcionaba en la Fase 2 (login, multiempresa, roles/permisos, clientes,
catalogo de servicios, asignacion de servicios a clientes) se probo de
extremo a extremo despues del refactor y se comporta identico.

### Agregado

- **Capa de Servicios** (`app/Services/`): `AuthService`, `CompanyService`,
  `ClientService`, `UserService`, `ServiceService`, `AuditService`,
  `NotificationService`. Los controladores dejaron de contener logica de
  negocio o SQL.
- **Repositories** (`app/Repositories/`): `ClientRepository`,
  `CompanyRepository`, `UserRepository`, `RoleRepository`,
  `PermissionRepository`, `ServiceRepository`, `ClientServiceRepository`,
  `HostingRepository` (preparado, sin uso activo), `QueueRepository`.
  Sustituyen a las antiguas clases estaticas `app/Models/*`.
- **Contenedor de Inyeccion de Dependencias** (`app/Core/Container.php` +
  `app/Core/App.php`): resuelve Services/Repositories/Controllers por
  autowiring via Reflection. El Router ahora crea los controladores con
  `App::make()` en vez de `new`.
- **Sistema de eventos** (`app/Core/Dispatcher.php`, `app/Core/Events/`,
  `app/Core/Listeners/`): `ClientCreated`, `UserCreated`, `ServiceCreated`,
  `CompanyCreated` estan conectados a `AuditTrailListener`, que registra la
  bitacora. `HostingCreated`, `HostingSuspended`, `HostingActivated`,
  `InvoicePaid` quedan definidos y documentados para las Fases 4/5, sin
  ningun disparador todavia.
- **Cola de tareas** (`app/Jobs/`, `app/Repositories/QueueRepository.php`,
  `bin/queue-worker.php`, `storage/queue/`): basada en la tabla `jobs`
  (MySQL). `NotificationService` encola correos en vez de "enviarlos"; el
  job `SendEmailJob` deja constancia en el log tecnico (no hay integracion
  SMTP real todavia, por diseño de esta fase).
- **Integraciones preparadas** (`app/Contracts/`, `app/Integrations/`):
  interfaces `HostingProviderInterface`, `DnsProviderInterface`,
  `SslProviderInterface`, `PaymentGatewayInterface`, `CfdiProviderInterface`,
  y un adaptador esqueleto por proveedor (cPanel/WHM, ResellerPanel,
  Cloudflare, Let's Encrypt, Stripe, PayPal, Mercado Pago, OpenPay, CFDI).
  Ningun adaptador ejecuta llamadas HTTP reales todavia.
- **Sistema de configuracion** (`config/*.php` + `app/Core/Config.php`):
  `app`, `database`, `security`, `mail`, `hosting`, `billing`, `cloudflare`,
  `cpanel`, `resellerpanel`, `payment`, `cfdi`. `Database` y `Session` ya
  leen de aqui en vez de `Env` directamente.
- **Logger centralizado** (`app/Core/Logger.php`): niveles `INFO`,
  `WARNING`, `ERROR`, `CRITICAL`, `SECURITY`; nuevo metodo `Logger::event()`
  con registro estructurado (fecha, usuario, empresa, IP, navegador,
  accion, resultado, duracion).
- **Soft delete generalizado**: `deleted_at`/`deleted_by` en `companies`,
  `users`, `service_plans` (ademas de `clients`, que ya lo tenia desde la
  Fase 1). Eliminar un servicio del catalogo ahora es una baja logica, no
  un `DELETE` fisico.
- **UUID**: columna `uuid` (unica) en `clients`, `companies`, `users`,
  `service_plans`, generada por `app/Core/Uuid.php` (UUID v4 sin
  dependencias externas) en cada alta nueva.
- **Esqueleto de API REST** (`api/v1/`, `public/api.php`, `routes/api.php`,
  `app/Controllers/Api/V1/`): un unico endpoint activo,
  `GET /api/v1/ping`, para verificar el andamiaje. Sin endpoints de
  negocio todavia.
- **Sistema de plugins** (`modules/`, `app/Core/ModuleManager.php`):
  escanea manifiestos `module.json`. Ningun modulo instalado aun.
- **Cache** (`app/Core/Cache/CacheInterface.php` +
  `app/Core/Cache/FileCache.php`): driver inicial de filesystem,
  intercambiable por Redis/APCu/Memcached cambiando un binding en
  `app/bootstrap.php`.
- **Migracion** `database/migrations/003_phase2_5_core_hardening.sql`:
  agrega UUID, soft delete e indices adicionales sobre el esquema de la
  Fase 1/2.

### Cambiado

- `Core\Auth` y `Core\Tenant` dejaron de contener SQL: ahora resuelven sus
  dependencias (`UserRepository`, `RoleRepository`, `CompanyRepository`,
  `AuthService`) via el Container, manteniendo exactamente la misma API
  publica (`Auth::check()`, `Auth::id()`, `Auth::can()`, `Auth::role()`,
  `Auth::logout()`, `Tenant::companyId()`, etc.) para no romper ninguna
  vista ni controlador existente.
- `ServicePlanController` y `ClientServiceController` ahora comparten
  `ServiceService` (antes cada uno llamaba a su propio Model).
- Eliminar un servicio del catalogo (`ServiceService::delete`) paso de un
  `DELETE` fisico bloqueado por FK a una baja logica bloqueada por una
  regla de negocio explicita (`isInUseByAnyClient`). El resultado que ve
  el usuario es identico.

### Eliminado

- `app/Models/*` (6 archivos: `Client`, `Company`, `ClientService`, `Role`,
  `ServicePlan`, `User`) — reemplazados integramente por
  `app/Repositories/*`.
- `app/Core/Model.php` — reemplazado por `app/Core/Repository.php`
  (instanciable, recibe `PDO` por constructor en vez de acceder a
  `Database::connection()` de forma estatica).

### Sin cambios (verificado con pruebas de regresion)

- Login, control de intentos fallidos, CSRF, XSS, sesiones seguras.
- Multiempresa: selector de empresa activa, aislamiento de datos entre
  tenants.
- Roles y permisos: `superadmin`, `admin`, `support` se comportan igual
  (probado explicitamente que `support` sigue bloqueado con 403 en
  `/clients/create`).
- CRUD de clientes, catalogo de servicios, asignacion de servicios a
  clientes, gestion de usuarios.
