From c4ff0478b7e4955860658a4e0505c04caad2e93e Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 20 Sep 2026 21:11:35 +0200 Subject: [PATCH] =?UTF-8?q?Issue=20067=20=E2=80=94=20fold=20in=20the=20emb?= =?UTF-8?q?edded-vs-provisioned=20axis?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Naming which provider is only half of how a module gets a database. The other half: a module may carry its own version/fork-pinned instance, module-network only, no published port, not a provision — and the model has no word for it. Add it as a second axis with its own open questions. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- .../00-report.md | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/04-ISSUES/067-a-provision-cannot-name-which-provider-serves-it/00-report.md b/04-ISSUES/067-a-provision-cannot-name-which-provider-serves-it/00-report.md index 20a7bcd..72b3108 100644 --- a/04-ISSUES/067-a-provision-cannot-name-which-provider-serves-it/00-report.md +++ b/04-ISSUES/067-a-provision-cannot-name-which-provider-serves-it/00-report.md @@ -59,6 +59,36 @@ provider, and a consumer has no field in which to choose. Modelled as mesh-scoped, that topology is expressible only by accident. To carry it deliberately the provision must be able to name its provider. +## A second axis: provisioned against a provider, or embedded and private + +Naming *which* provider is only half of "how a module gets a database". There is a +second, distinct case the model also cannot express: a module that does **not** +consume a shared provider at all, but carries its **own** instance inside its own +composition — on its own module network, publishing no host port, visible to +nothing else in the mesh. This is legitimate and sometimes necessary: some +containers pin a database *server* version or need a fork or extension set (a +customised postgres, a vector extension) that the node's shared provider does not +offer, so they must run their own alongside the main container. + +The distinction that matters: + +- **Provisioned** — the module requires a provision and is bound to a *named + node-scoped provider* (the first axis above). This should be the default; on the + mesh being migrated onto, most per-module databases are vanilla servers on old + version pins that could simply be consolidated onto the node's shared provider. +- **Embedded and private** — the module ships its own instance because a fork or + version genuinely forces it. Its credential is still a mesh-generated secret, not + a module-authored password; but the *instance* is module-internal — same module + network only, no published port, **not registered as a provision**, so nothing + else can bind to it and it cannot collide on a well-known port. + +The model has no word for the second case. A module that carries a private instance +looks, to the mesh, either like nothing (an undeclared container) or like a provider +it must not be treated as. "Embed only when a fork or version forces it; otherwise +provision against the node's provider" is the rule the design should be able to +state and check — and the invisibility of an embedded instance (own network, no host +port, not a provision) should be an enforceable property, not a convention. + ## Open questions - Where does the provider name live — on the provision definition (`scope: "node"` @@ -76,3 +106,8 @@ provider, and a consumer has no field in which to choose. - Does this interact with secret rotation (the issue-scope of `rotate`) — must rotation address a specific provider's credential holders rather than "the provision's"? +- When a module carries an **embedded, private** instance rather than consuming a + provider, how is that declared so the mesh knows it is module-internal — not a + provision, not published, not bindable by anything else — and can enforce it? +- What decides embed-vs-provision — is it the module's declaration alone, or may an + operator override at assignment (consolidate this one onto the node's provider)?