# SDD 07 — Bus de init y de agente

El sistema se controla por **tuberías UNIX puras**, no por parseo de archivos `.service`
complejos. Hay dos canales, con propósitos distintos:

1. **`/run/init.control`** — FIFO de control **humano**, texto crudo. Ergonomía máxima.
2. **`/run/agent.sock`** — socket de control de **agente** (IA, scripts), JSON-líneas con
   framing y autenticación. Parseable y fiable.

## 1. El init por eventos UNIX

Tu init no lee configuraciones pesadas: expone una API por FIFO. Cualquier proceso —un script,
un binario, o tú tecleando— controla el estado del sistema enviando bytes crudos:

```sh
echo "restart network" > /run/init.control
echo "start web"       > /run/init.control
echo "stop  web"       > /run/init.control
```

Los servicios no se declaran en archivos pesados; se **inyectan dinámicamente**. El estado del
sistema es un flujo vivo y maleable que manipulas con herramientas estándar (`cat`, `echo`,
`grep`). Los servicios viven como directorios con un script `run` ejecutable (estilo s6/runit),
no como unidades declarativas opacas:

```
/etc/service/web/run        # script ejecutable; el init lo supervisa
/etc/service/network/run
```

## 2. Por qué un segundo canal para la IA

El FIFO crudo es perfecto para humanos pero malo como API de máquina: no tiene framing fiable,
ni forma de devolver eventos correlacionados, ni de saber **quién** habla. La IA necesita:

- enviar comandos estructurados y recibir **eventos** correlacionados (éxito/fallo de un build,
  crash de un servicio),
- **autenticación** del peer (que no cualquier proceso dispare builds o inyecte binarios),
- un protocolo pequeño, legible y versionado.

Por eso `/run/agent.sock` es un socket UNIX con:

- **framing** = JSON-líneas (un objeto JSON por línea, `\n`-terminado),
- **auth** = `SO_PEERCRED` (UID/GID/PID del peer verificados por el kernel) + capacidades que
  el humano concede explícitamente (ver [SDD 08](08-ai-integration.md)),
- **versión** en el handshake.

## 3. Protocolo del bus de agente

### Handshake

```json
{"t":"hello","ver":1,"client":"claude-agent"}
{"t":"welcome","ver":1,"caps":["compile","query"]}   // caps según lo que el humano concedió
```

### Comandos (cliente → hammerd)

| Comando | Forma | Efecto |
|---|---|---|
| `COMPILE` | `{"t":"compile","recipe":{…}}` o `{"repo","commit","patch","build"}` | dispara un build en el lab |
| `INJECT` | `{"t":"inject","artifact":"b3:…","target":"/bin/grep","overlay":"<id>"}` | hidrata en un overlay (o real si hay cap) |
| `QUERY` | `{"t":"query","what":"file","path":"/etc/network.conf"}` | estado de un archivo/servicio/artefacto |
| `INIT` | `{"t":"init","cmd":"start web"}` | proxy autenticado al control del init |

### Eventos (hammerd → cliente)

| Evento | Forma | Significado |
|---|---|---|
| `BUILD_READY` | `{"t":"build_ready","artifact":"b3:…","recipe":"grep"}` | build terminó OK |
| `BUILD_FAILED` | `{"t":"build_failed","recipe":"grep","log_tail":"…"}` | build falló, con cola de log |
| `CRASHED` | `{"t":"crashed","service":"web","code":127}` | un servicio supervisado murió |
| `MODIFIED` | `{"t":"modified","path":"/bin/grep","by":{…}}` | el diario registró una mutación |

Ejemplo del bucle de autorreparación: la IA modifica el binario del servidor web, este falla
al arrancar; `hammerd` emite `{"t":"crashed","service":"web","code":127}`; la IA, escuchando,
lee el log (texto plano en `/var/log`), corrige la fuente, recompila, y reenvía `start web`.
Para el humano, el sistema "se autorreparó" — pero cada paso quedó en el bus y en el diario.

## 4. Seguridad del bus

- **Sin auth, sin comandos.** Conexión que no completa `hello` válido se cierra.
- **Capacidades mínimas.** Por defecto un agente sólo obtiene `query`. `compile`, `inject` (a
  overlay) e `inject-real` (al FHS real) se conceden explícita y separadamente.
- **`inject-real` es especial.** Inyectar al sistema real (no a overlay) requiere una capacidad
  aparte y, por política, confirmación humana. El flujo recomendado de la IA es siempre overlay
  + `commit` humano.
- **Todo comando con efecto se registra** (en el diario y/o un audit log del bus).

## 5. Interfaz

```rust
// hammerd
pub async fn serve_agent_bus(sock: &Path, caps_policy: CapsPolicy) -> Result<()>;
pub fn init_control_send(line: &str) -> Result<()>;   // escribe en /run/init.control
```

CLI de conveniencia: `hammer ctl "start web"` (humano) · la IA usa el socket directamente.
