Referencia de Tipos de Entrada

Referencia completa de todos los tipos de entrada disponibles en Wippy.

Las entradas se referencian entre sí usando el formato namespace:name. El registro conecta automáticamente las dependencias basándose en estas referencias, asegurando que los recursos se inicialicen en el orden correcto.

Ver También

Runtime de Lua

Tipo Descripción
function.lua Punto de entrada de función Lua
process.lua Proceso Lua de larga duración
workflow.lua Flujo de trabajo Temporal (determinístico)
library.lua Biblioteca Lua compartida
module.lua Interfaz de módulo Lua
function.lua.bc Bytecode de función precompilado
library.lua.bc Bytecode de biblioteca precompilado
process.lua.bc Bytecode de proceso precompilado
workflow.lua.bc Bytecode de workflow precompilado
- name: handler
  kind: function.lua
  source: file://handler.lua
  method: main
  modules:
    - http
    - json
  imports:
    utils: app.lib:helpers  # Importar otra entrada como módulo
Use imports para referenciar otras entradas Lua. Se vuelven disponibles vía require("alias_name") en su código.

Servicios HTTP

Tipo Descripción
http.service Servidor HTTP (enlaza puerto)
http.router Prefijo de ruta y middleware
http.endpoint Endpoint HTTP (método + ruta)
http.static Servicio de archivos estáticos
# Servidor HTTP
- name: gateway
  kind: http.service
  addr: ":8080"
  lifecycle:
    auto_start: true

# Router con middleware
- name: api
  kind: http.router
  meta:
    server: gateway
  prefix: /api
  middleware:
    - cors
    - ratelimit

# Endpoint
- name: users_list
  kind: http.endpoint
  meta:
    router: app:api
  method: GET
  path: /users
  func: list_handler

API Lua: Ver Módulo HTTP

local http = require("http")
local req = http.request()
local resp = http.response()

resp:set_status(200)
resp:write_json({users = get_users()})

Bases de Datos

Tipo Descripción
db.sql.sqlite Base de datos SQLite
db.sql.postgres Base de datos PostgreSQL
db.sql.mysql Base de datos MySQL
db.cdc.postgres Fuente de Change Data Capture de Postgres (ver CDC)
db.cdc.sqlite Fuente de Change Data Capture de SQLite (ver CDC)

SQLite

- name: database
  kind: db.sql.sqlite
  file: "./data/app.db"
  lifecycle:
    auto_start: true

# En memoria para pruebas
- name: testdb
  kind: db.sql.sqlite
  file: ":memory:"

PostgreSQL

- name: database
  kind: db.sql.postgres
  host: localhost
  port: 5432
  database: dbname
  username: user
  password: pass
  options:
    sslmode: disable
  pool:
    max_open: 25
    max_idle: 5
    max_lifetime: "30m"
  lifecycle:
    auto_start: true

MySQL

- name: database
  kind: db.sql.mysql
  host: localhost
  port: 3306
  database: dbname
  username: user
  password: pass
  options:
    parseTime: "true"
  lifecycle:
    auto_start: true

Consulta Database para referencias a secretos ${env:NAME}, opciones TLS y ajuste del pool de conexiones. Cuando cambia un valor respaldado por env detrás de una entrada de base de datos, el pool se intercambia en vivo — los préstamos activos terminan con la configuración de conexión anterior.

API Lua: Ver Módulo SQL

local sql = require("sql")
local db, err = sql.get("app:database")

local rows, err = db:query("SELECT * FROM users WHERE id = ?", user_id)
db:execute("INSERT INTO logs (msg) VALUES (?)", message)

Almacenes Clave-Valor

Tipo Descripción
store.memory Almacén clave-valor en memoria
store.sql Almacén clave-valor respaldado por SQL
store.kv.raft KV replicado en cluster, fuertemente consistente (Raft compartido)
store.kv.crdt KV replicado en cluster, eventualmente consistente (gossip/CRDT)
# Almacén en memoria
- name: cache
  kind: store.memory
  lifecycle:
    auto_start: true

# Almacén respaldado por SQL
- name: persistent_store
  kind: store.sql
  database: app:database
  table_name: kv_store
  lifecycle:
    auto_start: true

# Almacén replicado en cluster (requiere clustering)
- name: deployments
  kind: store.kv.raft
  namespace: deploy

Los tipos store.kv.* requieren que el clustering esté habilitado. Ver Store para los compromisos de consistencia.

API Lua: Ver Módulo Store

local store = require("store")
local s, err = store.get("app:cache")

s:set("user:123", user_data, 3600)  -- TTL en segundos
local data = s:get("user:123")

Colas

Tipo Descripción
queue.driver.memory Driver de cola en memoria
queue.driver.amqp Driver AMQP (RabbitMQ)
queue.driver.sqs Driver AWS SQS
queue.queue Declaración de cola
queue.consumer Consumidor de cola
# Driver
- name: queue_driver
  kind: queue.driver.memory
  lifecycle:
    auto_start: true

# Cola
- name: jobs
  kind: queue.queue
  driver: queue_driver

# Consumidor
- name: job_consumer
  kind: queue.consumer
  queue: app:jobs
  func: job_handler
  concurrency: 4
  prefetch: 10
  lifecycle:
    auto_start: true

API Lua: Ver Módulo Queue

local queue = require("queue")

-- Publicar un mensaje
queue.publish("app:jobs", {task = "process", id = 123})

-- En un handler de consumidor: el cuerpo del mensaje es el argumento del handler
local function main(data)
    -- acceder a los metadatos de entrega mediante el mensaje actual
    local msg = queue.message()
    local id = msg:id()
    local priority = msg:header("priority")
    msg:ack()
end
El func del consumidor se invoca una vez por mensaje con el cuerpo del mensaje como argumento. Use queue.message() dentro del handler para el id() de la entrega, header()/headers() y ack()/nack().

Gestión de Procesos

Tipo Descripción
process.host Host de ejecución de procesos
process.service Proceso supervisado (envuelve process.lua)
terminal.host Host de terminal/CLI
pg.scope Scope de grupo de procesos (ver Grupos de Procesos)
# Host de procesos (donde se ejecutan los procesos)
- name: processes
  kind: process.host
  host:
    workers: 32             # Goroutines worker (por defecto: NumCPU)
    queue_size: 1024        # Capacidad de cola global
    local_queue_size: 256   # Cola por worker
  lifecycle:
    auto_start: true

# Definición de proceso
- name: worker_process
  kind: process.lua
  source: file://worker.lua
  method: main

# Servicio de proceso supervisado
- name: worker
  kind: process.service
  process: app:worker_process
  host: app:processes
  input: ["arg1", "arg2"]
  lifecycle:
    auto_start: true
    restart:
      max_attempts: 10

- name: terminal
  kind: terminal.host
  lifecycle:
    auto_start: true
Use process.service cuando necesite que un proceso se ejecute como servicio supervisado con reinicio automático. El campo process referencia una entrada process.lua.

Actualizar una entrada process.host en vivo reescala host.workers en su lugar — los procesos en ejecución, los PIDs y las colas se preservan. host.queue_size, host.local_queue_size y lifecycle quedan fijados en la construcción: una actualización en vivo que los cambie se rechaza, igual que redimensionar los workers de un host cuyos workers se gestionan por afinidad.

Seguridad de proceso

Las entradas process.lua y process.lua.bc aceptan un bloque security: de nivel superior. Forma parte de la entrada, por lo que se aplica a cada spawn de ese proceso, tanto en process.host como en terminal.host:

- name: worker_process
  kind: process.lua
  source: file://worker.lua
  method: main
  security:
    actor:
      id: system.worker
      meta:
        tenant: acme
    policies:
      - app.security:worker_policy
    groups:
      - app.security:background_jobs
Campo Descripción
actor.id Identidad de actor bajo la que se ejecuta el proceso; reemplaza al actor heredado
actor.meta Atributos del actor que evalúan las políticas
policies IDs de registro (namespace:name) de políticas fusionadas en el scope
groups IDs de registro de grupos de políticas cuyas políticas se fusionan en el scope

La resolución ocurre cuando el proceso arranca y es atómica: si alguna política o grupo listado no puede resolverse, el spawn falla y no se instala ningún contexto parcial. Omitir actor hereda el actor del proceso que hace el spawn; omitir tanto policies como groups hereda su scope. function.lua, function.lua.bc, process.lua y process.lua.bc aceptan todos el bloque.

Una entrada de comando puede además declarar meta.command.security, que se aplica solo cuando la entrada se lanza como comando CLI — ver Seguridad de comandos. No afecta a los spawns ordinarios.

Ver Security.

Temporal (Flujos de Trabajo)

Tipo Descripción
temporal.client Conexión de cliente Temporal
temporal.worker Worker Temporal
- name: temporal_client
  kind: temporal.client
  address: "localhost:7233"
  namespace: "default"
  auth:
    type: none  # none, api_key, mtls
  lifecycle:
    auto_start: true

- name: temporal_worker
  kind: temporal.worker
  client: temporal_client
  task_queue: "main-queue"
  lifecycle:
    auto_start: true

Almacenamiento en la Nube

Tipo Descripción
config.aws Configuración AWS
cloudstorage.s3 Acceso a bucket S3
- name: aws
  kind: config.aws
  region: "us-east-1"
  access_key_id: ${env:AWS_ACCESS_KEY_ID}
  secret_access_key: ${env:AWS_SECRET_ACCESS_KEY}

- name: uploads
  kind: cloudstorage.s3
  config: app:aws
  bucket: "my-uploads"
  endpoint: ""  # Opcional, para servicios compatibles con S3

API Lua: Ver Módulo Cloud Storage

local cloudstorage = require("cloudstorage")
local storage, err = cloudstorage.get("app:uploads")

storage:upload_object("files/doc.pdf", file_content)
local url = storage:presigned_get_url("files/doc.pdf", {expiration = 3600})
Use endpoint para conectarse a servicios compatibles con S3 como MinIO o DigitalOcean Spaces.

Sistemas de Archivos

Tipo Descripción
fs.directory Acceso a directorio
fs.embed Sistema de archivos embebido de solo lectura
- name: data_dir
  kind: fs.directory
  directory: "./data"
  auto_init: true   # Crear si no existe
  mode: "0755"      # Permisos

API Lua: Ver Módulo Filesystem

local fs = require("fs")
local filesystem, err = fs.get("app:data_dir")

local file = filesystem:open("output.txt", "w")
file:write("Hello, World!")
file:close()

Entorno

Tipo Descripción
env.storage.memory Almacén de env en memoria
env.storage.file Almacén de env basado en archivo
env.storage.os Entorno del SO
env.storage.static Almacenamiento estático de solo lectura clave-valor
env.storage.router Router de env (múltiples almacenes)
env.variable Variable de entorno
- name: os_env
  kind: env.storage.os

- name: file_env
  kind: env.storage.file
  file_path: ".env"
  auto_create: true

- name: defaults
  kind: env.storage.static
  values:
    PUBLIC_API_HOST: "https://api.example.com"
    APP_ENV: "production"

- name: app_env
  kind: env.storage.router
  storages:
    - app:os_env
    - app:file_env
    - app:defaults

API Lua: Ver Módulo Env

local env = require("env")

local api_key = env.get("API_KEY")
env.set("CACHE_TTL", "3600")
El router intenta los almacenes en orden. La primera coincidencia gana para lecturas; las escrituras van al primer almacén de la lista.

Plantillas

Tipo Descripción
template.jet Plantilla Jet individual
template.set Configuración de conjunto de plantillas
# Conjunto de plantillas con configuración del motor
- name: templates
  kind: template.set
  engine:
    development_mode: false
    extensions:
      - ".jet"
      - ".html.jet"

# Plantilla individual
- name: email_template
  kind: template.jet
  source: file://templates/email.jet
  set: app:templates

API Lua: Ver Módulo Template

local templates = require("templates")
local set, err = templates.get("app:templates")

local html = set:render("email", {
    user = "Alice",
    message = "Welcome!"
})

Seguridad

Tipo Descripción
security.policy Política de seguridad con condiciones
security.policy.expr Política basada en expresiones
security.token_store Almacén de tokens
# Política basada en condiciones
- name: admin_policy
  kind: security.policy
  policy:
    actions: "*"
    resources: "*"
    effect: allow
    conditions:
      - field: "actor.meta.role"
        operator: eq
        value: "admin"

# Política basada en expresiones
- name: owner_policy
  kind: security.policy.expr
  policy:
    actions: "*"
    resources: "*"
    effect: allow
    expression: 'actor.id == meta.owner_id || actor.meta.role == "admin"'
  groups:
    - operators

Los grupos de políticas los forman las propias políticas: una política lista bajo groups: los IDs de grupo a los que pertenece, y un grupo es el conjunto de políticas que lo nombran. No hay un tipo de entrada de grupo aparte. Los IDs de grupo son IDs de registro — un nombre simple se resuelve en el namespace de la política que lo declara, por lo que operators arriba se convierte en app.security:operators cuando se declara en el namespace app.security. Las entradas referencian grupos por su namespace:name completo.

API Lua: Ver Módulo Security

local security = require("security")

-- Verificar permiso antes de acción
if security.can("delete", "users", {user_id = id}) then
    delete_user(id)
end

-- Obtener actor actual
local actor = security.actor()
Se evalúan todas las políticas en el ámbito. Un deny de cualquier política coincidente prevalece sobre cualquier allow; si no hay ningún deny, un allow coincidente concede el acceso. El orden no importa.

Contratos (Inyección de Dependencias)

Tipo Descripción
contract.definition Interfaz con especificaciones de métodos
contract.binding Mapea métodos de contrato a implementaciones de funciones
# Definir la interfaz del contrato
- name: greeter
  kind: contract.definition
  methods:
    - name: greet
      description: Returns a greeting message
    - name: greet_with_name
      description: Returns a personalized greeting
      input_schemas:
        - format: "application/schema+json"
          definition: {"type": "string"}
      output_schemas:
        - format: "application/schema+json"
          definition: {"type": "string"}

# Funciones de implementación
- name: greeter_greet
  kind: function.lua
  source: file://greeter_greet.lua
  method: main

- name: greeter_greet_name
  kind: function.lua
  source: file://greeter_greet_name.lua
  method: main

# Enlazar métodos del contrato a implementaciones
- name: greeter_impl
  kind: contract.binding
  contracts:
    - contract: app:greeter
      default: true
      methods:
        greet: app:greeter_greet
        greet_with_name: app:greeter_greet_name

Uso desde Lua:

local contract = require("contract")

-- Abrir binding por ID
local greeter, err = contract.open("app:greeter_impl")

-- Llamar métodos
local result = greeter:greet()
local personalized = greeter:greet_with_name("Alice")

-- Verificar si instancia implementa contrato
local is_greeter = contract.is(greeter, "app:greeter")

API Lua: Ver Módulo Contract

Marque un binding como default: true para usarlo cuando se abra un contrato sin especificar un ID de binding. Un contrato solo puede tener un binding por defecto.

Ejecución

Tipo Descripción
exec.native Ejecución de comandos nativos
exec.docker Ejecución de contenedores Docker
- name: native_exec
  kind: exec.native
  default_work_dir: "/app"
  command_whitelist:
    - "ls"
    - "cat"

- name: docker_exec
  kind: exec.docker
  image: "python:3.11-slim"
  default_work_dir: "/workspace"
  auto_remove: true
  memory_limit: 536870912  # 512MB
  command_whitelist:
    - "python"

Runtime WASM

Tipo Descripción
function.wat Función WebAssembly (formato de texto WAT)
function.wasm Función WebAssembly (binario)
process.wasm Proceso WebAssembly
# El texto WAT es source en línea
- name: sum_wat
  kind: function.wat
  source: file://sum.wat
  method: sum
  transport: payload   # o wasi-http

# El WASM binario se carga desde una entrada de filesystem y se verifica por hash
- name: sum
  kind: function.wasm
  fs: app:modules
  path: sum.wasm
  hash: sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
  method: sum
  transport: payload

function.wasm y process.wasm toman fs, path y hash — no hay campo source en una entrada binaria; source pertenece solo a function.wat. hash es obligatorio y debe ser sha256:<hex>; el módulo se rechaza si los bytes no coinciden.

Ver Resumen de WASM.

Redes

Tipo Descripción
network Overlay de red base
network.socks5 Overlay de proxy SOCKS5
network.i2p Overlay de red I2P
network.tailscale Overlay de Tailscale

Referenciado por http.service mediante network:, por funcs/process mediante la opcion network y por http_client mediante la opcion overlay_network. Ver Red.

Primitivas del Registro

Tipo Descripción
registry.entry Entrada de datos simple sin ningún servicio detrás (configuración específica de la aplicación)
ns.definition Definición de namespace
ns.requirement Declaración de requisito de namespace
ns.dependency Dependencia de namespace

Los tipos ns.* se escriben como cualquier otra entrada: un componente declara ns.definition y ns.requirement, y un host declara ns.dependency. Ver Construcción de Componentes.

Configuración de Ciclo de Vida

La mayoría de las entradas soportan configuración de ciclo de vida:

- name: service
  kind: some.kind
  lifecycle:
    auto_start: true          # Iniciar automáticamente
    start_timeout: 10s        # Tiempo máximo de inicio
    stop_timeout: 10s         # Tiempo máximo de apagado
    stable_threshold: 5s      # Tiempo para considerar estable
    depends_on:
      - app:database
    restart:                  # Política de reintento
      initial_delay: 1s
      max_delay: 90s
      backoff_factor: 2.0
      max_attempts: 0         # 0 = infinito
Use depends_on para asegurar que las entradas inicien en el orden correcto. El supervisor inicia una entrada dependiente solo después de que cada una de sus dependencias haya completado su propio inicio.

Formato de Referencia de Entrada

Las entradas se referencian usando el formato namespace:name:

# Definición
namespace: app.users
entries:
  - name: handler
    kind: function.lua

# Referencia desde otra entrada
func: app.users:handler

Sobrescribir entradas {id="overriding-entries"}

Cualquier campo de una entrada — incluido su kind — puede sobrescribirse en el arranque sin editar el YAML de origen, usando la sección de configuración override: o el flag de CLI -o. Las claves usan el formato namespace:entry:path:

override:
  app:gateway:addr: ":9090"        # campo de datos (una ruta simple apunta a data.*)
  app:worker:meta.priority: high    # campo meta
  app:db:kind: db.sql.postgres      # el kind tipado de la entrada
  app:db:data.kind: custom          # un campo de payload llamado literalmente "kind"
Ruta Apunta a
kind El kind tipado de la entrada (debe ser un string no vacío)
data.<field> o <field> simple Un campo en el payload de datos de la entrada
meta.<field> Un campo en los metadatos de la entrada

Las mismas sobrescrituras se aplican desde la CLI:

wippy run -o app:db:kind=db.sql.postgres -o app:gateway:addr=:9090

Los valores de CLI (-o) se convierten según su forma (true/false a bool, números a números, en otro caso string); los valores de la sección override: mantienen su tipo YAML. Para sobrescribir secciones globales de configuración en lugar de entradas, usa --set.