Merge pull request 'Research 039: a tool or verb that needs a person's approval' (#233) from research/039-a-tool-that-needs-a-persons-approval into main

This commit was merged in pull request #233.
This commit is contained in:
2026-10-08 22:30:03 +00:00
@@ -0,0 +1,109 @@
---
status: active
initiated: 2026-10-08
touches: []
became: []
---
# 039 — A tool or verb that needs a person's approval
A note to design from later, not a design.
## What is investigated
Whether a module's tool or a seat's verb can declare, in its manifest, that **calling it needs a
person's approval**, and the mesh then refuses the call without one.
The operator's idea, 2026-10-08: *"I think we need to be able to mark tools as 'requires human
approval'."*
The shape, as first seen:
- **The declaration is the tool's own.** The manifest marks a tool or verb as needing approval, beside
the rest of what it declares about itself.
- **The mesh enforces it, not the MCP client.** The tool runner, or the controller for a seat verb,
refuses the call unless it carries a **warrant**: the router's record that a person chose one option
of one ask, from the flow ADR 0259 sets out (hq pull request 211, not yet merged). An agent may ask;
it cannot act alone. A client-side prompt is no boundary, because any tool runner may call any tool
on any node (ADR 0175).
- **The ask carries** what is to be done, why, the exact arguments, and who asks. Its options are
Approve and Decline, Approve at the `approve` **assurance level**. On a warrant for Approve the call
goes ahead **once, with those arguments, before the warrant's expiry**; anything else is refused.
- **Where it is answered** until a channel that declares a verified sender (Telegram) is live: at the
operator's desk, or at the controller's terminal. Open: the desk answers only `acknowledge` options
([ADR 0258](../../02-DECISIONS/0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md)),
so the desk alone cannot approve.
## Why now
On 2026-10-08 the only thing between an agent and acts like a snapshot of the media library, a
whole-mesh push or the bus's upgrade was the agent asking in chat before it called the tool. Nothing in
the mesh would have refused the call. The same day, several holes were found in exactly this layer:
an agent on the control-node could become root without a person, and through the login shell's tool an
agent on any node could run a command there as an account that can (ADR 0259 §8 as revised, and
ADR 0266, hq pull request 225, not yet merged). Once agents run without root, **the tools are the
boundary**, and a tool that can do lasting harm needs a person behind each call.
## The first case: the login shell's `execute`
The operator decided on 2026-10-08 that the login shell seat's verb `execute` is the first tool to
need approval, on every node, once the mark exists. It runs any command it is given as the node's
operator account, and that account has passwordless sudo, so one call is root on that node. Until the
mark exists, the verb is removed on the control-node.
The calls it carried (about 300 across the four nodes, counted on 2026-10-08): about a third ran
something with sudo; most of the rest were reads, such as reading or searching a file, listing
containers, asking a unit's state, listing sockets, or looking up a user or a name.
So **narrow read tools must replace the common reads first**, each a tool of the module that owns the
area. Otherwise nearly every approval asked is for a read, and the operator learns to approve without
reading, which makes the approval worth nothing.
## Candidates seen on 2026-10-08
| Tool or verb | Why a person |
|---|---|
| the login shell's `execute` | decided: see above |
| the new zfs module's `zfs_snapshot` | a snapshot of the media library holds its space; on a scratch dataset it does not matter |
| `mesh-controller.push` | sends builds to nodes outside a walk |
| the bus's upgrade, `mesh-controller.bus upgrade` | already a step a person starts ([ADR 0236](../../02-DECISIONS/0236-a-build-is-judged-on-its-first-machine-and-put-back-by-something-other-than-itself-and-so-it-rolls-out-unattended.md) rule 6); today "a person" is whoever calls it |
| `mesh-delivery.release` | the glossary defines it as a person's word, and nothing checks that a person said it |
| the controller's `plans` go and stop | starts or halts a walk |
| a secret's `rotate` | can cut off every consumer of a credential |
| the places and accesses settings | being made terminal-only; approval is the other way |
| the media library's share and mounts (`nfs-server`, `mounts`) assignment | the library is the operator's sacred data |
## What it bears on
- **ADR 0259** (pull request 211): asks, the router, warrants and assurance levels. This effort adds a
new kind of asker: the tool runner or the controller asking on behalf of a call. Who the asker is
matters, because a warrant is issued to one asker alone.
- **ADR 0266** (pull request 225): agents without root. It makes the tool layer the boundary this
effort guards.
- **The `record` upgrade policy** (ADR 0236): "a person's push" is today only a convention.
- **The held delivery's release**: the same.
- **Issue 336** (pull request 228, a hold nobody is told about): an approval waiting with nobody told is
the same fault, so a waiting approval must be said, as a condition or on a channel.
- **The hand-act log** (ADR 0234 §8): a call made on a warrant is recorded with the warrant.
## Open questions
1. **Per tool or per argument.** A snapshot of the library needs a person; one of a scratch dataset
does not. Is the mark on the tool, on an argument's value, or decided by the tool from its arguments?
2. **Who may approve.** Only the operator role exists today. Is that enough for every tool?
3. **Replay and expiry.** One warrant, one call: how is "these exact arguments" bound to the warrant,
and how long does a warrant stay good?
4. **A call waiting for approval.** How is it shown: a condition, the asks list, the call's own answer?
5. **The MCP client while it waits.** Does the call block until answered, or return "asked, waiting"
with a handle the agent calls again?
6. **The answer before a verified channel exists.** The desk is `acknowledge` only; is the controller's
terminal the place, and how does it prove a person there?
7. **Per call, or per session or time window.** For a tool called as often as `execute`, does each
call need its own approval, or may one approval cover one agent session, or a stated span of time?
A wider approval is less noise and more reach for whoever holds it.
8. **Audit.** Is a warranted call a hand-act, and where is a declined or expired one recorded?
## How it will be checked
Measured so far: only the login shell's calls, above. The next evidence to gather: how many tools and verbs in the catalogue act on
data or on other nodes, and of those, how many are guarded by anything but the caller's restraint.