lamps

Draft spec · v0.1

LAMP: Least-Authority Module Protocol

A protocol for packaging capability — for humans at a terminal and agents behind a tool call, under one enforced ceiling.

Status working draft Date 2026-08-31 Reference synsema/lamp

Abstract

Agents and humans reach the world through the same blunt instrument: a shell whose permission model is over text, not effects. LAMP defines a portable unit — a lamp — that couples a program with a declared capability ceiling, and a contract between three parties: the author declares, the operator grants, the runtime enforces the intersection and keeps the record. A lamp is one thing a human runs and one structured tool an agent receives; neither can widen what it was given. The protocol is language-independent: any runtime that enforces the invariant can execute any lamp.

1The problem: permission over text

When an agent is handed a shell, the grant is a string match — this command line looks safe. But text does not bound effects: the same binary reads and destroys, the credential travels with the invocation, and every new command is a new negotiation. The result is either over-granting (one broad approval) or friction (a prompt per line), and in both cases the record of what was actually reached is reconstructed from logs after the fact, if at all.

The correct unit of permission is not the command but the capability: which hosts, which paths, which binaries, which databases — as effects, enforced below the program, not promised by it.

2The protocol: three parties, four verbs

LAMP is not a wire protocol; it is an authority protocol — an agreement about how capability is declared, granted, narrowed and recorded. Three parties participate, and none of them has to trust the other two:

3The invariant

Everything reduces to one inequality, checked at run time by the layer below the program:

effective declared manifest project session

what runs ⊆ what the code asks ∩ what each ceiling allows

Intersection is the only composition operator. A lamp can narrow what it was given and can never widen it; a dependency runs under its parent's effective ceiling, so composition cannot escalate privilege. Unbounded execution (exec with no named binary) is refused at load, unconditionally — the hole was never execution, it was execution with nothing bounding it.

4The unit: a lamp

A lamp is a folder — small enough to read whole before running any of it:

FileRole
lamp.jsonThe manifest: name, version, description, profile, the capability ceiling, the file list, and each tool with a JSON Schema for its parameters. This is the part read cheaply and often — by the CLI, by the agent, by the registry.
lamp.synThe program. Its interface is the manifest; its interior is never read by the caller, only executed under the ceiling. Reference lamps are written in Synsema, but the protocol does not require it.
.pulledWritten on install: source ref, version tag, and a sha256 per file — what arrived is what is hashed, and an unchanged pull is a no-op.

The same manifest serves the human and the agent — lamp run git log at a terminal and lamp_git_log() behind a tool call reach the same contract. There is no separate CLI implementation and agent implementation to drift apart: the lamp is the source of truth.

5Inspection before execution

Because the ceiling is text in the manifest and the requests are text in the source, a lamp's promise can be checked before it is ever enabled — a lint over families, with pattern matching left to the runtime, which is the thing that actually decides:

Fig. 1 — the linter names the overreach at pull time; the runtime refuses it at call time either way.

Trust, under LAMP, never means “I trust this developer.” It means “I understand what this lamp can reach, and the runtime will hold that boundary” — even if the source is malicious, the model is confused, or the lamp has a bug.

6Distribution

A lamp is distributed as files, not as an ecosystem: the manifest lists them, the installer fetches them one by one from a plain git host, hashes each, and records the result. Git tags give versions (lamp pull owner/repo@v1.2.0); a registry — when it exists — is a storefront over the same bytes, whose job is to answer the LAMP question rather than the package-manager question: not “where do I get this?” but “what authority am I granting to this machine or agent?” Long-term, identity becomes content-addressed (sha256:…) so builds are reproducible and lockable. Identity is the address: a lamp's name must equal the repo — or the folder — it lives in, and the owner in front of every name is the host's guarantee, not a claim in a file.

7Relation to existing layers

LayerRelation
MCPAn adapter, not the core model. MCP defines how an agent talks to tools over a wire; LAMP defines what a tool is allowed to do. Every enabled lamp is exposed as an MCP tool with its effective ceiling stated in the description — and the same lamp works with no MCP at all, from the CLI.
ContainersThe closest ancestor. Docker made software portable by packaging the filesystem; LAMP packages authority. The analogy is structural: spec / instance / runtime — the protocol is universal, each lamp is an instance, each runtime an implementation.
npm, pip, cargo…Implementation mechanisms, never identity. A lamp may be implemented over any ecosystem's tooling; the contract stays manifest + files + tools + capabilities, not package.json + node_modules.
The shellStill exists — as a lamp, with a ceiling and a human-written policy. It no longer defines what a tool is. Semantic capability first; shell fallback second.

8Reference implementation

The reference CLI, lamp, is three Synsema files compiled to a single static binary. It implements pull/update with per-file hashing, the promise linter, ceiling intersection, enable/disable as the human act, an MCP stdio server, ad-hoc evaluation under the session ceiling, and an append-only audit of every check. Six reference lamps — shell, git, npm-deps, skills, sql, http — exercise the contract; a hostile lamp exercises the refusals. Each claim in this paper is a test in the implementation.

A lamp is a least-authority module: one thing a human runs, one tool an agent gets, one ceiling the runtime enforces.