Skip to content

App.config conflates bundled defaults with operator config #268

Description

@arbrandes

Description

App.config does two unrelated jobs, and that is the bug. It holds the values an app author bundles at build time, and the values an operator supplies through site.config or the runtime config API. mergeApp flattens both into one object before addAppConfigs runs, so provenance is lost by the time getAppConfig resolves anything.

The consequence is that every key an app bundles is a key commonAppConfig can never supply. getAppConfig merges with merge({}, commonAppConfig, appConfigs[id]), so a value an operator sets site-wide loses to whatever the app's author shipped. Overrides are fragile for the same reason: an operator changing one value must spread the app's existing config back in, and forgetting the inner spread silently discards every other default.

Flipping the merge order is not the fix. MFE_CONFIG_OVERRIDES reaches apps through per-app config, so the flip breaks a channel operators depend on: edx-platform maps /api/mfe_config/v1 onto commonAppConfig and /api/mfe_config/v1?mfe=<name> onto per-app config, and an app-specific override must beat site-wide values.

The fix is to stop overloading one field. App.defaultConfig holds the app author's bundled values and resolves below commonAppConfig, which resolves below config. The two fields are held separately, so operator-supplied configuration can never write into an app's bundled defaults. ADR 0017 records the decision and #298 implements it.

Apps to update

Bundled defaults move from config to defaultConfig:

  • frontend-app-authn
  • frontend-app-learner-dashboard
  • frontend-app-catalog
  • frontend-template-application (no bundled defaults today; its example should demonstrate defaultConfig)

Checked and needing no change: frontend-app-notifications, frontend-app-instructor-dashboard, frontend-app-base-test, frontend-app-sample.

LLM usage notice

Filed with assistance from Claude.

Activity

  1. brian-smith-tcril commented on May 27, 2026

    @brian-smith-tcril
    Contributor

    Problems

    The proposed solution breaks overrides.

    translate_legacy_mfe_config translates what we'd get from /api/mfe_config/v1 into commonAppConfig and what we'd get from /api/mfe_config/v1?mfe=name_of_mfe into app configs.

    Thoughts

    It seems given the current state of things the ideal merge priority is

    • Lowest: Bundled app config
    • Next: Common app config (what we'd get from /api/mfe_config/v1)
    • Highest: App specific override config (what we'd get from /api/mfe_config/v1?mfe=name_of_mfe).

    This means we'd need a good way to differentiate between bundled app configs and app configs that come from a site config (or runtime API endpoint). No solutions are popping to mind but I'm sure it's doable.

    Other considerations

    I don't think the current state of things is set in stone, so I'd like to consider the big picture a bit.

    I think one of the main issues with the current state of things is that pretty much all config ends up in commonAppConfig (at least when pulling it from api/frontend_site_config/v1/).

    This comes from a translation of /api/mfe_config/v1 where "common" means "not an MFE specific override" as opposed to "this is relevant for multiple apps"

    I think in a post-legacy-config-translation-layer world I'd want commonAppConfig to refer to configuration values that are used by multiple apps, and for app-specific config values to come from the apps section of the frontend_site_config endpoint (DISABLE_ENTERPRISE_LOGIN is only used by frontend-app-authn but appears in commonAppConfig in my dev env for example).

    Another "out there" thought would be to just not have the frontend_site_config endpoint return commonAppConfig at all and instead just populate all the app specific config blocks (even if that means some values are duped). I'd want to have a sense of our "endgame" vision for the API endpoint before doing that though.

  2. self-assigned this
    on Jun 9, 2026
  3. arbrandes commented on Jul 8, 2026

    @arbrandes
    ContributorAuthor

    As discussed in the last FWG meeting, we decided not to make any changes to the architecture. Operators already have existing mechanisms to override commonAppConfig intentionally.

  4. moved this from Todo to Done in frontend-baseon Jul 8, 2026
  5. changed the title [-]commonAppConfig precedence: should site-wide config override bundled app config?[/-] [+]App.config conflates bundled defaults with operator config, so commonAppConfig can never win[/+] on Aug 28, 2026
  6. changed the title [-]App.config conflates bundled defaults with operator config, so commonAppConfig can never win[/-] [+]App.config conflates bundled defaults with operator config[/+] on Aug 28, 2026
  7. arbrandes commented on Aug 28, 2026

    @arbrandes
    ContributorAuthor

    In implementing overhangio/tutor-mfe#328, I realized the ergonomics of overriding shipped defaults was just bad. Reopened and submitted a fix.

  8. moved this from Done to In Review in frontend-baseon Aug 28, 2026
  9. moved this from In Review to Done in frontend-baseon Aug 28, 2026
  10. openedx-semantic-release-bot commented on Aug 28, 2026

    @openedx-semantic-release-bot

    🎉 This issue has been resolved in version 2.0.0-alpha.4 🎉

    The release is available on:

    Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions