---
slug: unified-dispatch-macaroon-atoms
title: "Unified dispatch: one runner for the terminal, browser, phone and cloud, and tokens that lend out exactly part of it"
kind: architecture
status: published
hash: 56570dc558de06e94dcba447a82c3427f6222d7a9ddca293b9878358830232d5
created: 2026-10-09T00:05:29.571Z
updated: 2026-10-09T04:17:36.711Z
summary: "Every capability of this system, from a shell command on a Mac to a browser session, an iMessage line, a cloud container and 1,500 web services, is one row called through one runner with one call shape. That single authority is then lent out in pieces: a scoped token, built on the macaroon construction, carries its own readable limits, can be narrowed by whoever holds it, can never be widened, and leaves a record of every use and every refusal. This is the design, the cryptography, the recorded proof and the honest edges."
tags: ["architecture","ai-agents","macaroons","authorization","capability-security","mcp","unified-dispatch"]
above: ["[[directory-ledger-pattern]]"]
below: ["[[task-payload-provenance-article]]"]
adjacent: ["[[atomic-tooling]]", "[[scoped-access]]", "[[authority-outside-the-model]]"]
nested: ["[[task-payload-provenance-article]]"]
---
# Unified dispatch: one runner for the terminal, browser, phone and cloud, and tokens that lend out exactly part of it

*Every capability of this system, from a shell command on a Mac to a browser session, an iMessage line, a cloud container and 1,500 web services, is one row called through one runner with one call shape. That single authority is then lent out in pieces: a scoped token, built on the macaroon construction, carries its own readable limits, can be narrowed by whoever holds it, can never be widened, and leaves a record of every use and every refusal. This is the design, the cryptography, the recorded proof and the honest edges.*

## The problem: an agent that can think but cannot reach

An assistant can know exactly what to do and still have no way to do it. Reading a web page, editing a file, driving a browser, sending a text from a real phone number and running a job in the cloud are five different interfaces with five different credentials in five different places. Most agent systems solve this one integration at a time, and every integration is another place where a call can be made without a limit and without a record.

**Unified dispatch** is the alternative this system is built on. There is one runner. Every capability, whatever it touches, is a row in the [[directory-ledger-pattern|Directory]], and every row is called the same way:

```json
{ "tool": "NAME", "args": { ... } }
```

The runner looks up the row, reads its contract, makes the real call to wherever the capability lives, and records the exchange on the Ledger. The caller never learns the upstream interface. A shell command on the owner's Mac and a REST call to a lead database are the same call with different names.

That gives the system one place to put two things that are usually scattered: **a permission check** and **a record**. Because every action crosses the same runner, a limit enforced there is enforced everywhere, and a record written there is complete. The second half of this article is about the token that carries those limits. The first half is about how much the runner reaches.

## What one runner reaches

| Surface | What the rows connect to |
|---|---|
| **Terminal** | Commands on the owner's Mac through the Mac command runner (`LOCAL_EXEC`, the `CLI_*` tools, AppleScript and Shortcuts) |
| **Browser** | Browser actions through the `BROWSER_*` tools, `PLAYWRIGHT`, and the `COMPUTER` tool's isolated persistent browser |
| **Phone and messaging** | iPhone operations through `PHONE_*`, iMessage through `IMSG_*` and the sign-in line, Shortcuts that run on the device |
| **Cloud** | `CLOUD_EXEC`, container agents and Workers |
| **Services** | Every web or API service whose contract is a Directory row: search, mail, ads, leads, patents, Cloudflare, Google, Stripe, Shopify |

These environments stay different underneath. A browser action still needs a browser to be available; a phone operation still needs the device to be connected; a service still needs a valid credential. What unifies them is the request and the result: one call shape in, one recorded exchange out. A script, an assistant, a Shortcut or a person pasting a link can look up a capability, open its contract and call the runner without being rewritten around each tool's native interface.

The useful consequence is that the execution surface can grow while the calling pattern stays fixed. Adding a capability is adding a row. Nothing that calls the runner has to change.

## One call, thirty wrappers

The contracts page renders every form of the canonical call for a given tool and states, for each, the only three things that vary: where it is sent, where the credential goes, and how the name and arguments are wrapped. Twenty-six forms are rendered for every tool: the build's REST door, a one-line URL, MCP over HTTP, an MCP client configuration, two command-line clients, a webhook, an Apple Shortcut, JavaScript and Python, an SDK method, a direct function call, MCP over stdio, WebSocket, server-sent events, GraphQL, SSH, a model's function call as the model would write it, and the OIP dispatch door with its dry-run form. A live scoped token adds three credential-free links. An upstream service adds its own call, made exactly as written.

Three of those forms (GraphQL, WebSocket, server-sent events) have no route yet; four (the SDK import, the direct function call, MCP over stdio, SSH) run only on the owner's machine. The contracts are generated from the row; they describe the call, not a promise that every transport is wired.

For the forms that do run, the order is fixed: **the permission checker sits in front of the runner.** A token's limits are therefore applied at the one point every interface passes through, which is the property that makes the limits worth having.

## Data and execution are one grammar

The original design note for this system draws two pipelines side by side:

```
DATA       TARGET → FILTER → SELECT → ORDER → PAGE → AGGREGATE → RETURN WHAT WAS ASKED FOR
EXECUTION  TARGET → ARGS   → DEPEND ON → RUN → PROJECT → RECEIPT
```

Reading a table and running a tool look different, but both end the same way: the caller should get back **what it asked for**, and the system should keep **the whole result** in case the caller asks a second question. A model that receives a warehouse when it asked for three rows wastes its context; a model that re-runs a tool to see a field it was not shown repeats a side effect.

The general envelope that unifies the two, one object with `target`, `op`, `where` or `args`, `select`, `with`, `order`, `page`, `control` and `want` for every capability and every data read, is written as a design and is **not implemented** as a single door. What is implemented is the projection half, inside the tools where it matters most:

- **The catalog projects to names.** Every tool with its description is 817,371 bytes; every tool name alone is 41,663 bytes, 19.6 times smaller (measured 9 October 2026). A model reads names, then opens one row.
- **Results project on the way back.** The `CODE`, `ARTICLE`, `COMPUTER` and `RESULT` tools take `return.select` (dot paths into the result), `return.max_bytes` and `return.mode` (`selected`, `full` or `reference`). The whole result is stored before it is reduced, and the answer carries a reference to it. Asking for the reference returns the stored result; it does not run the tool again. A budget cut is made at whole records or whole fields, never mid-field, and every answer states how large the whole payload was.

The invariant that matters, and the one most systems get wrong: **projection shapes what the model sees, never what the system keeps.** Nothing is silently truncated, nothing has to be re-run to be re-read, and a reviewer can always retrieve the part the model was not shown.

## Scoped tokens: lending out part of the authority

A runner that reaches a terminal, a browser, a phone and the cloud holds a great deal of authority. The build key opens all of it, which is the right key for the owner and the wrong key for everyone and everything else: a helper agent, a client, a model doing one task, a stranger who should see one search result. The principle is old; [least privilege is practiced by forcing a process to run with only those privileges required by the task](https://en.wikipedia.org/wiki/Principle_of_least_privilege). The problem has always been making it cheap enough to actually do.

A **scoped token** is a separate credential whose limits are written into it in plain text, checked by the runner before anything executes. Each limit is a **caveat**, one line a person can read:

```
tools = EXA_SEARCH
ways = rest,mcp
uses <= 3
expires < 2026-10-10T00:00:00.000Z
```

That token lets its holder run one search tool, from a program or an MCP client, at most three times, until midnight on 10 October. An attempt to send mail is refused before anything is sent, because `EMAIL_SEND` is not on the list. A fourth search is refused. The holder can read exactly what the token allows, and so can anyone they hand it to.

The holder can also make it smaller. Appending `uses <= 1` and handing the copy to a helper gives the helper one search. The helper's use also counts against the original three. Making ten copies creates no additional allowance. **Distributing work no longer requires distributing the key, and a narrower copy never resets its parent's limits.**

## The cryptography: a chain that only grows

The token is three parts:

```
g1.<payload>.<signature>
payload   = base64url of {"i": "<id>", "c": ["<caveat>", "<caveat>", …]}
signature = 43 characters: the last link of an HMAC-SHA256 chain, one link per caveat
```

The construction is the one from Google's 2014 paper on **macaroons**, credentials that [embed caveats that attenuate and contextually confine when, where, by who, and for what purpose a target service should authorize requests](https://research.google/pubs/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/). The mechanism is [nested, chained MACs](https://research.google/pubs/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/): each signature becomes the key that signs the next caveat.

```
root = HMAC(the build's access key, "misc-sheets grants v1")
s0   = HMAC(root, id)
s_k  = HMAC(s_(k-1), caveat_k)
the token carries s_n
```

Four properties follow from that arithmetic, and the checker enforces each:

1. **Only this build can start a chain.** The first link needs the root; the root needs the build's access key. Rotating the key ends every token at once.
2. **Anyone can narrow a token without asking the build.** The holder appends a caveat and computes the next link from the signature they already have. The result is a valid, smaller token. This is attenuation in the object-capability sense: [given one reference, create another with certain security restrictions](https://en.wikipedia.org/wiki/Object-capability_model), except that here it needs no server round trip and no storage. `delegate = no` stops further narrowing.
3. **Nobody can widen one.** Removing, changing or reordering a caveat would require computing a link backwards through HMAC. The checker recomputes the whole chain from the root and compares the last link in constant time.
4. **An unknown caveat refuses the call.** Caveats are joined by AND. A line the checker cannot parse is a refusal, never a pass. A system that passed on unknown limits would be a system whose limits could be bypassed by typo.

The payload is readable JSON, so the token is also its own documentation: the holder page at `/g?t=<token>` simply prints the caveats in plain words, then shows each of the token's doors filled in and ready to run.

## Eleven limits, read from one list in the code

The checker, the Console's token builder and the public [[scoped-access|scoped access page]] all read one array of limits in the source. None of them can name a limit the others do not enforce, which is how the documentation stays true by construction.

| Limit | Caveat | What it does |
|---|---|---|
| Tools | `tools = EXA_SEARCH,LEADS_*` | Which Directory rows may run; a trailing `*` covers a prefix |
| Ways | `ways = link,rest,mcp,chat,proof` | Which doors the token opens |
| Expires | `expires < <ISO time>` | When it stops |
| Uses | `uses <= N` | Tool runs and chat messages; counted along the chain |
| Task | `task = T-0207` | Files every run under one task; stops when the task is done |
| Areas | `area = /prefix/` | Every path-named argument must start with one of these prefixes |
| Argument rules | `arg EMAIL_SEND.to glob *@acme.com` | One argument of one tool must match `=`, `prefix`, `glob`, `in`, `<=` or `>=` |
| Person | `person = p_…` | Only that person, signed in by text from their phone, may use it from a browser |
| Whose keys | `keys = p_…` | Tools run with that person's own credentials (their Gmail, their iMessage line), never the build's |
| Model | `model = <model id>` | The model the holder talks to in the chat door |
| Hand on | `delegate = no` | Nothing may be appended after it |

Two of these carry design decisions worth knowing.

**Uses are counted per link.** Each `uses` caveat is charged against the link of the chain it sits on. A limit of 20 on a token covers every narrower copy made from it; a copy's own limit of 2 covers only that copy. Spending a use is an atomic compare-and-swap on the token's record, retried on conflict, so two concurrent runs cannot both take the last use.

**Whose keys can only be set at mint.** A narrowing that could add `keys = <someone else>` would move the token onto another person's accounts, which is a widening dressed as a caveat. The checker refuses a `keys` caveat that was not in the record written when the token was made. When a token carries `keys`, a tool that needs a credential the person has not stored is refused, and the refusal names the missing key.

## Five doors, one check, one record

| Door | Address | For |
|---|---|---|
| Link | `GET /g/run/<TOOL>?args=…&t=<token>` | A browser, a Shortcut, a model whose only tool is opening a page |
| REST | `POST /g/run`, `Authorization: Bearer <token>` | Any program |
| MCP | `POST /g/mcp`, same header | Claude, Codex, Cursor or any MCP client; it is shown only the tools the token allows |
| Chat | `/g/chat?t=<token>` | A page where the holder talks to a model that can run only the token's tools |
| Proof | `/w/<TASK>?t=<token>` | The read-only record of one task; runs nothing |

Every door that runs a tool goes through the same seven steps: parse the token (a malformed string is refused); recompute the chain and compare the last link; read the token's record (never minted, turned off, or narrowed from a turned-off link are all refusals); check every caveat in the order the token carries them; spend one use on every `uses` caveat in the chain, atomically; run the tool through the same runner the build key uses; write the call to the token's log and a `grant used` row to the Ledger with the token id, chain link, caveats, tool, door, arguments, status and duration. The runner records the tool's answer under the same call id.

A refusal writes a `grant refused` row with the caveat that refused it. The tool is not executed. One honest edge: refusal and durable recording are separate outcomes, so a storage failure during a refusal can leave a gap in the record even though the call was correctly stopped.

What needs the build and what does not: **narrowing needs nothing from the build.** Checking needs the root key and one read of the token's record. That one read buys three things a bare macaroon cannot do: counting uses, turning a token off, and seeing which narrower copies have been used. [Turning off a token turns off every copy narrowed from it; turning off one copy leaves the token it came from working](https://miscsubjects.com/a/scoped-access).

## A recorded run: the check made when this shipped

On 3 October 2026 a task was written with one purpose: prove a task-bound token end to end on the live build. Its completion condition, as written: two runs on the task's proof page, a refused run refused, and the token stopping when the task is marked done. A token was minted for it with `tools = WIKIPEDIA_SUMMARY,HTTP_ECHO_HEADERS`, `ways = rest,mcp`, `uses <= 10` and `task = T-0229`.

```widget
{
  "type": "json",
  "title": "T-0229, as its proof page records it",
  "ref": "#facts.recorded_check",
  "open_depth": 2
}
```

Two runs answered, at 2321 ms and 1351 ms. The task was marked done. Twenty-one minutes later a third run never left the build: the checker refused it on `task = T-0229` with the reason "its task T-0229 is done", and the proof page shows the refusal with the caveat beside it. The page is drawn from the checker's call log, not from anything the worker wrote. That is the whole point of the design in one small record: the worker [could not leave a call out, because it could not act without the token, and it could not add one, because the build writes the record](https://miscsubjects.com/a/scoped-access).

## Why this is a containment primitive, not just a permission system

Put the pieces together and a specific property appears. What an agent may do is checked by code outside the model. How its actions execute is decided by the runner, not improvised by the model. What record is kept is written by the runtime, at the boundary, before and after every call. On none of those three questions is the model consulted. A model that is wrong, manipulated, or working against its operator has nothing to lie to and nothing to lie with.

That makes unified dispatch plus scoped tokens a candidate control plane for the places where agent behaviour has to be bounded and then audited: a development sandbox, tool use during training, an evaluation harness, a deployment. A rollout can run under a token whose tools, arguments, paths, uses and lifetime are fixed in advance, and the record of what it did and every point where it tried to exceed its grant is produced independently of its own transcript. [[authority-outside-the-model|Authority outside the model]] states that claim carefully, including what it would take to make it fully true.

What is true today is narrower, and worth saying exactly. The permission checker is implemented and live: eleven caveats, uses counted atomically along the chain, every use and refusal recorded with the caveat that refused it. [No running agent of this build has been switched to scoped tokens](https://miscsubjects.com/a/scoped-access); they still hold the build key, so the checker constrains only the holders it is given to. Containment would further require every agent switched, the build key withdrawn from them, no route around the runner, network egress forced through it, and an adversarial test of that boundary. None of those is done. The mechanism is built; the enclosure is not.

## Where the design stops

- `area` checks arguments that name a path. The text of a shell command is not a path argument, so an area restriction does not confine a shell tool. Do not give shell tools to a token you limit by area.
- A token is a bearer credential unless it carries `person`. Whoever holds the string can use it within its limits.
- Caveats are first-party only. The macaroon paper's third-party caveats, discharged by another service, are not implemented.
- The checker reads tasks from the document the task list was kept in before it moved to a database table. A token bound to a task created since the move is refused as "does not exist" until the checker is pointed at the table.
- GraphQL, WebSocket and server-sent-event forms are rendered but have no route; four forms run only on the owner's machine.
- The general `want` envelope is a design. Projection runs today inside four tools, not at one door.

## Prior work

The signature chain is the construction in *Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud* (Birgisson, Politz, Erlingsson, Taly, Vrable and Lentczner, NDSS 2014), over HMAC as specified in RFC 2104, with the payload in the URL-safe base64 alphabet of RFC 4648. The attenuation property is the object-capability pattern. What this implementation adds is the binding: every caveat is checked against a concrete tool call in one runner, uses and refusals enter one Ledger, and a task caveat turns those records into a page a third party can be shown. The MCP door exposes the result to any client that speaks the [Model Context Protocol](https://modelcontextprotocol.io/specification/2025-06-18/server/tools), which sees only the tools the token allows.

## The rest of the series

- [[directory-ledger-pattern|The Directory and the Ledger]]: the catalog of rows that hold their own calls, and the append-only record of exact bytes that the runner writes to.
- [[atomic-tooling|Atomic tooling]]: the tools behind the runner that keep orchestration out of the model, and the `return` budgeting described above.
- [[task-payload-provenance-article|Task provenance]]: what the `task` caveat produces, in full, and the article a task can become.

## Facts

```json
{
  "measured_at": "2026-10-09T05:10:00Z",
  "call_shape": "{\"tool\": NAME, \"args\": {...}} sent to one tool runner",
  "surfaces": {
    "terminal": "commands on the owner's Mac through the Mac command runner (LOCAL_EXEC and the CLI_* tools)",
    "browser": "browser actions through BROWSER_* tools, PLAYWRIGHT and the COMPUTER tool's isolated browser",
    "phone_and_messaging": "PHONE_* and IMSG_* tools, the iMessage sign-in line, Shortcuts",
    "cloud": "CLOUD_EXEC, container agents, Workers",
    "services": "every web or API service whose contract is a Directory row"
  },
  "call_forms_per_tool": {
    "always": 26,
    "with_a_token": 29,
    "with_a_token_and_an_upstream_service": 30,
    "without_a_route_yet": [
      "graphql",
      "websocket",
      "sse"
    ],
    "owner_machine_only": [
      "sdk",
      "function_direct",
      "mcp_stdio",
      "ssh"
    ]
  },
  "two_pipelines": {
    "data": "TARGET → FILTER → SELECT → ORDER → PAGE → AGGREGATE → RETURN WHAT WAS ASKED FOR",
    "execution": "TARGET → ARGS → DEPEND ON → RUN → PROJECT → RECEIPT"
  },
  "general_envelope": {
    "fields": [
      "target",
      "op",
      "where | args",
      "select",
      "with",
      "order",
      "page",
      "control",
      "want"
    ],
    "status": "designed, not implemented; projection runs today inside the CODE, ARTICLE, COMPUTER and RESULT tools"
  },
  "projection": {
    "catalog": {
      "with_descriptions_bytes": 817371,
      "names_only_bytes": 41663,
      "ratio": 19.6
    },
    "result_reduction": {
      "tools": [
        "CODE",
        "ARTICLE",
        "COMPUTER",
        "RESULT"
      ],
      "return": {
        "select": "dot paths",
        "max_bytes": "integer",
        "mode": [
          "selected",
          "full",
          "reference"
        ]
      },
      "whole_result": "stored before reduction under a reference; fetching the reference does not run the tool again"
    }
  },
  "token": {
    "format": "g1.<payload>.<signature>",
    "payload": "base64url JSON {\"i\": id, \"c\": [caveat lines]}",
    "signature": {
      "chars": 43,
      "bytes": 32,
      "algorithm": "HMAC-SHA256 chain, one link per caveat"
    },
    "chain": [
      "root = HMAC(the build's access key, \"misc-sheets grants v1\")",
      "s0 = HMAC(root, id)",
      "s_k = HMAC(s_(k-1), caveat_k)",
      "the token carries s_n"
    ],
    "comparison": "constant time",
    "third_party_caveats": false
  },
  "limits": [
    {
      "name": "tools",
      "caveat": "tools = EXA_SEARCH,LEADS_*",
      "what": "which Directory rows may run; a trailing * covers a prefix"
    },
    {
      "name": "ways",
      "caveat": "ways = link,rest,mcp,chat,proof",
      "what": "which doors the token opens"
    },
    {
      "name": "expires",
      "caveat": "expires < <ISO time>",
      "what": "when it stops"
    },
    {
      "name": "uses",
      "caveat": "uses <= N",
      "what": "tool runs and chat messages, counted along the chain"
    },
    {
      "name": "task",
      "caveat": "task = T-0207",
      "what": "files every run under one task; stops when the task is done"
    },
    {
      "name": "area",
      "caveat": "area = /prefix/",
      "what": "every path-named argument must start with one of these"
    },
    {
      "name": "arg",
      "caveat": "arg EMAIL_SEND.to glob *@acme.com",
      "what": "one argument of one tool must match =, prefix, glob, in, <= or >="
    },
    {
      "name": "person",
      "caveat": "person = p_…",
      "what": "only that person, signed in, may use it from a browser"
    },
    {
      "name": "keys",
      "caveat": "keys = p_…",
      "what": "tools run with that person's own credentials, never the build's; set only at mint"
    },
    {
      "name": "model",
      "caveat": "model = <model id>",
      "what": "the model the holder talks to in the chat door"
    },
    {
      "name": "delegate",
      "caveat": "delegate = no",
      "what": "nothing may be appended after it"
    }
  ],
  "doors": {
    "link": "GET /g/run/<TOOL>?args=...&t=<token>",
    "rest": "POST /g/run",
    "mcp": "POST /g/mcp",
    "chat": "/g/chat?t=<token>",
    "proof": "/w/<TASK>?t=<token>"
  },
  "check_sequence": [
    "parse; a malformed string is refused",
    "recompute the chain from the root and compare the last link",
    "read the token's record: minted, not turned off, no turned-off link in its chain",
    "check each caveat in token order; an unknown caveat refuses",
    "spend one use on every uses caveat in the chain, atomically",
    "run through the same tool runner the build key uses",
    "write the call log and a grant used or grant refused Ledger row"
  ],
  "recorded_check": {
    "task": "T-0229",
    "date": "2026-10-03",
    "token_caveats": [
      "tools = WIKIPEDIA_SUMMARY,HTTP_ECHO_HEADERS",
      "ways = rest,mcp",
      "expires < 2026-10-03T22:41:13.648Z",
      "uses <= 10",
      "task = T-0229"
    ],
    "calls": [
      {
        "at": "2026-10-03T21:41:18.679Z",
        "tool": "WIKIPEDIA_SUMMARY",
        "result": "answered",
        "ms": 2321
      },
      {
        "at": "2026-10-03T21:41:23.646Z",
        "tool": "HTTP_ECHO_HEADERS",
        "result": "answered",
        "ms": 1351
      },
      {
        "at": "2026-10-03T22:02:42.146Z",
        "tool": "WIKIPEDIA_SUMMARY",
        "result": "refused before it ran",
        "caveat": "task = T-0229",
        "reason": "its task T-0229 is done"
      }
    ],
    "read_from": "the proof page /w/T-0229, opened with the owner key on 9 October 2026"
  },
  "scoped_tokens_used_by_running_agents": false,
  "series": [
    "directory-ledger-pattern",
    "unified-dispatch-macaroon-atoms",
    "atomic-tooling",
    "task-payload-provenance-article"
  ]
}
```

## Sources

1. [Scoped access: the page the build writes from its own code](https://miscsubjects.com/a/scoped-access) — “Every capability of this build runs through one dispatch authority. A scoped token is a link-sized string that carries its own limits: which tools, by which doors, how many times, until when, for which task, inside which folders, for whom.” (sha256 257f6287e22a3fce)
2. [Scoped access: the chain](https://miscsubjects.com/a/scoped-access) — “The chain is the whole idea, borrowed from macaroons.” (sha256 ee83b07aee561a62)
3. [Scoped access: checking a token](https://miscsubjects.com/a/scoped-access) — “To check a token, the build recomputes the chain from its root and compares the last link. Change, reorder or remove any caveat and the chain no longer matches. A new build key changes the root and ends every token at once.” (sha256 4b8a49e754ff3b02)
4. [Scoped access: every limit](https://miscsubjects.com/a/scoped-access) — “A caveat this build does not know is a refusal, never a pass. A refusal says which caveat refused it, and is itself a Ledger row.” (sha256 e9f94721b1e457dc)
5. [Scoped access: handing a token on, smaller](https://miscsubjects.com/a/scoped-access) — “They cannot remove a caveat, because they cannot compute a link backwards. So a model can give a helper agent exactly the part of its own access the helper needs.” (sha256 5741a9580d8ebc72)
6. [Scoped access: what a use is](https://miscsubjects.com/a/scoped-access) — “A use is one tool run or one chat message; opening a page is not a use” (sha256 c40614e3dfcfa2cb)
7. [Scoped access: turning a token off](https://miscsubjects.com/a/scoped-access) — “Turning off a token turns off every copy narrowed from it; turning off one copy leaves the token it came from working.” (sha256 aaa928c953aa19df)
8. [Scoped access: the proof page](https://miscsubjects.com/a/scoped-access) — “The worker could not leave a call out, because it could not act without the token, and it could not add one, because the build writes the record.” (sha256 3c09e45853488de9)
9. [Scoped access: what is not yet switched](https://miscsubjects.com/a/scoped-access) — “No running agent of this build has been switched to scoped tokens” (sha256 8f8e1b185216aed6)
10. [Scoped access: the MCP door](https://miscsubjects.com/a/scoped-access) — “and see only the tools the token allows.” (sha256 0f7ee74bcd9a8aa6)
11. [Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud (NDSS 2014)](https://research.google/pubs/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/) — “macaroons embed caveats that attenuate and contextually confine when, where, by who, and for what purpose a target service should authorize requests” (sha256 c9d336b5640d0404)
12. [Macaroons: the construction](https://research.google/pubs/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/) — “Macaroons are based on a construction that uses nested, chained MACs (e.g., HMACs) in a manner that is highly efficient, easy to deploy, and widely applicable.” (sha256 4a698f4cbd8d4f66)
13. [RFC 2104: HMAC](https://www.rfc-editor.org/rfc/rfc2104.html) — “This document describes HMAC, a mechanism for message authentication using cryptographic hash functions.” (sha256 6b088e54fa0573bb)
14. [RFC 4648: Base64 with URL and filename safe alphabet](https://www.rfc-editor.org/rfc/rfc4648.html) — “This encoding is technically identical to the previous one, except for the 62:nd and 63:rd alphabet character” (sha256 5eed6872a581189e)
15. [Object-capability model: attenuation](https://en.wikipedia.org/wiki/Object-capability_model) — “given one reference of an object, create another reference for a proxy object with certain security restrictions, such as only permitting read-only access or allowing revocation.” (sha256 c8b4e7b61e50a1c4)
16. [Principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) — “least privilege is practiced by forcing a process to run with only those privileges required by the task” (sha256 bb54f2dd00395ed3)
17. [Model Context Protocol: a tool is a name](https://modelcontextprotocol.io/specification/2025-06-18/server/tools) — “Each tool is uniquely identified by a name and includes metadata describing its schema.” (sha256 54937f6ab6ea7907)
18. [Authority outside the model](https://miscsubjects.com/a/authority-outside-the-model) — “In this build a model does not set its own authority” (sha256 09ffea57374c7155)

---

**above:** [[directory-ledger-pattern]]

**below:** [[task-payload-provenance-article]]

**adjacent:** [[atomic-tooling]], [[scoped-access]], [[authority-outside-the-model]]

**nested:** [[task-payload-provenance-article]]
