Skip to main content
A capability is a named permission: orders:read, net:search, fs:read. Nothing more mysterious than that, a short label for one kind of access to the world. Three parties each state their side in writing, and the statements are checked against each other at load, before a single step runs.

Three statements, one check

The program declares its ceiling. At the top of the artifact:
This is not what the program will do on a given run. It is the most it could ever do. Because the declaration is a line in a reviewable text file, it is diffable data: a program that never declared network access cannot quietly grow it, because the file would change and the change would show in review like any other line. Every tool and hole declares its needs. A host tool names them in its attribute:
A tool or hole that touches nothing declares caps []. Each piece’s needs must fit under the program’s ceiling as a subset, and this is checked at load: a ceiling that says only kb:read cannot contain a tool that needs orders:read, and the violation is a load error, not an incident in production. The host states its grants. Whoever runs the program has the final word. Serve the file but grant only the FAQ capability:
The program’s caps must be a subset of the host’s grants or loading refuses, up front and by name, before a token is spent. In an embedding binary the same grants come from RuntimeEnv::grant(cap), and the same subset check runs inside Interpreter::load.

The empty sandbox

Permission systems usually fail by omission: a deny list forgets an entry, or a check gets bypassed by a code path nobody audited. The DSRs sandbox inverts this. When a sandboxed hole or a Code Mode script starts, its environment contains only what the host granted. An ungranted capability is not a blocked call inside the sandbox; the function for it does not exist there at all. Ungrant orders:read and the sandbox simply contains no order_lookup, so no script, however creative, can invoke it. There is nothing to bypass. Deny lists require perfect memory; empty sandboxes do not. This is why a model writing JavaScript in the sandbox is not being trusted. It is being contained by construction: the sandbox starts empty, and only grants get placed inside.

Local modules and loaded files

When you run your own #[module] directly, nobody asks you to --allow anything. The native parts are already in your binary, compiled from your own source, and a gate between you and code you wrote yourself withholds nothing. The module’s generated env() therefore grants its own declared ceiling, and the declaration serves as documentation plus the fence around any sandboxed parts. The moment the same program travels as a .dsrs file, trust resets to zero. A host loading the file re-checks the program’s caps against its own grants, and the program gets exactly what the host allows. Same declaration, two enforcement postures, both consistent with who wrote what.

Declarations are data

Every capability statement lives in the artifact as plain text: the caps { ... } ceiling at the top, and caps [...] on each printed tool and hole. That makes the permission surface reviewable with the same machinery as any other change. A pull request that widens a program’s ceiling is a visible diff on one line, and a load failure names the exact missing set, as in the error above.

See also