Files
hq/02-DECISIONS/0095-the-control-plane-is-the-way-to-ask-a-module.md
T
jschoubben ad4a5ea004 ADR 0152: the operator's surface is a module, the console
The work order's group-3 question answered: an ordinary module the mesh assigns to the machine a
person sits at, holding a minted credential, calling tools under a manifest grant (invokes), serving
MCP on loopback. Design 34; pointers in 33, 25 and 0095; module check designed into 12 (issue 148);
README stops claiming an indexing nothing provides (issue 006).
2026-09-30 16:08:52 +02:00

3.5 KiB

topic, status, date, deciders, reconstructed, extends
topic status date deciders reconstructed extends
the tiers accepted 2026-09-21 jochen false 02-DECISIONS/0047-a-module-runs-its-code-as-its-own-process-with-its-own-account.md

95. The control plane is the way to ask a module

Context

A module serves tools over the broker under an account scoped to what it emits, consumes and serves (ADR 0047). A tool call is a request and a reply: the caller creates a reply queue and publishes to the serving module's request key, and no module's scope grants either — nor should it, since a module that only publishes events has no business declaring queues. So a module could serve tools and nothing in the mesh could call them (issue 049): not an operator at a terminal, not an agent acting for one.

Considered Options

  1. Calling is a grant: a module declares it may be asked, and a consumer is issued an account that may create a reply queue and publish to that module's request key. Deferred: a module-to-module call is the only caller that resembles what the mesh mints today, and none asks for one yet.
  2. The control plane is the way in. Adopted. It holds a connection that may already, so a person or an agent asks through it, and every question passes one process — which is where an audit of who asked what belongs.

Decision

mesh-controller ask <module> <tool> [json] publishes the request on the tool exchange under <module>.<tool>, with a private reply queue bound under its own name, waits for the answer whose correlation matches, and prints it as the module gave it. A tool that answered with an error has answered: the answer is printed and the exit status says so. A module that never answers is said to have not answered, with where to look.

A module declares nothing about being asked: serving a tool is being askable through the control plane. A module-to-module call, if one is wanted, is a grant like any other and a later decision.

Consequences

Anything with the control plane in reach can ask any module anything it serves. What got harder: nothing outside the control plane can, and the control plane's connection is one more thing on the path of every question — a cost accepted for the audit it buys.

The mechanism changed — 2026-09-30, by ADR 0152. What stands: ask on the control plane, and that every call passes an account whose permission list says what it may ask. What moved: "nothing outside the control plane can" stopped being true when a person's account gained a publish grant per tool (design 25 §7, 2026-09-28), and ADR 0152 takes the first option above for a module as well — a manifest declares invokes, and the bus grants exactly that publish side. The audit the second option bought is the bus's permission list, which derives both.

How it is checked

A tools-only bed asks a served tool through the control plane and asserts an answer arrived — an error, since the lab has no upstream and no token, which is an answer where a timeout would not be.

References