Repository: meltano/meltano

Issue:
Ignore setting values when selecting store location and store=auto
Given the following meltano.yml

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      repository: meltano/meltano
environments:
- name: dev
- name: staging
- name: prod
```

if I run `meltano --environment=prod config tap-github set repository "meltano/meltano meltano/hub"`

I get 

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      repository: meltano/meltano meltano/hub
environments:
- name: dev
- name: staging
- name: prod
```

another scenario I tested:

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
environments:
- name: dev
- name: staging
- name: prod
```

`meltano config tap-github set repository "meltano/meltano"`

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
```

`meltano --no-environment config tap-github set start_date "some_date"`

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      start_date: some_date
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
```

`meltano --environment=prod config tap-github set start_date "some_other_date"`

```yaml
# UNEXPECTED RESULT
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      start_date: some_other_date
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
```

`meltano --environment=prod config tap-github set start_date "some_other_date" --store=meltano_environment`

```yaml
#EXPECTED RESULT
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      start_date: some_other_date
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          start_date: some_other_date
```

### Updated Spec Proposal (AJ, 2022-06-14)

https://github.com/meltano/meltano/issues/6116#issuecomment-1155873908
Ignore setting values when selecting store location and store=auto
Given the following meltano.yml

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      repository: meltano/meltano
environments:
- name: dev
- name: staging
- name: prod
```

if I run `meltano --environment=prod config tap-github set repository "meltano/meltano meltano/hub"`

I get 

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      repository: meltano/meltano meltano/hub
environments:
- name: dev
- name: staging
- name: prod
```

another scenario I tested:

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
environments:
- name: dev
- name: staging
- name: prod
```

`meltano config tap-github set repository "meltano/meltano"`

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
```

`meltano --no-environment config tap-github set start_date "some_date"`

```yaml
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      start_date: some_date
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
```

`meltano --environment=prod config tap-github set start_date "some_other_date"`

```yaml
# UNEXPECTED RESULT
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      start_date: some_other_date
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
```

`meltano --environment=prod config tap-github set start_date "some_other_date" --store=meltano_environment`

```yaml
#EXPECTED RESULT
default_environment: dev
plugins:
  extractors:
  - name: tap-github
    variant: singer-io
    pip_url: tap-github
    config:
      start_date: some_other_date
environments:
- name: dev
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          repository: meltano/meltano
- name: staging
- name: prod
  config:
    plugins:
      extractors:
      - name: tap-github
        config:
          start_date: some_other_date
```

### Updated Spec Proposal (AJ, 2022-06-14)

https://github.com/meltano/meltano/issues/6116#issuecomment-1155873908


Discussion:
This is the default `--store=auto` setting trying to pick the “best” location, which here means "the current location".

Which makes sense if the value is currently in `.env`, because if the value exists there, setting it in `meltano.yml` would net actually affect the value that’s read as `.env` takes precedence, but doesn’t make sense when the default location (under `environments`) takes precedence over the current location (basic `meltano.yml`).

I think the `AutoStore` should learn to prefer `environments` if `--environment` is explicitly passed. Whether it should _always_ prefer `environments`, even if `--environment` is missing and there's only a `default_environment`, depends on what we decide in https://github.com/meltano/meltano/issues/3419#issuecomment-1150239801, since we may decide there that `meltano config <plugin> set` should not respect `default_environment`.
@DouweM and @tayloramurphy - I don't know if this spec is ready for @kgpayne to pick up.

As I've requested elsewhere, I would prefer if `--store=auto` used deterministic resolution of which store to use, without any awareness of - or influence from - other already-set variables. This seems like the most direct, stable, predictable, and testable behavior. 

I prefer to have @kgpayne hold on development until spec is resolved and agreed. 

@aaronsteers The current auto store behavior was to address https://gitlab.com/meltano/meltano/-/issues/2171, where I'd just said "If the setting has already been overwritten: use that location" without reasoning to back it up. Then, the only writable locations where `.env`, `meltano.yml`, and the system DB, and it made sense then to prefer overwriting the current value instead of adding a new possibly conflicting value in a difference place. That still feels right to me, but I'm open to @tayloramurphy deciding to change that.
> Then, the only writable locations where .env, meltano.yml, and the system DB

Yeah, I think it made more sense when there were fewer available stores. We'll soon have 5 or 7 stores and I think "auto" should just be "we pick the store for you based on your context and the sensitivity level of the setting". Otherwise debugging where each value landed will be a nightmare.

The available stores:

1. systemdb
2. dotenv
3. meltano.yml top-level
4. meltano.yml environment-level
5. https://github.com/meltano/meltano/issues/2982
6. https://github.com/meltano/meltano/issues/3152
7. https://github.com/meltano/meltano/issues/5138
9. https://github.com/meltano/meltano/issues/2859

Some of these are ephemeral and some may not have access to "check if something is there already" when we run. The preference of where to store values should _only_ be based on (1) how Meltano is running, (2) what stores are available to Meltano when `config set` is called.

> I would prefer if --store=auto used deterministic resolution of which store to use, without any awareness of - or influence from - other already-set variables. 

@aaronsteers I agree with this and as we have more locations it's really the only scalable solution for the auto store. It's not clear to me how we would have to update the alerts to the user on the command line about the current value vs where something was stored, but similar to what we did with environments, having a clear and predictable order of operations would make sense to me.
Thanks, @tayloramurphy . Thanks, @DouweM.

Pseudocode proposal below for "store=auto":

```py
def get_auto_store(...):
    if readonly:
        # Can only save to remote db:
        return store.SYSTEMDB

    elif is_secret:
        # As of now we would just return `store.DOTENV`
        # When we have settings to explicitly configure the preferred secrets backend, that would take precedence here
        return get_default_secrets_store() or store.DOTENV

    elif is_meltano_setting:
        # These should only be set at top level
        if set_as_global is False:
            # an environment was requested but this is not allowed/recommended
            warn_or_fail("Meltano settings should be set using `--global` or `--no-environment`")

         return store.MELTANO_YML_TOP_LEVEL

    elif set_as_global or environment_name is None:
         # No environment is set or --global was passed
         return store.MELTANO_YML_TOP_LEVEL

    else return store.MELTANO_YML_ENVIRONMENT

```

Does this look like the right logic? (Please ignore any mistakes in constant names, etc. I'm just trying to communicate the behavior in a readable manner.) 


cc @kgpayne, @cjohnhanson, @edgarrmondragon, @tayloramurphy  
> ...it made sense then to prefer overwriting the current value instead of adding a new possibly conflicting value in a difference place. That still feels right to me...

I think the Environments feature changes the assumption that the current store is likely the best, on the basis that Environments are specifically designed to override other stores. So I am generally in favour of:

i) Implementing a deterministic resolution of auto-store based on the setting type and current context (i.e Environment) only, as per AJ's suggestion.
ii) Improving logging messages to explain where auto-store placed a setting value and how to use `--store` if auto made a different choice to the users intent.
iii) Adding visibility of setting values across _all_ stores to the CLI `config list` command, to help users view and debug the resolution order of their settings in a particular context (especially for projects with config spread across multiple files).
This is the default `--store=auto` setting trying to pick the “best” location, which here means "the current location".

Which makes sense if the value is currently in `.env`, because if the value exists there, setting it in `meltano.yml` would net actually affect the value that’s read as `.env` takes precedence, but doesn’t make sense when the default location (under `environments`) takes precedence over the current location (basic `meltano.yml`).

I think the `AutoStore` should learn to prefer `environments` if `--environment` is explicitly passed. Whether it should _always_ prefer `environments`, even if `--environment` is missing and there's only a `default_environment`, depends on what we decide in https://github.com/meltano/meltano/issues/3419#issuecomment-1150239801, since we may decide there that `meltano config <plugin> set` should not respect `default_environment`.
@DouweM and @tayloramurphy - I don't know if this spec is ready for @kgpayne to pick up.

As I've requested elsewhere, I would prefer if `--store=auto` used deterministic resolution of which store to use, without any awareness of - or influence from - other already-set variables. This seems like the most direct, stable, predictable, and testable behavior. 

I prefer to have @kgpayne hold on development until spec is resolved and agreed. 

@aaronsteers The current auto store behavior was to address https://gitlab.com/meltano/meltano/-/issues/2171, where I'd just said "If the setting has already been overwritten: use that location" without reasoning to back it up. Then, the only writable locations where `.env`, `meltano.yml`, and the system DB, and it made sense then to prefer overwriting the current value instead of adding a new possibly conflicting value in a difference place. That still feels right to me, but I'm open to @tayloramurphy deciding to change that.
> Then, the only writable locations where .env, meltano.yml, and the system DB

Yeah, I think it made more sense when there were fewer available stores. We'll soon have 5 or 7 stores and I think "auto" should just be "we pick the store for you based on your context and the sensitivity level of the setting". Otherwise debugging where each value landed will be a nightmare.

The available stores:

1. systemdb
2. dotenv
3. meltano.yml top-level
4. meltano.yml environment-level
5. https://github.com/meltano/meltano/issues/2982
6. https://github.com/meltano/meltano/issues/3152
7. https://github.com/meltano/meltano/issues/5138
9. https://github.com/meltano/meltano/issues/2859

Some of these are ephemeral and some may not have access to "check if something is there already" when we run. The preference of where to store values should _only_ be based on (1) how Meltano is running, (2) what stores are available to Meltano when `config set` is called.

> I would prefer if --store=auto used deterministic resolution of which store to use, without any awareness of - or influence from - other already-set variables. 

@aaronsteers I agree with this and as we have more locations it's really the only scalable solution for the auto store. It's not clear to me how we would have to update the alerts to the user on the command line about the current value vs where something was stored, but similar to what we did with environments, having a clear and predictable order of operations would make sense to me.
Thanks, @tayloramurphy . Thanks, @DouweM.

Pseudocode proposal below for "store=auto":

```py
def get_auto_store(...):
    if readonly:
        # Can only save to remote db:
        return store.SYSTEMDB

    elif is_secret:
        # As of now we would just return `store.DOTENV`
        # When we have settings to explicitly configure the preferred secrets backend, that would take precedence here
        return get_default_secrets_store() or store.DOTENV

    elif is_meltano_setting:
        # These should only be set at top level
        if set_as_global is False:
            # an environment was requested but this is not allowed/recommended
            warn_or_fail("Meltano settings should be set using `--global` or `--no-environment`")

         return store.MELTANO_YML_TOP_LEVEL

    elif set_as_global or environment_name is None:
         # No environment is set or --global was passed
         return store.MELTANO_YML_TOP_LEVEL

    else return store.MELTANO_YML_ENVIRONMENT

```

Does this look like the right logic? (Please ignore any mistakes in constant names, etc. I'm just trying to communicate the behavior in a readable manner.) 


cc @kgpayne, @cjohnhanson, @edgarrmondragon, @tayloramurphy  
> ...it made sense then to prefer overwriting the current value instead of adding a new possibly conflicting value in a difference place. That still feels right to me...

I think the Environments feature changes the assumption that the current store is likely the best, on the basis that Environments are specifically designed to override other stores. So I am generally in favour of:

i) Implementing a deterministic resolution of auto-store based on the setting type and current context (i.e Environment) only, as per AJ's suggestion.
ii) Improving logging messages to explain where auto-store placed a setting value and how to use `--store` if auto made a different choice to the users intent.
iii) Adding visibility of setting values across _all_ stores to the CLI `config list` command, to help users view and debug the resolution order of their settings in a particular context (especially for projects with config spread across multiple files).

Resolving patch:
diff --git a/src/meltano/core/settings_store.py b/src/meltano/core/settings_store.py
--- a/src/meltano/core/settings_store.py
+++ b/src/meltano/core/settings_store.py
@@ -1133,17 +1133,32 @@ def stores(self) -> list[SettingValueStore]:
         stores.remove(SettingValueStore.AUTO)
         return stores
 
+    def ensure_supported(self, store, method="set"):
+        """Return if a given store is supported for the given method.
+
+        Args:
+            store: The store to check.
+            method: The method to check for the given store.
+
+        Returns:
+            True if store supports method.
+        """
+        try:
+            manager = self.manager_for(store)
+            manager.ensure_supported(method)
+            return True
+        except StoreNotSupportedError:
+            return False
+
     def auto_store(  # noqa: WPS231 # Too complex
         self,
         name: str,
-        source: SettingValueStore,
         setting_def: SettingDefinition | None = None,
     ) -> SettingValueStore | None:
         """Get first valid writable SettingValueStore instance for a Setting.
 
         Args:
             name: Setting name.
-            source: Default SettingValueStore.
             setting_def: SettingDefinition. If None is passed, one will be discovered using `self.find_setting(name)`.
 
         Returns:
@@ -1151,39 +1166,48 @@ def auto_store(  # noqa: WPS231 # Too complex
         """
         setting_def = setting_def or self.find_setting(name)
 
-        store: SettingValueStore = source
-
-        prefer_dotenv = (
-            setting_def and (setting_def.is_redacted or setting_def.env_specific)
-        ) or source is SettingValueStore.ENV
-
-        tried = set()
-        while True:
-            try:
-                manager = self.manager_for(store)
-                manager.ensure_supported("set")
-                return store
-            except StoreNotSupportedError:
-                tried.add(store)
-
-                if SettingValueStore.MELTANO_ENV not in tried and not prefer_dotenv:
-                    store = SettingValueStore.MELTANO_ENV
-                    continue
-
-                if SettingValueStore.MELTANO_YML not in tried and not prefer_dotenv:
-                    store = SettingValueStore.MELTANO_YML
-                    continue
-
-                if SettingValueStore.DOTENV not in tried:
-                    store = SettingValueStore.DOTENV
-                    continue
+        # only the system database is available in readonly mode
+        if self.project.readonly:
+            if self.ensure_supported(store=SettingValueStore.DB):
+                return SettingValueStore.DB
+            return None
 
-                if SettingValueStore.DB not in tried:
-                    store = SettingValueStore.DB
-                    continue
+        # value is a secret
+        if setting_def and setting_def.is_redacted:
+            if self.ensure_supported(store=SettingValueStore.DOTENV):
+                return SettingValueStore.DOTENV
+            elif self.ensure_supported(store=SettingValueStore.DB):
+                return SettingValueStore.DB
+            # ensure secrets don't leak into other stores
+            return None
 
-                break
+        # value is env-specific
+        if setting_def and setting_def.env_specific:
+            if self.ensure_supported(store=SettingValueStore.DOTENV):
+                return SettingValueStore.DOTENV
+
+        # no active meltano environment
+        if not self.project.active_environment:
+            # return root `meltano.yml`
+            if self.ensure_supported(store=SettingValueStore.MELTANO_YML):
+                return SettingValueStore.MELTANO_YML
+            # fall back to dotenv
+            elif self.ensure_supported(store=SettingValueStore.DOTENV):
+                return SettingValueStore.DOTENV
+            # fall back to meltano system db
+            elif self.ensure_supported(store=SettingValueStore.DB):
+                return SettingValueStore.DB
+            return None
 
+        # any remaining config routed to meltano environment
+        if self.ensure_supported(store=SettingValueStore.MELTANO_ENV):
+            return SettingValueStore.MELTANO_ENV
+        # fall back to dotenv
+        elif self.ensure_supported(store=SettingValueStore.DOTENV):
+            return SettingValueStore.DOTENV
+        # fall back to meltano system db
+        elif self.ensure_supported(store=SettingValueStore.DB):
+            return SettingValueStore.DB
         return None
 
     def get(
@@ -1223,7 +1247,7 @@ def get(
 
         metadata["source"] = found_source
 
-        auto_store = self.auto_store(name, found_source, setting_def=setting_def)
+        auto_store = self.auto_store(name, setting_def=setting_def)
         if auto_store:
             metadata["auto_store"] = auto_store
             metadata["overwritable"] = auto_store.can_overwrite(found_source)
@@ -1248,7 +1272,6 @@ def set(self, name: str, path: list[str], value, setting_def=None) -> dict:
         setting_def = setting_def or self.find_setting(name)
 
         current_value, metadata = self.get(name, setting_def=setting_def)
-        source = metadata["source"]
 
         if setting_def:
             if value == setting_def.value:
@@ -1256,7 +1279,8 @@ def set(self, name: str, path: list[str], value, setting_def=None) -> dict:
                 self.unset(name, path, setting_def=setting_def)
                 return {"store": SettingValueStore.DEFAULT}
 
-        store = self.auto_store(name, source, setting_def=setting_def)
+        store = self.auto_store(name, setting_def=setting_def)
+        logger.debug(f"AutoStoreManager returned store '{store}'")
         if store is None:
             raise StoreNotSupportedError("No storage method available")
 


Test patch:
diff --git a/tests/meltano/api/controllers/test_orchestration.py b/tests/meltano/api/controllers/test_orchestration.py
--- a/tests/meltano/api/controllers/test_orchestration.py
+++ b/tests/meltano/api/controllers/test_orchestration.py
@@ -49,15 +49,6 @@ def test_get_configuration(
             assert config_metadata["secure"]["auto_store"] == "dotenv"
             assert config_metadata["secure"]["overwritable"] is True
 
-            # make sure that `boolean` cannot be overwritten
-            assert plugin_settings_service.get_with_source(
-                "boolean", session=session
-            ) == (False, SettingValueStore.ENV)
-            assert config["boolean"] is False
-            assert config_metadata["boolean"]["source"] == "env"
-            assert config_metadata["boolean"]["auto_store"] == "dotenv"
-            assert config_metadata["boolean"]["overwritable"] is False
-
             # make sure the `hidden` setting is still present
             # but hidden in the response
             assert plugin_settings_service.get_with_source(
diff --git a/tests/meltano/cli/test_config.py b/tests/meltano/cli/test_config.py
--- a/tests/meltano/cli/test_config.py
+++ b/tests/meltano/cli/test_config.py
@@ -96,3 +96,52 @@ def test_config_meltano_test(self, project, cli_runner):
             str(result.exception)
             == "Testing of the Meltano project configuration is not supported"
         )
+
+
+class TestCliConfigSet:
+    def test_environments_order_of_precedence(
+        self, project, cli_runner, tap, project_plugins_service
+    ):
+        with mock.patch(
+            "meltano.cli.config.ProjectPluginsService",
+            return_value=project_plugins_service,
+        ):
+            # set base config in `meltano.yml`
+            result = cli_runner.invoke(
+                cli,
+                ["--no-environment", "config", "tap-mock", "set", "test", "base-mock"],
+            )
+            assert_cli_runner(result)
+            base_tap_config = next(
+                (
+                    tap
+                    for tap in project.meltano["plugins"]["extractors"]
+                    if tap["name"] == "tap-mock"
+                ),
+                {},
+            )
+            assert base_tap_config["config"]["test"] == "base-mock"
+
+            # set dev environment config in `meltano.yml`
+            result = cli_runner.invoke(
+                cli,
+                ["--environment=dev", "config", "tap-mock", "set", "test", "dev-mock"],
+            )
+            assert_cli_runner(result)
+            dev_env = next(
+                (
+                    env
+                    for env in project.meltano["environments"]
+                    if env["name"] == "dev"
+                ),
+                {},
+            )
+            tap_config = next(
+                (
+                    tap
+                    for tap in dev_env["config"]["plugins"]["extractors"]
+                    if tap["name"] == "tap-mock"
+                ),
+                {},
+            )
+            assert tap_config["config"]["test"] == "dev-mock"
diff --git a/tests/meltano/core/test_settings_store.py b/tests/meltano/core/test_settings_store.py
--- a/tests/meltano/core/test_settings_store.py
+++ b/tests/meltano/core/test_settings_store.py
@@ -154,70 +154,44 @@ def test_auto_store(
         environment,
         monkeypatch,
     ):
-        def auto_store(source):
-            return subject.auto_store(setting_name, source)
-
-        # Not writable
-        assert auto_store(Store.CONFIG_OVERRIDE) == preferred_store
-        assert auto_store(Store.ENV) == Store.DOTENV
-        assert auto_store(Store.DEFAULT) == preferred_store
-
-        # Writable
-        assert auto_store(Store.DOTENV) == Store.DOTENV
-        assert auto_store(Store.MELTANO_YML) == Store.MELTANO_YML
-        assert auto_store(Store.DB) == Store.DB
+        assert subject.auto_store(setting_name) == preferred_store
 
         # Meltano environment is selected only when there's an active environment
-        assert auto_store(Store.MELTANO_ENV) == preferred_store
         with monkeypatch.context() as mpc:
             mpc.setattr(project, "active_environment", environment)
-            assert auto_store(Store.MELTANO_ENV) == Store.MELTANO_ENV
-
-        # Fall back when writable store is not supported
-        with unsupported(Store.DB):
-            assert auto_store(Store.DB) == preferred_store
+            if preferred_store == Store.MELTANO_YML:
+                assert subject.auto_store(setting_name) == Store.MELTANO_ENV
 
         with unsupported(Store.DOTENV):
             # Sensitive settings won't fall back on `meltano.yml`
-            if preferred_store == Store.DOTENV:
-                assert auto_store(Store.DOTENV) == Store.DB
+            if setting_name == "password":
+                assert subject.auto_store(setting_name) == Store.DB
             else:
-                assert auto_store(Store.DOTENV) == Store.MELTANO_YML
-                assert auto_store(Store.MELTANO_ENV) == Store.MELTANO_YML
+                assert subject.auto_store(setting_name) == Store.MELTANO_YML
                 with monkeypatch.context() as mpc:
                     mpc.setattr(project, "active_environment", environment)
-                    assert auto_store(Store.DOTENV) == Store.MELTANO_ENV
+                    assert subject.auto_store(setting_name) == Store.MELTANO_ENV
 
         with unsupported(Store.MELTANO_YML):
-            assert auto_store(Store.MELTANO_YML) == Store.DOTENV
-            assert auto_store(Store.MELTANO_ENV) == Store.DOTENV
-            with monkeypatch.context() as mpc:
-                mpc.setattr(project, "active_environment", environment)
-                assert auto_store(Store.MELTANO_ENV) == Store.DOTENV
+            # fall back on dotenv
+            if preferred_store == Store.MELTANO_YML:
+                assert subject.auto_store(setting_name) == Store.DOTENV
+                with monkeypatch.context() as mpc:
+                    mpc.setattr(project, "active_environment", environment)
+                    assert subject.auto_store(setting_name) == Store.DOTENV
 
         with unsupported(Store.DOTENV), unsupported(Store.MELTANO_YML):
-            assert auto_store(Store.DOTENV) == Store.DB
-            assert auto_store(Store.MELTANO_YML) == Store.DB
-            assert auto_store(Store.MELTANO_ENV) == Store.DB
+            assert subject.auto_store(setting_name) == Store.DB
             with monkeypatch.context() as mpc:
                 mpc.setattr(project, "active_environment", environment)
-                assert auto_store(Store.MELTANO_ENV) == Store.DB
+                assert subject.auto_store(setting_name) == Store.DB
 
             with unsupported(Store.DB):
-                assert auto_store(Store.DOTENV) is None
-                assert auto_store(Store.MELTANO_YML) is None
-                assert auto_store(Store.DB) is None
-                assert auto_store(Store.MELTANO_ENV) is None
+                assert subject.auto_store(setting_name) is None
 
         monkeypatch.setattr(project, "readonly", True)
 
-        assert auto_store(Store.CONFIG_OVERRIDE) == Store.DB
-        assert auto_store(Store.ENV) == Store.DB
-        assert auto_store(Store.DOTENV) == Store.DB
-        assert auto_store(Store.MELTANO_YML) == Store.DB
-        assert auto_store(Store.DB) == Store.DB
-        assert auto_store(Store.DEFAULT) == Store.DB
-        assert auto_store(Store.MELTANO_ENV) == Store.DB
+        assert subject.auto_store(setting_name) == Store.DB
 
     def test_get(  # noqa: WPS213
         self,
@@ -247,7 +221,7 @@ def test_get(  # noqa: WPS213
         value, metadata = subject.get("regular")
         assert value == "from_db"
         assert metadata["source"] == Store.DB
-        assert metadata["auto_store"] == Store.DB
+        assert metadata["auto_store"] == Store.MELTANO_YML
         assert metadata["overwritable"] is True
 
         set_value_store("from_meltano_yml", Store.MELTANO_YML)
@@ -270,15 +244,15 @@ def test_get(  # noqa: WPS213
         value, metadata = subject.get("regular")
         assert value == "from_dotenv"
         assert metadata["source"] == Store.DOTENV
-        assert metadata["auto_store"] == Store.DOTENV
-        assert metadata["overwritable"] is True
+        assert metadata["auto_store"] == Store.MELTANO_YML
+        assert metadata["overwritable"] is False
 
         setting_def = subject.find_setting("regular")
         monkeypatch.setenv(dummy_settings_service.setting_env(setting_def), "from_env")
         value, metadata = subject.get("regular")
         assert value == "from_env"
         assert metadata["source"] == Store.ENV
-        assert metadata["auto_store"] == Store.DOTENV
+        assert metadata["auto_store"] == Store.MELTANO_YML
         assert metadata["overwritable"] is False
 
         monkeypatch.setitem(
@@ -330,13 +304,8 @@ def set_value(value):
             Store.DB.manager, "set", side_effect=StoreNotSupportedError
         ):
             metadata = set_value("from_db")
-            assert metadata["store"] == Store.DB
-            assert_value_source("from_db", Store.DB)
-
-        # Uses current store
-        metadata = set_value("from_db_new")
-        assert metadata["store"] == Store.DB
-        assert_value_source("from_db_new", Store.DB)
+            assert metadata["store"] == Store.MELTANO_YML
+            assert_value_source("from_db", Store.MELTANO_YML)
 
         # Falls back on `meltano.yml` when current source is not writable
         with unsupported(Store.DB):
@@ -361,37 +330,25 @@ def set_value(value):
         assert metadata["store"] == Store.MELTANO_YML
         assert_value_source("from_meltano_yml", Store.MELTANO_YML)
 
-        # Uses current store
-        metadata = set_value("from_meltano_yml_new")
-        assert metadata["store"] == Store.MELTANO_YML
-        assert_value_source("from_meltano_yml_new", Store.MELTANO_YML)
-
         with unsupported(Store.MELTANO_YML):
             # Falls back on `.env` when current store is not supported
             metadata = set_value("from_dotenv")
             assert metadata["store"] == Store.DOTENV
             assert_value_source("from_dotenv", Store.DOTENV)
 
-        # Uses current store
-        metadata = set_value("from_dotenv_new")
-        assert metadata["store"] == Store.DOTENV
-        assert_value_source("from_dotenv_new", Store.DOTENV)
-
         # Falls back on `meltano.yml` when `.env` is not supported
         with unsupported(Store.DOTENV):
             metadata = set_value("from_meltano_yml")
             assert metadata["store"] == Store.MELTANO_YML
-
             # Even though `.env` can't be overwritten
-            assert_value_source("from_dotenv_new", Store.DOTENV)
+            assert_value_source("from_dotenv", Store.DOTENV)
 
         # Falls back on system database when neither `.env` or `meltano.yml` are supported
         with unsupported(Store.DOTENV), unsupported(Store.MELTANO_YML):
             metadata = set_value("from_db")
             assert metadata["store"] == Store.DB
-
             # Even though `.env` can't be overwritten
-            assert_value_source("from_dotenv_new", Store.DOTENV)
+            assert_value_source("from_dotenv", Store.DOTENV)
 
         # Fails if no stores are supported
         with unsupported(Store.DOTENV), unsupported(Store.MELTANO_YML), unsupported(
@@ -400,7 +357,7 @@ def set_value(value):
             with pytest.raises(StoreNotSupportedError):
                 set_value("nowhere")
 
-            assert_value_source("from_dotenv_new", Store.DOTENV)
+            assert_value_source("from_dotenv", Store.DOTENV)
 
         # Falls back on system database when project is readonly
         monkeypatch.setattr(project, "readonly", True)
@@ -408,7 +365,7 @@ def set_value(value):
         assert metadata["store"] == Store.DB
 
         # Even though `.env` can't be overwritten
-        assert_value_source("from_dotenv_new", Store.DOTENV)
+        assert_value_source("from_dotenv", Store.DOTENV)
 
     def test_unset(  # noqa: WPS213
         self,