# Manifiesto y firma

> El archivo orkan-module.toml, las capacidades que declara un módulo, cómo se firma el paquete y cómo se publica.

El **manifiesto** `orkan-module.toml` declara qué es el módulo y qué necesita. La **firma** demuestra quién lo ha publicado. Orkan comprueba las dos cosas al instalarlo.

## El manifiesto

```toml
id = "acme.echo"
version = "0.1.0"
name = "Acme echo"
description = "Devuelve la entrada tal cual."
publisher = "acme"
world = "orkan:module/node-module@1.0.0"
min_host_version = "1.0.0"
credential_types = []

[[capabilities]]
kind = "network.http"
allowed_hosts = ["api.example.com"]

[files]
```

| Campo | Notas |
| --- | --- |
| `id` | DNS inverso en minúsculas, con al menos dos segmentos (`acme.echo`). El espacio `orkan.*` está **reservado** a la clave oficial de Gnevoo. |
| `version` | Versión semver del paquete. |
| `name`, `publisher` | Obligatorios. `description` es opcional, pero conviene rellenarla. |
| `world` | `orkan:module/node-module@1.0.0` o `orkan:module/trigger-module@1.0.0`. |
| `min_host_version` | La versión mínima de Orkan que necesita el módulo. |
| `capabilities` | Lista de capacidades, sin repetir. |
| `credential_types` | Tipos de cuenta propios del módulo. |
| `files` | Hash SHA-256 de cada archivo. **Lo rellena `pack`**: no lo escribas a mano. Debe existir la tabla `[files]`, aunque esté vacía. |

Cualquier clave que no sea de esta lista es un error. Los archivos del paquete solo pueden ser `module.wasm` (obligatorio), `README.md`, `LICENSE`, `icon.svg` y lo que cuelgue de `assets/`.

## Capacidades

Una capacidad es un permiso concreto. **Lo que no declares queda denegado**, y si el componente importa algo sin declarar su capacidad, Orkan rechaza el módulo.

| `kind` | Qué desbloquea |
| --- | --- |
| `network.http` | Peticiones HTTP a `allowed_hosts` (nombres exactos, IP o `*.dominio`). |
| `network.socket` | Conexiones TCP/UDP a `allowed_endpoints` (`host:puerto`). |
| `credentials.inject` | Que Orkan ponga la autenticación de la cuenta en la petición, sin que el módulo vea la clave. |
| `credentials.read-secret` | Leer en claro un campo secreto. Es la de más riesgo: úsala solo si la inyección no sirve. |
| `state` | Guardar estado entre ejecuciones. |
| `binary` | Leer y crear archivos. |
| `ai` | Llamar a modelos de IA de Orkan. |
| `sql` | Consultas SQL con una cuenta. |
| `flow` | Solo `orkan.core`. |

Consejos: declara solo lo que el componente importa (`orkan-module build` te lo dice); usa dominios exactos; prefiere `credentials.inject` a `credentials.read-secret`; pide `network.socket` solo para protocolos que no sean HTTP.

**Hosts que aprueba cada instalación.** Un módulo genérico que no conoce sus servidores de antemano puede declarar `hosts = "installation"` en lugar de una lista fija: entonces la lista la aprueba quien administra cada Orkan. Solo vale para módulos oficiales o verificados.

**Quién aprueba qué.** Al instalar, quien administra el Orkan ve las capacidades que pide el módulo. Si una actualización pide **más**, queda pendiente hasta que se aprueben.

## La firma

El paquete lleva `module.sig`: una firma **Ed25519** sobre el hash del manifiesto en su forma canónica. Por eso cualquier cambio en el manifiesto obliga a volver a empaquetar.

```bash
orkan-module keygen --out ./claves
orkan-module pack --key ./claves/<key_id>.pk8
orkan-module verify <id>-<version>.orkmod --trust ./claves/trust.toml
```

-   `keygen` crea `<key_id>.pk8` (clave **privada**, no la compartas ni la subas), `<key_id>.pub` (pública) y `trust.toml`, un almacén de confianza local para `verify`.
-   `pack` calcula los hashes, escribe `module.sig` y genera `<id>-<version>.orkmod`.
-   `verify` comprueba firma, hashes, manifiesto y que las capacidades declaradas cubren los imports.

Niveles de confianza según la clave que firma:

| Nivel | Qué es |
| --- | --- |
| **Oficial** | Firmado con la clave oficial de Gnevoo. Es el único que puede usar `orkan.*`. |
| **Verificado** | Paquete de un desarrollador que ha pasado las comprobaciones y la revisión de Gnevoo. |
| **Privado** | Firmado con la clave de una organización, para su propio Orkan. |
| **Sin firma** | Solo para desarrollo local (`--allow-unsigned`). Nunca en el registro. |

## Publicar

Publicar en el catálogo exige una **invitación de Gnevoo**: [escríbenos](mailto:contact@gnevoo.es). El recorrido es:

1.  **Canjear la invitación** (`orkan-module redeem`): da un token de publicación que se muestra una sola vez. Guárdalo en un archivo con permisos restringidos.
2.  **Registrar tu clave pública** (`orkan-module register-key <clave>.pub`).
3.  **Empaquetar y verificar** (`pack`, `verify`).
4.  **Publicar** (`orkan-module publish <paquete>.orkmod`).
5.  **Revisión**: el staff de Gnevoo revisa el paquete; cuando lo aprueba, entra en el catálogo firmado. Una versión publicada es **inmutable**: para cambiar el código, sube la versión.

`orkan-module list` muestra el estado de tus paquetes. `orkan-module yank` (retirar una versión propia) todavía no está disponible en el registro.

> **Nunca publiques tu clave privada**
>
> Nunca publiques tu clave privada
> 
> Solo se sube el `.orkmod` firmado y, una vez, la clave pública. El token de publicación tampoco va a registros ni al chat.
