diff --git a/02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md b/02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md index 644268b..54af58f 100644 --- a/02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md +++ b/02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md @@ -1,6 +1,6 @@ --- topic: what runs on it -status: proposed +status: accepted date: 2026-09-25 deciders: jochen reconstructed: false diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index 52f763b..be0909d 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -205,7 +205,7 @@ python3 00-META/checks/index.py fail if stale - **0091** — [A mount is declared, and there are three things it can be](0091-a-mount-is-declared-three-ways.md) - **0099** — [A step that runs once names what it reads, and runs again when it changed](0099-a-step-that-runs-once-names-what-it-reads.md) - **0110** — [A seat is held by one assignment, from a closed set, and it may deliver a provision](0110-a-seat-is-a-module-assignment-from-a-closed-set.md) -- **0112** — [A module definition names no node, no mesh and no path: everything it needs is a requirement the mesh resolves](0112-a-module-definition-names-no-node-mesh-or-path.md) *(proposed)* +- **0112** — [A module definition names no node, no mesh and no path: everything it needs is a requirement the mesh resolves](0112-a-module-definition-names-no-node-mesh-or-path.md) - **0113** — [The vault makes every shared secret, a provider makes resources and data, and the mesh carries both](0113-the-vault-makes-every-secret.md) *(proposed)* - **0114** — [A credential two parties hold rotates over two credentials; one a single party holds rotates in place, staged; and retiring a credential never removes what it reached](0114-a-shared-credential-rotates-over-two-credentials.md) *(proposed)* - **0115** — [One assignment of a module per node: the module's name is the assignment's identity](0115-one-assignment-of-a-module-per-node.md) *(proposed)* diff --git a/04-ISSUES/134-a-definition-may-still-name-the-mesh/00-report.md b/04-ISSUES/134-a-definition-may-still-name-the-mesh/00-report.md new file mode 100644 index 0000000..f5471d2 --- /dev/null +++ b/04-ISSUES/134-a-definition-may-still-name-the-mesh/00-report.md @@ -0,0 +1,66 @@ +--- +status: open +opened: 2026-09-28 +located-in: [mesh-catalog, mesh-controller internal/catalogue] +fixed-by: +amended-design: +--- + +# 134 — A definition may still name the mesh, and the check that would say so does not exist + +## What was observed + +[ADR 0112](../../02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md) says a module +definition names no node, no mesh and no host path, and states how that is checked: + +> A catalogue test finds no domain name in any definition value. + +There is no such test. Run by hand on 2026-09-28, across the 72 manifests in the catalogue, the +question it asks has 15 answers. They are not all the same kind of thing, and the difference matters +more than the count: + +**Values the mesh acts on** — seven: + +| module | where | what it names | +|---|---|---| +| keycloak | `env.KC_HOSTNAME` | this installation's public name for itself | +| minio | `env.MINIO_BROWSER_REDIRECT_URL` | the same, for its console | +| invoicing | a resource's `image` | a named registry rather than the mesh's artifact store | +| builder | `build.artifacts[].context.repository` | the forge, by URL | +| route-proxy | `build.artifacts[].context.repository` | the forge, by URL | +| route-adapter | a resource's `content` | a proxy's dynamic configuration | +| novox.be | `module` | the module is named after the domain it serves | + +**Prose** — eight, in `listens[].why`: de-spiegel, mailu, n8n, only-office, photos, photos-eef, +photos-filip, portainer. Each explains what a port is for and mentions the public name it is reached +by. Nothing reads these; a check written as a string search would report them, and reporting them as +violations of the same rule would be wrong. + +## Why it matters beyond this instance + +**An unenforced rule is indistinguishable from a wrong one, and costs more, because people believe +it.** The record says the mesh is name-agnostic, four design documents rest on that, and a reader +checking whether it holds finds that it does not — in the places that matter most. The two forge URLs +are what a build reaches into for its source; the two hostnames are what a service tells a browser +about itself. + +**It is the difference between a mesh and this mesh.** A definition carrying `novox.be` is a +definition that can only be installed here. The whole point of the rule is that the same catalogue +raises a different mesh with a different name, and today seven modules would need editing to do it. + +**And the shape of the fix is not the same for each.** A public name is an operator's choice about an +assignment, which ADR 0112 already provides for; a forge URL should be a path on the git seat +([ADR 0111](../../02-DECISIONS/0111-a-build-source-is-on-the-git-seat-or-external.md)); an image from a named +registry is a question about the artifact store, not about naming. Counting them together would hide +that. + +## Open questions + +- Does a domain in a `why` string break the rule? It is documentation the mesh never reads, and a + check that cannot tell the two apart will either pass things it should catch or fail things nobody + should change. +- Where does a service's public name live, concretely — a setting on the assignment, or a fact the + mesh composes from the node's domain? ADR 0112 says a requirement the mesh resolves; the two + hostnames above are the first real cases. +- Should a build context name a repository on the git seat rather than by URL, and if so, what does + that mean for a context in *another* mesh's forge?