From f583502fc953339abf0b0eda5a5f4eeceb340c1b Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 1 Sep 2026 03:05:43 +0200 Subject: [PATCH] =?UTF-8?q?023=20fixed=20=E2=80=94=20the=20mesh=20says=20w?= =?UTF-8?q?ho=20a=20consumer=20is,=20and=20what=20it=20is=20bound=20to?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both halves had one cause: the mesh knew something and did not say it. Who a consumer is now comes from one derivation, sent to the provider in its grant and to the consumer in its binding, so the two agree by construction. The provisioners use the name they are given and refuse to invent one, because a name of their own would create a login the consumer could never guess while everything reported success. Bound values reach the file that needs them through the symmetric twin of the sealed placeholder — simpler, because they are not secret, so the control plane fills them in and the host gains nothing. The lab run meant to prove this failed in a way that looked like the fix being wrong: rotation could not authenticate against a real database. The cause was the suite rebuilding the control plane's image and not the provisioner's, so an image built that minute ran against a provisioner built the day before. That is 005's family and is recorded with the issue, because the misleading part is worth more than the fix. --- 03-DESIGN/01-to-be/16-module-coverage.md | 17 ++++----- .../00-report.md | 36 +++++++++++++++++-- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/03-DESIGN/01-to-be/16-module-coverage.md b/03-DESIGN/01-to-be/16-module-coverage.md index 2db5f48..e2a2642 100644 --- a/03-DESIGN/01-to-be/16-module-coverage.md +++ b/03-DESIGN/01-to-be/16-module-coverage.md @@ -119,15 +119,16 @@ the consumer's side did not refuse, it just gave two of the three no credential. written to date had one consumer per node, which is the natural shape of a small test and not the shape of a machine. -**A consumer still cannot build a connection string** -([`023`](../../04-ISSUES/023-a-consumer-cannot-build-a-connection-string/00-report.md), open). It -is given its own password in whatever shape its configuration needs, and the host, port and user -name are still out of reach: the user name is invented by the provisioner and recorded nowhere, -and the bound values sit in a JSON document that an application reading `KEY=value` cannot use. +**A consumer could not build a connection string** +([`023`](../../04-ISSUES/023-a-consumer-cannot-build-a-connection-string/00-report.md), fixed). It +had its password in the right shape and the host, port and user name were out of reach: the user +name was invented by the provisioner and recorded nowhere, and the bound values sat in a JSON +document that an application reading `KEY=value` cannot use. -The asymmetry is worth stating, because it is backwards. **The secret is the hard case** — the -mesh must not be able to read it — and the secret is the part that now arrives. The host and port -are ordinary facts held in the clear, and they are the ones stuck. +The asymmetry was backwards, which is what made it worth stating. **The secret is the hard case** — +the mesh must not be able to read it — and the secret was the part that already arrived. The host +and port are ordinary facts held in the clear, and they were the ones stuck. Both halves came from +the same thing: the mesh knew something and did not say it. ## What the survey found that is not about coverage diff --git a/04-ISSUES/023-a-consumer-cannot-build-a-connection-string/00-report.md b/04-ISSUES/023-a-consumer-cannot-build-a-connection-string/00-report.md index 0bbb280..c9853f6 100644 --- a/04-ISSUES/023-a-consumer-cannot-build-a-connection-string/00-report.md +++ b/04-ISSUES/023-a-consumer-cannot-build-a-connection-string/00-report.md @@ -1,8 +1,8 @@ --- -status: located +status: fixed opened: 2026-09-01 located-in: [mesh-control] -fixed-by: +fixed-by: mesh-control 122680b amended-design: --- @@ -77,3 +77,35 @@ was fixed. Keycloak, Gitea, Mailu and MinIO all have manifests that parse and resolve, and none of them can start. This is what stands between the module set and a running one. + +## Fixed + +Both halves had the same cause: **the mesh knew something and did not say it.** + +**Who a consumer is, said once.** `ConsumerIdentity(node, module)` is one derivation, sent to the +provider in its grant and to the consumer in its binding — so the two agree by construction rather +than by two conventions that happened to match on the day they were written. The provisioners now +use the name they are given and **refuse to invent one** if the mesh says nothing: falling back to +a name of their own would create a login the consumer could never guess, and everything would +report success. They also refuse a name that does not carry the mesh's prefix, because that prefix +is how withdrawal finds what it made. + +**Bound values reach the file that needs them.** `${bound:provision:key}` is the symmetric twin of +the sealed placeholder and simpler: these values are not secret, so the control plane fills them +in before sending, and the host gains no field and learns no format. `at`, `as` and `from` are +true of any provision; every other key comes from what the provider said it *serves*, so the +control plane still learns nothing about what a `postgres-database` is. + +Keycloak and Gitea now produce complete connection strings — asserted from the manifests on disk, +checking that every part is filled, that no placeholder survives as a value, and that the password +is still a hole only the host can close. + +### Also found, and separate + +The lab run that was meant to prove this failed in a way that looked like the fix being wrong: a +rotation test could not authenticate against a real database. The cause was that the suite +rebuilt the control plane's image and not the provisioner's, so a run with an image built that +minute used a provisioner built the day before. Fixed in `mesh-lab`; it is +[`005`](../005-pipeline-test-harness-unbuildable/00-report.md)'s family — a rebuild covering +most of what a run uses is worse than one covering none, because the run that follows it is +believed.