"""Runtime configuration helpers that keep secret values out of manifests.""" from __future__ import annotations import os import re from pathlib import Path POSTGRES_IDENTIFIER = re.compile(r"^[a-z_][a-z0-9_]*$") def database_target(default: str | Path | None = None) -> str | Path: """Return the configured database target, preferring a mounted secret file.""" url_file = os.getenv("SBOM_NEXUS_DATABASE_URL_FILE") if url_file: path = Path(url_file) try: value = path.read_text(encoding="utf-8").strip() except OSError as exc: raise RuntimeError(f"Unable to read SBOM_NEXUS_DATABASE_URL_FILE: {path}") from exc if not value: raise RuntimeError(f"SBOM_NEXUS_DATABASE_URL_FILE is empty: {path}") return value url = os.getenv("SBOM_NEXUS_DATABASE_URL") if url: return url path = os.getenv("SBOM_NEXUS_DATABASE_PATH") if path: return path if default is None: raise RuntimeError( "Configure SBOM_NEXUS_DATABASE_URL_FILE, SBOM_NEXUS_DATABASE_URL, " "or SBOM_NEXUS_DATABASE_PATH" ) return default def migration_role() -> str | None: """Return the durable PostgreSQL role that must own migrated objects.""" role = os.getenv("SBOM_NEXUS_MIGRATION_ROLE") if not role: return None if not POSTGRES_IDENTIFIER.fullmatch(role): raise RuntimeError("SBOM_NEXUS_MIGRATION_ROLE must be a PostgreSQL identifier") return role