diff --git a/01-RESEARCH/011-the-module-graph/features.md b/01-RESEARCH/011-the-module-graph/features.md index 82d05d4..0e2aa48 100644 --- a/01-RESEARCH/011-the-module-graph/features.md +++ b/01-RESEARCH/011-the-module-graph/features.md @@ -85,6 +85,23 @@ Nothing replaces it, because it was never one concept: | prerequisite-* | an **edge** in the graph | the catalogue | | verify, verifiers | the host's **read-back** | the host | +## Tools are a facet, and their consumer is not a module + +The most common content in the catalogue: 56 of 126 modules carry a tool surface, more than +carry a service. + +It survives the split, and it does not fit either half cleanly. A tool is not an artifact and +not node state — it is a **contract the mesh publishes on a module's behalf**, and what consumes +it is an **agent**, not another module. + +That is a second audience, and the design has only described one. A module `provides` things +other modules require; a module also `provides` things agents call. Same word, different +consumer, different lifecycle — a tool appears when the module is assigned somewhere and +disappears when it is not, and nothing in the graph edges says so. + +Whether that is one relation with two audiences or two relations is undecided, and it is the +kind of question that is cheap now and expensive later. + ## What is lost, and should not be **Detection.** Features are detected from the directory rather than declared, and the reason is diff --git a/01-RESEARCH/011-the-module-graph/worked-provider.md b/01-RESEARCH/011-the-module-graph/worked-provider.md index ac36f81..d016ac8 100644 --- a/01-RESEARCH/011-the-module-graph/worked-provider.md +++ b/01-RESEARCH/011-the-module-graph/worked-provider.md @@ -122,6 +122,54 @@ The pieces that follow, none of them settled here: - **Moving a binding moves data.** Whatever the mechanism, changing it is a migration and not a configuration change, and a design that lets it look like the latter will lose something. +## Provisioning is early, not late + +An assumption worth killing: that provisioning is something the control plane does for +consumers once a mesh is running. + +**The mesh's own registry is a provisioned database.** So is its virtual host on the broker. +Neither exists until something creates them, and nothing in the mesh works until they do. The +order is: + +``` +1 the store runs from the bundle the host carries +2 a database is created in it a provisioning step +3 the mesh's own schema is applied a migration, against that database +4 the control plane starts and only now is there a mesh +5 everything else is provisioned the ordinary path +``` + +Steps 2 and 3 happen **before there is a mesh to do them**. So provisioning is not a +control-plane service that consumers use; it is part of the bootstrap, and part of what the +carried bundle has to be able to express. + +**Which strains what a declaration is.** [ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md) +has the host applying *declared state on this machine*. A database inside a running store is not +a file or a unit — and at bootstrap it is, at least, local: the store is on the same machine as +the host applying the bundle. + +Later it is not. A consumer on one node provisioned from a store on another is the ordinary +case, and reaching it is not the host's job. So the same operation is local at bootstrap and +remote afterwards, which is either two mechanisms or one mechanism with a boundary crossing in +it. Undecided, and it is the sharpest unresolved thing in this file. + +## A migration belongs to the consumer and runs on the provider + +A game defines migrations. They run against the database the store granted **it**. So the +migration is: + +- **owned** by the consumer — it is that module's schema, versioned with that module; +- **hosted** by the provider — it runs inside something the consumer does not control; +- **ordered** after the provisioning edge — there is nothing to migrate until the grant exists; +- **scoped** to the grant — the consumer's migrations touch its database and no other. + +Ownership crosses the edge, which nothing in *provides* and *requires* expresses. And it is the +*action* category from [`features.md`](features.md) made concrete: not an artifact, not node +state, and not something the host can apply, because the thing it changes is not the machine. + +It also gives a consumer's own install an internal order — **provisioned, then migrated, then +started** — that depends on an edge rather than on the module's contents. + ## What still has no answer **How many instances of postgres should exist?** One per mesh is wrong — a node that must work