# Despliegue de LavanderOS en un dominio temporal

## 1. Objetivo y alcance

Publicar una instancia de prueba bajo un subdominio HTTPS estable, sin convertirla todavía en producción comercial. El dominio temporal permitirá validar acceso remoto, celulares, QR, correo, impresoras y posteriormente callbacks OAuth y webhooks.

Ejemplo usado en esta guía: `https://beta.example.com`. Debe sustituirse por el dominio real.

## 2. Requisitos del servidor

- Linux con PHP 8.0 o superior; se recomienda una versión compatible todavía mantenida por el proveedor.
- MySQL o MariaDB con `utf8mb4`.
- Composer 2.
- Apache o Nginx con certificado TLS válido.
- Extensiones PHP requeridas por Yii2, QR y Excel: `ctype`, `curl`, `dom`, `fileinfo`, `gd`, `intl`, `json`, `mbstring`, `mysqlnd`/`pdo_mysql`, `openssl`, `simplexml`, `xml`, `xmlreader`, `xmlwriter`, `zip` y `zlib`.
- Acceso SSH, cron y posibilidad de cambiar el `DocumentRoot`.

El `DocumentRoot` del subdominio debe apuntar exclusivamente a `backend/web`. El repositorio, `.env`, `common`, `console` y `vendor` no deben quedar expuestos como archivos web.

## 3. Preparación recomendada

1. Crear el subdominio y apuntar su DNS al servidor.
2. Configurar su raíz pública como `/ruta/lavansys/backend/web`.
3. Emitir y habilitar el certificado HTTPS.
4. Forzar redirección HTTP a HTTPS.
5. Crear una base vacía y un usuario MySQL exclusivo con permisos sólo sobre esa base.
6. Confirmar que el servidor puede ejecutar procesos de consola con la misma versión de PHP del sitio.

No se utilizará `root` de MySQL en el servidor.

## 4. Publicación inicial

En una instalación nueva:

```bash
git clone https://github.com/luisangel/lavansys.git lavansys
cd lavansys
composer install --no-dev --prefer-dist --optimize-autoloader
php init --env=Production --overwrite=All
cp .env.production.example .env
```

`php init --overwrite=All` se usa sólo durante la primera instalación. Ejecutarlo nuevamente puede reemplazar archivos locales de configuración.

Editar `.env` directamente en el servidor y reemplazar todos los valores de ejemplo. El archivo no debe descargarse a carpetas públicas, enviarse por mensajería ni agregarse a Git.

## 5. Clave de cookies y configuración Yii

Después de inicializar producción, generar una clave aleatoria de al menos 64 caracteres:

```bash
php -r "echo bin2hex(random_bytes(32)), PHP_EOL;"
```

Guardar el resultado en `COOKIE_VALIDATION_KEY` dentro de `.env`. Debe ser diferente de la instalación local. La plantilla Production rechaza claves cortas y configura las cookies de identidad y sesión como `Secure`, `HttpOnly` y `SameSite=Lax`. El archivo `backend/web/index.php` y el comando `yii` generados por Production deben mantener `YII_DEBUG=false` y `YII_ENV='prod'`.

## 6. Variables de entorno

Partir de [`.env.production.example`](../.env.production.example). Para el dominio temporal:

```dotenv
APP_ENV=prod
APP_DEBUG=0
APP_QR_ENTRY_URL="https://beta.example.com/index.php"
```

`APP_QR_ENTRY_URL` debe ser accesible desde el celular que escaneará el código. Al cambiar al dominio definitivo será necesario generar nuevas etiquetas o conservar una redirección permanente desde el dominio temporal.

Mercado Pago permanecerá en `sandbox`. Las credenciales de plataforma y las futuras conexiones OAuth por lavandería se configurarán cuando se implemente esa fase.

## 7. Directorios escribibles

El usuario con el que corre PHP necesita escritura únicamente donde la aplicación genera contenido:

```text
backend/runtime
backend/web/assets
backend/web/uploads
console/runtime
```

Crear `backend/web/uploads` si aún no existe. Como referencia:

```bash
mkdir -p backend/runtime backend/web/assets backend/web/uploads console/runtime
chmod -R 775 backend/runtime backend/web/assets backend/web/uploads console/runtime
```

La propiedad debe asignarse al usuario/grupo real del servicio web. No utilizar permisos `777`.

## 8. Base de datos y RBAC

Con `.env` ya configurado:

```bash
php yii migrate --migrationPath=@yii/rbac/migrations --interactive=0
php yii migrate --interactive=0
php yii rbac/init
php yii user/create-admin
```

En una base completamente vacía las migraciones RBAC se aplican primero porque las migraciones de la aplicación registran permisos y asignaciones. En una actualización, conservar un respaldo y ejecutar después únicamente las migraciones pendientes.

Los comandos de creación de datos demo están bloqueados cuando `APP_ENV` no es `dev` y no deben utilizarse en el servidor.

## 9. Apache y Nginx

La configuración debe:

- servir `backend/web/index.php` como entrada;
- impedir listado de directorios;
- respetar el archivo `.htaccess` si se usa Apache;
- limitar el tamaño de cargas según la validación de logotipos;
- enviar `X-Content-Type-Options`, `Referrer-Policy` y una política de frames adecuada;
- marcar cookies de sesión e identidad como `Secure`, `HttpOnly` y `SameSite=Lax` bajo HTTPS;
- no exponer errores PHP al navegador.

Antes del piloto se endurecerán estos encabezados y cookies en la configuración de producción del proyecto.

## 10. Correo

Configurar `MAILER_DSN`, remitente y direcciones administrativas desde `.env`. La contraseña de aplicación de Gmail debe tratarse como secreto y rotarse si alguna vez fue expuesta.

Antes de habilitar correos masivos:

1. enviar una activación a una cuenta controlada;
2. verificar remitente, enlaces HTTPS y codificación;
3. confirmar que no aparezcan contraseñas ni tokens en logs;
4. configurar SPF, DKIM y DMARC cuando exista el dominio definitivo.

## 11. Cron

Ejecutar diariamente la generación de notificaciones de pruebas próximas a vencer:

```cron
15 7 * * * cd /ruta/lavansys && /usr/bin/php yii notification/generate 3 >/dev/null 2>&1
```

Usar rutas absolutas reales. Los errores deben dirigirse a un log protegido o a un sistema de monitoreo; no deben descartarse de forma permanente después del piloto.

## 12. Proceso de actualización

Para cada versión:

1. crear respaldo de base y archivos subidos;
2. activar una ventana de mantenimiento si la migración lo requiere;
3. ejecutar `git pull --ff-only` sobre la rama aprobada;
4. ejecutar `composer install --no-dev --prefer-dist --optimize-autoloader`;
5. ejecutar `php yii migrate --interactive=0`;
6. ejecutar `php yii rbac/init` cuando cambie el catálogo de permisos;
7. limpiar/publicar assets sólo mediante mecanismos no destructivos;
8. ejecutar pruebas de humo y retirar mantenimiento.

Nunca utilizar `git reset --hard` para desplegar ni sobrescribir `.env`, cargas o configuración local.

## 13. Lista de verificación

### Seguridad

- [ ] HTTPS válido y HTTP redirigido.
- [ ] `DocumentRoot` apunta a `backend/web`.
- [ ] `.env`, `.git`, logs y respaldos no son descargables.
- [ ] `YII_DEBUG=false` y `YII_ENV=prod`.
- [ ] Clave de cookies única.
- [ ] Usuario MySQL exclusivo, sin privilegios globales.
- [ ] Contraseñas demo cambiadas o cuentas demo inexistentes.
- [ ] Permisos de archivos sin `777`.

### Funcionalidad

- [ ] Inicio y cierre de sesión.
- [ ] Roles y menús correctos.
- [ ] Alta de lavandería y propietario.
- [ ] Apertura/cierre de caja.
- [ ] Creación, pago, impresión y entrega de orden.
- [ ] Logo y cargas persistentes después de actualizar.
- [ ] QR abre la orden desde un celular externo.
- [ ] Exportación Excel.
- [ ] Correos de activación y bienvenida.
- [ ] Cron de notificaciones.

### Operación

- [ ] Respaldo probado y restauración ensayada.
- [ ] Logs protegidos y con rotación.
- [ ] Espacio en disco y base monitorizados.
- [ ] Fecha, hora y zona horaria verificadas.
- [ ] Procedimiento de reversión documentado.

## 14. Mercado Pago en el dominio temporal

El dominio temporal con HTTPS puede utilizarse para probar OAuth y webhooks. Las URLs registradas en Mercado Pago deberán coincidir exactamente con las rutas publicadas. Al migrar al dominio definitivo habrá que actualizar callbacks, webhooks y variables del servidor.

Durante las primeras pruebas no se acreditará una orden por el simple retorno del navegador. Sólo una consulta autenticada o un webhook firmado e idempotente podrá confirmar el pago.
