diff --git a/01-RESEARCH/011-the-module-graph/00-overview.md b/01-RESEARCH/011-the-module-graph/00-overview.md index d9e12b6..ae77ea9 100644 --- a/01-RESEARCH/011-the-module-graph/00-overview.md +++ b/01-RESEARCH/011-the-module-graph/00-overview.md @@ -17,6 +17,11 @@ touches: Whether the catalogue's missing structure is a **graph** — modules declaring what they need, what they offer, and what they exclude — and what that replaces. +**[`cases.md`](cases.md) enumerates what a module can be** — twenty kinds of thing the mesh has +to install, run, own or know about — and extracts the axes a manifest must express. Two of those +axes appear in no current thinking: **how many instances** a thing may have, and **whether two +can coexist**. + **The design is in [`proposal.md`](proposal.md): one kind of edge.** A module provides names and requires names, and that single relation absorbs requiring a module, requiring a resource, and the interface-and-adapter idea. An abstract name is legitimate **only where providers are diff --git a/01-RESEARCH/011-the-module-graph/cases.md b/01-RESEARCH/011-the-module-graph/cases.md new file mode 100644 index 0000000..8c0485c --- /dev/null +++ b/01-RESEARCH/011-the-module-graph/cases.md @@ -0,0 +1,128 @@ +# 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](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) 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](../../02-DECISIONS/0010-applications-live-in-their-own-repository.md)). 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](../012-the-minimum-viable-node/00-overview.md)). + +**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](00-overview.md) 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.