# Despliegue seguro ICYLAB OS

Este paquete se despliega como una aplicación completa bajo la carpeta `app/`.
No contiene credenciales, documentos operativos, cargas de usuarios ni archivos
generados por facturación.

## Antes de desplegar

1. Rotar las credenciales que estaban en la copia anterior: base de datos,
   Google OAuth/Maps, FACTO sandbox/producción, SMTP y secreto de cron.
2. Respaldar archivos y base de datos.
3. Cerrar temporalmente `ICYLAB_BILLING_PRODUCTION_ISSUE_ENABLED`.
4. Preparar un directorio de evidencia y respaldo fuera de la raíz pública.

## Despliegue

Ejemplo desde la cuenta cPanel, adaptando rutas:

```bash
bash app/ops/deploy_billing_readiness.sh \
  --app-root /home/icyla826/app.icylab.cl \
  --package-root /ruta/al/paquete-extraido \
  --backup-dir /home/icyla826/backups/icylab-YYYYMMDD-HHMMSS \
  --private-config-path /home/icyla826/private_config.php \
  --db-defaults-file /home/icyla826/.my.cnf \
  --db-name NOMBRE_BASE
```

El instalador:

- rechaza paquetes que contengan `core/private_config.php`;
- mueve y verifica la configuración privada fuera del webroot;
- respalda archivos reemplazados y la base de datos;
- pone en cuarentena archivos ajenos al manifiesto;
- pone en cuarentena ejecutables y directivas inesperadas dentro de
  `uploads/`, `storage/` y `assets/uploads/`;
- aplica el overlay limpio y valida la sintaxis PHP disponible en el servidor.

La cuarentena queda dentro del directorio de respaldo. No se elimina
automáticamente.

## Habilitación productiva por etapas

Con emisión cerrada:

```bash
php /home/icyla826/app.icylab.cl/scripts/billing_production_preflight.php \
  --env=production --stage=readiness --strict \
  --json=/ruta/evidencia/preflight-readiness.json
```

Para el primer piloto deben estar configurados y vigentes:

- `ICYLAB_BILLING_PRODUCTION_CANARY_MODE=true`;
- una lista no vacía de tipos documentales permitidos;
- usuarios permitidos;
- clientes permitidos;
- monto máximo positivo;
- frase de confirmación explícita;
- fecha futura de término del piloto.

Después de habilitar emisión y completar esas restricciones:

```bash
php /home/icyla826/app.icylab.cl/scripts/billing_production_preflight.php \
  --env=production --stage=pilot --strict \
  --json=/ruta/evidencia/preflight-pilot.json
```

No emitir si el preflight devuelve algún `FAIL`.

## Conciliación de cotizaciones existentes

Primero sólo contar candidatas:

```bash
php /home/icyla826/app.icylab.cl/scripts/reconcile_quote_invoice_statuses.php \
  --env=production --limit=10000
```

Después del respaldo y del preflight, aplicar:

```bash
php /home/icyla826/app.icylab.cl/scripts/reconcile_quote_invoice_statuses.php \
  --env=production --limit=10000 --apply=RECONCILE_QUOTES
```

La conciliación sólo infiere una relación cuando existe exactamente una
cotización elegible. Los casos ambiguos quedan sin tocar para revisión manual.
Los estados automáticos son `Facturada`, `Esperando pago` y `Pagada`.

## Reversión

Cerrar primero los tres gates productivos. Luego usar el script de rollback
con el mismo directorio de respaldo. La cuarentena no se restaura
automáticamente, para no reintroducir archivos sospechosos.

