--- status: accepted date: 2026-08-28 deciders: jochen reconstructed: false extends: 0064-a-build-edge-is-a-third-kind.md --- # 65. The core library is the mesh's domain, and types ship with their modules ## Context [ADR 0030](0030-the-repository-structure.md) describes the shared library as *"contracts shared across tiers: types, not behaviour"* — a guard against what the current one became, which is a package holding too much code and, with it, everybody's dependencies. **The guard is aimed at the wrong thing.** *Types, not behaviour* sounds safe and does not address the fault: a library everything depends on is a hub whether it holds types or code. The fan-in is what makes a change expensive, and *types not behaviour* leaves the fan-in exactly where it was. [ADR 0064](0064-a-build-edge-is-a-third-kind.md) makes this measurable rather than a matter of taste: a module's cost is its **inbound build edges**, and a type hub has as many as a code hub. ## Decision ### Types ship with the module they belong to A type is part of a module's contract, so it travels with the module. A consumer needing `inventory`'s types depends on **`inventory`** — a real edge, narrow and visible — instead of both depending on a hub where the relationship cannot be seen. **This trades one wide edge for several narrow ones, and that is the improvement.** Under [ADR 0064](0064-a-build-edge-is-a-third-kind.md) a change to one module's types now invalidates its actual consumers, rather than everything that touched the hub. ### The core library holds the mesh's own domain, and that is the test Not *shared code*. A drawer labelled shared is a drawer everything goes in, which is how the current one grew. > **The core library holds what is true of the mesh regardless of which context you are in.** [Research 011](../01-RESEARCH/011-the-module-graph/00-overview.md) already found what that is: **a module, a node, and an assignment.** Those three are the mesh's domain — every context speaks about them, and none of them belongs to one context. The test, applied to a candidate: *would this still mean the same thing in a context that had never heard of the one it came from?* A node does. A pipeline stage does not — that is delivery's. A grant does not — that is provisioning's. **Domain-driven is the point rather than the label.** The current library is what happens when the organising idea is *who else might want this*: the answer is always yes, so everything is admitted. *Is this the mesh's domain* has a defensible no. ### Why this stays small on its own A domain model changes when what the mesh **is** changes, which is rare. A shared-code drawer changes whenever anybody writes something reusable, which is constantly. So the core library inherits the property the graph is supposed to reveal — **few changes, many dependants** — rather than fighting for it. ## Consequences - **[ADR 0030](0030-the-repository-structure.md)'s description of the shared library is superseded.** *Types, not behaviour* is replaced by *the mesh's domain*, and its types move to the modules that own them. The rest of 0030 — the naming rule and the repository list — stands. - **A module now publishes its own contract**, which it does not do today. That is real work and it is the same work as making a module a self-contained artifact, so it is not additional. - **The check is not the one that was proposed and is better.** *The build output contains no runtime code* would have enforced *types, not behaviour* — a rule now withdrawn. What replaces it is **inbound build edges**, which is a measurement rather than a prohibition: the core library should have many, and anything else acquiring many is turning into a hub. That is visible while it happens rather than after. - **Fewer things will be shared, and some code will be written twice.** That is the trade and it should be said plainly: the current library exists because sharing felt free. Under this it has a name, an owner and a visible edge, and two similar functions in two modules is often the better answer — `how-we-build` §8 already says three similar lines beat a premature abstraction. - **Nothing here says how a module publishes its types**, and the answer differs per language. That belongs with delivery. ## References - [ADR 0030](0030-the-repository-structure.md) — the description this replaces. - [ADR 0064](0064-a-build-edge-is-a-third-kind.md) — what makes fan-in measurable. - [Research 011](../01-RESEARCH/011-the-module-graph/00-overview.md) — module, node, assignment.