Borrador de la spec · v0.1
LAMP: Least-Authority Module Protocol
Un protocolo para empaquetar capacidad — para humanos en una terminal y agentes detrás de una herramienta, bajo un techo que se hace cumplir.
Resumen
Agentes y humanos alcanzan el mundo con el mismo instrumento romo: una shell cuyo modelo de permisos es sobre texto, no sobre efectos. LAMP define una unidad portable — una lamp — que une un programa con un techo de capacidades declarado, y un contrato entre tres partes: el autor declara, el operador concede, el runtime hace cumplir la intersección y guarda el registro. Una lamp es una cosa que un humano ejecuta y una herramienta estructurada que un agente recibe; ninguno puede ampliar lo que se le dio. El protocolo es independiente del lenguaje: cualquier runtime que haga cumplir el invariante puede ejecutar cualquier lamp.
1El problema: permiso sobre texto
Cuando a un agente se le entrega una shell, la concesión es una comparación de texto — esta línea de comando parece segura. Pero el texto no acota efectos: el mismo binario lee y destruye, la credencial viaja con la invocación, y cada comando nuevo es una negociación nueva. El resultado es sobre-conceder (una aprobación amplia) o fricción (una confirmación por línea), y en ambos casos el registro de lo que realmente se alcanzó se reconstruye desde los logs después del hecho, si acaso.
La unidad correcta de permiso no es el comando sino la capacidad: qué hosts, qué rutas, qué binarios, qué bases de datos — como efectos, aplicados por debajo del programa, no prometidos por él.
2El protocolo: tres partes, cuatro verbos
LAMP no es un protocolo de cable; es un protocolo de autoridad — un acuerdo sobre cómo la capacidad se declara, se concede, se estrecha y se registra. Participan tres partes, y ninguna tiene que confiar en las otras dos:
-
El autordeclara. El manifiesto fija el techo de la lamp — cada familia de efecto que podrá tocar (
net,file,exec,db…), acotada por patrón. -
El operadorconcede — una vez. Un techo de proyecto y un techo de sesión, escritos por un humano, acotan todo lo que corre. Habilitar una lamp es un acto humano, nunca una herramienta que un agente pueda llamar.
-
El runtimehace cumplir y audita. El programa corre bajo la intersección de los tres techos. Cada chequeo — concedido o negado — vuelve como datos estructurados y se agrega al registro.
3El invariante
Todo se reduce a una desigualdad, verificada en tiempo de ejecución por la capa debajo del programa:
lo que corre ⊆ lo que el código pide ∩ lo que cada techo permite
La intersección es el único operador de composición. Una lamp puede estrechar lo que se le dio y
nunca puede ampliarlo; una dependencia corre bajo el techo efectivo de su padre, así que la composición
no puede escalar privilegios. La ejecución sin límite (exec sin binario nombrado) se
rechaza al cargar, sin condiciones — el agujero nunca fue la ejecución, fue la ejecución
sin nada que la acote.
exec=gitconcedidoenv=LAMP_*concedidostdoutconcedidosecret("*")negadonet(collector…)negadofile.read("/*")negado
4La unidad: una lamp
Una lamp es una carpeta — lo bastante pequeña para leerla entera antes de ejecutar nada:
| Archivo | Rol |
|---|---|
| lamp.json | El manifiesto: nombre, versión, descripción, perfil, el techo de capacidades, la lista de archivos, y cada herramienta con JSON Schema para sus parámetros. Es la parte que se lee barato y a menudo — el CLI, el agente, el registro. |
| lamp.syn | El programa. Su interfaz es el manifiesto; su interior nunca lo lee quien llama, solo se ejecuta bajo el techo. Las lamps de referencia están escritas en Synsema, pero el protocolo no lo exige. |
| .pulled | Se escribe al instalar: la ref de origen, el tag de versión y un sha256 por archivo — lo que llegó es lo que se hashea, y un pull sin cambios no hace nada. |
El mismo manifiesto sirve al humano y al agente —
lamp run git log en una terminal y lamp_git_log() detrás de una
herramienta llegan al mismo contrato. No hay una implementación de CLI y otra de agente
que puedan divergir: la lamp es la fuente de verdad.
5Inspección antes de la ejecución
Como el techo es texto en el manifiesto y los pedidos son texto en el código, la promesa de una lamp puede verificarse antes de habilitarla — un lint sobre familias, dejando el matching de patrones al runtime, que es quien decide de verdad:
lamp pull ./evil-formatterBREAKS ITS PROMISE — asks for 3 thing(s) it never declared: ! secret("*") ! net("collector.attacker.example") ! file.read("/*")Confiar, bajo LAMP, nunca significa «confío en este desarrollador». Significa «entiendo qué puede alcanzar esta lamp, y el runtime va a sostener ese límite» — aunque el código sea malicioso, el modelo esté confundido o la lamp tenga un bug.
6Distribución
Una lamp se distribuye como archivos, no como un ecosistema: el manifiesto los lista, el
instalador los trae uno a uno desde un host git común, hashea cada uno y registra el
resultado. Los tags de git dan las versiones (lamp pull owner/repo@v1.2.0); un registro —
cuando exista — es una vitrina sobre los mismos bytes, cuyo trabajo es responder la pregunta
de LAMP y no la del gestor de paquetes: no «¿de dónde saco esto?» sino
«¿qué autoridad le estoy concediendo a esta máquina o agente?». A largo plazo la identidad
pasa a direccionarse por contenido (sha256:…) para builds reproducibles y bloqueables.
La identidad es la dirección: el nombre de una lamp debe ser igual al repo — o a la carpeta — donde vive,
y el owner delante de cada nombre es la garantía del host, no una declaración en un archivo.
7Relación con las capas existentes
| Capa | Relación |
|---|---|
| MCP | Un adaptador, no el modelo central. MCP define cómo un agente habla con herramientas por un cable; LAMP define qué puede hacer una herramienta. Cada lamp habilitada se expone como herramienta MCP con su techo efectivo en la descripción — y la misma lamp funciona sin MCP, desde el CLI. |
| Contenedores | El ancestro más cercano. Docker hizo portable el software empaquetando el sistema de archivos; LAMP empaqueta autoridad. La analogía es estructural: spec / instancia / runtime — el protocolo es universal, cada lamp es una instancia, cada runtime una implementación. |
| npm, pip, cargo… | Mecanismos de implementación, nunca identidad. Una lamp puede
implementarse sobre las herramientas de cualquier ecosistema; el contrato sigue siendo manifiesto + archivos + tools +
capacidades, no package.json + node_modules. |
| La shell | Sigue existiendo — como una lamp, con techo y una política escrita por un humano. Ya no define qué es una herramienta. Capacidad semántica primero; shell como respaldo. |
8Implementación de referencia
El CLI de referencia, lamp, son tres archivos Synsema compilados a un único
binario estático. Implementa pull/update con hash por archivo, el linter de promesas, la
intersección de techos, enable/disable como acto humano, un servidor MCP por stdio, evaluación
ad-hoc bajo el techo de sesión, y un audit de solo-agregar de cada chequeo. Seis lamps de referencia —
shell, git, npm-deps, skills,
sql, http — ejercitan el contrato; una lamp hostil ejercita los
rechazos. Cada afirmación de este paper es un test en la implementación.
Una lamp es un módulo de mínima autoridad: una cosa que un humano ejecuta, una herramienta que un agente recibe, un techo que el runtime hace cumplir.