123 lines
8.2 KiB
Markdown
123 lines
8.2 KiB
Markdown
---
|
|
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.
|
|
|
|
> **Progressive insight — 2026-10-03.** The context above calls the thirty-one remaining containers
|
|
> tool containers handed what a bundle cannot receive. Measured the same day while building this
|
|
> record: nine of them run only tools; three run a main of their own; twenty import, beside their
|
|
> tools, the module's own long-running code — event handlers that subscribe on the bus and
|
|
> provisioners that act on grants — under the module's own bus identity, and some reach their
|
|
> service by a container network name or need a package the image installed. That code is not a
|
|
> tool and is not this record's to move: under
|
|
> [ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md)
|
|
> §3 it is a `process` bundle, and how it is given its credential, its words and its reach is the
|
|
> open question of [design 38](../03-DESIGN/01-to-be/38-building-the-operators-machine.md) WP4c.
|
|
> Decision 4 applies to these containers' tools; the containers themselves go when their other
|
|
> code has moved. The decision and its options stand.
|
|
|
|
## 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
|