# SIGA — Qué hacer ahora (opción B: sin reescritura)

> Hoja de acción concreta para `https://miproyecto.com.co/siga/`.
> La guía completa sigue siendo [DESPLIEGUE.md](DESPLIEGUE.md).

---

## RONDA 11 — Corrección: asignación académica

Tres fallos, una sola causa: la columna `activo` de `curso_asignatura` no se
estaba respetando de forma consistente.

**Sube solo un archivo, sin SQL:**

```
app/Modules/Academico/Services/AsignacionService.php
```

Qué estaba mal y qué hace ahora:

1. **Quitar una asignatura no la quitaba de la lista.** La consulta que arma
   la oferta no filtraba por `activo`, así que la fila seguía apareciendo
   aunque la acción sí la hubiera desactivado. Ahora se filtra.
2. **No dejaba volver a añadir una asignatura ya retirada.** Decía «esa
   asignatura ya está en el curso», porque contaba la fila inactiva. Ahora,
   si la fila existe pero está retirada, **se reactiva** en lugar de
   rechazarla. Insertar otra sería imposible: la clave única es
   (curso, asignatura) sin importar el estado.
3. **Copiar la oferta saltaba los cursos que tuvieran esa asignatura
   retirada.** Ahora también los reactiva.

Ojo con una cosa: al volver a añadir una asignatura retirada, **el docente
titular no vuelve solo**. Hay que asignarlo otra vez, a propósito — igual que
al reactivar un docente.

---

## RONDA 10 — Cuentas administrativas (más superadministradores)

Faltaba: hasta ahora el único superadministrador era el que creó el
instalador, y no había forma de crear otro ni de cambiar roles.

### Sube por FTP (sin SQL)

```
app/Modules/Seguridad/Services/CredencialService.php
app/Modules/Seguridad/Controllers/UsuariosController.php
app/Views/seguridad/usuarios.php
app/Core/Application.php
config/rutas.php
```

### Cómo crear otro superadministrador

**Control → Usuarios** → abre *«Crear una cuenta administrativa»* → elige el
rol **Superadministrador**, escribe los datos de la persona y **la contraseña**.

Si la persona ya existe en el sistema (por ejemplo, un coordinador que además
va a ser superadmin) **no se le crea una segunda cuenta**: se le añade el rol a
la que ya tiene. Dos cuentas para la misma persona es justo lo que rompe la
trazabilidad de la auditoría.

### Administrar una cuenta existente

Botón **Administrar** en cada fila del listado. Desde ahí se puede:

- **Otorgar y quitar roles** (una cuenta no puede quedarse sin ninguno).
- **Activar o desactivar** la cuenta.
- **Levantar el bloqueo** por intentos fallidos, sin cambiar la contraseña.
- **Restablecer la contraseña**.

### Las reglas de seguridad que aplican

- **Solo se administra hacia abajo.** Un coordinador no puede tocar la cuenta
  de un superadmin ni otorgar ese rol: se ascendería a sí mismo en dos clics.
  Un superadmin sí puede crear otros superadmins — que es lo que necesitas.
- **Nadie se administra a sí mismo** por esta vía.
- **Las cuentas privilegiadas (Superadmin, Coordinador) no reciben contraseña
  generada.** La escribes tú y se exige fuerte: mínimo 10 caracteres, con
  mayúscula, minúscula y número. Una cuenta con todos los permisos protegida
  por cuatro dígitos sería la más fácil de adivinar del sistema.
- Todo queda auditado: quién otorgó qué rol, a quién y cuándo. Y los intentos
  rechazados también.

---

## RONDA 9 — Fase 7: boletines

Nos saltamos la Fase 6 (dashboards) a petición tuya. No hay problema: los
boletines dependen de las notas, no de los tableros.

### 1. Sube por FTP

```
database/install/08_fase7_boletines.sql    ← NUEVO (5 columnas de configuración)
app/Modules/Boletines/                     ← NUEVA carpeta completa
app/Views/boletines/                       ← NUEVA carpeta completa
app/Core/Application.php
app/Modules/Institucion/Services/AnioService.php
app/Modules/Institucion/Controllers/AniosController.php
app/Views/institucion/anio_detalle.php
app/Views/layouts/app.php
config/rutas.php
```

### 2. Aplica el SQL

**Control → Actualizar BD**. Esta vez no crea tablas: solo añade la
configuración del boletín al año.

### 3. Configura el boletín

**Institución → Años y periodos → el año**, sección **Boletín**:

- **Organización:** agrupado por área con nota de área, o lista plana de
  asignaturas. Es la decisión DP-05, ahora configurable.
- **Cómo se calcula la nota de área:** ponderada por intensidad horaria (lo
  habitual) o media simple. Con ponderada, un área cuyas asignaturas no
  tengan IH cargada cae sola a media simple.
- Tres interruptores: puesto en el curso, desempeños, gráfica de evolución.

### 4. Genera

**Académico → Boletines** → elige año, periodo y curso. Marca estudiantes e
*Imprimir los marcados*, o *Imprimir el curso completo*.

Se abre una pestaña nueva con los boletines listos. **Ctrl + P** →
*Destino: Guardar como PDF*. Cada estudiante sale en su propia página.

### Por qué no hay "motor de PDF"

SIGA se despliega por FTP sin Composer, así que no hay librería de PDF
disponible. Las que se pueden meter a mano (FPDF) fallan justo en el criterio
de aceptación del plan: `ÑÁÉÍÓÚÜ`. El HTML que produce el navegador da un PDF
con la codificación perfecta, se imprime igual de bien, y 35 boletines no
agotan la memoria del hosting. Según DP-02 la entrega a la familia es física
de todos modos.

### Lo que trae el boletín

Encabezado con escudo, resolución y DANE · datos del estudiante y su curso ·
notas por área y asignatura con su nivel de desempeño · los logros del
periodo (con el texto personalizado si el estudiante tiene uno) ·
observaciones del docente y del director de grupo · promedio, puesto y número
de asignaturas perdidas · gráfica de evolución en SVG · la escala impresa al
pie · tres firmas.

**Legible en blanco y negro:** los desempeños se distinguen por el texto y el
borde, nunca solo por el color. Las asignaturas perdidas van subrayadas.

### Detalle que conviene saber

El **puesto se calcula sobre el curso completo**, aunque imprimas un solo
boletín. Si no, el puesto cambiaría según a quién le imprimas, que sería
absurdo.

Y **no se guarda copia del boletín**: se calcula desde las notas cada vez. Así
los promedios del boletín coinciden siempre con los de la planilla, en vez de
tener dos versiones de la verdad que un día dejan de coincidir.

---

## RONDA 8 — Fase 5: notas, desempeños y recuperaciones

### 1. Sube por FTP

```
database/install/07_fase5_notas.sql        ← NUEVO (6 tablas + 1 columna)
app/Modules/Notas/                         ← NUEVA carpeta completa
app/Views/notas/                           ← NUEVA carpeta completa
app/Core/Application.php
app/Modules/Institucion/Services/AnioService.php
app/Modules/Institucion/Controllers/AniosController.php
app/Views/institucion/anio_detalle.php
app/Views/layouts/app.php
public/assets/js/siga.js
config/rutas.php
```

### 2. Aplica el SQL

**Control → Actualizar BD**. Copia de la base antes: este script además añade
una columna a `anios_academicos`.

### 3. Cómo se usa

1. **Institución → Años y periodos → el año** — abajo hay un selector nuevo:
   **política de recuperación**. Déjalo en «tope en la nota aprobatoria» si no
   tienes claro qué dice el SIEE del colegio.
2. **Abre un periodo** desde esa misma pantalla. Sin periodo abierto no se
   puede calificar, y es a propósito.
3. **Académico → Desempeños** — escribe los logros de la asignatura para ese
   periodo, o cópialos de otro grupo.
4. **Académico → Notas** — crea las actividades del periodo con su peso
   (si solo pones una nota, crea una del 100 %), y califica.

### La pantalla de calificar

- Escribe **`35`** y se guarda **3.5**. **`4`** se guarda **4.0**. **`55`** se
  rechaza. No hay que teclear puntos decimales 32 veces.
- **Enter** o **flecha abajo** bajan al siguiente estudiante de la misma
  columna. Un curso completo se califica sin tocar el ratón.
- El **promedio y el desempeño se actualizan mientras escribes**.
- **Se guarda solo** unos segundos después de dejar de escribir. El botón
  *Guardar todo* fuerza el guardado.
- Si **coordinación cierra el periodo mientras un docente digita**, el
  guardado falla con un mensaje claro y **lo digitado no se pierde**.
- Las actividades **sin calificar no cuentan** para el promedio. Contarlas
  como cero le pondría un 1.0 a todo el curso el primer día.
- **Toda modificación de nota queda en auditoría** con el valor anterior y el
  nuevo.
- Un docente **solo ve y califica sus asignaturas**, y no basta con cambiar el
  número en la URL: se revalida contra la base en cada acción.

### Recuperaciones

Aparecen automáticamente los estudiantes por debajo de la nota aprobatoria.
La nota original **nunca se borra**: se guarda junto a la de recuperación y a
la definitiva que resulta de aplicar la política del año. Y en las tres
políticas, una recuperación nunca deja al estudiante peor que antes.

---

## RONDA 7 — Usuarios, credenciales y correcciones

### 1. Sube por FTP

```
app/Modules/Seguridad/                     ← NUEVA carpeta completa
app/Views/seguridad/                       ← NUEVA carpeta completa
app/Core/Response.php
app/Core/Application.php
app/Modules/Personas/Controllers/AcudientesController.php
app/Views/personas/estudiantes.php
app/Views/personas/acudientes.php
app/Views/layouts/app.php
config/rutas.php
```

Sin SQL: no hay tablas nuevas.

### 2. Sobre exportar usuarios "con su contraseña"

**No se puede, y es a propósito.** SIGA guarda un hash bcrypt, no la
contraseña. Nadie —ni el Superadmin, ni quien entre a la base de datos por
phpMyAdmin— puede leerlas. Es justo lo que hace que un volcado robado de la
base no entregue las cuentas del colegio.

Lo que sí puedes hacer, en **Control → Usuarios**:

- **Exportar CSV del listado**: nombre, documento, usuario, roles, estado,
  último acceso. Sin contraseñas.
- **Crear las cuentas que faltan** por grupo (docentes, acudientes,
  estudiantes). Las contraseñas se generan en ese momento, salen en pantalla
  **una vez**, y se descargan en CSV o se imprimen.
- **Restablecer en lote** todas las contraseñas de un rol. Sirve para el
  arranque del año: generas y repartes. Invalida las claves que estuvieran
  usando, así que confírmalo sabiendo eso.

En los dos últimos casos el CSV se abre bien en Excel (lleva BOM y separador
`;`) y todas las cuentas quedan obligadas a cambiar la clave al entrar.

### 3. Correcciones de la ronda anterior

- **Editar estudiante y acudiente sí existía**, pero el botón decía *Abrir* y
  el formulario quedaba al final de una página larga. Ahora dice **Editar** y
  el enlace salta directo a la ficha.
- **Vincular estudiante ↔ acudiente** ahora se puede desde los dos lados: en
  la ficha del estudiante (como estaba) y en la del acudiente (nuevo). En el
  listado de estudiantes, la columna *Acudientes* es un enlace que lleva
  directo al bloque de vinculación.

---

## RONDA 6 — Fase 4: estudiantes, acudientes y matrícula

### 1. Sube por FTP

```
database/install/06_fase4_matricula.sql    ← NUEVO (5 tablas)
app/Modules/Personas/                      ← NUEVA carpeta completa
app/Views/personas/                        ← NUEVA carpeta completa
app/Core/Application.php
app/Modules/Dashboard/Controllers/DashboardController.php
app/Views/layouts/app.php
config/rutas.php
```

### 2. Aplica el SQL

**Control → Actualizar BD** → *Aplicar actualizaciones pendientes*.
Copia de la base antes, como siempre.

### 3. El flujo, en orden

1. **Personas → Acudientes.** Regístralos primero: al crear el estudiante ya
   podrás vincularlos. Busca SIEMPRE por documento antes de crear.
2. **Personas → Estudiantes.** Busca por documento, crea la ficha, y desde la
   misma ficha vincula sus acudientes con el parentesco.
3. **Personas → Matrícula.** Elige año y curso, y matricula. El código
   (MAT-2026-000001) se genera solo.

El dashboard sube a 100 %.

### Lo que conviene saber

- **Una matrícula nunca se borra.** Se retira, se cancela o se gradúa, y queda
  el motivo, la fecha y quién lo hizo en el historial de la matrícula.
- **Los traslados muestran el impacto antes de confirmar**: si el curso destino
  es de otro grado, o le faltan asignaturas del actual, lo avisa.
- **Los datos de salud del estudiante** (RH, EPS, observaciones médicas) solo
  los ve quien tenga el permiso `estudiantes.ver_sensibles`. Un docente no.
  Y quien no los ve, tampoco los borra al guardar la ficha.
- **La cuenta del acudiente es opcional.** Se puede crear después desde la
  lista, con el botón *Crear cuenta*.

### Lo que NO incluye esta entrega

Dos puntos del plan de la Fase 4 quedaron fuera, a propósito:

- **El wizard de matrícula de 5 pasos con guardado de borrador.** El mismo
  recorrido está resuelto en tres pantallas (acudiente → estudiante →
  matrícula), que es funcionalmente equivalente. El wizard con borrador
  persistente es trabajo aparte; dime si lo quieres y lo hago.
- **El importador masivo desde CSV/Excel.** Estaba marcado [RT]
  (recomendación, no requisito). Tiene sentido montarlo cuando haya que cargar
  el colegio completo de una vez.

---

## RONDA 5 — Fase 3: plan de estudios, docentes y asignación académica

### 1. Sube por FTP

```
database/install/05_fase3_academico.sql    ← NUEVO (4 tablas)
app/Modules/Academico/                     ← NUEVA carpeta completa
app/Views/academico/                       ← NUEVA carpeta completa
app/Core/Application.php
app/Core/BaseController.php
app/Modules/Institucion/Services/EstructuraService.php
app/Modules/Institucion/Controllers/EstructuraController.php
app/Views/institucion/estructura.php
app/Modules/Dashboard/Controllers/DashboardController.php
app/Views/layouts/app.php
public/assets/css/siga.css
config/rutas.php
```

### 2. Aplica el SQL

**Control → Actualizar BD** → *Aplicar actualizaciones pendientes*.
Verás `05_fase3_academico.sql` como pendiente. Saca copia de la base antes.

### 3. Configura, en este orden

1. **Estructura → Áreas y asignaturas.** Pulsa *crear el plan de estudios
   estándar*: crea las nueve áreas de la Ley 115 con sus asignaturas
   habituales. Desactiva lo que el colegio no dicte.
2. **Personas → Docentes.** Registra cada docente. Si dejas marcada la casilla
   de cuenta de acceso, al guardar aparece **una sola vez** el usuario y la
   contraseña: anótalos ahí mismo. El usuario es su número de documento y
   deberá cambiar la clave al entrar.
3. **Estructura → Asignación académica.** Elige un curso, añade sus
   asignaturas con la intensidad horaria, y usa *copiar la oferta* para
   replicarla al resto. Después asigna el docente titular de cada una desde
   el desplegable de la tabla.

Al final, la tabla **Carga por docente** te muestra cuántos cursos, asignaturas
y horas lleva cada uno, y arriba te avisa cuántas asignaturas quedan sin
titular. El dashboard sube a 83 %.

### Lo que ya funciona sin que se vea

- Un docente que entre con su cuenta verá esa misma pantalla, pero **solo con
  sus asignaturas**. El filtro está en la consulta, no en la vista.
- Al desactivar un docente se le retiran las asignaciones y su cuenta deja de
  entrar. Al reactivarlo, las asignaciones **no** vuelven solas: hay que
  reasignarlas a propósito.
- Copiar cursos de un año a otro ahora arrastra también el plan de asignaturas,
  pero nunca los docentes.

---

## RONDA 4 — Fase 2: colegio, años, periodos, grados, cursos y escala

### 1. Sube todo esto por FTP

```
database/install/04_fase2_estructura.sql   ← NUEVO (las tablas)
app/Shared/Support/Migrador.php            ← NUEVO
app/Shared/Support/Validador.php           ← NUEVO
app/Modules/Institucion/                   ← NUEVA carpeta completa
app/Views/institucion/                     ← NUEVA carpeta completa
app/Core/Application.php
app/Core/Request.php
app/Core/BaseController.php
app/Views/layouts/app.php
app/Views/dashboard/index.php
app/Modules/Dashboard/Controllers/DashboardController.php
config/rutas.php
```

### 2. Crea las tablas nuevas

Entra a SIGA y ve a **Control → Actualizar BD** (o directamente a
`…/index.php/actualizar`). Verás `04_fase2_estructura.sql` marcado como
*pendiente*. Pulsa **Aplicar actualizaciones pendientes**.

De aquí en adelante, cada fase se instala así: subir los archivos y pulsar
ese botón. No hace falta phpMyAdmin.

> Antes de aplicar, saca una copia de la base de datos desde cPanel.
> El script es idempotente, pero una copia nunca sobra.

### 3. Configura, en este orden

1. **Institución → Colegio.** NIT, DANE, municipio y rector. Arriba te dice
   qué falta para poder emitir boletines.
2. **Institución → Años y periodos.** Crea el año, con sus fechas y el número
   de periodos. Los periodos y la escala de desempeño se generan solos.
3. En el detalle del año: ajusta fechas y pesos de los periodos (deben sumar
   100 %) y revisa la escala. Cuando no queden avisos, pulsa **Activar año**.
4. **Estructura → Grados y cursos.** Pulsa *crear los grados estándar*
   (los 14 grados colombianos), desactiva los que el colegio no ofrezca, y
   luego *crear los cursos que faltan*.

El dashboard debería pasar de 17 % a 67 %.

---

## RONDA 3 — URGENTE: el `.env` es descargable

Confirmado: `https://miproyecto.com.co/siga/.env` devuelve el archivo con la
contraseña de la base de datos. Hay que cerrarlo **hoy**, y sin depender del
`.htaccess`, que en este hosting es justo lo que no funciona.

La solución es mover la configuración a **`config/entorno.php`**, un archivo
`.php` cuya primera línea es `<?php exit; ?>`. Si alguien lo pide por el
navegador, PHP lo ejecuta y la respuesta sale **vacía** — no hay forma de
descargarlo, funcione o no el `.htaccess`. Y además `config/` ya tiene su
propio `.htaccess`, que sí da 403. Doble barrera, independientes.

### Paso 1 — Sube primero el código (si no, SIGA se queda sin configuración)

```
app/Core/Env.php
app/Core/Config.php
app/Core/Application.php
app/Modules/Instalador/Controllers/InstaladorController.php
.env.example
```

### Paso 2 — Mueve la configuración (cPanel, sin volver a escribir la contraseña)

1. **Administrador de archivos** → carpeta `siga/` (con *Mostrar archivos ocultos*).
2. Selecciona `.env` → botón **Mover** → destino `siga/config/`.
3. Ya dentro de `config/`, selecciona el archivo → **Cambiar nombre** → `entorno.php`.
4. Selecciona `entorno.php` → **Editar** → añade como **primera línea**, sola:

   ```
   <?php exit; ?>
   ```

   El resto del archivo se queda exactamente igual. Guarda.

### Paso 3 — Comprueba

| Dirección | Resultado esperado |
|---|---|
| `…/siga/config/entorno.php` | página **en blanco** (ni contenido ni descarga) |
| `…/siga/.env` | 404: el archivo ya no está ahí |
| `…/siga/` | SIGA entra normalmente |

Si SIGA da error de configuración, es que el archivo no quedó en
`siga/config/entorno.php` o le falta la primera línea.

### Paso 4 — Cambia la contraseña de la base de datos

**Esto no es opcional.** Esa contraseña estuvo publicada en internet, así que
hay que darla por comprometida aunque el sitio sea nuevo.

1. cPanel → **Bases de datos MySQL** → usuario `dyd_demo` → *Cambiar contraseña*.
2. Genera una nueva con el botón *Generador de contraseñas* y guárdala.
3. Vuelve a `config/entorno.php` → **Editar** → pon la nueva en `DB_PASSWORD=`.
4. Recarga SIGA: si entra, quedó bien.

Cambia también el valor de `APP_KEY` (basta con alterar unos cuantos caracteres
al azar). Hoy no firma nada, así que es prevención, no urgencia.

### Paso 5 — Limpia lo temporal

Borra del servidor `siga/public/prueba.php` y `siga/public/diagnostico.php`.

Con esto, `htaccess-RAIZ-solo-proteccion.txt` deja de ser necesario para las
credenciales. Súbelo si quieres, pero ya no es lo que te protege.

---

## RONDA 2 — la instalación ya funcionó, falta el ingreso

Estado: el instalador corrió bien, pero al ir a iniciar sesión sale
«Página no encontrada». Sube estos archivos y vuelve a probar:

| Archivo | Qué cambia |
|---|---|
| `index.php` (en la raíz de `siga/`, **nuevo**) | hace que `https://miproyecto.com.co/siga/` lleve a la aplicación, sin `.htaccess`. También quita el listado de la carpeta. |
| `app/Core/Request.php` | ahora limpia el prefijo también de `PATH_INFO`: hay servidores FastCGI que devuelven ahí la ruta completa (`/siga/public/index.php/ingresar`), y eso hacía que ninguna ruta coincidiera. |
| `app/Core/ErrorHandler.php` | la pantalla 404 recibe datos de diagnóstico. |
| `app/Views/errors/404.php` | añade un desplegable **«Detalles técnicos»** con la ruta detectada. |
| `app/Views/instalador/paso5_finalizado.php` | quita una referencia obsoleta al `.htaccess`. |
| `public/prueba.php` (**reescrito**) | ahora usa sintaxis de PHP antigua, para que no pueda fallar por el lenguaje. Antes daba 500. |

Después:

1. Abre `https://miproyecto.com.co/siga/` — debe llevarte a SIGA.
2. Si vuelve a salir «Página no encontrada», **abre el desplegable “Detalles
   técnicos”** de esa pantalla y mándame lo que dice. Ahí está la respuesta:
   dice qué ruta detectó, de dónde la sacó y con qué `SCRIPT_NAME`.
3. Abre también `https://miproyecto.com.co/siga/public/prueba.php` y pulsa el
   botón de la sección 1. Ahora sí debería cargar.

---

## Qué ha cambiado y por qué

El error 500 venía de los `.htaccess` de reescritura, no del código PHP. En este
hosting, una directiva que `AllowOverride` no permite **no se ignora: tumba toda
la carpeta con un 500**, y por eso caía incluso `diagnostico.php`.

Así que SIGA **ya no necesita `.htaccess` ni `mod_rewrite` para funcionar**. Las
direcciones internas pasan a tener esta forma:

```
https://miproyecto.com.co/siga/public/index.php/ingresar
```

Los `.htaccess` de `app/`, `config/`, `database/`, `storage/` y `tests/`
(los de 295 bytes, los que ya daban 403 correctamente) **se quedan como están**.
Solo desaparecen los dos que reescribían URLs.

---

## Paso 1 — Quitar del servidor los dos `.htaccess` que rompen

En **cPanel → Administrador de archivos**, con *Mostrar archivos ocultos* activado:

| Archivo en el servidor | Acción |
|---|---|
| `siga/.htaccess` | renombrar a `htaccess-viejo.txt` |
| `siga/public/.htaccess` | renombrar a `htaccess-viejo.txt` |

No los borres todavía, solo renómbralos: si algo sale mal, se vuelve atrás en un clic.

**Comprueba ya mismo:** abre `https://miproyecto.com.co/siga/public/diagnostico.php`.
Debería volver a cargar. Si carga, el diagnóstico está confirmado y seguimos.

---

## Paso 2 — Subir los archivos nuevos

Sube por FTP, **sobrescribiendo**:

```
app/Core/Request.php          ← enrutado sin reescritura
app/Core/Application.php      ← pasa $assets a las vistas
app/Views/                    ← carpeta completa (los enlaces a css/js cambian)
public/index.php              ← nueva constante SIGA_ESTILO_URL
public/prueba.php             ← archivo nuevo, temporal
```

En la raíz de `siga/` sobra ya cualquier `htaccess-*.txt` viejo: bórralos para no confundirte.

---

## Paso 3 — Confirmar el estilo de URL

Abre:

```
https://miproyecto.com.co/siga/public/prueba.php
```

Pulsa el botón **“Probar …/prueba.php/prueba-ok”**:

- **La página vuelve a cargar y arriba dice `PATH_INFO recibido: /prueba-ok`**
  → perfecto, no hay que tocar nada. Ve al paso 4.

- **Sale un 404**
  → este hosting no admite PATH_INFO. Abre `public/index.php`, cambia:
  ```php
  define('SIGA_ESTILO_URL', 'ruta');
  ```
  por
  ```php
  define('SIGA_ESTILO_URL', 'consulta');
  ```
  vuelve a subirlo, y las direcciones pasarán a ser
  `…/index.php?_r=/ingresar`. Funciona igual de bien, solo son más feas.

---

## Paso 4 — Instalar

```
https://miproyecto.com.co/siga/public/index.php/instalar
```

(o `…/index.php?_r=/instalar` si tuviste que cambiar al estilo `consulta`).

Sigue los 4 pasos del instalador. Ten a mano el nombre de la base de datos,
el usuario y la contraseña que creaste en cPanel.

---

## Paso 5 — Cerrar el despliegue

1. **Borra del servidor** `siga/public/prueba.php` y `siga/public/diagnostico.php`.
   Exponen información del entorno y ya no hacen falta.

2. **Protege el `.env`.** Al no haber `.htaccess` en `siga/`, el archivo con la
   contraseña de la base de datos es descargable. Comprueba si lo es abriendo
   `https://miproyecto.com.co/siga/.env` — si el navegador lo muestra o lo
   descarga, hay que taparlo:

   - Sube `htaccess-RAIZ-solo-proteccion.txt` a la carpeta `siga/`.
   - Renómbralo a `.htaccess` desde cPanel.
   - Vuelve a abrir `https://miproyecto.com.co/siga/public/index.php`.
     - Si carga → listo, quedó protegido.
     - Si da 500 → renómbralo otra vez a `.txt` y avísame: en ese caso movemos
       las credenciales a `config/`, que ya está protegida y no depende de esto.

3. **Opcional, para más adelante:** si algún día quieres las URLs sin `index.php`,
   están las instrucciones en `public/htaccess-PUBLIC-reescritura-opcional.txt`.
   No es necesario y puede volver a dar 500; no pierdes nada dejándolo como está.

---

## Si algo falla

Pide el **error_log** en cPanel (*Métricas → Errores*, o el archivo `error_log`
dentro de la carpeta). Con un 500 de Apache, ahí aparece la línea exacta
(`.htaccess: <directiva> not allowed here`) y se resuelve al primer intento.
