# Contrato WIT

> El contrato entre Orkan y sus módulos: los mundos, lo que exporta un módulo, lo que ofrece el host y qué capacidad exige cada import.

El contrato entre `orkan-server` y un [módulo](https://wiki.itsorkan.com/desarrolladores/modulos/) está escrito en **WIT** y se llama `orkan:module@1.0.0`. Es la fuente de verdad: lo que hay aquí es un resumen.

> **Estado**
>
> Estado
> 
> La versión 1 está en **borrador**: se congela en la puerta de la fase actual del proyecto. Después, solo admite cambios compatibles (1.x).

## Mundos

| Mundo | Qué exporta | Quién lo usa |
| --- | --- | --- |
| `node-module` | `node` | Módulos con pasos. |
| `trigger-module` | `node` y `trigger` | Módulos con pasos y pasos de inicio. |
| `core-module` | Lo anterior, más el import `host-flow` | **Reservado a `orkan.core`.** Un módulo de terceros no puede usarlo. |

## Lo que exporta un módulo

**`node`**

-   `describe`: devuelve un JSON versionado con los pasos, sus parámetros, puertos y tipos de cuenta.
-   `execute`: ejecuta un paso. Recibe el contexto de la ejecución, los parámetros ya resueltos (los datos de pasos anteriores, evaluados), los **slots de cuentas** y los elementos de entrada por puerto.
-   `resolve-options`: opciones dinámicas de un campo (las listas desplegables del editor).
-   `test-credential`: comprueba una cuenta contra el servicio.

**`trigger`** (pasos de inicio)

-   `handle-webhook`: verifica la firma del proveedor y normaliza la petición.
-   `poll`: una consulta periódica. Orkan programa la frecuencia y guarda el cursor.
-   `listen`: escucha cooperativa para conexiones largas (por ejemplo, IMAP IDLE): Orkan llama en bucle, con un plazo por llamada.

## Lo que ofrece el host

| Import | Para qué | Capacidad que exige |
| --- | --- | --- |
| `host-log`, `types` | Escribir registros (Orkan oculta los secretos conocidos y limita el ritmo). | Ninguna |
| `wasi:http/outgoing-handler` | Peticiones HTTP a los servidores permitidos. | `network.http` |
| `wasi:sockets/*` y `host-net` | Conexiones TCP/UDP a los `host:puerto` permitidos. | `network.socket` |
| `host-state` | Guardar estado entre ejecuciones (ámbitos `node`, `workflow` y `module`). | `state` |
| `host-binary` | Leer archivos de los elementos de entrada y crear nuevos. | `binary` |
| `host-ai` | Llamar a modelos de IA de Orkan. | `ai` |
| `host-sql` | Consultas SQL parametrizadas con una cuenta. | `sql` |
| `host-credentials.read-secret` | Leer en claro un campo secreto. Alto riesgo. | `credentials.read-secret` |
| `host-flow` | Esperas, subautomatizaciones y respuestas a enlaces. | `flow` (solo `orkan.core`) |
| `wasi:io`, `clocks`, `random`, `cli/std*` | Lo básico de WASI. | Ninguna |
| `wasi:filesystem/*`, `wasi:cli/environment` | Tolerados, pero **vacíos**: sin directorios ni variables. | Ninguna |

Al instalar un módulo, Orkan inspecciona los imports reales del componente y **rechaza el módulo si falta alguna capacidad por declarar**. `orkan-module build` hace la misma comprobación antes de empaquetar.

## Reglas que fija el contrato

-   Los elementos y los parámetros viajan como **JSON en texto**; los puertos, por índice.
-   El módulo **nunca elige** qué cuenta usa: solo el nombre lógico que declaró. Orkan le pasa un slot y pone la autenticación real justo antes de que la petición salga, por lo que no ve la clave. Esto necesita además la capacidad `credentials.inject`.
-   Un error `transient` puede llevar `retry-after-ms` para respetar los límites de ritmo del servicio.
-   WASI 0.2 no deja que un componente mantenga tareas propias entre llamadas: por eso `listen` es cooperativo y el estado va por `host-state`.

## Errores

Variantes de `node-error` y qué hace Orkan con cada una:

| Variante | Se reintenta |
| --- | --- |
| `user`, `config`, `credential`, `denied` | No |
| `transient` | Sí, respetando `retry-after-ms` |
| `internal` | Sí; no la uses para fallos que se repetirán siempre |

Siguiente: [manifiesto y firma](https://wiki.itsorkan.com/desarrolladores/manifiesto-y-firma/).
