8cd5392ec3
.env.example shipped a valid, PUBLIC base64 key — if a user didn't replace it, every credential got encrypted with a publicly-known key and everything still "worked," so the footgun was silent. - .env.example now ships an obvious placeholder (CHANGE_ME_generate_with_...) with a "you MUST replace this" note and the openssl hint. - web + worker validate LYRA_SECRET_KEY at startup: missing / placeholder / wrong-length ⇒ loud FATAL banner and refuse to start (web via the Next.js instrumentation hook, worker via _require_secret_key before touching the DB). The old public example key ⇒ a loud WARNING but not fatal, since an existing install may have encrypted its creds under it (rotating needs re-entry). - Validation lives in an edge-safe web/src/lib/secret-key.ts (no node:crypto) so the instrumentation hook bundles for both runtimes; crypto.ts re-exports. - README emphasizes generating a fresh key + keeping it stable. Verified live: worker exits 1 on placeholder/unset before any DB call; web instrumentation throws and refuses to serve on the placeholder. web 138 tests, worker 204/7-skip, tsc clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
import base64
|
|
|
|
import pytest
|
|
|
|
from lyra_worker.crypto import PLACEHOLDER_SECRET_KEY, secret_key_problem
|
|
|
|
_GOOD = base64.b64encode(b"x" * 32).decode()
|
|
_LEGACY = "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY="
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _clean_env(monkeypatch):
|
|
monkeypatch.delenv("LYRA_SECRET_KEY", raising=False)
|
|
|
|
|
|
def test_missing_key_is_fatal(monkeypatch):
|
|
assert secret_key_problem() == ("LYRA_SECRET_KEY is not set", True)
|
|
|
|
|
|
def test_placeholder_is_fatal(monkeypatch):
|
|
monkeypatch.setenv("LYRA_SECRET_KEY", PLACEHOLDER_SECRET_KEY)
|
|
msg, fatal = secret_key_problem()
|
|
assert fatal is True and "placeholder" in msg
|
|
|
|
|
|
def test_wrong_length_is_fatal(monkeypatch):
|
|
monkeypatch.setenv("LYRA_SECRET_KEY", base64.b64encode(b"short").decode())
|
|
msg, fatal = secret_key_problem()
|
|
assert fatal is True and "32 bytes" in msg
|
|
|
|
|
|
def test_legacy_public_key_warns_not_fatal(monkeypatch):
|
|
monkeypatch.setenv("LYRA_SECRET_KEY", _LEGACY)
|
|
msg, fatal = secret_key_problem()
|
|
assert fatal is False and "PUBLIC" in msg
|
|
|
|
|
|
def test_good_key_is_fine(monkeypatch):
|
|
monkeypatch.setenv("LYRA_SECRET_KEY", _GOOD)
|
|
assert secret_key_problem() is None
|