Files
hq/01-RESEARCH/011-the-module-graph/cases.md
T
jschoubben ae099482a9 011: twenty cases, and two axes nothing covers
Before settling a schema, what a module can actually be. Twenty kinds of thing,
with the hard ones at the end because they are the point.

The ordinary nine are unsurprising: a supervised service, a system package with
configuration, an application a person launches, a command-line tool, a library
that never runs, a one-shot task, a scheduled one, an adapter, and a standalone
application whose only difference is where its source lives.

The eleven that break a naive schema are where the work is. Something that is a
service AND an application — a git forge is consumed as a remote and operated
through a web interface, and neither reading is wrong. Something that provides
and consumes, because provider and consumer are ends of edges rather than kinds
of module. Something the mesh installs that then becomes a node CAPABILITY,
which means a node's provides-list is partly derived from what is installed on
it and not only detected. Something that must be adopted rather than installed.
Something that is a set rather than a thing. Something with exactly one instance
for the whole mesh, where assigning it twice is not redundancy but two meshes.
Something that is not software at all — a firewall policy, a DNS record, pure
desired state, which fits the host's declaration model exactly and an installable
package model not at all. An agent. The host itself, which is not a module and
needs a schema that can say so. And the things the mesh depends on and does not
control, which are why a node can be perfectly configured and still not work.

Nine axes come out of it. Two are covered by nothing anyone has proposed: HOW
MANY INSTANCES a thing may have, and WHETHER TWO CAN COEXIST — `excludes` covers
part of the second and nothing covers the first.

And one question the cases sharpen: is "runs" a property or a kind? The axes say
property — one schema with a field saying how it runs, `never` included. The
alternative is several kinds of module with different schemas, which is the
taxonomy this effort already rejected once for services and applications.
2026-08-26 22:48:20 +02:00

7.3 KiB

What a module can be

Every kind of thing the mesh has to install, run, own or know about, before deciding what a manifest says. Written to be argued with: a case here that turns out not to exist should be struck, and one that is missing is a hole in whatever schema follows.

The hard cases are at the end, and they are the point.

The ordinary cases

1 — A supervised service. A container the mesh runs and keeps running. Nobody starts it; it is simply up. A relational store, a message broker, an object store, a dashboard.

2 — A system package with configuration. Not a container. Installed into the machine, configured through files, run by the service manager. A firewall, a resolver, an overlay. Note: ADR 0037 says applying these is the host's job — so what the module contributes is the deciding, not the doing.

3 — An application a person launches. Installed on a node, started by a human, running only while they use it. An editor, a chat client, a file manager, a terminal.

4 — A command-line tool. Installed, on the path, run when invoked. No service, no window. A formatter, a query client, a backup utility.

5 — A library. Never runs at all. Consumed at build time by other modules. An SDK.

6 — A one-shot task. Runs once, changes something, exits. A schema migration, a data import, a seed.

7 — A scheduled task. Runs repeatedly on a timer, exits each time. A backup, a prune, a report.

8 — An adapter. Exists to make several unlike things look alike behind one name. A model provider behind an assistant interface.

9 — A standalone application in its own repository. Same shape as any of the above; the difference is only where its source lives (ADR 0010). Worth listing because a schema that assumes a monorepo path would exclude it.

The cases that break a naive schema

10 — Something that is a service and an application. A git forge is consumed by other modules as a remote and a registry, and operated by a person through a web interface. A web analytics service grants a tracking identity and is a dashboard somebody reads. Neither is a service-or-application choice; both are true simultaneously.

11 — Something that provides to others and consumes from others. The store provides databases and needs a filesystem. The forge provides a registry and needs a database. Provider and consumer are not kinds of module; they are ends of edges.

12 — Something the mesh installs that then becomes a node capability. The container runtime is installed by the mesh, and once it works, the node provides container-runtime to everything else. So a module can change what its node provides. The node's provides-list is therefore partly derived from what is installed on it, not only detected from what was already there — and the two have to agree.

13 — Something that must be adopted rather than installed. The machine already has the package manager, the container runtime, possibly the version control system, each with configuration somebody chose. The module does not install it; it takes it over (research 012).

14 — Something that is a set, not a thing. Core infrastructure is not installable — it is a name for the concrete modules a working node needs. Whether that is a module whose only content is requires, or a query over the graph, or a pinned list outside the catalogue, is undecided and is one of the sharper questions here.

15 — Something with one instance for the whole mesh. There is one mesh database, not one per node. Assigning it to two nodes is not redundancy, it is two meshes. Contrast with a terminal, where per-node is the only sensible reading.

16 — Something that may be installed several times over. Two terminals coexist happily. Two things wanting port 443 do not. Two message brokers might be fine or might be a split brain, and nothing in provides and requires distinguishes those.

17 — Something that is not software at all. A firewall policy. A DNS record. A certificate. It owns no binary, runs nothing, and is entirely desired state — which is the one case that fits the host's declaration model exactly and fits an installable-package model not at all.

18 — An agent. The mesh's own premise is that agents are participants. An agent has an identity, a licence, a node it runs on, and work it does. Whether that is a module, a record in the control plane, or something else is not obvious, and getting it wrong shapes everything about how agents are assigned.

19 — The host itself. Tier 0 installs everything else and is installed by hand. It is not a module, and a schema that cannot say so has a bootstrap problem hiding in it.

20 — Something the mesh depends on and does not control. A domain registrar, an upstream resolver, a certificate authority, an electricity supply. Almost certainly not modules — but the mesh's health depends on them, and they are the reason a node can be perfectly configured and still not work.

What varies across the cases

The list above matters less than this. These are the axes a manifest has to express, and each one is a question the schema must answer or deliberately refuse.

Axis Range Sharpest case
Does it run? supervised · launched by a person · once · on a timer · never 5, 6, 7, 17
Who starts it? the mesh · a human · nothing 1 vs 3
Where does it come from? container image · system package · our source · already on the machine 12, 13
Does it provide to other modules? a resource · an abstract name · nothing 8, 11
Does it hold state? yes, and it matters where · no 1 vs 3
How many instances? one per mesh · one per node · many per node 15, 16
Can two coexist? yes · no · only with different settings 16
Is it installed or adopted? installed · adopted · either, depending on the machine 13
Does installing it change what the node provides? yes · no 12

Two of these are not in any current thinking, and both come from the hard cases: how many instances (15) and can two coexist (16). excludes covers part of the second and nothing covers the first.

Questions the cases raise

  • Is "runs" a property or a kind? The axes suggest a property — one schema, with a field saying how it runs, never included. The alternative is several kinds of module with different schemas, which is the taxonomy research 011 already rejected once for services and applications.
  • Is an agent a module? (18) If yes, the schema carries identity and licensing. If no, the mesh has two catalogues.
  • Is core infrastructure a module? (14) A module whose only content is requires is either elegant or a category pretending to be a thing — the same trap database was.
  • What names one-per-mesh? (15) Nothing in provides, requires or excludes says it, and getting it wrong means two of something that must be one.
  • Where does a policy live? (17) Pure desired state fits the host's declaration exactly. Whether it is a module at all, or something the control plane derives and no catalogue entry exists for, is open.