From 4db99f21577fdf175f14594028d0136e700b814a Mon Sep 17 00:00:00 2001 From: Samuel Glauser Date: Wed, 26 Aug 2026 13:55:16 +0200 Subject: [PATCH] =?UTF-8?q?fix(chart):=20DevLogin's=20admin=20list=20reach?= =?UTF-8?q?ed=20no=20container=20=E2=80=94=20it=20was=20never=20templated?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DevLogin is a PAIR of settings and only one was rendered: Authentication__EnableDevLogin templated -> the login appears Authentication__DevAdminUsers ABSENT -> nobody is ever granted admin DevAuthController.IsConfiguredDevAdmin reads DevAdminUsers and calls UserOnboardingService.GrantPlatformAdmin for a match. With the key absent the list is always empty, so a developer signs in successfully and then administers nothing -- and there is no error anywhere, because the configmap names every key explicitly and the Deployment's only env path is envFrom on it. A key the template does not list is simply absent, while helm reports success. The symptom is the misleading part: it reads as "DevLogin does not work", which sends you to the auth code rather than to the chart. Confirmed on a live local install rather than argued from the template: an overlay setting BOTH keys rolled out clean, and the pod came up with EnableDevLogin=true and no DevAdminUsers at all. Third occurrence of this defect class, after Modules__Root (#1924) and Modules__Required__N (#2104). The general guard from #2104 covers keys a TRACKED values file sets; these two are set by a developer in their own out-of-band overlay, so nothing was watching them -- hence a test that names the pair. written before the fix 1 failed (DevAdminUsers), 1 passed (EnableDevLogin) after the fix 2 passed line removed again the DevAdminUsers case fails, naming the key Gates: chart invariants clean across all 3 values combinations; MeshWeaver.Documentation.Test 62/62. Co-Authored-By: Claude Opus 5 --- .../helm/templates/memex-portal/config.yaml | 8 +++ .../2026-08-26-dev-login-grants-its-admins.md | 25 +++++++ .../DevLoginConfigBindingTest.cs | 68 +++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-26-dev-login-grants-its-admins.md create mode 100644 test/MeshWeaver.Documentation.Test/DevLoginConfigBindingTest.cs diff --git a/deploy/helm/templates/memex-portal/config.yaml b/deploy/helm/templates/memex-portal/config.yaml index bde68daada..d06c12673e 100644 --- a/deploy/helm/templates/memex-portal/config.yaml +++ b/deploy/helm/templates/memex-portal/config.yaml @@ -444,6 +444,14 @@ data: # (client secrets) come from the SecretProviderClass, not here. Authentication__Provider: "{{ .Values.config.memex_portal.Authentication__Provider | default "" }}" Authentication__EnableDevLogin: "{{ .Values.config.memex_portal.Authentication__EnableDevLogin | default "false" }}" + {{- /* DevLogin is a PAIR. EnableDevLogin turns the built-in developer login on; DevAdminUsers is + the comma-separated list of ids that get platform admin when they sign in that way + (DevAuthController.IsConfiguredDevAdmin -> UserOnboardingService.GrantPlatformAdmin). + Templating one without the other yields a portal you can log into and then administer + nothing on — and it fails SILENTLY, because a key this configmap does not list never + reaches a container while helm reports success. Same defect as Modules__Root (#1924) and + Modules__Required__N (#2104). */}} + Authentication__DevAdminUsers: "{{ .Values.config.memex_portal.Authentication__DevAdminUsers | default "" }}" Authentication__Microsoft__ClientId: "{{ .Values.config.memex_portal.Authentication__Microsoft__ClientId | default "" }}" Authentication__Microsoft__TenantId: "{{ .Values.config.memex_portal.Authentication__Microsoft__TenantId | default "" }}" Authentication__Google__ClientId: "{{ .Values.config.memex_portal.Authentication__Google__ClientId | default "" }}" diff --git a/src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-26-dev-login-grants-its-admins.md b/src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-26-dev-login-grants-its-admins.md new file mode 100644 index 0000000000..713477c9bf --- /dev/null +++ b/src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-26-dev-login-grants-its-admins.md @@ -0,0 +1,25 @@ +--- +Name: The developer login can grant its administrators again +Category: Fix +Description: A self-hosted or local portal could enable the built-in developer login, but the list of ids it should grant platform admin to never reached the container — so you could sign in and then administer nothing. The setting is now rendered like its partner. +Icon: PersonKey +Order: -20260826 +--- + +# The developer login can grant its administrators again + +The built-in developer login is two settings, not one: `Authentication:EnableDevLogin` turns it on, +and `Authentication:DevAdminUsers` names the ids that should become platform administrators when +they sign in that way. Only the first was rendered into the portal's configuration. The second was +accepted in a deployment's values file, reported as applied, and then reached nothing. + +The result was a portal you could log into and then administer nothing on — with no error anywhere, +because a setting the configuration template does not list is simply absent rather than rejected. +That reads as "the developer login does not work", which is the wrong place to look. + +Both halves are now rendered together, and a test asserts the pair rather than either alone, so one +cannot be added again without the other. + +This is the third setting to go missing the same way, after the module root and the required-module +list. The general guard added with those catches any key a *tracked* values file sets; these two are +set by a developer in their own local overlay, where nothing was watching. diff --git a/test/MeshWeaver.Documentation.Test/DevLoginConfigBindingTest.cs b/test/MeshWeaver.Documentation.Test/DevLoginConfigBindingTest.cs new file mode 100644 index 0000000000..87e34e4d1e --- /dev/null +++ b/test/MeshWeaver.Documentation.Test/DevLoginConfigBindingTest.cs @@ -0,0 +1,68 @@ +#pragma warning disable CS1591 + +using System; +using System.IO; +using System.Text.RegularExpressions; +using Xunit; + +namespace MeshWeaver.Documentation.Test; + +/// +/// 🚨 DevLogin is a PAIR of settings, and both must reach the container. +/// +/// Authentication:EnableDevLogin turns the built-in developer login on; +/// Authentication:DevAdminUsers is the comma-separated list of ids that get platform admin +/// when they sign in that way (DevAuthController.IsConfiguredDevAdmin → +/// UserOnboardingService.GrantPlatformAdmin). One without the other is a portal you can log +/// into and then administer nothing on. +/// +/// The configmap names every key explicitly and the Deployment's only env path is +/// envFrom on it, so a key the template does not list is silently dropped — helm +/// reports success, the value reaches no container, and the symptom is not "bad configuration" but +/// "DevLogin does not work". EnableDevLogin was templated and DevAdminUsers was not, +/// which is exactly that shape: the login appears, and the admin grant never happens. +/// +/// This is the same defect class as Modules__Root (#1924) and +/// Modules__Required__N (#2104). The general guard in +/// PlatformBakeLaneGuard catches it only for keys a tracked values file SETS; these two are +/// set by the developer in their own out-of-band overlay, so nothing was watching them. +/// +public class DevLoginConfigBindingTest +{ + private static string ConfigMap() + { + var dir = new DirectoryInfo(AppContext.BaseDirectory); + while (dir is not null && !File.Exists(Path.Combine(dir.FullName, "MeshWeaver.slnx"))) + dir = dir.Parent; + Assert.NotNull(dir); + return File.ReadAllText(Path.Combine(dir!.FullName, + "deploy", "helm", "templates", "memex-portal", "config.yaml")); + } + + /// The template with its comments removed — a key named only in prose is not bound. + private static string ExecutableTemplate(string template) + { + var withoutHelmComments = Regex.Replace( + template, @"\{\{-?\s*/\*.*?\*/\s*-?\}\}", "", RegexOptions.Singleline); + return string.Join("\n", withoutHelmComments + .Split('\n') + .Where(l => !l.TrimStart().StartsWith('#'))); + } + + [Theory] + [InlineData("Authentication__EnableDevLogin")] + [InlineData("Authentication__DevAdminUsers")] + public void DevLoginSetting_IsBoundInTheConfigMap(string key) + { + var code = ExecutableTemplate(ConfigMap()); + + Assert.True( + Regex.IsMatch(code, $@"^\s{{2}}{Regex.Escape(key)}:\s", RegexOptions.Multiline) + && code.Contains($".Values.config.memex_portal.{key}", StringComparison.Ordinal), + $"'{key}' is not rendered by deploy/helm/templates/memex-portal/config.yaml. The " + + "configmap names every key explicitly and the Deployment's only env path is envFrom " + + "on it, so an overlay that sets this reaches NO container — silently, with helm " + + "reporting success. DevLogin's two settings only work as a pair: the login without " + + "the admin list is a portal nobody can administer."); + } +}