Skip to content

Platform API: support repeatable -config flag, make it required #2874

Description

@renuka-fernando

Description

Adopt the layered multi-config-file pattern from #2865 in the Platform API (platform-api) so configuration can be a complete base file plus thin environment/deployment overlays, and unify its config-flag behavior with the rest of the platform's Go components.

Behavior

  • The -config flag becomes repeatable (e.g. -config base.toml -config prod.toml). 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).
  • Merge semantics follow koanf: nested tables (maps) deep-merge; list/array values are replaced, not appended. This must be documented so overlays that set list keys are understood to replace the base list.
  • Use koanf StrictMerge so a type-mismatched override across files fails loudly rather than silently.
  • {{ env }} / {{ file }} interpolation runs once, after all files are merged (and after the existing Cut(platform_api) subtree narrowing), 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 config file path: omitting -config, or passing a path that does not exist/parse, must fail fast (non-zero exit) before serving — never silently boot on env + built-in defaults. This matches the fail-closed startup posture (GO-AUTH-011) and the "required, no default" decision standardized across all Go components.
  • Correct the now-misleading flag help text ("optional; env vars take priority over the file"): there is no koanf env provider, so env values reach config only through explicit {{ env }} interpolation tokens, not as an independent override source.

Rationale for unification
All four Go components (gateway-controller, gateway policy-engine, platform-api, AI Workspace BFF) currently disagree on what happens when -config is omitted (required vs. optional-defaults vs. default-path). This unifies them on: repeatable -config, at least one file required, no default path, no silent-defaults fallback.

Affected code

  • platform-api/cmd/main.go — replace the single flag.String("config", ...) with a repeatable flag.Var slice; require at least one file.
  • platform-api/config/config.goLoadConfig becomes variadic, looping k.Load(file.Provider(p), toml.Parser()) over all paths in order using a StrictMerge koanf instance before the existing Cut/interpolate/unmarshal; the configFilePath singleton var and SetConfigPath setter become slice-based.
  • platform-api/platform/options.go — add a repeatable/variadic WithConfigPaths option alongside WithConfigPath.

Version

No response

Related Issue

#2865

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions