# modules/matilda/ — Administración de servidores

**Propósito.** Administrar servidores de forma declarativa: se describe
el inventario deseado (hosts, contenedores Docker, vhosts de proxy
inverso) y matilda renderiza la configuración y calcula el plan que
reconcilia el estado actual con el deseado.

## Crates

| crate            | tipo | rol                                                          |
| ---------------- | ---- | ------------------------------------------------------------ |
| `matilda-core`   | lib  | Modelo: `Host`, `Container`, `VHost`, `Inventory`            |
| `matilda-config` | lib  | Renderizado: `Container` → docker-compose / `docker run`; `VHost` → nginx |
| `matilda-plan`   | lib  | Reconciliación: `plan(actual, deseado)` → lista ordenada de `Action`s |
| `matilda-apply`  | lib  | Puente plan→ejecución: `Action`s → `ApplyStep`s (archivos + comandos) y script de shell |

App: `apps/matilda` — demo CLI (`cargo run -p matilda`).

## Flujo

```text
  Inventory (deseado) ──► matilda-config ──► docker-compose.yml + nginx
        │
        └──► matilda-plan ◄── Inventory (actual) ──► Plan { actions }
```

- **Declarativo**: el inventario describe *qué* debe existir; nadie
  ejecuta nada en `core`/`config`/`plan` — son funciones puras.
- **Plan ordenado**: crear contenedores antes que vhosts; eliminar
  vhosts antes que sus contenedores. Determinista (inventario en
  `BTreeMap`).

## Dependencias

- `config` y `plan` ← `matilda-core`. Todos `#![forbid(unsafe_code)]`.
- Cero Docker, cero SSH, cero disco — sólo modelos y strings.

## Crates de ejecución

| crate            | tipo | rol                                                          |
| ---------------- | ---- | ------------------------------------------------------------ |
| `matilda-ghost`  | lib  | Ejecuta los `ApplyStep`s en la máquina destino (escribe archivos, corre comandos) + `dry_run`; reporta paso a paso |
| `matilda-linker` | lib  | Aplica los pasos en un host **remoto** por SSH (`brahman-ssh-multiplex`); mismo `ApplyReport` |

CLI: `apps/matilda` — `example` / `plan` / `script` / `apply`
(local · `--dry-run` · `--host usuario@host` por SSH).

## Estado

`core` + `config` + `plan` + `apply` + `ghost` + `linker` implementados
y verdes (~42 tests) + CLI. La cadena va de la declaración (inventario
JSON) al plan, al script y a la aplicación —local, en seco o remota—.

**Pendiente**: `matilda-discover` (leer el estado actual del servidor —
`docker inspect`, sitios de nginx— para un diff real en vez de partir
de un inventario vacío) y `matilda-app`, el frontend GPUI.
