diff --git a/04-ISSUES/232-a-consumer-authenticates-against-a-database-its-user-does-not-live-in/00-report.md b/04-ISSUES/232-a-consumer-authenticates-against-a-database-its-user-does-not-live-in/00-report.md new file mode 100644 index 0000000..04d174a --- /dev/null +++ b/04-ISSUES/232-a-consumer-authenticates-against-a-database-its-user-does-not-live-in/00-report.md @@ -0,0 +1,60 @@ +--- +status: resolved +opened: 2026-10-04 +located-in: [mesh-catalog modules/photos] +fixed-by: mesh-catalog#264 +amended-design: +--- + +# 232 — A consumer authenticates against a database its user does not live in, and one fault hid it behind another + +## What was observed + +Fixing [issue 225](../225-a-provisioner-cannot-read-the-grant-secrets-since-its-code-left-the-container/00-report.md) +on the control machine, 2026-10-04. With the grant secrets readable again the provisioner created +both consumers' users at once, and one consumer still could not connect: + +``` +Authentication succeeded | user: mesh_novox_invoice | authDb: mesh_novox_invoice +Authentication succeeded | user: mesh_novox_photos | authDb: mesh_novox_photos +Authentication failed | user: mesh_novox_photos | authDb: admin + UserNotFound: Could not find user "mesh_novox_photos" for db "admin" +``` + +The provider creates each consumer's user **in that consumer's own database**, which is what the +first two lines are. `photos` asks for `admin`. Its sibling `invoicing`, against the same +provider, asks for `${bound:mongodb-database:as}` — the name the mesh gave it — and works. + +The password was never the problem: the grant secret and the value in the consumer's environment +hash identically. + +## Why it matters beyond this instance + +**One fault wore the other's clothes.** While the provisioner could not read its secrets at all, +*no* user existed, so `UserNotFound ... for db "admin"` was a true and complete account of issue +225. Fixing 225 is what made the wrong database visible — before that, every symptom pointed at +the thing that was already broken, and a second fault behind it was indistinguishable. + +That is the general shape worth keeping: **a fault that explains the symptom is not evidence +there is only one.** The check is to fix the first and look again, rather than to close both on +one explanation. + +It also says something about the interface. Which database a consumer authenticates against is +part of what `mongodb-database` means, and it is spelled out by hand in each consumer. Two +consumers of one provider wrote two different answers, and only one was right; nothing compared +them. That is the shape [issue 124](../124-a-consumer-cannot-be-told-what-its-provider-derived/00-report.md) +records for a derived bucket, here for the authentication database — +[ADR 0202](../../02-DECISIONS/0202-a-provider-declares-what-it-derives-for-each-consumer.md)'s +mechanism is what would remove it, by letting the provider say it once. + +## Resolved + +`photos` asks for `${bound:mongodb-database:as}`, as `invoicing` already did (mesh-catalog#264). +**How it is checked:** the module is rebuilt and pushed, and `photos-server` connects — verified +on the control machine rather than inferred from the manifest. + +## What this leaves open + +Nothing compares two consumers' idea of one interface. The provider could serve the +authentication database as a derived value under ADR 0202 and neither consumer would state it; +that is a candidate for the next consumer of this interface, not a repair of this one.