--- topic: what runs on it status: accepted date: 2026-09-04 deciders: jochen reconstructed: false extends: 0027-a-provision-names-what-the-consumer-is-coupled-to.md --- # 46. A module's configuration is its assignment's, not its manifest's ## Context A module is assigned to a node — `assign `, always to a machine; there is no assignment to the mesh. "Mesh" is a *scope*, not a place: a `provides` or a `claim` scoped `mesh` reaches the whole mesh, but the module still runs on a node. So the two kinds of thing a module can carry are the manifest (what the module *is*) and, separately, what it should do *here* — which differs by deployment and by node. The mesh already has the second: **settings**. `settings set [--node ]` — with a node it is that machine's, without it the whole mesh's — layered over what the module declares and applied at resolution, changeable without editing the module and without a rebuild. That is the surface a meshboard would edit. But settings today reach only a module's **config-file content** (a mergeable file the module owns). Configuration that is not a file has been landing in the manifest instead, statically — a registrar's zone and domain, the address public names point at, and, most sharply, `listens.from`. That last one is the tell: whether a port is open to the private overlay or to the public internet is a *per-node deployment choice* — the same database internal on one machine and public on another — and a value fixed in the manifest is one value for every machine, so it cannot be. Static configuration in the manifest is configuration in the wrong place: it cannot vary per node, and it cannot change without a new module version. ## Decision ### The manifest is identity and defaults; the assignment's settings are the configuration A module's manifest declares what it is — what it provides, requires and claims, the shape of its resources — and, for anything configurable, a **default**. The values that make a running instance *this* instance are settings, carried by the assignment: per-node, or mesh-wide when no node is named, applied over the defaults at resolution. Change one and the next reconcile carries it; nothing is edited on a machine and nothing is rebuilt. ### Settings drive the configurable fields the manifest marks, not only file content Settings extend beyond a config file's content to the manifest fields a module declares settable — foremost: - **`listens.from`**: a module declares its safe default (`from: mesh`), and a per-node setting raises or lowers it. postgres declares `listens: [{ port: 5432, from: mesh }]`; on the machine that should expose it, a setting makes that port `from: anywhere`. Same module, different exposure, and the firewall ([ADR 0045](0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md)) is computed from the effective value, so the packet filter follows the setting. - **A provider's own configuration**: a registrar's zone, domain and the ingress its names point at ([ADR 0044](0044-a-public-name-is-provisioned-like-any-capability.md)) are mesh-wide settings, not manifest constants — one mesh's Cloudflare zone is not another's, and the module description is the same for both. ### Unset is the default, and an unknown setting is refused A field with no setting keeps the manifest's default, so a module runs correctly configured by nobody. A setting that matches no settable field — like a config value that reaches no file today — is named, not silently dropped, so a misspelled setting is found rather than believed (the discipline of `UnusedSettings`, and of [ADR 0043](0043-a-module-broker-account-is-scoped-by-emits-and-consumes.md): a declaration is enforced or it is a comment). ## Consequences - The postgres case works: one module, `from: mesh` by default, `from: anywhere` where a setting says so — internal on ace, public on novox, changeable live. - Provider modules stop carrying a mesh's specifics: `cloudflare-dns` describes *a Cloudflare registrar*, and *which* zone and ingress is a setting, so the same module serves every mesh. - Configuration becomes a thing a meshboard manages — set per node or mesh-wide, applied on the next reconcile — rather than a manifest edit and a rebuild ([ADR 0011](0011-managed-files-are-generated-never-edited.md): the way you change a managed thing is not by editing it). - What a manifest may not do is grow a value that differs per machine; if it differs per machine it is a setting, and the manifest holds only the default. ## References - [ADR 0027](0027-a-provision-names-what-the-consumer-is-coupled-to.md) — what is provisioned on declaration; its per-instance values are the assignment's. - [ADR 0011](0011-managed-files-are-generated-never-edited.md) — a managed thing is changed through the mesh, not by editing it; settings are that, for configuration. - [ADR 0045](0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md) — the firewall follows the effective `listens.from`, so making `from` a setting makes exposure a setting. - [ADR 0044](0044-a-public-name-is-provisioned-like-any-capability.md) — the provider whose zone and ingress are settings, not manifest constants.