110 lines
4.1 KiB
Python
110 lines
4.1 KiB
Python
"""The template has to name every setting the application actually needs.
|
|
|
|
Twenty-two settings have no default, so a deployment missing one fails at
|
|
startup — one at a time, in whatever order pydantic happens to check them. The
|
|
template exists so that is discoverable by reading. A template that has fallen
|
|
behind the code is the same problem with an extra step, so it is pinned here.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import re
|
|
|
|
import pytest
|
|
|
|
TEMPLATE = pathlib.Path(__file__).resolve().parent.parent / ".env.example"
|
|
SETTINGS = pathlib.Path(__file__).resolve().parent.parent / "app" / "config" / "settings.py"
|
|
|
|
|
|
def _declared() -> dict[str, bool]:
|
|
"""Every setting, mapped to whether it is required (has no default)."""
|
|
body = SETTINGS.read_text(encoding="utf-8").split("class Settings", 1)[1]
|
|
found = {}
|
|
for line in body.splitlines():
|
|
match = re.match(r"^ ([A-Z][A-Z0-9_]*)\s*:\s*([^=]+?)\s*(=\s*(.+))?$", line)
|
|
if match:
|
|
found[match.group(1)] = match.group(3) is None
|
|
return found
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def template() -> str:
|
|
assert TEMPLATE.exists(), f"{TEMPLATE} is missing"
|
|
return TEMPLATE.read_text(encoding="utf-8")
|
|
|
|
|
|
def test_every_required_setting_is_in_the_template(template):
|
|
"""A missing one is a deployment that fails at startup for a reason nobody
|
|
wrote down."""
|
|
missing = [
|
|
name
|
|
for name, required in _declared().items()
|
|
if required and f"\n{name}=" not in f"\n{template}"
|
|
]
|
|
assert not missing, f"required settings absent from .env.example: {missing}"
|
|
|
|
|
|
SCRIPT_ONLY = {
|
|
"AUDIT_BACKFILL_DATABASE_URL",
|
|
}
|
|
|
|
|
|
def test_the_template_names_no_setting_that_does_not_exist(template):
|
|
"""A stale entry is worse than a missing one: somebody sets it and wonders
|
|
why nothing changed."""
|
|
declared = _declared()
|
|
named = re.findall(r"^([A-Z][A-Z0-9_]*)=", template, flags=re.MULTILINE)
|
|
unknown = sorted({n for n in named if n not in declared and n not in SCRIPT_ONLY})
|
|
assert not unknown, f".env.example names settings the app does not read: {unknown}"
|
|
|
|
|
|
def test_every_script_only_variable_says_so_in_the_template(template):
|
|
"""The exemption above is only safe if the template is explicit.
|
|
|
|
An operator reading `AUDIT_BACKFILL_DATABASE_URL=` next to the settings the
|
|
application does read would reasonably assume the application reads this one
|
|
too — and then wonder why setting it changed nothing.
|
|
"""
|
|
for name in SCRIPT_ONLY:
|
|
assert f"\n{name}=" in f"\n{template}", f"{name} is missing from the template"
|
|
preamble = template.split(f"\n{name}=")[0]
|
|
comment = preamble.rsplit("\n\n", 1)[-1]
|
|
assert "scripts/" in comment, (
|
|
f"{name} is read by a script rather than by the application, and the "
|
|
"comment above it in .env.example should name that script"
|
|
)
|
|
|
|
|
|
def test_no_script_only_variable_is_also_a_real_setting():
|
|
"""If one is added to `Settings` later, the exemption becomes a lie that
|
|
hides a genuinely stale entry."""
|
|
declared = _declared()
|
|
overlap = sorted(SCRIPT_ONLY & set(declared))
|
|
assert not overlap, (
|
|
f"these are real settings and should not be exempt: {overlap}"
|
|
)
|
|
|
|
|
|
def test_the_template_holds_no_real_secret(template):
|
|
"""It is committed. Anything that looks like a live value is a leak."""
|
|
for line in template.splitlines():
|
|
if not re.match(r"^[A-Z][A-Z0-9_]*=", line):
|
|
continue
|
|
name, _, value = line.partition("=")
|
|
if not any(word in name for word in ("SECRET", "PASSWORD", "KEY", "TOKEN")):
|
|
continue
|
|
if value.isdigit() or name.endswith("_ID"):
|
|
continue
|
|
assert value == "" or "change-me" in value, (
|
|
f"{name} in .env.example looks like a real value"
|
|
)
|
|
|
|
|
|
def test_the_dangerous_defaults_stay_off(template):
|
|
"""Public signup produced tenant-less accounts the code treated as platform
|
|
superadmins, and requiring replay controls before the modules send them
|
|
refuses every legitimate call."""
|
|
assert "ALLOW_PUBLIC_SIGNUP=False" in template
|
|
assert "MODULE_TRUST_REQUIRE_REPLAY_CONTROLS=False" in template
|