From 0aa8f62e0c72a901a3129179fbdb26bfb3d9a979 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 14 Sep 2026 22:08:40 +0200 Subject: [PATCH] =?UTF-8?q?Issue=20049=20=E2=80=94=20a=20module=20serves?= =?UTF-8?q?=20tools=20and=20nothing=20may=20call=20them?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A module's broker account is scoped to what it declares it emits and consumes. A tool call needs a reply queue, which that scope does not cover and should not. So the account is right, the request is reasonable, and no account exists that can make it — asking a module its own question, from its own container, with its own credential, is refused. It matters because a module's tools are its operator-facing surface: the catalogue serves the five questions it exists to answer and nothing can reach them. It is also why a running module keeps being mistaken for a working one — a test that cannot ask anything checks a container is up, and that substitution has hidden two faults this week. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- .../00-report.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 04-ISSUES/049-a-module-can-serve-tools-and-nothing-can-call-them/00-report.md diff --git a/04-ISSUES/049-a-module-can-serve-tools-and-nothing-can-call-them/00-report.md b/04-ISSUES/049-a-module-can-serve-tools-and-nothing-can-call-them/00-report.md new file mode 100644 index 0000000..7bab926 --- /dev/null +++ b/04-ISSUES/049-a-module-can-serve-tools-and-nothing-can-call-them/00-report.md @@ -0,0 +1,72 @@ +--- +status: open +opened: 2026-09-14 +located-in: [] +fixed-by: +amended-design: +--- + +# 049 — A module can serve tools, and nothing is allowed to call them + +## Symptom + +A module serves tools over the broker. Asking it one, from inside that same module's own container, +using its own credential, is refused: + +``` +Error: Channel closed by server: 403 (ACCESS-REFUSED) with message +"ACCESS_REFUSED - User '-' doesn't have permissions to queue 'amq.gen-...'" +``` + +A module's broker account is scoped to what it declares it emits and consumes. A tool call is a +request and a reply, and the reply arrives on a temporary queue the caller creates — which that +scope does not cover, and should not: a module that only publishes events has no business declaring +queues. + +So the account is right and the request is reasonable, and there is no account that can make it. + +## Why this matters + +**A module's tools are its operator-facing surface, and nothing can reach it.** The catalogue serves +five: what this mesh holds, what a module is made of, what provides a given provision, what depends +on a module, and what is stale. Those are the questions the catalogue exists to answer, and today +the answer to "how does anyone ask one" is that they run a container joined to the broker's network +namespace and authenticate as the substrate's bootstrap admin. + +**It is why a running module gets mistaken for a working one.** A test that cannot ask a module +anything checks that its container is up, and a container being up is not a claim about function. +That substitution has now hidden two separate faults in one week — a crash-looping runtime beside a +healthy container of a similar name, and a catalogue that was never installed at all. + +**The mesh already has the shape for this.** An account scoped to a purpose, minted by the mesh and +sealed to a holder, is exactly what provisioning does. What is missing is the recognition that +*asking* is a use of a module, the way pulling is a use of the artifact store +([042](../042-nothing-gives-a-node-an-account-for-a-registry/00-report.md)) rather than something +that happens beneath it. + +## Evidence + +The refusal above, from a module invoking its own tool with the credential the mesh gave it. The +working alternative, which is the measure of the gap: + +``` +docker run --rm --network container: \ + -e MESH_BROKER_URL=amqp://@127.0.0.1:/ \ + invoke '{}' +``` + +That is the bootstrap credential, host-local, with no scope at all. It works, and nothing about it +should be how a mesh is asked a question. + +## Open questions + +- **Who is the caller?** An operator at a terminal, an agent acting for one, and another module are + three different holders with three different scopes, and only the last resembles anything the + mesh mints today. +- **Should calling be a grant like any other** — 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 queue? +- **Should the control plane be the way in?** It holds an admin connection already, and a + `mesh-control` subcommand for asking a module a question would need no new account — at the cost + of routing every question through one process and its privileges. +- **What does a module declare about being asked?** Serving a tool is already declared. Whether it + may be asked by anyone who can reach the broker, or only by named holders, is not.