ADR 0159: a tool call names the machine, every answer says which answered, a holder's runtime serves its seat's verbs; issue 182; designs 33 and 34
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
||||
---
|
||||
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)
|
||||
@@ -172,6 +172,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0156** — [An artifact is what a build produces, the artifact store serves every kind, and its seat is named for its scope](0156-an-artifact-is-what-a-build-produces-and-the-store-is-named-for-its-scope.md)
|
||||
- **0157** — [A build says what it does on the bus, as it happens](0157-a-build-says-what-it-does-on-the-bus-as-it-happens.md)
|
||||
- **0158** — [A provider with one credential shares it with every consumer, and the vault remakes it for all of them at once](0158-a-provider-with-one-credential-shares-it-with-every-consumer.md)
|
||||
- **0159** — [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](0159-a-tool-call-names-the-machine-and-a-holder-serves-its-seats-verbs.md)
|
||||
|
||||
### Its tiers, from the bottom up
|
||||
|
||||
|
||||
Reference in New Issue
Block a user