Files
hq/01-RESEARCH/005-domain-grouping/analysis.md
T
jschoubben e1febe8e0f Renumber the records 1 to 23
The consolidation left a sparse sequence -- 1, 4, 6, 7, 9, 10, 12, 15, 16, 18,
19, 25, 34, 35, 36, 37, 40, 42, 44, 45, 48, 49, 58 -- where the gaps were only
the archaeology of what used to be there.

Renumbered contiguously. Renames run in ascending order, so every target number
is already free and no two files ever collide.

The reference rewrite is one simultaneous pass rather than a sequence of
replacements. Numbers moved into slots other numbers were vacating -- the node
host went 37 to 16 while the lab went 16 to 9 -- so replacing one at a time
would have cascaded and silently pointed things at the wrong record.

Seven plain-text references survived the merges as prose rather than links,
naming records that no longer existed: the enrolment token, the link boundary,
what a declaration is, reachability, the repository structure. Each mapped to
the consolidated record that now holds it.

Verified rather than assumed: every [ADR NNNN](path) link now has matching text
and target, checked across the whole repository, and the checker passes.

Frontmatter `consolidates:` lists dropped -- they named records that are gone,
and each consolidated record already says in prose what it absorbed.
2026-08-28 23:28:34 +02:00

6.8 KiB

effort, updated
effort updated
005-domain-grouping 2026-08-23

Which modules actually change together

Method

Every commit in the code repository's main branch that touches the module catalogue, reduced to the set of modules it touched. Platform-namespace modules are excluded — their decomposition is settled by ADR 0008. Modules that no longer exist are excluded, because pre-rename names dominate the raw signal and describe a catalogue nobody works in.

Commits touching more than eight modules are excluded from pair counting: a sweep across forty modules says the sweep happened, not that the modules are related.

Finding 1 — these modules overwhelmingly change alone

Measure Value
Non-platform modules today 89
Commits touching at least one 312
Commits touching two to eight together 33 — 10%
Modules that never co-change with anything 50 of 89

Nine commits in ten touch exactly one module. More than half the catalogue has never been edited alongside anything else.

This is the first thing a grouping proposal has to survive, and it is not what the premise predicts.

Finding 2 — two clusters exist

Everything above two co-changes falls into one of two groups.

The provisioned infrastructure providers. The densest cluster: the relational stores with each other and with the cache, the broker, the object store and the image registry — a strongly connected set, six to two co-changes per pair.

Reachability. The reverse proxy with the resolver, the firewall and the VPN; the firewall with the intrusion filter. Three to two co-changes per pair.

Outside those: a torrent client with the VPN, twice. A login manager with a media player, twice. Nothing else reaches two.

Finding 3 — the provider cluster is manifest churn, not cohesion

This is the result that matters, and it is only visible by reading the commits rather than counting them.

Every multi-provider commit is a cross-cutting change to the machinery, applied N times:

Date What the commit did
2026-04-15 modules own their tools — decentralised tool serving
2026-04-24 filesystem-driven feature detection; manifest boilerplate removed
2026-04-27 remove runtime dependencies that were only build dependencies
2026-05-01 hooks move into their own directory with their own package
2026-05-05 hooks renamed to a stage-and-feature convention; legacy install scripts removed
2026-08-06 verify by shape in the SDK, not by copying a script into every module
2026-08-11 bind declared volume paths that leaked an anonymous volume per deploy
2026-08-23 scope services to the local network and mesh; respect the profile gate

Not one of them is a change to what a database is. They are all "the manifest contract changed, therefore every manifest changed".

Two consequences follow.

Merging the providers into one module would not have prevented a single one of these commits. It would have made the same edit land in one file rather than six — which is a diff-size improvement, not a boundary.

And the history already shows the correct fix being applied, repeatedly and successfully: verify by shape in the SDK, not by copying a script into every module. When the same edit must be made in every provider, the answer that worked was moving the concern into the machinery, not merging the modules that carry it.

Co-change here measures coupling to the manifest contract. It does not measure domain cohesion, and using it as though it did would group the catalogue by which modules are most boilerplate-heavy.

Finding 4 — reachability holds up

The same reading applied to the reachability cluster gives a different answer. Most of its twenty-five multi-module commits are the same machinery churn — but not all, and the remainder are genuine:

Date What the commit did
2026-07-29 let the mesh's proxy coexist with another listener on the same port
2026-08-03 derive public split-DNS from node accessors so requests stop hairpinning
2026-08-06 firewall mesh-only by default, public by declaration

Each is one intent — change how a node is reachable — landing across the proxy, the resolver, the firewall and the VPN together. That is exactly the shape ADR 0017 describes, and it is the only place in the catalogue where the measurement finds it.

The 2026-08-23 scoping commit is the sharpest case: it spans the reachability cluster and two providers, because "which network is this exposed on" is a reachability question asked of a database.

What this means for ADR 0017

The record's principle stands, and its scope needs narrowing. Grouping by domain is:

  • Justified by evidence for reachability. One intent, several modules, repeatedly.
  • Argued against by evidence for the providers. The coupling is to the manifest contract, and the demonstrated fix is to move the concern into the machinery.
  • Unsupported either way for the fifty modules that co-change with nothing. Silence is not evidence of independence — many are simply rarely touched — but there is no measured basis for grouping them, and a proposal that groups them is drawn from intuition. It should say so.

The catalogue's shape is still wrong in the way the record describes. Measurement says grouping is the right fix in fewer places than the record implies, and that a second fix — moving cross-cutting concerns into the machinery — accounts for most of what looks like grouping pressure.

Recommendation on the provisioning reference

Asked directly, and stated as an opinion because it is not yet decided.

Do not group the provider modules. Three reasons, in order of weight:

  1. The evidence for grouping them is the wrong evidence. Finding 3.
  2. A requirement names a provider module. Grouping providers means a consumer names a resource type and something else chooses the implementation. That is not a folder move; it is implementation selection, a substantially larger design with its own failure modes, and nothing currently asks for it.
  3. It would hide which implementation serves a requirement — the one place the mesh most needs to be explicit, and precisely the indirection ADR 0017 warns grouping causes.

A provider module is already exactly one purpose: it provisions one resource type. That is a boundary, not an accident of installation.

Still to do

  • Draw the list for the cases where grouping is justified, and say plainly which entries rest on measurement and which on judgement.
  • Decide the ~50 silent modules: correctly sized, or unmeasured?
  • Test the reachability grouping against the migration cost — the modules in it are among the most-changed in the catalogue, so churn during a move is not hypothetical.