Repository navigation
Modules__Root could not reach a container — the chart never rendered it - #1924
Merged
Merged
Conversation
A module that ships in the image is not automatically active: /mcp and every other module route is mapped by MapMeshModuleEndpoints from Modules:Assemblies, which is the appsettings baseline UNION the store-activation sidecar. Both the sidecar and the landed DLLs are written under Modules:Root. Unset, that root is AppContext.BaseDirectory — /app — which is READ-ONLY in the container. #1891 established that and made the key configurable so a deployment could point it at its shared writable volume. Memex#53 then set `config.memex_portal.Modules__Root: /data` in all three AKS values files, with the commit message "Modules__Root belongs in the chart — that is why it kept vanishing". It kept vanishing because the chart does not render it. memex-portal-config names every key explicitly, there is no catch-all range over config.memex_portal, and the Deployment's only env path is envFrom on that ConfigMap plus the secret. So a values key this template omits produces exactly nothing, with no error anywhere — the failure mode deploy/aks documents as "un-templated chart keys are silently dropped". Three values files set the key; no container ever saw it. Verified on the live local deployment before the fix: the ConfigMap carries zero Modules* keys, /app/modules is read-only, /data is writable, no modules/activation.json exists, and MeshWeaver.Mcp.dll sits unused in the image while /mcp answers 404. So template it, defaulting to Deployment__DataRoot — the shared writable volume by construction — rather than emitting a blank, which ModuleRoot reads as absent and resolves straight back to the read-only /app. An explicit value still wins. helm template … | grep Modules__Root neutral defaults → /data AKS overlay → /data memex-local → /data --set /mnt/modules → /mnt/modules deploy/aks/scripts/check-chart-invariants.sh → all 3 combinations consistent memex-local additionally pins it in values.local.defaults.yaml: a laptop install gets the writable root without regenerating its user overlay, and a module landed there survives `memex-local update`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The chart fix alone would leave the next key to vanish the same way, so pin the rule that was missing rather than only the instance that broke. check-chart-invariants exists because `replicas.portal: 2` sat in git for a month being consumed by nothing. Modules__Root is that defect in the other direction, and this ConfigMap invites it: the template names every key explicitly and the Deployment's only env path is envFrom on it, so a key the template omits reaches no container. helm reports success either way — the values file is syntactically perfect and the template simply never mentions it. Invariant 8 asserts that every key the platform requires a deployment to be able to set is RENDERED, and renders non-blank. Blank matters as much as absent whenever the consumer treats blank as unset: ModuleRoot does, falling back to the read-only /app, so an empty string silently restores the defect the key exists to cure. Red first, against main's own chart: ::error::[main, unfixed] the rendered memex-portal-config carries no 'Modules__Root' 1 contradiction(s) across 7 invariants — exit 1 Green on this branch, all three shipped combinations (self-host, AKS overlay, memex-local). Negative control: forcing both Modules__Root and Deployment__DataRoot blank fails on the BLANK arm, not the missing one — so the two halves of the assertion are independently live rather than one covering for the other. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…hes-the-configmap
Category: Fix — a user notices this one. Anything shipping as a module was absent from a deployment that never set the key, and the MCP server is the visible case: its address answered "not found" on a portal that was healthy in every other respect. Written for the reader, not the mechanism: what was missing, why nothing said so, and what changed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a Helm-chart configuration omission that prevented Modules__Root from reaching the running memex-portal container, which in turn blocked store-installed modules (e.g., MCP) from being activated because the default module root resolves to a read-only location inside the container.
Changes:
- Template
Modules__Rootinto thememex-portal-configConfigMap, defaulting it toDeployment__DataRootwhen unset/blank. - Add chart/homebrew defaults so local installs get a writable module root without regenerating overlays.
- Extend
check-chart-invariantswith a new invariant that asserts required config keys are rendered and non-blank.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-20-installed-modules-can-be-activated.md | Adds a “What’s New” entry documenting the restored ability to activate installed modules once the config key reaches the portal. |
| deploy/homebrew/share/values.local.defaults.yaml | Pins Modules__Root to /data for memex-local so landed/activated modules persist across updates. |
| deploy/helm/values.yaml | Introduces a neutral Modules__Root: "" default indicating “follow Deployment__DataRoot via the template”. |
| deploy/helm/templates/memex-portal/config.yaml | Renders Modules__Root into the ConfigMap and defaults it to Deployment__DataRoot to avoid the read-only /app fallback. |
| deploy/aks/scripts/check-chart-invariants.py | Adds invariant #8 to ensure Modules__Root is present and non-blank in the rendered ConfigMap. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
This was referenced Aug 23, 2026
Modules__Required could not reach a container — and the guard that would have caught all three
#2104
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
A module that ships in the image is not automatically active.
/mcpand every other module route is mapped byMapMeshModuleEndpointsfromModules:Assemblies, which is the appsettings baseline ∪ the store-activation sidecar. Both the sidecar and the landed DLLs are written underModules:Root.Unset, that root is
AppContext.BaseDirectory—/app— which is read-only in the container. #1891 established exactly this and made the key configurable so a deployment could point it at its shared writable volume. Memex#53 then setconfig.memex_portal.Modules__Root: /datain all three AKS values files, titled "Modules__Root belongs in the chart — that is why it kept vanishing."It kept vanishing because the chart does not render it.
memex-portal-confignames every key explicitly, there is no catch-all range overconfig.memex_portal, and the Deployment's only env path isenvFromon that ConfigMap plus the Secret. A values key this template omits produces exactly nothing, with no error anywhere — the failure modedeploy/aksdocuments as "un-templated chart keys are silently dropped". Three values files set the key; no container ever saw it.Verified on a live deployment, before the fix
…and after, on the same portal:
Modules__Root=/datareaches the process, the sidecar is read, the entry passes its platform floor (module built againstMeshWeaver.Graph/3.0.0-rc4.ci.0, platform3.0.0-rc5.ci.0),MeshWeaver.Mcp.dllis mapped into the process (/proc/1/maps), andPOST /mcp→ 401 with a properwww-authenticate: Bearer resource_metadata=…challenge. An MCP client reconnects and serves real calls.What changed
deploy/helm/templates/memex-portal/config.yaml— templatesModules__Root, defaulting toDeployment__DataRootrather than emitting a blank. Blank is not harmless:ModuleRoottreats it as absent and falls back to the read-only/app, silently restoring the defect the key exists to cure. An explicit value still wins.deploy/helm/values.yaml— neutral default""(follow the data root).deploy/homebrew/share/values.local.defaults.yaml— pins/datafor memex-local, so a laptop install gets a writable root without regenerating its user overlay, and a landed module survivesmemex-local update.deploy/aks/scripts/check-chart-invariants.py— invariant 8, so the next key cannot vanish the same way.The gate, written test-first
check-chart-invariantsexists becausereplicas.portal: 2sat in git for a month being consumed by nothing. This is that defect in the other direction, so the rule is pinned rather than just the instance.Red, against main's own chart:
Green on this branch, all three shipped combinations:
Negative control: forcing both
Modules__RootandDeployment__DataRootblank fails on the blank arm, not the missing arm — the two halves of the assertion are independently live rather than one covering for the other.Risk
Low, and inert on merge. No workflow applies this chart:
main-cd.ymlbuilds and publishes images and never touches helm; the only helm-aware workflow ischart-drift.yml, a scheduled read-only drift detector. The chart takes effect when someone deliberately deploys.On AKS the key currently resolves to read-only
/app, so nothing can be store-activated today. After this it resolves to/data, which those pods already mount — and it stays inert until a module is actually activated. It cannot change existing behaviour, only unblock intended behaviour.Checks
Found while doing this — filed separately, NOT in this PR
Widening that guard from
PreWarm__*to everyconfig.memex_portalkey surfaces three more keys set indeploy/aks/values.aks.yamlthat no template renders:SelfUpdate__MinRollInterval,WebhookInbox__Targets__0,AzureFoundry__Models__3. Templating them would change live AKS behaviour, and two are recent deliberate work, so they belong to their owner rather than to this PR. Issue: #1925.🤖 Generated with Claude Code