Issue 118 and ADR 0112 (proposed): a module definition names no node, no mesh and no path
Issue 118 records what a review of where module code reads its files found: 789 host-path strings in 70 of the catalogue's 71 definitions, every one a decision the definition makes about a machine. Mounts are checked (ADR 0091); the same paths retyped as values are not. It records what that has already allowed — a DNS provider that would provision nobody silently, a contributions file that names credentials by host path and so forces every provider to mount at the identical path, an SDK loop that treats an unwritten contributions file as empty without a word, defaults in code that disagree with their own manifests — and that no module can be assigned to one node twice, because every identity is keyed by the module's name. ADR 0112, proposed for review, answers it the way ADR 0038 answered ports: a definition names variables, and installing it resolves every one or refuses, from three sources — the assignment's own configuration, provisions the mesh resolves against a contract, and what the mesh generates or knows. A directory becomes a provision: the module requires one by name with its owner, mode and persistence, and where it lands is the assignment's. The mesh's own files stop carrying host paths. An assignment gets an identity of its own, so a module may run twice on one node. Checking copies for agreement was rejected as checking something that should not exist; rewriting paths per assignment was rejected as inferring which strings are paths by their shape. Syntax, a node's default layout, and when a second instance becomes possible are left to the design.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
---
|
||||
status: open
|
||||
opened: 2026-09-25
|
||||
located-in: []
|
||||
fixed-by:
|
||||
amended-design:
|
||||
---
|
||||
|
||||
# 118 — A module definition decides where its files live on the machine
|
||||
|
||||
## What was observed
|
||||
|
||||
A review of where module code reads its files turned up a cross-cutting pattern. Every module
|
||||
definition in the catalogue chooses, in its own manifest, where on the machine its files live.
|
||||
Counted on the catalogue's `main`, 2026-09-25:
|
||||
|
||||
| where in the definition | host-path strings |
|
||||
|---|---|
|
||||
| directory and file resources | 257 |
|
||||
| container mounts, host side | 230 |
|
||||
| own secrets | 78 |
|
||||
| bindings | 53 |
|
||||
| env-files | 50 |
|
||||
| secrets | 35 |
|
||||
| container environment | 28 |
|
||||
| accesses | 21 |
|
||||
| receives, grants | 24 |
|
||||
| everything else | 13 |
|
||||
|
||||
**789 host-path strings in 70 of the 71 definitions.** Mounts are checked: a container may not
|
||||
mount a path its module never declared ([ADR 0091](../../02-DECISIONS/0091-a-mount-is-declared-three-ways.md)).
|
||||
Nothing checks the same path where it is retyped as a value: an environment variable, an env-file
|
||||
line, a literal in module code.
|
||||
|
||||
### Where that has already gone wrong
|
||||
|
||||
- **A provider that would provision nobody, silently.** One DNS provider mounts its grants
|
||||
directory at a short path inside its container, then tells its provisioner to read the
|
||||
contributions file at the host path, which does not exist in there. Nothing requires the
|
||||
provision today, so it has not failed yet. When a consumer arrives, it will get no record, and
|
||||
nobody will be told.
|
||||
- **The mesh's own wire carries host paths into containers.** Each contribution names its
|
||||
consumer's credential as "the file on this machine holding that consumer's credential", a host
|
||||
path computed from the provider's grants directory. So every provider has to mount that directory
|
||||
at the *identical* path, or it cannot read what it was given. Eleven of the twelve providers do.
|
||||
It is a convention nothing states or checks, and the twelfth is the provider above.
|
||||
- **The warning that would have caught it is lost in the SDK.** The control plane always writes the
|
||||
contributions file, even when empty, so a provider can tell "nothing asked" from "never written".
|
||||
The SDK's reconcile loop treats an unreadable file as empty, and logs nothing.
|
||||
- **Code carries copies with nothing checking them.** Several modules default a path in code when an
|
||||
environment variable is unset. Five of those defaults disagree with the value their own manifest
|
||||
sets. One of them is a host path used inside a container that does not mount it.
|
||||
|
||||
### And a module cannot be assigned to one node twice
|
||||
|
||||
Everything that identifies a running module is keyed by the module's name: its directories, its
|
||||
container names, the login it presents to a provider, its broker account. Two assignments of one
|
||||
module to one node would share every one of them. Assigning the same application twice is an
|
||||
ordinary need: production beside staging, one site per customer, two instances of one service
|
||||
configured differently, two stores of one engine.
|
||||
|
||||
## Why it matters beyond this instance
|
||||
|
||||
A definition that names machine paths is not portable between nodes. It cannot follow data onto a
|
||||
second disk, or onto a machine being adopted with its data already in place, without editing the
|
||||
module. It cannot run twice on one node. It keeps every path in two or three places with nothing
|
||||
checking that they agree. The defects above are what that allows, and each was found by reading,
|
||||
not by any check.
|
||||
|
||||
## Open questions
|
||||
|
||||
- Should a definition name any host path at all, or should every location come from the
|
||||
assignment and the mesh?
|
||||
- If a directory is something a module *requires* rather than *declares*, what is its contract:
|
||||
ownership, mode, whether it is kept when the module goes?
|
||||
- What identifies an assignment, if a module may be assigned to one node more than once?
|
||||
- What would the contributions file carry instead of host paths, so a provider needs no
|
||||
identical-path mount?
|
||||
Reference in New Issue
Block a user