--- status: located opened: 2026-09-30 located-in: [mesh-controller internal/catalogue/dir_into.go, mesh-controller internal/catalogue/declaration.go, mesh-catalog modules] fixed-by: amended-design: --- # 174 — The mesh's own files for a module are placed by the definition, not by the mesh ## What was observed After every module's *own* data directory was placed by the mesh ([issue 119](../119-a-module-definition-decides-where-its-files-live/00-report.md)), the catalogue still carries **232 host paths in 50 definitions**, all of one kind: where the mesh writes what it makes *for* the module — its sealed bus credential (`own-secrets.broker`), its merged config file, its bindings — under `/var/lib/mesh//…`, and the directory resource that creates that subtree. Not one of those files is the module's. The mesh mints the credential, composes the binding, merges the config; the definition only says where to put them, and says it the same way seventy times. ## Why this is here Design 27's answer to *what sits beneath a node's root* (2026-09-26) is that the mesh's writes need no module-visible reservation: **what the mesh writes for a module is the mesh's plumbing, placed where the mesh chooses and mounted in, never part of the module's contract.** The definition today names that place, so a definition is not yet free of host paths — and a node whose root is elsewhere would place the module's data there and the mesh's files still under `/var/lib/mesh`. The path-preserving test that let issue 119 close does not cover this: it proves a *placed* directory resolves to what was named, and these are not placed. ## What it would take A word for "the mesh's file for this module", or none: `own-secrets` values, a merged config file and a binding could be named by key alone, with the mesh choosing `/mesh//` and mounting it where the container says. The container side of the mount already exists in every definition (`/run/secrets/broker`, `/run/config/config.json`); only the host side would go. The change is in the controller, once, and then a mechanical edit of fifty definitions, which the same test that proved 119 can prove again with the rule extended. ## Open questions - Does `own-secrets` keep its map shape with the value becoming the *container* path rather than the host path, or does the mount stay where it is and the host side become a placeholder the mesh fills, `${mesh:}`? - A binding file today lands wherever `binds` says; a module's code reads it from an environment variable naming the container path. If the host side is the mesh's, is the container side still the definition's to choose? It should be: it is the software's contract.