You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adopt the layered multi-config-file pattern in the Developer Portal (portals/developer-portal, Node.js/Express) so configuration can be a complete base file plus thin environment/deployment overlays, and unify its config-loading behavior with the platform's Go components. This is the JavaScript counterpart of #2865 (gateway-controller + policy-engine), #2873 (AI Workspace BFF), and #2874 (Platform API).
Current state
src/config/configLoader.js loads a single, hardcoded path configs/config.toml (path.join(process.cwd(), 'configs', 'config.toml')) at module import time, via require('./config/configLoader') in src/server.js.
If that file is absent, loadTomlConfig() returns {} and the portal silently runs on built-in DEFAULTS — the same silent-defaults fallback the other components removed.
There is no --config flag and no process.argv handling. {{ env }} / {{ file }} interpolation and the mergeOver deep-merge (over DEFAULTS) already exist, and the APIP_DP_* env-prefix override was already removed (env reaches config only via explicit {{ env }} tokens).
Behavior (target)
Add a repeatable --config flag (mirroring the Go components' -config). Files are merged in the order given with last-wins precedence (a key set in a later file overrides the same key from an earlier file), layered over DEFAULTS.
Merge semantics: nested tables (maps) deep-merge; list/array values are replaced, not appended — document this so overlays that set list keys replace the base list. Confirm/adjust mergeOver so arrays replace rather than merge index-wise.
{{ env }} / {{ file }} interpolation runs once, after all files are merged, so a token declared in the base can be resolved by a later overlay. Secrets stay in interpolation sources, not in the overlay TOMLs.
--config becomes required and there is no default path / no silent-defaults fallback: omitting --config, or passing a path that does not exist/parse, must fail fast (non-zero exit) at startup rather than silently booting on DEFAULTS.
Rationale for unification
All the platform's config loaders should behave identically: repeatable --config, at least one file required, no default path, no silent-defaults fallback. Because there is no env-var provider (env enters only through {{ env }} tokens in a file), a missing config file means "running on pure built-in defaults", which for a portal handling auth/session/secret config must fail fast.
Notes / scope
Config currently materializes at module import (configLoader exports a resolved config object). Moving to a required --config flag means resolving argv and loading config during startup (e.g. in src/server.js) rather than as an import side effect — a larger refactor than the Go components required.
Deployment: the container relies on configs/config.toml being present (mounted); the docker-entrypoint.sh ENTRYPOINT and the developer-portal-ui-helm-chart must be updated to pass --config <path> explicitly once the flag is required (the same adjustment made for the AI Workspace BFF image in AI Workspace BFF: support repeatable -config flag, make it required #2873).
Affected code
portals/developer-portal/src/config/configLoader.js — accept one or more config paths (from argv), loop-load and deep-merge with last-wins, drop the fs.existsSync → {} silent fallback.
portals/developer-portal/src/server.js — parse --config (repeatable, required) and resolve config at startup instead of relying on the import-time singleton.
portals/developer-portal/Dockerfile / docker-entrypoint.sh and kubernetes/helm/developer-portal-ui-helm-chart — pass --config explicitly.
Description
Adopt the layered multi-config-file pattern in the Developer Portal (
portals/developer-portal, Node.js/Express) so configuration can be a complete base file plus thin environment/deployment overlays, and unify its config-loading behavior with the platform's Go components. This is the JavaScript counterpart of #2865 (gateway-controller + policy-engine), #2873 (AI Workspace BFF), and #2874 (Platform API).Current state
src/config/configLoader.jsloads a single, hardcoded pathconfigs/config.toml(path.join(process.cwd(), 'configs', 'config.toml')) at module import time, viarequire('./config/configLoader')insrc/server.js.loadTomlConfig()returns{}and the portal silently runs on built-inDEFAULTS— the same silent-defaults fallback the other components removed.--configflag and noprocess.argvhandling.{{ env }}/{{ file }}interpolation and themergeOverdeep-merge (overDEFAULTS) already exist, and theAPIP_DP_*env-prefix override was already removed (env reaches config only via explicit{{ env }}tokens).Behavior (target)
--configflag (mirroring the Go components'-config). Files are merged in the order given with last-wins precedence (a key set in a later file overrides the same key from an earlier file), layered overDEFAULTS.mergeOverso arrays replace rather than merge index-wise.{{ env }}/{{ file }}interpolation runs once, after all files are merged, so a token declared in the base can be resolved by a later overlay. Secrets stay in interpolation sources, not in the overlay TOMLs.--configbecomes required and there is no default path / no silent-defaults fallback: omitting--config, or passing a path that does not exist/parse, must fail fast (non-zero exit) at startup rather than silently booting onDEFAULTS.Rationale for unification
All the platform's config loaders should behave identically: repeatable
--config, at least one file required, no default path, no silent-defaults fallback. Because there is no env-var provider (env enters only through{{ env }}tokens in a file), a missing config file means "running on pure built-in defaults", which for a portal handling auth/session/secret config must fail fast.Notes / scope
configLoaderexports a resolvedconfigobject). Moving to a required--configflag means resolving argv and loading config during startup (e.g. insrc/server.js) rather than as an import side effect — a larger refactor than the Go components required.configs/config.tomlbeing present (mounted); thedocker-entrypoint.shENTRYPOINT and thedeveloper-portal-ui-helm-chartmust be updated to pass--config <path>explicitly once the flag is required (the same adjustment made for the AI Workspace BFF image in AI Workspace BFF: support repeatable -config flag, make it required #2873).Affected code
portals/developer-portal/src/config/configLoader.js— accept one or more config paths (from argv), loop-load and deep-merge with last-wins, drop thefs.existsSync→{}silent fallback.portals/developer-portal/src/server.js— parse--config(repeatable, required) and resolve config at startup instead of relying on the import-time singleton.portals/developer-portal/Dockerfile/docker-entrypoint.shandkubernetes/helm/developer-portal-ui-helm-chart— pass--configexplicitly.Version
No response
Related Issue
#2865, #2873, #2874