What you pay for, what Discord drops, and pixiv switched off #251
@@ -69,3 +69,69 @@ def test_missing_key_with_env_var_bootstraps(tmp_path, monkeypatch):
|
||||
key_path = tmp_path / "bootstrap.b64"
|
||||
CredentialCrypto(key_path) # no bootstrap_ok kwarg — relies on env
|
||||
assert key_path.exists()
|
||||
|
||||
|
||||
# --- #3422: the install docs quote this module, so they must keep agreeing --
|
||||
#
|
||||
# README.md and .env.example both print the literal failure a new installer
|
||||
# hits, and the literal path and env var they must act on. That is the right
|
||||
# call — a stranger greps for the string their terminal showed them — but it
|
||||
# means those two files now DEPEND on this module's wording, with nothing
|
||||
# connecting them. The characteristic defect of the install surface is exactly
|
||||
# this: the documented behaviour and the code drift apart, and the code is the
|
||||
# one that is right.
|
||||
#
|
||||
# Presence checks on both sides, deliberately: an absence check against prose
|
||||
# would pass for the wrong reason the moment a sentence were reworded
|
||||
# (snippet #3352).
|
||||
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
_INSTALL_DOCS = ("README.md", ".env.example")
|
||||
|
||||
|
||||
def test_the_bootstrap_refusal_still_reads_the_way_the_docs_quote_it(tmp_path, monkeypatch):
|
||||
"""The three things a reader is told to look for, in the raised message."""
|
||||
from backend.app.services.credential_crypto import (
|
||||
_BOOTSTRAP_ENV_VAR,
|
||||
MissingCredentialKey,
|
||||
)
|
||||
monkeypatch.delenv(_BOOTSTRAP_ENV_VAR, raising=False)
|
||||
with pytest.raises(MissingCredentialKey) as exc:
|
||||
CredentialCrypto(tmp_path / "absent.b64")
|
||||
message = str(exc.value)
|
||||
# The sentence README.md reproduces verbatim.
|
||||
assert "Fernet key file not found at" in message
|
||||
# The variable both docs tell the operator to set.
|
||||
assert _BOOTSTRAP_ENV_VAR in message
|
||||
# The alternative the docs lean on — that a restored instance restores the
|
||||
# key rather than minting one. Losing this line loses the whole point.
|
||||
assert "restore the key file" in message
|
||||
|
||||
|
||||
def test_the_install_docs_name_the_real_key_path_and_variable():
|
||||
"""Pins the two literals, read from the code rather than retyped here.
|
||||
|
||||
Changing `_CREDENTIAL_KEY_PATH` or the env var name without updating the
|
||||
docs fails this — which is the only thing standing between a rename and a
|
||||
README that sends strangers to a path that does not exist.
|
||||
"""
|
||||
from backend.app import _CREDENTIAL_KEY_PATH
|
||||
from backend.app.services.credential_crypto import _BOOTSTRAP_ENV_VAR
|
||||
|
||||
for name in _INSTALL_DOCS:
|
||||
text = (_REPO_ROOT / name).read_text()
|
||||
assert str(_CREDENTIAL_KEY_PATH) in text, f"{name} does not name the key path"
|
||||
assert _BOOTSTRAP_ENV_VAR in text, f"{name} does not name the bootstrap variable"
|
||||
|
||||
|
||||
def test_compose_passes_the_bootstrap_variable_through():
|
||||
"""The docs say "set it in .env"; that only works if compose forwards it.
|
||||
|
||||
Without this line the instruction is silently inert — the operator sets the
|
||||
variable, the container never sees it, and the failure is identical to not
|
||||
having set it at all.
|
||||
"""
|
||||
from backend.app.services.credential_crypto import _BOOTSTRAP_ENV_VAR
|
||||
|
||||
compose = (_REPO_ROOT / "docker-compose.yml").read_text()
|
||||
assert f"{_BOOTSTRAP_ENV_VAR}: ${{{_BOOTSTRAP_ENV_VAR}" in compose
|
||||
|
||||
Reference in New Issue
Block a user