The fact-check found mailu, whose user is its mailbox, so 0114 rotates over two credentials rather than two logins, the adapter choosing what a credential is. Also: minio keeps non-empty buckets; five backends take their admin credential only at first init, so single-party rotation is staged; postgres ownership moves to a non-login role; the harness keys by consumer; rotation state lives with the vault. Consistency fixes across 0110-0113, 26 and 27; issue 103 resolved by mesh-host PR #22.
85 lines
4.3 KiB
Markdown
85 lines
4.3 KiB
Markdown
---
|
|
status: located
|
|
opened: 2026-09-25
|
|
located-in: [mesh-catalog modules, mesh-controller internal/catalogue]
|
|
fixed-by:
|
|
amended-design:
|
|
---
|
|
|
|
# 119 — 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. Ten of the eleven providers with a
|
|
grants directory do. It is a convention nothing states or checks, and the eleventh is the
|
|
provider above.
|
|
- **The warning that would have caught it is lost in the SDK.** The controller 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.
|
|
|
|
[ADR 0112](../../02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md), which answers
|
|
this report, declines that need rather than meeting it. A module is assigned at most once to a node,
|
|
because every identity in the mesh is already a module on a node. The cases above become different
|
|
modules, or the same module on different machines.
|
|
|
|
## 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?
|