Files
hq/04-ISSUES/122-a-module-cannot-ask-for-its-own-public-name/00-report.md
T
jochen e399a2c148 Issue 122: the pattern is already on main, in five modules
Asked whether merging the three reviewed changes would set a precedent. It would not: five modules
already carry a name belonging to this one mesh — a workflow module stating its host, protocol and
absolute webhook URL, and two carrying a full clone URL for a repository on the mesh's own forge.

That changes what the issue is for. There is no version of this catalogue today that does not name
the mesh it was written in, so refusing three changes buys nothing and a mechanism is the only thing
that removes any of them. The three were merged on that reading, each PR saying so.
2026-09-26 15:07:22 +02:00

83 lines
4.8 KiB
Markdown

---
status: located
opened: 2026-09-26
located-in: [mesh-controller internal/catalogue/declaration.go, mesh-catalog modules/keycloak, mesh-catalog modules/minio, mesh-catalog modules/nextcloud]
fixed-by:
amended-design:
---
# 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 `nextcloud` to 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.
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](../../02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md) (proposed)
makes in full, and what [issue 119](../119-a-module-definition-decides-where-its-files-live/00-report.md)
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.