From 0126f413b33221f1164b1552da33b6566d2a657d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20B=C3=BCrgi?= Date: Wed, 26 Aug 2026 12:00:25 +0200 Subject: [PATCH 1/2] fix(#2235): the helm chart only ever gave WebhookInbox a single target slot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memex-cloud's overlay set WebhookInbox__Targets__0 to Hosting/PlatformBuilds (the new platform-release inbox target) and helm rendered it correctly into the ConfigMap — but the live Deployment already carried a hand-set `kubectl set env WebhookInbox__Targets__0=Store/Payments` from before this chart key existed (the pre-existing Stripe payments inbox). Kubernetes gives an explicit Deployment env: entry priority over the same-named var sourced via envFrom, so the ConfigMap's correct value was silently and permanently shadowed: helm reported success, the rendered ConfigMap held the right value, and the running pod kept answering 404 for Hosting/PlatformBuilds — which is exactly what CD's notify-platform-update hit on every promoted build since 08-22, with nothing visibly wrong anywhere. Confirmed live (memex-cloud, 2026-08-26): kubectl get configmap ... WebhookInbox__Targets__0 -> Hosting/PlatformBuilds (correct) kubectl exec ... printenv WebhookInbox__Targets__0 -> Store/Payments (shadowed) Root cause is that the chart only ever templated ONE indexed slot (WebhookInbox__Targets__0), so a deployment needing a second webhook target had nowhere to put it except colliding on the same index by hand. This adds WebhookInbox__Targets__1 as a real second slot, following the same index-by-index pattern already used for OpenRouter__Models__N / AzureFoundry__Models__N (EveryConfigKeySetInAValuesFile_IsBoundInTheConfigMap requires each key spelled out explicitly, never a range). Companion overlay change: Systemorph/Memex#121 (private repo) sets memex-cloud's __0 to match what is actually live (Store/Payments) and adds __1 = Hosting/PlatformBuilds on the fresh, never-shadowed slot. Landing both plus a helm-release deploy of memex-cloud is what actually restores delivery — this PR only adds the chart capability. Verified: helm template renders both slots correctly (`helm template memex ./deploy/helm -f ./deploy/helm/values.yaml -f ./deploy/aks/values.aks.yaml`); PlatformBakeLaneGuard (incl. EveryConfigKeySetInAValuesFile_IsBoundInTheConfigMap) 9/9 green. No What's New entry: chart/config-only, matching precedent (#2268, #1925, #1999) — no portal-user-visible change. Co-Authored-By: Claude Opus 5 (1M context) --- deploy/aks/values.aks.yaml | 7 +++++++ deploy/helm/templates/memex-portal/config.yaml | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/deploy/aks/values.aks.yaml b/deploy/aks/values.aks.yaml index 3fba3c14f6..45eb02ec62 100644 --- a/deploy/aks/values.aks.yaml +++ b/deploy/aks/values.aks.yaml @@ -86,6 +86,13 @@ config: # provisioned for anything to read the inbox — an allowlisted target with no watcher # stores deliveries nobody consumes. WebhookInbox__Targets__0: "Hosting/PlatformBuilds" + # A deployment that ALSO needs a second inbox target (e.g. memex-cloud additionally listens + # on Store/Payments for Stripe) sets __1 too — never a second writer of __0. See #2235: a + # hand-set `kubectl set env WebhookInbox__Targets__0=...` on the live Deployment permanently + # shadows whatever this ConfigMap renders for that SAME name (explicit `env:` beats `envFrom`), + # so the platform-build target silently never took effect even though the ConfigMap was + # correct. Leave empty when only one target is needed. + WebhookInbox__Targets__1: "" # ---- Instance branding (per-env) ---------------------------------------- # Large Safari bookmark / Start-Page / Add-to-Dock tile (apple-touch-icon, 180×180 PNG). # This ships the PROJECT's own mark (Systemorph builds MeshWeaver — the chart's diff --git a/deploy/helm/templates/memex-portal/config.yaml b/deploy/helm/templates/memex-portal/config.yaml index bde68daada..2745e87e06 100644 --- a/deploy/helm/templates/memex-portal/config.yaml +++ b/deploy/helm/templates/memex-portal/config.yaml @@ -317,6 +317,16 @@ data: # default; "empty = inert" is only true for strings. SelfUpdate__MinRollInterval: "{{ .Values.config.memex_portal.SelfUpdate__MinRollInterval | default "01:00:00" }}" WebhookInbox__Targets__0: "{{ .Values.config.memex_portal.WebhookInbox__Targets__0 }}" + # 🚨 #2235: a SECOND slot, because index 0 is not this template's alone to give. memex-cloud + # hand-set WebhookInbox__Targets__0=Store/Payments directly on the Deployment (kubectl set env, + # unrecorded, pre-dating this chart key) BEFORE the platform-release broadcast existed. Explicit + # `env:` entries win over the SAME-named var sourced via `envFrom` (this ConfigMap), so that + # stray override silently shadows whatever this template renders for __0 forever — the overlay + # correctly set Targets__0=Hosting/PlatformBuilds, helm reported success, the ConfigMap held the + # right value, and the live pod still ran with Store/Payments. CD's notify-platform-update then + # 404'd on every promoted build with no error anywhere until #2268 made the 404 fail loud. A + # deployment needing more than one inbox target sets __0 AND __1 (not two writers of __0). + WebhookInbox__Targets__1: "{{ .Values.config.memex_portal.WebhookInbox__Targets__1 }}" # The MODULES a deployment refuses to run without (MeshBuilderModuleActivation.RequiredKey). # The image ships a baseline list in appsettings; a deployment OVERRIDES an entry by name here, # and blanks one it cannot satisfy. From 6886ae2b563a01a58ddf390720e93d0b6e849c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20B=C3=BCrgi?= Date: Wed, 26 Aug 2026 12:06:13 +0200 Subject: [PATCH 2/2] review: default both WebhookInbox slots to "" so an unset key can't allowlist "" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot review on #2352: a values file that omits WebhookInbox__Targets__1 (or __0) entirely made Helm render the literal string "" for that key — non-whitespace, so it would pass WebhookInboxEndpoints' IsNullOrWhiteSpace filter and silently allowlist a bogus target string. Same `| default ""` pattern already used two lines above for SelfUpdate__MinRollInterval. Verified: `helm template` with an overlay that sets neither key now renders "" for both (was previously the untested path); the two prior scenarios (values.aks.yaml's real values; the intended memex-cloud overlay) render unchanged. PlatformBakeLaneGuard 9/9 green, fresh .trx after a Release/-warnaserror rebuild. Co-Authored-By: Claude Opus 5 (1M context) --- deploy/helm/templates/memex-portal/config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/helm/templates/memex-portal/config.yaml b/deploy/helm/templates/memex-portal/config.yaml index 2745e87e06..55e3af557d 100644 --- a/deploy/helm/templates/memex-portal/config.yaml +++ b/deploy/helm/templates/memex-portal/config.yaml @@ -316,7 +316,7 @@ data: # exactly how the 2026-08-23 memex operator-enablement deploy wedged. A typed key needs a real # default; "empty = inert" is only true for strings. SelfUpdate__MinRollInterval: "{{ .Values.config.memex_portal.SelfUpdate__MinRollInterval | default "01:00:00" }}" - WebhookInbox__Targets__0: "{{ .Values.config.memex_portal.WebhookInbox__Targets__0 }}" + WebhookInbox__Targets__0: "{{ .Values.config.memex_portal.WebhookInbox__Targets__0 | default "" }}" # 🚨 #2235: a SECOND slot, because index 0 is not this template's alone to give. memex-cloud # hand-set WebhookInbox__Targets__0=Store/Payments directly on the Deployment (kubectl set env, # unrecorded, pre-dating this chart key) BEFORE the platform-release broadcast existed. Explicit @@ -326,7 +326,7 @@ data: # right value, and the live pod still ran with Store/Payments. CD's notify-platform-update then # 404'd on every promoted build with no error anywhere until #2268 made the 404 fail loud. A # deployment needing more than one inbox target sets __0 AND __1 (not two writers of __0). - WebhookInbox__Targets__1: "{{ .Values.config.memex_portal.WebhookInbox__Targets__1 }}" + WebhookInbox__Targets__1: "{{ .Values.config.memex_portal.WebhookInbox__Targets__1 | default "" }}" # The MODULES a deployment refuses to run without (MeshBuilderModuleActivation.RequiredKey). # The image ships a baseline list in appsettings; a deployment OVERRIDES an entry by name here, # and blanks one it cannot satisfy.