Files
hq/03-DESIGN/00-as-is/10-module-catalogue.md
T
jschoubben 333356cff3 Order the records the way the system is learned
Jochen asked whether the order made sense. It did not -- it followed when
things happened to be decided, which after consolidation is fictional anyway
since record 5 alone folds decisions taken across a week.

Concretely wrong before: the domain statement sat at 8, after five engineering
rules; the constitution was scattered across 5, 12 and 17; the tiers landed at
15, 16, 21 and 22 with process records in between.

Now it walks: what the mesh is (1-3), its tiers from the bottom up (4-8), what
runs on them and how it gets there (9-10), how it is built (11-16), how it is
checked (17-18), how we work (19-23).

Two things made this safe rather than free. It is a permutation, not a
compaction, so the renames go through temporary names -- otherwise two files
want one slot and one is lost. And the reference rewrite is a single
simultaneous pass, because almost every number moved into a slot another number
was vacating; replacing one at a time would have cascaded and pointed things at
the wrong record while still resolving.

Verified: 284 [ADR NNNN](path) links across the repository, all with matching
text and target.

The ordering principle is now stated in 19 rather than left implicit -- the
repository already said "the numbering is the flow" about its folders, and
there was no reason for the records to be the exception.
2026-08-28 23:30:42 +02:00

127 lines
6.9 KiB
Markdown

---
layer: as-is
status: implemented
code: [hal]
updated: 2026-08-23
decisions:
- 02-DECISIONS/0009-modules-and-the-graph.md
- 02-DECISIONS/0015-applications-live-in-their-own-repository.md
- 02-DECISIONS/0009-modules-and-the-graph.md
---
# The catalogue, and what its shape says
The catalogue holds **124 modules**. Thirty-three belong to the mesh's own domain; the other
ninety-one run *on* the mesh rather than being *of* it
([ADR 0001](../../02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md)).
The count is not the finding. The **shape** is.
## How it is organised today
By namespace, and the namespace records origin rather than purpose:
- **The mesh's own namespace** holds the platform: the runtime and its daemons, the shared
library, delivery, provisioning, configuration synchronisation, knowledge, identity, the
board, developer tooling, and node presentation.
- **A second namespace** holds the work domain — tasks, workflows, agents, meetings — split
across a handful of packages that share one schema.
- **Everything else sits flat at the top level**, one directory per piece of software.
## What the flat level actually contains
Grouped by what they are *for* — a grouping the catalogue itself does not express:
| Purpose | Roughly |
|---|---|
| Data and storage services the mesh provisions against | Relational and document databases, a cache, an object store, a package registry, a time-series store |
| Messaging and identity | A message broker, an identity provider |
| Reachability | A VPN, a firewall, an intrusion filter, an SSH daemon, a resolver, a certificate authority, a reverse proxy, network equipment control |
| Forge and container plumbing | Forge integrations, an image registry, container lifecycle and retention |
| Media libraries | Acquisition, organisation, playback, transcoding, streaming |
| Workstation and desktop | Browser, file manager, monitors, session management, audio, package management, runtime managers |
| Hardware-specific support | Power and firmware control for particular hardware, filesystem management |
| Collaboration and productivity | File sync, office tooling, boards, automation, chat and messaging bridges, mail, analytics, dashboards, home automation, issue trackers and wikis |
| Third-party organisation integrations | Systems belonging to organisations outside the mesh |
Every row is several modules, and **no row is a thing the mesh can see**. Four modules
together constitute "how a node is reachable", and they have no relationship the mesh can
assign, version, reason about or replace as one unit. A change to how the mesh handles
connectivity is made four times.
## What the shape records
**The catalogue's shape records what was installed, not what anything is for.** One module is
the unit of one piece of software, because that is the only granularity the module system
offers.
This is the same failure [ADR 0001](../../02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md)
names for the platform core — *boundaries drawn by deployment accident rather than by domain* —
appearing outside it, at four times the scale. The core is being recomposed; the flat level is
addressed in principle by
[ADR 0009](../../02-DECISIONS/0009-modules-and-the-graph.md), which
deliberately does not yet settle the domain list.
## Where the shape came from
The catalogue's shape is not arbitrary and it is not a series of mistakes. **This repository
began as a dotfiles repository**, and most of what looks inexplicable is inherited from that
directly.
The evidence is in the first two days of history: *adopt desktop dotfiles and scripts from the
original dotfiles repository*; *per-node dotfile overrides*; *service symlinking, node
`.dfignore`, headless server support* — all on 2026-02-24 and 2026-02-25, before anything
resembling a mesh existed. Forty-five commits mention dotfiles.
Read that way, several things stop being puzzles:
| Feature of today's shape | Dotfiles ancestor |
|---|---|
| One flat directory per piece of software | Exactly how a dotfiles repository is organised |
| **Linking rather than copying** as a stated design principle | How every dotfiles manager works — the whole category is built on it |
| **Adoption** — taking over a machine that already exists, with its own configuration | The core dotfiles verb, and the reason a machine could be brought in at all |
| **Per-node overrides** | Per-host dotfile overrides, generalised into per-node module settings |
| Desktop and workstation modules — browser, file manager, editors, session, audio, personal scripts | Dotfiles content that became "modules" when modules became the only unit |
| An ignore file controlling what is placed on a machine | A dotfiles manager's ignore file |
The generalisation from *place files on my machines* to *manage a mesh of nodes* was the right
move and it worked. What it did not do is revisit the assumptions underneath, because they were
never stated as assumptions — they were just how the thing already worked.
**This is the most useful single fact for anyone changing the catalogue**, and it is why the
linking principle in particular reads as a deliberate architectural choice when it is an
inheritance. See [ADR 0012](../../02-DECISIONS/0012-the-mesh-creates-no-symlinks.md), whose case
this strengthens: the argument for links was never made *for a mesh*.
It also explains the measurement in
[research 005](../../01-RESEARCH/005-domain-grouping/analysis.md). Fifty modules that never
change alongside anything are not fifty missing domains — many are dotfiles-era entries for one
piece of software, which never shared a domain because they never had one.
## Two properties worth keeping
Whatever replaces the shape, two things about it are right.
**Uniformity.** A media server and the mesh's own coordinator are installed, provisioned,
delivered and verified by identical machinery. The mesh's own components hold no privilege —
which is what makes dogfooding structural rather than a discipline, and what makes moving a
module out of the repository safe.
**Placement is already decided.** A standalone application belongs in its own repository
([ADR 0015](../../02-DECISIONS/0015-applications-live-in-their-own-repository.md)), and reviewers reject
it in the monorepo. The catalogue's flat level is not a dumping ground by policy; it is one by
history.
## Known inconsistencies in the catalogue itself
Recorded because a reader will meet them:
- A documented requirement that every capability-exposing module declare the core runtime as a
dependency is met by **zero** modules.
- A firewall-scoping key is declared by five manifests and read by none
([`04-ISSUES/003`](../../04-ISSUES/003-firewall-scope-is-read-by-no-code/00-report.md)).
- A connections block in the manifest is metadata: it describes a module's reachability and
wires nothing.
- At least one module deliberately runs outside the standard per-module supervision, for
reasons recorded in the operational memory. The standard path is not universal.