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"
|
key_path = tmp_path / "bootstrap.b64"
|
||||||
CredentialCrypto(key_path) # no bootstrap_ok kwarg — relies on env
|
CredentialCrypto(key_path) # no bootstrap_ok kwarg — relies on env
|
||||||
assert key_path.exists()
|
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