# REMEDIACIONES PENDIENTES SOBRE EL SISTEMA EXISTENTE Acciones que **no** puede resolver la API v1 por sí sola porque requieren intervenir el sistema en producción (`/var/www/html/recargas/`) o modificar datos existentes. Ninguna se ha ejecutado. Cada una indica situación, problema, cambio, impacto y rollback. --- ## R-01 · Rotar credenciales expuestas — **URGENTE** **Situación.** `config/config.php` contiene, en texto plano dentro del webroot, la contraseña de la base de datos de producción y las credenciales de MidasRed producción. `CLAUDE.md` (también servible) las reproduce. **Problema.** Cualquier fuga del fuente o un fallo de `AllowOverride` entrega control total: lectura de toda la base y capacidad de ejecutar recargas facturables reales. **Cambio.** Rotar contraseña de BD y credenciales de MidasRed; mover a `.env` fuera del webroot; purgar los valores de `CLAUDE.md` y de cualquier respaldo en el árbol. **Impacto.** Requiere actualizar `config/config.php`, `/etc/recarga.do/api.env` y cualquier otro consumidor de forma coordinada. **Ventana de mantenimiento obligatoria:** la rotación de la contraseña de BD corta todo el sistema hasta que ambos lados coincidan. **Rollback.** Restaurar las credenciales previas en ambos archivos. --- ## R-02 · Hashear los 610 secretos de API en texto plano — **URGENTE** **Situación.** 347 filas de `api_tokens.api_secret` y 263 de `clientes.api_secret` guardan el secreto en claro (prefijo `sk_l…`, 72 caracteres). Solo 2 usan bcrypt. **Problema.** Una sola lectura de la base compromete las credenciales de todos los clientes. **Cambio propuesto, en dos etapas para no romper integraciones:** 1. *Etapa de convivencia (ya soportada).* `Authenticate` acepta ambos formatos y marca `secreto_legado` en el contexto de cada petición. Permite medir cuántos clientes siguen con secreto plano antes de cortar. 2. *Etapa de rotación.* Emitir un secreto nuevo por cliente, entregarlo una sola vez, almacenar únicamente `password_hash()`, y fijar una fecha de corte tras la cual se rechace todo secreto no hasheado. **Impacto.** Cada cliente debe actualizar su credencial. Exige comunicación previa y una ventana de convivencia. **Rollback.** Conservar la columna `api_secret` original hasta completar la migración; revertir es dejar de exigir el formato hasheado. --- ## R-03 · Activar el control de acceso del sistema legado **Situación.** `api/auth_guard.php` está en modo OBSERVE (`AUTH_GUARD_ENFORCE = false`) y solo lo usa `process-recharge.php`. Los otros 18 endpoints de `api/` no verifican pertenencia. **Problema.** Hallazgo C-01: cualquiera puede gastar el saldo de cualquier empresa. **Cambio.** (a) Revisar los logs `[AUTH_GUARD] ok via=…` para confirmar que el tráfico legítimo autentica correctamente. (b) Activar `AUTH_GUARD_ENFORCE = true`. (c) Extender el guard a los 18 endpoints restantes. **Impacto.** Alto y deliberado: cualquier integración que hoy dependa de la falta de control dejará de funcionar. Por eso el paso (a) no es opcional. **Rollback.** Volver `AUTH_GUARD_ENFORCE` a `false`. > **REQUIERE VALIDACIÓN:** cuánto tráfico actual resuelve `via=none`. Determina si se > puede activar directamente o hace falta una migración por fases. --- ## R-04 · Reconstruir el libro mayor de débitos **Situación.** `movimientos_balance` tiene **1** asiento de tipo `debito` frente a 43,123 transacciones completadas por RD$ 5,527,395.94. **Problema.** No existe trazabilidad contable de los cobros. La conciliación es imposible y no puede auditarse ninguna reclamación de cliente. **Cambio.** (a) La API v1 ya asienta todo movimiento. (b) Para el histórico, generar asientos de reconstrucción a partir de `transacciones` en estado `completada`, marcados como tales para no confundirlos con asientos originales. **Impacto.** Solo inserciones; ninguna modificación de datos existentes. **Rollback.** Eliminar los asientos marcados como reconstruidos. > **REQUIERE VALIDACIÓN** del área financiera antes de generar 43,123 asientos retroactivos. --- ## R-05 · Unificar la fuente de verdad del saldo **Situación.** El saldo vive en `empresas.saldo_actual` y en `empresa_balances.saldo_actual`. **96 empresas divergen** en más de RD$0.01. **Problema.** No hay criterio automático para decidir cuál es correcta. **Cambio.** (a) Declarar `empresa_balances` como única fuente de verdad —la API v1 ya lo hace. (b) Conciliar las 96 divergencias una a una contra `movimientos_balance` y los depósitos registrados. (c) Dejar de escribir `empresas.saldo_actual` y, en una fase posterior, marcarla como obsoleta. **Impacto.** El paso (b) exige revisión caso por caso: puede implicar ajustes de saldo real. **Rollback.** No aplica al paso (b): un ajuste de saldo debe corregirse con otro ajuste asentado, nunca revertido en silencio. --- ## R-06 · Resolver las 367 transacciones pendientes **Situación.** 367 transacciones en `pendiente` por RD$ 43,381.00, algunas antiguas. No existe barrido que las concilie, pese a que `checkRechargeStatus($xid)` está implementado. **Problema.** Estado financiero indeterminado: no se sabe si esas recargas se entregaron. **Cambio.** Ejecutar `RechargeService::reconciliar()` sobre cada una e instalar el cron de barrido (ver `DEPLOYMENT.md`). **Impacto.** Puede resultar en cobros legítimos no realizados o en devoluciones pendientes. Conviene procesarlas en lotes pequeños y revisar los resultados. **Rollback.** Cada liquidación queda asentada en `movimientos_balance` y es auditable. > **NO CONFIRMADO:** si MidasRed conserva el estado de transacciones de hace meses. Debe > comprobarse con una muestra antes del lote completo. --- ## R-07 · Endurecer el sistema legado Acciones menores, independientes entre sí: | Acción | Hallazgo | |---|---| | `display_errors = 0` en `api/process-recharge.php` | A-01 | | Dejar de devolver `$e->getMessage()` al cliente | A-02 | | Activar `CURLOPT_SSL_VERIFYPEER` en `MidasRedAPI.php:178` y en `index.php` | A-03 | | Bajar `CURLOPT_TIMEOUT` de 180 s a ~30 s | A-03 | | Rotar `JWT_SECRET` a un valor aleatorio fuera del código | A-04 | | Corregir los 7 `api_secret_hash` truncados | A-05 | | Normalizar los 8 `empresas.ambiente = ''` a `production` | B-02 | | Retirar del webroot los ~40 `test_*.php` / `debug*.php` | B-03 | | Purgar `oauth_states` (55,386 filas) y `proyecto_webhook_logs` (38,417) | — | | Unificar colaciones a `utf8mb4` | B-01 | Todas requieren tocar producción y deben planificarse por separado. --- ## Orden sugerido 1. **R-01** (rotar credenciales) — la exposición es total mientras no se haga. 2. **R-03** (activar control de acceso) — tras verificar los logs. 3. **R-06** (resolver pendientes) — hay dinero en estado indeterminado. 4. **R-02** (hashear secretos) — requiere coordinación con clientes. 5. **R-05** y **R-04** (integridad contable) — requieren validación financiera. 6. **R-07** — endurecimiento incremental.