Grants and capabilities

A capability is a named power: the ability to make a network call, read a key, run a command. A grant is you handing one of those powers to a block. Together they make the sandbox model concrete — and they live in the source, so they're reviewable like any other code.

The host functions

There is a small, fixed set of host functions the Dock brokers — the powers a block can actually call by name and must grant:

A block that grants fetch can call fetch; it cannot suddenly also reach another host function. Powers don't bleed.

Beyond the live host functions, the Dock maintains a broader capability catalog — named capabilities (net, kv, secrets, fs, exec, publish, …) and the WIT interface each projects. The catalog is the vocabulary the toolchain reasons about; the host functions above are what a guest can call today. (publish is the agent ship path: it lets an agent export a facet app surface it manages and deploy it to the edge — see Authoring an agent.)

Granting a power

A block requests only what it needs. The default is nothing — a sandbox with no grants can compute and return a value, and that's all. You add a power by naming it in the block header's grant: list, and the weave wires the matching host import into the compiled module:

sandbox :scrape
sandbox :scrape, grant: [fetch] do
  extern char* fetch(const char* url);
  char* run(const char* url){ return fetch(url); }   // the host brokers the call
end

A block that never grants fetch is flagged by the audit if it calls it — the grant is the contract. The grant token is the host-function name (fetch, emit, …), the exact name the audit matches against the block's body.

The audit is the point

Because grants are written down and the one parser reads them off the tree, the toolchain can audit them. The capability audit runs at weave/build time: it matches every host function a block calls against the functions it grants, and an ungranted call is a hard error, not a silent capability.

A reviewer (or an agent) sees at a glance that :scrape reaches the network and the report-renderer doesn't. There's no hidden System.cmd, no smuggled socket — if a block can touch the outside world, the grant says so, in the file, in the diff.

(work check is a separate, faster gate: it resolves [[refs]] and validates auth/route policy. The capability audit is the weave/build's job.)

Least power, by default

The model rewards asking for less. Grant load when you only need to read a value by key, not the network. Grant nothing when the block is pure. The narrower the grant, the smaller the audit, and the easier the block is to trust — which is exactly the property you want when an agent is writing the code.

Next: the powers that are deliberately not on this list, and why — The three walls.