The five modules this report first named were what a first look found. A sweep of all 71: 49 public domains across 26, the node's own name 58 times across 19, a routable IP 12 times in one, 798 absolute paths across 70 (issue 119's number, grown), and no email addresses at all. The sharpest case is not a domain: a mail module states the node's public IPv4 as the address it trusts a real-IP header from, so a node that moves or gains a second address stops attributing mail correctly, silently. Two upstream resolvers are excluded deliberately — naming a public DNS service is a policy default, true of any mesh, not a fact about this one.
6.0 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | ||||
|---|---|---|---|---|---|---|---|---|
| located | 2026-09-26 |
|
122 — A module cannot ask for its own public name, so three manifests wrote this mesh's names into the catalogue
What was observed
Reviewing the open module changes on 2026-09-26, three of them independently put a name belonging to one particular mesh into a module definition, each for a different piece of software and each as the only way to make the software work:
- The identity provider's manifest gains
KC_HOSTNAME: https://<label>.<public-domain>as a literal, because the software generates absolute URLs and, behind a proxy, cannot derive them. - The object store's manifest gains
MINIO_BROWSER_REDIRECT_URL: https://<label>.<public-domain>as a literal, for the same reason — its console redirects to an absolute URL. - The file-sync module's S3 bucket is renamed from
nextcloudto a name carrying this mesh's own name, so the module matches a bucket that already exists here.
No reviewer introduced these carelessly: each is the value the software needs, and there is nowhere else to put it.
And they are not the first. Asked whether merging them would set a precedent, the catalogue answered no: five modules already on the main branch carry one. The clearest is the workflow automation module, whose environment file states its host, its protocol and a full absolute webhook URL as literals; two more — the proxy and the builder — carry a complete clone URL for a repository on this mesh's own forge, scheme, host and port included.
Counted properly, 2026-09-26. The five were what a first look found. A sweep of all 71 definitions, for values that could only be true of one installation:
| What is named | Occurrences | Modules |
|---|---|---|
| A public domain, or a name under one | 49 | 26 |
| The node's own name | 58 | 19 |
| A routable IP address | 12 | 1 |
| An absolute path on the machine | 798 | 70 |
| An email address | 0 | 0 |
The path row is issue 119, counted again and grown. The rest is this issue. Thirty of the seventy-one definitions name this installation in one of the first three ways, and the worst single case is not a domain at all: a mail module states the node's own public IPv4 as the address it trusts a real-IP header from, so a node that moves, or gains a second address, silently stops attributing mail to the right sender. A private subnet, the mail domain, the site name and the administrator's domain sit in the same block of values.
Two upstream resolvers are excluded from the count deliberately: naming a public DNS service is a policy default, true of any mesh that wants it, not a fact about this one.
So the three under review are the visible edge of a pattern the catalogue already follows, which changes what this issue is for. It is not a matter of refusing three changes; there is no version of this catalogue today that does not name the mesh it was written in, and a mechanism is the only thing that removes any of them.
What the mesh offers instead, and why none of it answers
A manifest may interpolate ${secret:…}, ${seat:…}, ${bound:…}, ${port:…} and
${machine:…}. The machine form resolves at, name and address — the machine's identity on the
private network. None of them yields a public name.
The mesh does compose public names: a route contribution's label is joined to the node's public
domain, <label>.<public-domain>, and the mesh interprets neither half. That happens inside the
controller when a declaration is built, and the result reaches the proxy that serves the route. It
does not reach the module that asked for the route, so a module that must tell its own software
what it will be reached at cannot read what the mesh already worked out.
So the workaround is the only expressible option: write the answer down, in the definition, for the one mesh it is true of.
Why it matters beyond these three
A module definition is meant to hold what is true of the module everywhere, with everything particular to an installation resolved at assignment — the argument ADR 0112 (proposed) makes in full, and what issue 119 found for paths. A hostname is the same kind of fact as a path, and arriving by the same route: not because anyone disagreed with the principle, but because the mechanism that would honour it does not exist yet.
The cost is concrete. A second mesh installing the identity provider from this catalogue gets the first mesh's hostname, and its login flow breaks in a way that looks like a proxy fault. Nothing checks for it: a literal hostname in an env value is a well-formed string, and no rule distinguishes it from a version number.
The bucket case is the same shape with a different subject — an adopted resource's real name is also particular to one installation, and also has nowhere to live but the definition.
Open questions
- Should a module be able to name what it will be reached at — a
route-scoped interpolation resolving to the composed public name of a route it contributes, so the answer the mesh already computes is the one the software is told? That is the smallest fix and it stays within the existing vocabulary. - Does the scheme belong to it? Every instance here wrote
https://, which is true of a route the proxy terminates and not of the module's own port. - For an adopted resource such as an existing bucket: is that a setting on the assignment (where ADR 0112 would put it), and if so what reads it — the provisioner, or the module's own values?
- What check would notice the next one? A definition naming a public domain is detectable in the shape of the value, which is more than nothing, and less than a rule.