ADR 0192: a tools bundle declares what it is given, and the runtime hands it to that bundle alone; research 020 graduated; design 38 WP4b
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
---
|
||||
status: active
|
||||
status: graduated
|
||||
initiated: 2026-10-03
|
||||
touches: [the tool runtime, the catalogue's tool bundles, the controller's declaration composer, settings, own secrets, 03-DESIGN/01-to-be/38-building-the-operators-machine.md]
|
||||
became: []
|
||||
became: [02-DECISIONS/0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md, 03-DESIGN/01-to-be/38-building-the-operators-machine.md]
|
||||
---
|
||||
|
||||
# 020 — What a bundled tool is given
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
---
|
||||
topic: what runs on it
|
||||
status: accepted
|
||||
date: 2026-10-03
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md
|
||||
---
|
||||
|
||||
# 192. A tools bundle declares what it is given, and the runtime hands it to that bundle alone
|
||||
|
||||
## Context
|
||||
|
||||
[ADR 0175](0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md) put one
|
||||
runtime on every node serving every module's tools from a bundle, and
|
||||
[ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md)
|
||||
said a module's own code is bundles and never an image. The two holders that moved first
|
||||
([to-be 38](../03-DESIGN/01-to-be/38-building-the-operators-machine.md) WP4) needed nothing a
|
||||
bundle does not have: a fixed path, and root. Research
|
||||
[020](../01-RESEARCH/020-what-a-bundled-tool-is-given/00-overview.md) measured the rest before
|
||||
they move: thirty-three modules still run their tools as a container on the runtime's image, and
|
||||
thirty-one of them are handed, through the container's environment and mounts, things a bundle
|
||||
has no way to receive — the module's configuration file, its own secret as a file, the service's
|
||||
address with the port the mesh chose, a provision's address, a directory of grants. Every one of
|
||||
those is a file the mesh already places on the machine or a value the controller already composes
|
||||
for the container, per module per machine, from references the manifest writes: a placed
|
||||
directory, a chosen port. And the SDK's tool contributor is a function of an environment that the
|
||||
runtime calls without one, so every bundle reads the process's four words.
|
||||
|
||||
Without a rule, each of the thirty-one would answer the question its own way, and the runtime's
|
||||
process would be the one place where every module's paths meet.
|
||||
|
||||
## Considered Options
|
||||
|
||||
1. **The bundle declares its environment on its artifact, and the mesh composes it as a
|
||||
container's.** Chosen. The tools artifact gains `env`: names to values, the values written with
|
||||
the references the composer already resolves for a container — `${dir:…}`, `${port:…}` — and
|
||||
what was a mount target becomes the host path itself. The controller composes one environment
|
||||
per bundle per machine into the runtime's declaration. The runtime hands it to that bundle's
|
||||
contributor, or to the child it launches, and to nothing else. The tool code reads the names it
|
||||
read before.
|
||||
2. **The runtime derives it from the module's placed manifest** — a conventional word per
|
||||
directory and port, no new field. Rejected: a convention the thirty-one tools must be rewritten
|
||||
to, the runtime learning the composer's job, and a module that names its file one way and a
|
||||
module that names it another needing different words regardless.
|
||||
3. **The tool asks the controller over the bus.** Rejected: a tool that cannot start until the
|
||||
bus answers fails in the one case tools exist for, and a secret crossing the bus to reach a file
|
||||
already on the machine is a disclosure for nothing.
|
||||
4. **Leave each module to its own device.** Rejected by the measurement: thirty-one modules, one
|
||||
question.
|
||||
|
||||
## Decision
|
||||
|
||||
**1. A tools bundle says what it is given, on its artifact.** `build.artifacts[].env` names the
|
||||
words the bundle reads and their values. A value is a path or a constant, composed with the
|
||||
references a container's environment may use; **never a secret's content.** A secret reaches a
|
||||
tool the way it reaches a container: as a file the mesh places, whose path the environment names.
|
||||
A bundle that declares no `env` is given nothing beyond the runtime's own words, which is what the
|
||||
two holders that moved have.
|
||||
|
||||
**2. The mesh composes it, per bundle per machine, as it composes a container's.** The same
|
||||
references, resolved the same way, to the host's own paths. The composed environment travels in
|
||||
the node's declaration beside the bundle's archive; a change to it is a change to the bundle for
|
||||
the purpose of `restart-on`.
|
||||
|
||||
**3. The runtime hands each bundle its own environment, and nothing of another's.** A bundle
|
||||
imported into the runtime's process receives it as the argument its contributor is written to
|
||||
take; a bundle launched as a child ([ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md) §2)
|
||||
receives it as the child's environment, over the runtime's own words. The runtime's process
|
||||
environment is not where a module's words go, and a tool that reads the process's environment
|
||||
rather than the one it was handed finds the runtime's four words and no module's.
|
||||
|
||||
**4. The remaining tool containers move in one change** after this is built, each proven by its
|
||||
tools answering from the runtime, and the registration gate of
|
||||
[to-be 38](../03-DESIGN/01-to-be/38-building-the-operators-machine.md) WP2 then refuses the
|
||||
container shape for every module, as ADR 0188 already provides.
|
||||
|
||||
## Consequences
|
||||
|
||||
- The manifest gains one field on one artifact kind; the composer gains one more thing to resolve
|
||||
with references it has; the runtime gains the hand-off and the separation. The thirty-one modules'
|
||||
tool code does not change, and their conversion is the move of a container's `env` with its
|
||||
mounts folded into host paths.
|
||||
- A tool's inputs become legible in the manifest where its container hid them in mounts: what a
|
||||
module's tools read is declared beside what the module writes.
|
||||
- What got harder: the runtime must keep thirty-one environments apart in one process, and a
|
||||
bundle's author must not reach for the process's environment. The separation is a rule the
|
||||
runtime's test holds, not a property of the language.
|
||||
- `MESH_BROKER_FILE` is not a bundle's to declare: the runtime speaks with the node's credential
|
||||
([ADR 0175](0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md)), and
|
||||
a module's own bus credential went with its container.
|
||||
|
||||
## How it is checked
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| A value in a bundle's `env` is a path or a constant, never a secret's content | the catalogue's manifest check refuses a `${secret:…}` reference in a bundle's `env`, naming this record |
|
||||
| The composer resolves a bundle's `env` as a container's | the controller's composition test: one module, one bundle with `${dir:…}` and `${port:…}` in its `env`, the declaration carrying the host paths and the chosen port |
|
||||
| Each bundle sees its own environment and no other's | the runtime's test: two bundles with different `env`, loaded in one runtime, each answering with its own words and none of the other's; the same for a launched bundle |
|
||||
| A change to a bundle's environment restarts the runtime | the composition test above, with `restart-on` naming the bundle |
|
||||
| Live | a module whose tools read a configuration file and a token file answers from the runtime on one machine with no container |
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0175](0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md),
|
||||
[ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md)
|
||||
- Research [020](../01-RESEARCH/020-what-a-bundled-tool-is-given/00-overview.md) — the measurement
|
||||
and the options
|
||||
- [to-be 38](../03-DESIGN/01-to-be/38-building-the-operators-machine.md) — where the work is listed
|
||||
@@ -291,6 +291,7 @@ python3 00-META/checks/index.py fail if stale
|
||||
- **0182** — [Inside a home, the mesh owns the directory and the files it places, writes into the tool's own files, and holds everything else as found](0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md)
|
||||
- **0183** — [The Anthropic licence manager is a module holding a seat; it hands each node's agent its token over the bus, sealed; the controller and the host have no part](0183-the-anthropic-licence-manager-is-a-module-and-hands-tokens-to-the-agent-over-the-bus.md)
|
||||
- **0188** — [A module's own code is bundles in any language, and a tools bundle speaks MCP to the runtime](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md)
|
||||
- **0192** — [A tools bundle declares what it is given, and the runtime hands it to that bundle alone](0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md)
|
||||
|
||||
### How it is built
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ decisions:
|
||||
- 02-DECISIONS/0160-the-mesh-issues-an-assignments-subjects-and-a-runtime-serves-what-it-is-issued.md
|
||||
- 02-DECISIONS/0149-the-live-mesh-is-the-test-bed.md
|
||||
- 02-DECISIONS/0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md
|
||||
- 02-DECISIONS/0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md
|
||||
---
|
||||
|
||||
# 38. Building the operator's machine
|
||||
@@ -222,8 +223,27 @@ proven on all four machines — `status`, `banned` and the module's own `fail2ba
|
||||
the runtime, no `mesh-fail2ban` container, the runtime serving both bundles. Two holders moved; of the
|
||||
thirty-three tool containers the catalogue held, thirty-one remain, and all but these two carried their
|
||||
module's configuration and secrets in the container's environment, which a bundle does not have — the
|
||||
question research [020](../../01-RESEARCH/020-what-a-bundled-tool-is-given/00-overview.md) opens
|
||||
before the rest move.
|
||||
question research [020](../../01-RESEARCH/020-what-a-bundled-tool-is-given/00-overview.md) opened
|
||||
and [ADR 0192](../../02-DECISIONS/0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md)
|
||||
settled the same day: a tools bundle declares `env` on its artifact, the composer resolves it as a
|
||||
container's, the runtime hands each bundle its own. That is WP4b below.
|
||||
|
||||
## WP4b — Every tool container moves
|
||||
|
||||
*mesh-controller, mesh-tools, mesh-catalog. One day. The rest of ADR 0175, under ADR 0192.*
|
||||
|
||||
**What changes**, in order: the manifest's tools artifact gains `env` and the catalogue check
|
||||
refuses a secret's content in it; the composer resolves a bundle's `env` per machine and carries it
|
||||
beside the bundle's archive, `restart-on` included; the runtime hands each bundle its own
|
||||
environment — the contributor's argument for an imported bundle, the child's environment for a
|
||||
launched one — and a test holds two bundles apart. Then the thirty-one remaining tool containers
|
||||
move in one change: each container's `env` becomes its tools artifact's, mount targets folded into
|
||||
the host paths they came from, the container, its base images, its Dockerfile and its own bus
|
||||
credential gone. Last, the registration gate refuses the container shape for every module.
|
||||
|
||||
**Proof.** The controller's and the runtime's tests named in ADR 0192; live, every module's tools
|
||||
answer from the runtime on the machines that run it, `docker ps` shows no tool container on any of
|
||||
the four, and `status` is well.
|
||||
|
||||
## WP5 — The shell, on a server first
|
||||
|
||||
|
||||
Reference in New Issue
Block a user