# Actualización en cPanel · NimiApps 0.1.0 → 0.2.0 (ENT-002)

Este manual actualiza la instalación de **staging** que ya funciona con la
versión 0.1.0 (ENT-001). No es una instalación nueva: se conservan `.env`, la
base de datos, `storage/` (logs, sesiones, caché de archivos), `vendor/` y los
dos `.htaccess` del servidor.

Datos de esta instalación:

| Dato                     | Valor                                                     |
|--------------------------|-----------------------------------------------------------|
| Usuario de cPanel        | `nimiapss`                                                |
| Carpeta de la aplicación | `/home/nimiapss/public_html/staging.nimiapps.com/`        |
| Document root            | `/home/nimiapss/public_html/staging.nimiapps.com/public/` |
| URL                      | https://staging.nimiapps.com                              |
| PHP                      | 8.3 (ea-php83) · MariaDB 10.6                             |

Tiempo estimado: 20–30 minutos, de los cuales la web está en mantenimiento
unos 5–10.

> **Importante.** No hay vuelta atrás automática. La vuelta atrás se hace con
> las copias de seguridad del paso 5 y el apartado 15 de este manual. No
> continúes si las copias no se han creado bien.

## Índice

1. [Qué cambia y qué no](#1-qué-cambia-y-qué-no)
2. [Contenido del paquete](#2-contenido-del-paquete)
3. [Verificar y subir el ZIP](#3-verificar-y-subir-el-zip)
4. [Comprobar la versión instalada](#4-comprobar-la-versión-instalada)
5. [Copias de seguridad](#5-copias-de-seguridad)
6. [Simulación (sin cambios)](#6-simulación-sin-cambios)
7. [Modo mantenimiento](#7-modo-mantenimiento)
8. [Actualizar los archivos](#8-actualizar-los-archivos)
9. [Cachés y migraciones](#9-cachés-y-migraciones)
10. [Permisos](#10-permisos)
11. [Configurar el correo (SMTP)](#11-configurar-el-correo-smtp)
12. [Crear el primer administrador](#12-crear-el-primer-administrador)
13. [Diagnóstico y fin del mantenimiento](#13-diagnóstico-y-fin-del-mantenimiento)
14. [Comprobaciones en el navegador](#14-comprobaciones-en-el-navegador)
15. [Volver atrás](#15-volver-atrás)
16. [Errores frecuentes](#16-errores-frecuentes)
17. [Limpieza](#17-limpieza)

---

## 1. Qué cambia y qué no

**Se añade o sustituye** (lista exacta en `manifiesto/`):

- Código de la aplicación: autenticación, espacios de trabajo, organizaciones,
  roles, invitaciones, panel y `/admin`.
- 8 migraciones nuevas (`database/migrations/2026_10_21_*`). Solo **añaden**
  tablas y columnas; no borran ni modifican datos.
- Vistas, traducciones (`lang/es`), CSS compilado (`public/build`).
- `config/microapps.php`, `config/auth.php`, `config/mail.php`,
  `config/logging.php`, `routes/web.php`, `bootstrap/app.php`, `.env.example`.
- Documentación (`README.md` y los cuatro documentos de ENT-002).

**No se toca:**

| Elemento                      | Motivo                                                       |
|-------------------------------|--------------------------------------------------------------|
| `.env`                        | Credenciales del servidor. Solo lo editas tú en el paso 11.  |
| `.htaccess` (raíz)            | `Require all denied`: protege la carpeta de la aplicación.   |
| `public/.htaccess`            | Contiene la autorización expresa añadida en el servidor.     |
| `vendor/`                     | ENT-002 no cambia dependencias (`composer.lock` idéntico).   |
| `storage/`, `bootstrap/cache/`| Logs, sesiones y cachés del servidor.                        |
| Base de datos                 | Solo cambia con `migrate` (paso 9), que únicamente añade.    |

El archivo antiguo `public/build/assets/app-c66wexFq.css` queda en el servidor
sin uso (el nuevo `manifest.json` apunta a `app-C0d66-7m.css`). Es inofensivo
y se deja para no borrar nada.

**No hace falta:** Node.js, npm, Composer, Git, ni un proceso de colas. Los
correos se envían en el momento (sin `queue:work`).

## 2. Contenido del paquete

```
nimiapps-v0.2.0-actualizacion/
├── LEEME.txt
├── actualizar.sh                        Script de actualización
├── ACTUALIZACION-CPANEL-ENT-002.md      Este manual
├── ARQUITECTURA-ENT-002.md
├── PRUEBAS-ENT-002.md
├── CAMBIOS-ENT-002.md
├── manifiesto/
│   ├── archivos-nuevos.txt              Archivos que se añaden
│   ├── archivos-modificados.txt         Archivos que se sustituyen
│   ├── ent001-esperado.sha256           Huella que deben tener hoy (0.1.0)
│   └── paquete.sha256                   Huella de cada archivo del paquete
└── archivos/                            Archivos de la versión 0.2.0
```

Qué hace `actualizar.sh`, en orden, deteniéndose ante cualquier error:

1. Se niega a ejecutarse como `root`.
2. Comprueba PHP 8.3 y la integridad del paquete (`paquete.sha256`).
3. Comprueba que la carpeta de destino es una instalación con `artisan`,
   `.env` y `vendor/`, y que la versión instalada es **0.1.0**. Si ya es 0.2.0
   y todo coincide, lo dice y termina sin tocar nada.
4. Exige el modo mantenimiento (salvo con `--simular`).
5. Comprueba que ninguno de los archivos que va a sustituir tiene cambios
   locales respecto a ENT-001, y que no existe ya ningún archivo «nuevo» con
   otro contenido. Si encuentra alguno, **no copia nada** y lo lista.
6. Guarda los archivos que va a sustituir en
   `~/nimiapps-respaldos/actualizacion-ent002-FECHA/`, junto con la lista de
   archivos nuevos y un script `restaurar-archivos.sh`.
7. Copia cada archivo a un nombre temporal y lo renombra (no deja archivos a
   medio escribir). `config/microapps.php` (la versión) se copia el último:
   si algo falla antes, la instalación sigue diciendo 0.1.0 y el script se
   puede repetir.
8. Verifica la huella SHA-256 de todo lo copiado.

No ejecuta migraciones, no borra archivos y no copia la base de datos.

## 3. Verificar y subir el ZIP

### 3.1 En tu ordenador, antes de subirlo

Abre `nimiapps-v0.2.0-actualizacion.zip.sha256` con un editor de texto y
compara la huella con la del ZIP:

- Windows (PowerShell): `Get-FileHash nimiapps-v0.2.0-actualizacion.zip -Algorithm SHA256`
- macOS: `shasum -a 256 nimiapps-v0.2.0-actualizacion.zip`
- Linux: `sha256sum -c nimiapps-v0.2.0-actualizacion.zip.sha256`

### 3.2 Subirlo fuera de public_html

Con el **Administrador de archivos** de cPanel, sube el ZIP y el `.sha256` a
tu carpeta personal **`/home/nimiapss`** (no a `public_html`).

### 3.3 Comprobar y descomprimir por SSH

```bash
cd /home/nimiapss
sha256sum -c nimiapps-v0.2.0-actualizacion.zip.sha256
# Debe decir: nimiapps-v0.2.0-actualizacion.zip: OK

ls -d nimiapps-v0.2.0-actualizacion 2>/dev/null && echo "YA EXISTE: bórrala o renómbrala antes"
unzip -q nimiapps-v0.2.0-actualizacion.zip
ls nimiapps-v0.2.0-actualizacion
```

## 4. Comprobar la versión instalada

Define estas variables en la sesión SSH (se usan en el resto del manual):

```bash
PHP=/opt/cpanel/ea-php83/root/usr/bin/php        # o PHP=php si "php -v" ya da 8.3
APP=/home/nimiapss/public_html/staging.nimiapps.com
PAQ=/home/nimiapss/nimiapps-v0.2.0-actualizacion
$PHP -v | head -1                                  # Debe ser PHP 8.3.x
cd $APP
grep "'version'" config/microapps.php              # Debe decir '0.1.0'
$PHP artisan microapps:check                       # Debe terminar sin errores
```

Si la versión no es `0.1.0`, **detente**: este paquete solo actualiza desde la
0.1.0.

## 5. Copias de seguridad

Las copias se guardan en `/home/nimiapss/nimiapps-respaldos/`, **fuera de
public_html**, para que no se puedan descargar desde la web.

### 5.1 Base de datos

Mira el nombre de la base de datos y del usuario en `.env` (sin mostrar la
contraseña):

```bash
grep -E '^DB_(DATABASE|USERNAME)=' $APP/.env
```

Haz la copia (te pedirá la contraseña de la base de datos, que está en
`DB_PASSWORD` del `.env`):

```bash
mkdir -p ~/nimiapps-respaldos && chmod 700 ~/nimiapps-respaldos
FECHA=$(date +%Y%m%d-%H%M)
mysqldump --single-transaction --routines --triggers --default-character-set=utf8mb4 \
  -u NOMBRE_USUARIO_BD -p NOMBRE_BD > ~/nimiapps-respaldos/bd-antes-ent002-$FECHA.sql
ls -lh ~/nimiapps-respaldos/bd-antes-ent002-$FECHA.sql
tail -1 ~/nimiapps-respaldos/bd-antes-ent002-$FECHA.sql   # Debe ser "-- Dump completed ..."
```

Si prefieres hacerlo sin SSH: cPanel → **phpMyAdmin** → selecciona la base de
datos → **Exportar** → método rápido, formato SQL.

### 5.2 Archivos

Copia completa de la carpeta de la aplicación (incluye `.env`, `vendor/` y los
`.htaccess`):

```bash
tar -czf ~/nimiapps-respaldos/archivos-antes-ent002-$FECHA.tar.gz \
  -C /home/nimiapss/public_html staging.nimiapps.com
ls -lh ~/nimiapps-respaldos/archivos-antes-ent002-$FECHA.tar.gz
chmod 600 ~/nimiapps-respaldos/*
```

Además, cPanel → **Copias de seguridad** permite descargar una copia completa
de la cuenta si quieres una tercera copia.

## 6. Simulación (sin cambios)

```bash
PHP=$PHP bash $PAQ/actualizar.sh $APP --simular
```

Debe terminar con **«Todo listo para actualizar. No se ha modificado nada.»**
Avisará de que la aplicación no está en mantenimiento: es normal en la
simulación.

Si dice **«Modificado localmente»** o **«Ya existe y es distinto»**, no sigas:
esos archivos del servidor no son los de ENT-001. Guárdalos aparte, revisa qué
cambio tienen y consúltalo antes de continuar.

## 7. Modo mantenimiento

```bash
cd $APP
$PHP artisan down
```

La web mostrará la página de mantenimiento (código 503) hasta el paso 13.

## 8. Actualizar los archivos

```bash
PHP=$PHP bash $PAQ/actualizar.sh $APP
```

Debe terminar con **«Archivos actualizados correctamente. La aplicación SIGUE
en modo mantenimiento.»** y mostrar la carpeta de la copia de los archivos
sustituidos (`~/nimiapps-respaldos/actualizacion-ent002-FECHA/`). Anota esa
ruta.

Si se detiene con un error, lee el mensaje: no habrá copiado nada (pasos 1–5)
o te indicará cómo restaurar (paso de copia). La web sigue en mantenimiento.

## 9. Cachés y migraciones

Primero se borran las cachés de configuración y rutas de la 0.1.0, después se
ejecutan las migraciones y al final se generan las cachés nuevas:

```bash
cd $APP
$PHP artisan config:clear
$PHP artisan route:clear
$PHP artisan view:clear
$PHP artisan event:clear
$PHP artisan migrate --force
$PHP artisan optimize
```

`migrate` debe mostrar 8 migraciones `2026_10_21_00000X_...` con `DONE`. La
última (`link_users_to_workspaces`) crea el espacio personal de los usuarios
que ya existieran.

Nunca ejecutes `migrate:fresh`, `migrate:reset` ni `db:wipe` en staging:
borran la base de datos.

Se usan estos comandos en lugar de `optimize:clear` para no vaciar la caché de
la aplicación (tabla `cache`), que guarda, entre otras cosas, los contadores
de intentos de acceso.

## 10. Permisos

Los archivos nuevos se crean con permisos 644 (carpetas 755), que es lo que
espera PHP-FPM en cPanel. Para comprobarlo:

```bash
cd $APP
find app config database lang resources routes public/build -type f ! -perm 644 | head
find app config database lang resources routes public/build -type d ! -perm 755 | head
ls -l .env            # Debe ser -rw------- (600)
```

Si los dos `find` muestran algo, corrígelo con:

```bash
find app config database lang resources routes public/build -type f -exec chmod 644 {} +
find app config database lang resources routes public/build -type d -exec chmod 755 {} +
```

`storage/` y `bootstrap/cache/` no cambian y deben seguir siendo escribibles.

## 11. Configurar el correo (SMTP)

ENT-002 envía correos: verificación de email, recuperación de contraseña,
invitaciones y avisos de seguridad. Sin SMTP la aplicación funciona, pero los
correos no salen del servidor.

### 11.1 Crear la cuenta de correo

cPanel → **Cuentas de correo electrónico** → crea, por ejemplo,
`no-responder@nimiapps.com`. En **Conectar dispositivos** verás el servidor de
salida (normalmente `mail.nimiapps.com`) y los puertos (465 con SSL/TLS o 587
con STARTTLS).

### 11.2 Editar .env

Edita `$APP/.env` con el **Administrador de archivos** (botón *Edit*) o con
`nano $APP/.env`. Cambia o añade solo estas líneas:

```dotenv
MAIL_MAILER=smtp
MAIL_SCHEME=smtps
MAIL_HOST=mail.nimiapps.com
MAIL_PORT=465
MAIL_USERNAME=no-responder@nimiapps.com
MAIL_PASSWORD="contraseña de la cuenta de correo"
MAIL_FROM_ADDRESS="no-responder@nimiapps.com"
MAIL_FROM_NAME="NimiApps"
```

- Con el puerto 587 usa `MAIL_SCHEME=smtp` y `MAIL_PORT=587`.
- Pon la contraseña entre comillas dobles si tiene espacios o `#`.
- Comprueba también que `APP_URL=https://staging.nimiapps.com` (los enlaces de
  los correos se generan con ese valor) y `SESSION_SECURE_COOKIE=true`.
- Opcional: `NIMIAPPS_INVITATION_EXPIRE_HOURS=72` (validez de las invitaciones).
- No es necesario cambiar `APP_NAME`. Si lo cambias, cambia el nombre de la
  cookie de sesión y todas las sesiones abiertas se cierran.

### 11.3 Transporte de pruebas (sin SMTP)

Si todavía no quieres enviar correos reales, deja:

```dotenv
MAIL_MAILER=log
MAIL_LOG_CHANNEL=correo
```

Los correos (con sus enlaces) se escriben en `storage/logs/correo-FECHA.log`.
Ese archivo contiene enlaces válidos de verificación, recuperación e
invitación: bórralo cuando termines las pruebas.

### 11.4 Aplicar y probar

```bash
cd $APP
$PHP artisan config:clear
$PHP artisan optimize
$PHP artisan microapps:correo-prueba tu-email@dominio.com
```

Debe responder «Correo de prueba enviado a ...». Si da error, el mensaje
indica el motivo (autenticación, puerto, certificado) sin mostrar la
contraseña. Revisa también la carpeta de correo no deseado.

## 12. Crear el primer administrador

El acceso a `/admin` solo se concede por SSH. No hay contraseñas por defecto
ni ninguna página pública para hacerse administrador.

**Opción A (recomendada):** regístrate primero en
https://staging.nimiapps.com/registro, confirma el email y después:

```bash
$PHP artisan microapps:admin-crear tu-email@dominio.com
```

El comando muestra la cuenta y pide confirmación.

**Opción B:** crear la cuenta directamente desde SSH (pide nombre, apellidos y
contraseña, que no se muestra):

```bash
$PHP artisan microapps:admin-crear
```

Otros comandos: `microapps:admin-listar` y `microapps:admin-revocar EMAIL`.
`/admin` exige además que el email de la cuenta esté verificado.

## 13. Diagnóstico y fin del mantenimiento

```bash
cd $APP
$PHP artisan microapps:check
```

Debe mostrar `NimiApps 0.2.0 (ENT-002)` y terminar con
**«Resultado: instalación correcta»**. Los avisos posibles y su significado:

| Aviso                                         | Qué hacer                                     |
|-----------------------------------------------|-----------------------------------------------|
| `MAIL_MAILER=log`                             | Normal si aún no has configurado SMTP (11.3). |
| `Administradores de la plataforma: 0`         | Crea uno (paso 12).                           |
| `SESSION_SECURE_COOKIE` / `APP_URL usa https` | Revisa esos valores en `.env`.                |

Cualquier línea `[ERROR]` debe resolverse antes de seguir. Después:

```bash
$PHP artisan up
```

Opcionalmente, comprueba que los archivos coinciden con la 0.2.0:

```bash
sha256sum -c --quiet CHECKSUMS.sha256 && echo "INTEGRIDAD CORRECTA"
```

`CHECKSUMS.sha256` de la 0.2.0 no incluye los dos `.htaccess` (en el servidor
son distintos a propósito) ni `bootstrap/cache/*.php` (los regenera
`optimize`).

## 14. Comprobaciones en el navegador

Mínimo imprescindible (la lista completa está en `PRUEBAS-ENT-002.md`, Parte B):

1. https://staging.nimiapps.com muestra «NimiApps» y «0.2.0».
2. https://staging.nimiapps.com/estado devuelve `"estado":"ok"` y `"version":"0.2.0"`.
3. Registro, correo de verificación, acceso y panel.
4. https://staging.nimiapps.com/.env sigue devolviendo 403/404.

## 15. Volver atrás

No hay vuelta atrás automática. Elige el caso que corresponda. En todos, pon
antes la aplicación en mantenimiento (`$PHP artisan down`).

### 15.1 Falló la copia de archivos (antes de migrar)

```bash
bash ~/nimiapps-respaldos/actualizacion-ent002-FECHA/restaurar-archivos.sh
```

Pide escribir `RESTAURAR`. Devuelve los archivos sustituidos y borra los
archivos nuevos que creó la actualización (pueden quedar carpetas vacías, que
no afectan). Después:

```bash
cd $APP
$PHP artisan config:clear; $PHP artisan route:clear; $PHP artisan view:clear; $PHP artisan event:clear
$PHP artisan optimize
$PHP artisan microapps:check        # Debe decir 0.1.0 (ENT-001)
$PHP artisan up
```

### 15.2 Ya se ejecutaron las migraciones (deshacerlas)

Primero deshaz las 8 migraciones **con los archivos de la 0.2.0 todavía
instalados** (las migraciones están en ellos), y después restaura los archivos:

```bash
cd $APP
$PHP artisan migrate:status | tail -10       # Las 8 últimas deben ser 2026_10_21_*
$PHP artisan migrate:rollback --step=8 --force
bash ~/nimiapps-respaldos/actualizacion-ent002-FECHA/restaurar-archivos.sh
# y los comandos de caché, check y up de 15.1
```

Ten en cuenta que esto **borra las tablas de ENT-002** con su contenido
(organizaciones, miembros, invitaciones, auditoría) y las columnas
`last_name`, `current_workspace_id` y `last_login_at` de `users`. Las cuentas
de usuario se conservan, también las creadas con la 0.2.0.

### 15.3 Restauración completa desde las copias del paso 5

Devuelve archivos y base de datos exactamente al estado anterior. Se pierde
todo lo creado después (cuentas, organizaciones...).

```bash
cd /home/nimiapss/public_html
mv staging.nimiapps.com staging.nimiapps.com.fallida
tar -xzf ~/nimiapps-respaldos/archivos-antes-ent002-FECHA.tar.gz
```

Base de datos: borra las tablas que añadió ENT-002 y carga la copia (que
vuelve a crear las tablas de la 0.1.0 con sus datos):

```bash
mysql -u NOMBRE_USUARIO_BD -p NOMBRE_BD -e "SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS audit_logs, platform_admins, legal_acceptances, workspace_invitations, workspace_memberships, workspaces; SET FOREIGN_KEY_CHECKS=1;"
mysql -u NOMBRE_USUARIO_BD -p NOMBRE_BD < ~/nimiapps-respaldos/bd-antes-ent002-FECHA.sql
cd $APP
$PHP artisan microapps:check        # Debe decir 0.1.0 (ENT-001)
$PHP artisan up
```

Cuando todo funcione, guarda o borra `staging.nimiapps.com.fallida` (contiene
el `.env`: no la dejes indefinidamente dentro de `public_html`).

## 16. Errores frecuentes

| Síntoma                                                  | Causa y solución                                                                 |
|----------------------------------------------------------|----------------------------------------------------------------------------------|
| `actualizar.sh`: «PHP ... es demasiado antiguo»          | Ejecuta con `PHP=/opt/cpanel/ea-php83/root/usr/bin/php bash ...`.                |
| «el paquete está descomprimido dentro de la instalación» | Descomprime el ZIP en `/home/nimiapss`, no en `public_html`.                     |
| «Modificado localmente: ...»                             | Ese archivo se cambió en el servidor. Guárdalo aparte y consúltalo.              |
| Error 500 tras actualizar                                | Revisa `storage/logs/laravel-FECHA.log` y ejecuta los comandos del paso 9.       |
| `Base table or view already exists` en `migrate`         | Una migración se aplicó a medias. No uses `fresh`; consulta antes de seguir.     |
| No llegan los correos                                    | `microapps:correo-prueba`; revisa puerto/esquema y la carpeta de no deseado.     |
| Los enlaces del correo apuntan a otra dirección          | Corrige `APP_URL` en `.env` y ejecuta `config:clear` y `optimize`.               |
| «419 La página ha caducado» al enviar un formulario      | La sesión caducó: recarga. Si pasa siempre, revisa `SESSION_SECURE_COOKIE` y HTTPS. |
| «Demasiados intentos» (429)                              | Límite de intentos. Espera unos minutos.                                        |
| `/admin` responde «Acceso denegado»                      | La cuenta no es administradora o su email no está verificado (paso 12).          |

## 17. Limpieza

Cuando hayas validado la versión:

```bash
rm -rf /home/nimiapss/nimiapps-v0.2.0-actualizacion
rm -f /home/nimiapss/nimiapps-v0.2.0-actualizacion.zip /home/nimiapss/nimiapps-v0.2.0-actualizacion.zip.sha256
```

Conserva `~/nimiapps-respaldos/` al menos hasta la siguiente entrega. Si usaste
el transporte de pruebas, borra `storage/logs/correo-*.log`.
