We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
dev server hot reload has stopped working
## Description

In #5532 the `env` attribute was dropped from `SDConfig` in `sdconfig.py`. That value is checked in [`source.py`](https://github.com/freedomofpress/securedrop/blob/6246482157e31d0655a91c5e7284cc8550f2c289/securedrop/source.py#L11) and [`journalist.py`](https://github.com/freedomofpress/securedrop/blob/6246482157e31d0655a91c5e7284cc8550f2c289/securedrop/journalist.py#L26) to determine whether the Flask app will run in [debug](https://flask.palletsprojects.com/en/1.1.x/config/#DEBUG) mode. By default it will not, so the dev server has stopped responding to code changes.

Given the Flask documentation warnings about setting debug mode via code and not the `FLASK_DEBUG` environment variable, we may want to reevaluate all of this, but right now let's just get back to a properly functioning dev server.

## Steps to Reproduce

- Check out `develop` at a commit before the `sdconfig.py` change (eff931fa8a0e74d5c3be87e46c5d0f004f02e289).
- Run `make dev`.
- Change `securedrop/journalist_app/main.py` to trigger a reload, and confirm that the change is detected.
- Stop the dev server.
- Check out `develop` and run `make dev`.
- Change `securedrop/journalist_app/main.py` again, and observe that the change is not detected.

## Expected Behavior

That the dev server would notice code changes and reload to pick them up.

## Actual Behavior

It does not care one whit about your useless flailings. We are all `prod` now.

## Comments

Just need to restore `SDConfig.env`.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `securedrop/sdconfig.py`
Content:
```
1 from typing import Dict
2 from typing import Optional
3 
4 from typing import Type
5 
6 import config as _config
7 from typing import List
8 
9 
10 class SDConfig:
11     def __init__(self) -> None:
12         self.JOURNALIST_APP_FLASK_CONFIG_CLS = \
13             _config.JournalistInterfaceFlaskConfig  # type: Type
14 
15         self.SOURCE_APP_FLASK_CONFIG_CLS = \
16             _config.SourceInterfaceFlaskConfig  # type: Type
17 
18         self.DATABASE_ENGINE = _config.DATABASE_ENGINE  # type: str
19         self.DATABASE_FILE = _config.DATABASE_FILE  # type: str
20 
21         self.DATABASE_USERNAME = getattr(_config, "DATABASE_USERNAME", None)  # type: Optional[str]
22         self.DATABASE_PASSWORD = getattr(_config, "DATABASE_PASSWORD", None)  # type: Optional[str]
23         self.DATABASE_HOST = getattr(_config, "DATABASE_HOST", None)  # type: Optional[str]
24         self.DATABASE_NAME = getattr(_config, "DATABASE_NAME", None)  # type: Optional[str]
25 
26         self.ADJECTIVES = _config.ADJECTIVES  # type: str
27         self.NOUNS = _config.NOUNS  # type: str
28         self.WORD_LIST = _config.WORD_LIST  # type: str
29 
30         self.DEFAULT_LOCALE = _config.DEFAULT_LOCALE  # type: str
31         self.SUPPORTED_LOCALES = getattr(
32             _config, "SUPPORTED_LOCALES", [self.DEFAULT_LOCALE]
33         )  # type: List[str]
34 
35         self.GPG_KEY_DIR = _config.GPG_KEY_DIR  # type: str
36 
37         self.JOURNALIST_KEY = _config.JOURNALIST_KEY  # type: str
38         self.JOURNALIST_TEMPLATES_DIR = _config.JOURNALIST_TEMPLATES_DIR  # type: str
39 
40         self.SCRYPT_GPG_PEPPER = _config.SCRYPT_GPG_PEPPER  # type: str
41         self.SCRYPT_ID_PEPPER = _config.SCRYPT_ID_PEPPER  # type: str
42         self.SCRYPT_PARAMS = _config.SCRYPT_PARAMS  # type: Dict[str, int]
43 
44         self.SECUREDROP_DATA_ROOT = _config.SECUREDROP_DATA_ROOT  # type: str
45         self.SECUREDROP_ROOT = _config.SECUREDROP_ROOT  # type: str
46 
47         self.SESSION_EXPIRATION_MINUTES = _config.SESSION_EXPIRATION_MINUTES  # type: int
48 
49         self.SOURCE_TEMPLATES_DIR = _config.SOURCE_TEMPLATES_DIR  # type: str
50         self.TEMP_DIR = _config.TEMP_DIR  # type: str
51         self.STORE_DIR = _config.STORE_DIR  # type: str
52         self.TRANSLATION_DIRS = getattr(_config, "TRANSLATION_DIRS", None)  # type: Optional[str]
53 
54         self.WORKER_PIDFILE = _config.WORKER_PIDFILE  # type: str
55 
56         if _config.env == 'test':
57             self.RQ_WORKER_NAME = 'test'  # type: str
58         else:
59             self.RQ_WORKER_NAME = 'default'
60 
61     @property
62     def DATABASE_URI(self) -> str:
63         if self.DATABASE_ENGINE == "sqlite":
64             db_uri = (self.DATABASE_ENGINE + ":///" +
65                       self.DATABASE_FILE)
66         else:
67             if self.DATABASE_USERNAME is None:
68                 raise RuntimeError("Missing DATABASE_USERNAME entry from config.py")
69             if self.DATABASE_PASSWORD is None:
70                 raise RuntimeError("Missing DATABASE_PASSWORD entry from config.py")
71             if self.DATABASE_HOST is None:
72                 raise RuntimeError("Missing DATABASE_HOST entry from config.py")
73             if self.DATABASE_NAME is None:
74                 raise RuntimeError("Missing DATABASE_NAME entry from config.py")
75 
76             db_uri = (
77                 self.DATABASE_ENGINE + '://' +
78                 self.DATABASE_USERNAME + ':' +
79                 self.DATABASE_PASSWORD + '@' +
80                 self.DATABASE_HOST + '/' +
81                 self.DATABASE_NAME
82             )
83         return db_uri
84 
85 
86 config = SDConfig()  # type: SDConfig
87
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/securedrop/sdconfig.py b/securedrop/sdconfig.py
--- a/securedrop/sdconfig.py
+++ b/securedrop/sdconfig.py
@@ -53,7 +53,8 @@
 
         self.WORKER_PIDFILE = _config.WORKER_PIDFILE  # type: str
 
-        if _config.env == 'test':
+        self.env = getattr(_config, 'env', 'prod')  # type: str
+        if self.env == 'test':
             self.RQ_WORKER_NAME = 'test'  # type: str
         else:
             self.RQ_WORKER_NAME = 'default'

{"golden_diff": "diff --git a/securedrop/sdconfig.py b/securedrop/sdconfig.py\n--- a/securedrop/sdconfig.py\n+++ b/securedrop/sdconfig.py\n@@ -53,7 +53,8 @@\n \n         self.WORKER_PIDFILE = _config.WORKER_PIDFILE  # type: str\n \n-        if _config.env == 'test':\n+        self.env = getattr(_config, 'env', 'prod')  # type: str\n+        if self.env == 'test':\n             self.RQ_WORKER_NAME = 'test'  # type: str\n         else:\n             self.RQ_WORKER_NAME = 'default'\n", "issue": "dev server hot reload has stopped working\n## Description\r\n\r\nIn #5532 the `env` attribute was dropped from `SDConfig` in `sdconfig.py`. That value is checked in [`source.py`](https://github.com/freedomofpress/securedrop/blob/6246482157e31d0655a91c5e7284cc8550f2c289/securedrop/source.py#L11) and [`journalist.py`](https://github.com/freedomofpress/securedrop/blob/6246482157e31d0655a91c5e7284cc8550f2c289/securedrop/journalist.py#L26) to determine whether the Flask app will run in [debug](https://flask.palletsprojects.com/en/1.1.x/config/#DEBUG) mode. By default it will not, so the dev server has stopped responding to code changes.\r\n\r\nGiven the Flask documentation warnings about setting debug mode via code and not the `FLASK_DEBUG` environment variable, we may want to reevaluate all of this, but right now let's just get back to a properly functioning dev server.\r\n\r\n## Steps to Reproduce\r\n\r\n- Check out `develop` at a commit before the `sdconfig.py` change (eff931fa8a0e74d5c3be87e46c5d0f004f02e289).\r\n- Run `make dev`.\r\n- Change `securedrop/journalist_app/main.py` to trigger a reload, and confirm that the change is detected.\r\n- Stop the dev server.\r\n- Check out `develop` and run `make dev`.\r\n- Change `securedrop/journalist_app/main.py` again, and observe that the change is not detected.\r\n\r\n## Expected Behavior\r\n\r\nThat the dev server would notice code changes and reload to pick them up.\r\n\r\n## Actual Behavior\r\n\r\nIt does not care one whit about your useless flailings. We are all `prod` now.\r\n\r\n## Comments\r\n\r\nJust need to restore `SDConfig.env`.\r\n\n", "before_files": [{"content": "from typing import Dict\nfrom typing import Optional\n\nfrom typing import Type\n\nimport config as _config\nfrom typing import List\n\n\nclass SDConfig:\n    def __init__(self) -> None:\n        self.JOURNALIST_APP_FLASK_CONFIG_CLS = \\\n            _config.JournalistInterfaceFlaskConfig  # type: Type\n\n        self.SOURCE_APP_FLASK_CONFIG_CLS = \\\n            _config.SourceInterfaceFlaskConfig  # type: Type\n\n        self.DATABASE_ENGINE = _config.DATABASE_ENGINE  # type: str\n        self.DATABASE_FILE = _config.DATABASE_FILE  # type: str\n\n        self.DATABASE_USERNAME = getattr(_config, \"DATABASE_USERNAME\", None)  # type: Optional[str]\n        self.DATABASE_PASSWORD = getattr(_config, \"DATABASE_PASSWORD\", None)  # type: Optional[str]\n        self.DATABASE_HOST = getattr(_config, \"DATABASE_HOST\", None)  # type: Optional[str]\n        self.DATABASE_NAME = getattr(_config, \"DATABASE_NAME\", None)  # type: Optional[str]\n\n        self.ADJECTIVES = _config.ADJECTIVES  # type: str\n        self.NOUNS = _config.NOUNS  # type: str\n        self.WORD_LIST = _config.WORD_LIST  # type: str\n\n        self.DEFAULT_LOCALE = _config.DEFAULT_LOCALE  # type: str\n        self.SUPPORTED_LOCALES = getattr(\n            _config, \"SUPPORTED_LOCALES\", [self.DEFAULT_LOCALE]\n        )  # type: List[str]\n\n        self.GPG_KEY_DIR = _config.GPG_KEY_DIR  # type: str\n\n        self.JOURNALIST_KEY = _config.JOURNALIST_KEY  # type: str\n        self.JOURNALIST_TEMPLATES_DIR = _config.JOURNALIST_TEMPLATES_DIR  # type: str\n\n        self.SCRYPT_GPG_PEPPER = _config.SCRYPT_GPG_PEPPER  # type: str\n        self.SCRYPT_ID_PEPPER = _config.SCRYPT_ID_PEPPER  # type: str\n        self.SCRYPT_PARAMS = _config.SCRYPT_PARAMS  # type: Dict[str, int]\n\n        self.SECUREDROP_DATA_ROOT = _config.SECUREDROP_DATA_ROOT  # type: str\n        self.SECUREDROP_ROOT = _config.SECUREDROP_ROOT  # type: str\n\n        self.SESSION_EXPIRATION_MINUTES = _config.SESSION_EXPIRATION_MINUTES  # type: int\n\n        self.SOURCE_TEMPLATES_DIR = _config.SOURCE_TEMPLATES_DIR  # type: str\n        self.TEMP_DIR = _config.TEMP_DIR  # type: str\n        self.STORE_DIR = _config.STORE_DIR  # type: str\n        self.TRANSLATION_DIRS = getattr(_config, \"TRANSLATION_DIRS\", None)  # type: Optional[str]\n\n        self.WORKER_PIDFILE = _config.WORKER_PIDFILE  # type: str\n\n        if _config.env == 'test':\n            self.RQ_WORKER_NAME = 'test'  # type: str\n        else:\n            self.RQ_WORKER_NAME = 'default'\n\n    @property\n    def DATABASE_URI(self) -> str:\n        if self.DATABASE_ENGINE == \"sqlite\":\n            db_uri = (self.DATABASE_ENGINE + \":///\" +\n                      self.DATABASE_FILE)\n        else:\n            if self.DATABASE_USERNAME is None:\n                raise RuntimeError(\"Missing DATABASE_USERNAME entry from config.py\")\n            if self.DATABASE_PASSWORD is None:\n                raise RuntimeError(\"Missing DATABASE_PASSWORD entry from config.py\")\n            if self.DATABASE_HOST is None:\n                raise RuntimeError(\"Missing DATABASE_HOST entry from config.py\")\n            if self.DATABASE_NAME is None:\n                raise RuntimeError(\"Missing DATABASE_NAME entry from config.py\")\n\n            db_uri = (\n                self.DATABASE_ENGINE + '://' +\n                self.DATABASE_USERNAME + ':' +\n                self.DATABASE_PASSWORD + '@' +\n                self.DATABASE_HOST + '/' +\n                self.DATABASE_NAME\n            )\n        return db_uri\n\n\nconfig = SDConfig()  # type: SDConfig\n", "path": "securedrop/sdconfig.py"}], "after_files": [{"content": "from typing import Dict\nfrom typing import Optional\n\nfrom typing import Type\n\nimport config as _config\nfrom typing import List\n\n\nclass SDConfig:\n    def __init__(self) -> None:\n        self.JOURNALIST_APP_FLASK_CONFIG_CLS = \\\n            _config.JournalistInterfaceFlaskConfig  # type: Type\n\n        self.SOURCE_APP_FLASK_CONFIG_CLS = \\\n            _config.SourceInterfaceFlaskConfig  # type: Type\n\n        self.DATABASE_ENGINE = _config.DATABASE_ENGINE  # type: str\n        self.DATABASE_FILE = _config.DATABASE_FILE  # type: str\n\n        self.DATABASE_USERNAME = getattr(_config, \"DATABASE_USERNAME\", None)  # type: Optional[str]\n        self.DATABASE_PASSWORD = getattr(_config, \"DATABASE_PASSWORD\", None)  # type: Optional[str]\n        self.DATABASE_HOST = getattr(_config, \"DATABASE_HOST\", None)  # type: Optional[str]\n        self.DATABASE_NAME = getattr(_config, \"DATABASE_NAME\", None)  # type: Optional[str]\n\n        self.ADJECTIVES = _config.ADJECTIVES  # type: str\n        self.NOUNS = _config.NOUNS  # type: str\n        self.WORD_LIST = _config.WORD_LIST  # type: str\n\n        self.DEFAULT_LOCALE = _config.DEFAULT_LOCALE  # type: str\n        self.SUPPORTED_LOCALES = getattr(\n            _config, \"SUPPORTED_LOCALES\", [self.DEFAULT_LOCALE]\n        )  # type: List[str]\n\n        self.GPG_KEY_DIR = _config.GPG_KEY_DIR  # type: str\n\n        self.JOURNALIST_KEY = _config.JOURNALIST_KEY  # type: str\n        self.JOURNALIST_TEMPLATES_DIR = _config.JOURNALIST_TEMPLATES_DIR  # type: str\n\n        self.SCRYPT_GPG_PEPPER = _config.SCRYPT_GPG_PEPPER  # type: str\n        self.SCRYPT_ID_PEPPER = _config.SCRYPT_ID_PEPPER  # type: str\n        self.SCRYPT_PARAMS = _config.SCRYPT_PARAMS  # type: Dict[str, int]\n\n        self.SECUREDROP_DATA_ROOT = _config.SECUREDROP_DATA_ROOT  # type: str\n        self.SECUREDROP_ROOT = _config.SECUREDROP_ROOT  # type: str\n\n        self.SESSION_EXPIRATION_MINUTES = _config.SESSION_EXPIRATION_MINUTES  # type: int\n\n        self.SOURCE_TEMPLATES_DIR = _config.SOURCE_TEMPLATES_DIR  # type: str\n        self.TEMP_DIR = _config.TEMP_DIR  # type: str\n        self.STORE_DIR = _config.STORE_DIR  # type: str\n        self.TRANSLATION_DIRS = getattr(_config, \"TRANSLATION_DIRS\", None)  # type: Optional[str]\n\n        self.WORKER_PIDFILE = _config.WORKER_PIDFILE  # type: str\n\n        self.env = getattr(_config, 'env', 'prod')  # type: str\n        if self.env == 'test':\n            self.RQ_WORKER_NAME = 'test'  # type: str\n        else:\n            self.RQ_WORKER_NAME = 'default'\n\n    @property\n    def DATABASE_URI(self) -> str:\n        if self.DATABASE_ENGINE == \"sqlite\":\n            db_uri = (self.DATABASE_ENGINE + \":///\" +\n                      self.DATABASE_FILE)\n        else:\n            if self.DATABASE_USERNAME is None:\n                raise RuntimeError(\"Missing DATABASE_USERNAME entry from config.py\")\n            if self.DATABASE_PASSWORD is None:\n                raise RuntimeError(\"Missing DATABASE_PASSWORD entry from config.py\")\n            if self.DATABASE_HOST is None:\n                raise RuntimeError(\"Missing DATABASE_HOST entry from config.py\")\n            if self.DATABASE_NAME is None:\n                raise RuntimeError(\"Missing DATABASE_NAME entry from config.py\")\n\n            db_uri = (\n                self.DATABASE_ENGINE + '://' +\n                self.DATABASE_USERNAME + ':' +\n                self.DATABASE_PASSWORD + '@' +\n                self.DATABASE_HOST + '/' +\n                self.DATABASE_NAME\n            )\n        return db_uri\n\n\nconfig = SDConfig()  # type: SDConfig\n", "path": "securedrop/sdconfig.py"}]}