- Replaced @TIER: TRIVIAL with @COMPLEXITY: 1 - Replaced @TIER: STANDARD with @COMPLEXITY: 3 - Replaced @TIER: CRITICAL with @COMPLEXITY: 5 - Manually elevated specific critical/complex components to levels 2 and 4 - Ignored legacy, specs, and node_modules directories - Updated generated semantic map
57 lines
2.4 KiB
Python
57 lines
2.4 KiB
Python
# [DEF:backend.src.core.encryption_key:Module]
|
|
# @COMPLEXITY: 5
|
|
# @SEMANTICS: encryption, key, bootstrap, environment, startup
|
|
# @PURPOSE: Resolve and persist the Fernet encryption key required by runtime services.
|
|
# @LAYER: Infra
|
|
# @RELATION: DEPENDS_ON -> backend.src.core.logger
|
|
# @INVARIANT: Runtime key resolution never falls back to an ephemeral secret.
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
from cryptography.fernet import Fernet
|
|
|
|
from .logger import logger, belief_scope
|
|
|
|
DEFAULT_ENV_FILE_PATH = Path(__file__).resolve().parents[2] / ".env"
|
|
|
|
|
|
# [DEF:ensure_encryption_key:Function]
|
|
# @PURPOSE: Ensure backend runtime has a persistent valid Fernet key.
|
|
# @PRE: env_file_path points to a writable backend .env file or ENCRYPTION_KEY exists in process environment.
|
|
# @POST: Returns a valid Fernet key and guarantees it is present in process environment.
|
|
# @SIDE_EFFECT: May create or append backend/.env when key is missing.
|
|
def ensure_encryption_key(env_file_path: Path = DEFAULT_ENV_FILE_PATH) -> str:
|
|
with belief_scope("ensure_encryption_key", f"env_file_path={env_file_path}"):
|
|
existing_key = os.getenv("ENCRYPTION_KEY", "").strip()
|
|
if existing_key:
|
|
Fernet(existing_key.encode())
|
|
logger.reason("Using ENCRYPTION_KEY from process environment.")
|
|
return existing_key
|
|
|
|
if env_file_path.exists():
|
|
for raw_line in env_file_path.read_text(encoding="utf-8").splitlines():
|
|
if raw_line.startswith("ENCRYPTION_KEY="):
|
|
persisted_key = raw_line.partition("=")[2].strip()
|
|
if persisted_key:
|
|
Fernet(persisted_key.encode())
|
|
os.environ["ENCRYPTION_KEY"] = persisted_key
|
|
logger.reason(f"Loaded ENCRYPTION_KEY from {env_file_path}.")
|
|
return persisted_key
|
|
|
|
generated_key = Fernet.generate_key().decode()
|
|
with env_file_path.open("a", encoding="utf-8") as env_file:
|
|
if env_file.tell() > 0:
|
|
env_file.write("\n")
|
|
env_file.write(f"ENCRYPTION_KEY={generated_key}\n")
|
|
|
|
os.environ["ENCRYPTION_KEY"] = generated_key
|
|
logger.reason(f"Generated ENCRYPTION_KEY and persisted it to {env_file_path}.")
|
|
logger.reflect("Encryption key is available for runtime services.")
|
|
return generated_key
|
|
# [/DEF:ensure_encryption_key:Function]
|
|
|
|
# [/DEF:backend.src.core.encryption_key:Module]
|