# SIGA — Guía de despliegue por FTP

> ⚠️ **Si estás desplegando ahora mismo, empieza por [PASOS-AHORA.md](PASOS-AHORA.md).**
> SIGA ya **no necesita `.htaccess` ni `mod_rewrite`**: las URLs internas son del
> tipo `…/public/index.php/ingresar`. Las secciones de este documento que hablan
> de reescritura describen una configuración opcional.

> **Entrega actual:** Fase 0 + Fase 1 del [plan de desarrollo](docs/propuesta/14-plan-de-desarrollo.md).
> Núcleo técnico, seguridad, identidad, roles, permisos y auditoría.
> El resto de módulos aparece en el menú marcado como *pronto*.

---

## 1. Requisitos del servidor

| Requisito | Mínimo | Recomendado |
|---|---|---|
| PHP | 8.0 | **8.2 o superior** — ver [RG-01](docs/propuesta/00-hallazgos-y-decisiones.md#rg-01--php-80-está-fuera-de-soporte-de-seguridad--crítico) |
| MariaDB / MySQL | MariaDB 10.4 / MySQL 5.7 | MariaDB 10.11 LTS |
| Extensiones obligatorias | `pdo`, `pdo_mysql`, `mbstring`, `json`, `session` | + `gd`, `fileinfo`, `zip`, `openssl` |
| Apache | con `mod_rewrite` | + `mod_headers` |

**No hace falta Composer ni Node.js.** El proyecto no tiene dependencias externas:
autoloader propio, CSS y JS listos para servir.

---

## 2. Qué subir

Sube **todo el proyecto**, salvo:

- ❌ `docs/` — es documentación, no hace falta en el servidor (puedes subirla si quieres)
- ❌ `tests/`
- ❌ `.git/` si existe

El archivo `.env` **no existe todavía**: lo crea el instalador en el paso 2.

---

## 3. Dónde subirlo — elige tu escenario

### Escenario A — el dominio puede apuntar a una subcarpeta *(recomendado)*

Es el más seguro: el código queda fuera del alcance del navegador.

```
/home/tuusuario/
├── siga/
│   ├── app/            ← código
│   ├── config/
│   ├── database/
│   ├── storage/
│   ├── .env            ← lo crea el instalador
│   └── public/         ← 👈 apunta aquí el dominio
│       ├── index.php
│       ├── .htaccess
│       └── assets/
```

En cPanel: *Dominios → Cambiar raíz del documento* → `/home/tuusuario/siga/public`.

### Escenario B — `public_html` es fijo y no se puede cambiar

También funciona. Sube todo dentro de `public_html` (o de una subcarpeta suya):

```
/public_html/
├── app/          ← protegido por su .htaccess
├── config/       ← protegido
├── database/     ← protegido
├── storage/      ← protegido
├── public/
├── .htaccess     ← reescribe todo hacia public/ y bloquea las carpetas internas
└── .env
```

El `.htaccess` de la raíz ya está preparado para esto: redirige las peticiones a
`public/` y devuelve 403 en `app/`, `config/`, `storage/`, `database/` y `tests/`.

> Si lo pones en una subcarpeta (`/public_html/siga/`), el sistema detecta el
> prefijo automáticamente y las rutas siguen funcionando.

---

## 4. Permisos de carpetas

Desde el cliente FTP, clic derecho → *Permisos de archivo*:

| Carpeta | Permisos |
|---|---|
| `storage/` y todas sus subcarpetas | **755** (o **775** si 755 no basta) |
| El resto | 755 carpetas, 644 archivos |

El instalador verifica esto y te dice exactamente cuál falla.

---

## 5. Crear la base de datos

Desde el panel del hosting, antes de instalar:

1. Crea una base de datos **vacía**.
2. Cotejamiento: **`utf8mb4_unicode_ci`**.
   > Esto no es opcional. Con `latin1` o `utf8` (3 bytes) los apellidos con
   > **Ñ** y tildes se corrompen y hay que rehacer la carga de datos.
3. Crea un usuario y **asígnale todos los privilegios sobre esa base**.
4. Anota: nombre de la base, usuario y contraseña.

---

## 6. Ejecutar el instalador

Abre en el navegador la raíz de tu dominio. El sistema detecta que no está
instalado y te lleva a `/instalar`.

| Paso | Qué hace |
|---|---|
| **1 · Requisitos** | Verifica PHP, extensiones y permisos. Lo rojo bloquea, lo ámbar avisa. |
| **2 · Base de datos** | Prueba la conexión **antes** de guardar y crea el archivo `.env`. |
| **3 · Esquema** | Ejecuta los tres scripts de `database/install/`. Es idempotente. |
| **4 · Administrador** | Crea el colegio y tu cuenta Superadmin. |
| **5 · Listo** | Bloquea el instalador y te da la lista de verificación de producción. |

### Si el paso 2 no puede crear el `.env`

Algunos hostings no permiten que PHP escriba en la raíz. En ese caso el
instalador **te muestra el contenido exacto** del archivo: cópialo, guárdalo
como `.env` y súbelo por FTP junto a la carpeta `app/`. Después vuelve a enviar
el formulario.

### Si prefieres cargar el SQL a mano

Importa desde phpMyAdmin, **en este orden**:

```
database/install/01_esquema_base.sql
database/install/02_catalogos.sql
database/install/03_matriz_permisos.sql
```

Luego vuelve al instalador: detecta que el esquema ya existe y sigue al paso 4.

> **Por qué no basta con el SQL:** la contraseña del Superadmin debe pasar por
> `password_hash()` de PHP en tu propio servidor. No puede venir precalculada en
> un archivo `.sql` — sería un hash conocido públicamente.

---

## 7. Verificación después de instalar

Pruebas concretas, en orden. Son los criterios de aceptación de las Fases 0 y 1:

| # | Prueba | Resultado esperado |
|---|---|---|
| 1 | Ingresa con tu documento y contraseña | Entra al dashboard |
| 2 | Mira el bloque *Caracteres del español* del dashboard | Se ve `ñÑáéíóúÁÉÍÓÚüÜ` y `MUÑOZ ÑUSTES ÁVILA` sin símbolos raros |
| 3 | Cierra sesión y falla la contraseña **5 veces** | Al 5º intento: cuenta bloqueada 15 minutos |
| 4 | Abre `tudominio.com/.env` | **403 o 404.** Si muestra el contenido, el despliegue es inseguro |
| 5 | Abre `tudominio.com/app/Core/Database.php` | 403 o 404 |
| 6 | Abre `tudominio.com/storage/logs/` | 403 o 404 |
| 7 | Abre `tudominio.com/una-ruta-inventada` | Página 404 de SIGA con diseño, no error de Apache |
| 8 | Consulta la tabla `auditoria` en phpMyAdmin | Tiene el registro de la instalación con tu nombre |
| 9 | Abre el sistema en el celular | Menú hamburguesa, sin desplazamiento horizontal |
| 10 | Revisa `storage/logs/security-*.log` | Registra los ingresos y los intentos fallidos |

Si algo del 4 al 6 **sí muestra contenido**, el `.htaccess` no se está
aplicando: revisa que `AllowOverride All` esté habilitado, o mueve el proyecto
al Escenario A.

---

## 8. Antes de entregar al colegio

- [ ] **HTTPS activo.** Descomenta el bloque de redirección en `public/.htaccess`
      y pon `SESSION_SECURE=true` en `.env`. Sin HTTPS las contraseñas viajan en claro.
- [ ] `APP_DEBUG=false` en `.env`.
- [ ] Copia de seguridad diaria configurada **y restauración probada una vez**.
- [ ] Cambia `AUTH_PASSWORD_DIGITOS` a `6` si aprobamos esa recomendación
      ([DP-08](docs/propuesta/00-hallazgos-y-decisiones.md#dp-08--la-política-de-contraseñas-tiene-un-riesgo-de-seguridad-real)).

---

## 9. Actualizaciones posteriores

Para cada entrega nueva:

1. Respalda la base de datos.
2. Sube los archivos modificados por FTP (**nunca sobrescribas `.env`**).
3. Si la entrega trae scripts SQL nuevos en `database/install/`, impórtalos en
   phpMyAdmin en orden. La tabla `migraciones` lleva la cuenta de lo ya aplicado.
4. Borra el contenido de `storage/cache/`.

---

## 10. Solución de problemas

| Síntoma | Causa habitual | Solución |
|---|---|---|
| Página en blanco | Error fatal con `display_errors` apagado | Mira `storage/logs/app-*.log` |
| «SIGA no puede arrancar todavía» | Falta `.env` o una variable | El propio mensaje dice cuál |
| Error 500 en todas las rutas | `mod_rewrite` desactivado | Actívalo o pide al hosting `AllowOverride All` |
| 404 en todo menos la portada | El `.htaccess` no se aplica | Verifica que se subió (es un archivo oculto en FTP) |
| Acentos rotos | Cotejamiento de la base | Debe ser `utf8mb4_unicode_ci` |
| «No se pudo conectar» en el paso 2 | Credenciales o host | En algunos hostings el host no es `localhost` sino un nombre propio |
| Sesión que se cae al instante | Carpeta de sesiones sin permisos | Revisa permisos de `storage/` |
| El instalador vuelve a salir | Falta `storage/instalado.lock` | Se crea solo al terminar el paso 4 |
| Quiero reinstalar desde cero | — | Borra `storage/instalado.lock`, vacía la base y vuelve a `/instalar` |

---

## 11. Estructura del proyecto

```
siga/
├── app/
│   ├── Core/            núcleo: enrutador, vistas, BD, sesión, errores
│   ├── Modules/         un directorio por módulo funcional
│   ├── Shared/          servicios transversales: seguridad, auditoría, texto
│   └── Views/           plantillas
├── config/              configuración y definición de rutas
├── database/install/    scripts SQL numerados
├── docs/propuesta/      los 18 documentos de la propuesta aprobada
├── public/              ← única carpeta expuesta a la web
└── storage/             logs, caché, temporales, adjuntos (nunca públicos)
```

**Dónde tocar según lo que necesites:**

| Quiero… | Archivo |
|---|---|
| Cambiar colores o tipografía | `public/assets/css/siga.css` (bloque `:root`) |
| Añadir una ruta | `config/rutas.php` |
| Cambiar permisos de un rol | Tabla `rol_permiso` (es un `UPDATE`, no código) |
| Ajustar el bloqueo por intentos | `.env` → `AUTH_MAX_INTENTOS`, `AUTH_BLOQUEO_MINUTOS` |
| Ver qué pasó | `storage/logs/` y la tabla `auditoria` |
