100 lines
6.7 KiB
Markdown
100 lines
6.7 KiB
Markdown
---
|
|
topic: the mesh
|
|
status: accepted
|
|
date: 2026-10-01
|
|
deciders: jochen
|
|
reconstructed: false
|
|
extends: 02-DECISIONS/0152-the-operators-surface-is-a-module-the-console.md
|
|
---
|
|
|
|
# 159. A tool call names the machine it is for, every answer says which machine answered, and a holder's runtime serves its seat's verbs
|
|
|
|
## Context
|
|
|
|
[ADR 0152](0152-the-operators-surface-is-a-module-the-console.md) made a module's tools subjects on
|
|
the bus and the console the place a person reaches them. [ADR 0154](0154-the-meshs-own-verbs-are-the-controller-seats-tools.md)
|
|
made the mesh's own verbs the controller seat's tools, served by the controller. Design 33 said what
|
|
a seat's tools are, that holding a seat means serving them, and that a node-scoped seat's verb
|
|
carries the machine.
|
|
|
|
What was built stopped short in two places ([issue 182](../04-ISSUES/182-a-tool-call-reaches-whichever-instance-answers-first/00-report.md)).
|
|
A module's tools were one subject per module in one queue group, so with the database engine on two
|
|
machines a call reached whichever instance answered first, unnamed, and nobody could ask one machine's.
|
|
And no module served the verbs of a seat it held: the runtime did not know which seats its module
|
|
claimed, and no seat but the controller's declared verbs. The operator named it: a tool call must be
|
|
able to say *the store on the control node*, and the engine holding the store seat must serve the
|
|
store's tools as well as its own.
|
|
|
|
## Considered Options
|
|
|
|
1. **Leave the queue group and ask the controller which machine answered.** Nothing changes on the
|
|
bus; a caller cannot choose, only learn afterwards. Useless for the question that was asked.
|
|
2. **A subject per machine instead of one per module.** Every call names a machine; a stateless
|
|
module on three machines loses the one-of-them answer a queue group gives for free, and every
|
|
caller has to know where things run.
|
|
3. **Both subjects, and the machine in every answer.** An instance serves its module's subject in the
|
|
queue group as before, and the same subject with its machine as the last token. A caller that
|
|
names no machine gets one instance and is told which; a caller that names one gets that one. The
|
|
grant for a tool covers both. And a holder's runtime serves its seat's verbs by the same means,
|
|
from what the credential tells it.
|
|
|
|
## Decision
|
|
|
|
**Option 3.**
|
|
|
|
- **Two subjects per tool, one default.** `mesh.mod.<module>.tool.<tool>` in the queue group, and
|
|
`mesh.mod.<module>.tool.<tool>.<node>` served by the instance on that machine alone. In the
|
|
caller's words, `<module>.<tool>@<node>`. A runtime that does not know its machine serves only the
|
|
first, which is what it always did.
|
|
- **Every answer says which machine answered.** The reply carries the node; the console appends
|
|
*answered by <node>* as its own line after the module's unshaped answer, and `mesh call` prints it.
|
|
An answer from a module on several machines is never an answer from nowhere.
|
|
- **The console offers the machine on every module tool** as an optional `node` argument, lists it,
|
|
strips it into the subject and never passes it to the module. A seat's verb takes none: the seat's
|
|
scope decides where it is served.
|
|
- **The grant covers both subjects.** `invokes: [<module>.<tool>]` permits the plain subject and the
|
|
machine-addressed one; `*` already permitted everything beneath `tool`.
|
|
- **A holder's runtime serves its seat's verbs.** The broker credential the mesh writes names the
|
|
seats the module claims and, for each, its scope and the verbs the seat promises. The runtime
|
|
serves each verb with the module's tool of the same name on the seat's own subject — flat for a
|
|
mesh seat, with the machine for a node-scoped one — and the bus admits that subscription only
|
|
where the module holds the seat, because the holder's grant is composed from the holding. A
|
|
claimant that does not hold the seat here is refused the subscription and serves nothing. A
|
|
claimant missing a tool a seat promises is already refused at registration (design 33 §3).
|
|
- **The store seat's first verbs**, so the operator's question has an answer: `databases`, every
|
|
database the store holds with its owner and size, and `query`, one read-only statement against one
|
|
database. The database engine serves both as tools of those names and lists them in its definition.
|
|
Which verbs a seat serves is a decision per seat and binds every holder; these two are the smallest
|
|
set that makes the store askable.
|
|
|
|
## Consequences
|
|
|
|
- *List the databases of the store on the control node* is `mesh-store.databases` through the seat,
|
|
answered by its holder wherever it sits, or `postgres.databases@novox` through the module on one
|
|
named machine. Both say who answered.
|
|
- Every module's runtime serves one more subscription per tool and, for a claimant, one per promised
|
|
verb. No manifest changes for the per-machine half; the seat half needs each holder's definition to
|
|
list the seat's verbs among its tools, which registration already demands.
|
|
- The runtime change reaches a module when the module is rebuilt on the new runtime image; until
|
|
then that module answers only on its plain subject, and a call naming its machine is refused as
|
|
unserved, in words that say so.
|
|
- The credential gains `claims`; a module issued before this carries none and serves no seat verb
|
|
until it is issued again. `rollout mint` for the holders is the one-time cost.
|
|
|
|
## How this is checked
|
|
|
|
| Rule | Checked by |
|
|
|---|---|
|
|
| A call naming a machine reaches that machine's instance; an unnamed call reaches one and says which | mesh-tools, against a real bus: a module on two machines |
|
|
| A claimant serves a seat's verb on the seat's subject, and the answer names the machine | the same test |
|
|
| The console lists `node` on a module's tool and not on a seat's verb, and the answer carries *answered by* | mesh-tools, the MCP conformance test |
|
|
| The grant for a tool covers the plain and the machine-addressed subject | `TestInvokingAToolMayAddressTheMachineToo` (controller) |
|
|
| Live: the store's databases listed from the control node by name through the console, and through the store seat | done by hand after the roll-out and the catalogue's step |
|
|
|
|
## References
|
|
|
|
- [ADR 0152](0152-the-operators-surface-is-a-module-the-console.md) — extended: the surface carries the machine
|
|
- [ADR 0154](0154-the-meshs-own-verbs-are-the-controller-seats-tools.md), [ADR 0132](0132-a-seat-carries-the-tools-its-holder-must-serve.md) — the seat half, now for every holder
|
|
- [Design 33 — The tools the mesh answers](../03-DESIGN/01-to-be/33-the-tools-the-mesh-answers.md) §3, §4; [Design 34 — The console](../03-DESIGN/01-to-be/34-the-console.md) §3
|
|
- [Issue 182](../04-ISSUES/182-a-tool-call-reaches-whichever-instance-answers-first/00-report.md)
|