from __future__ import annotations import unittest from cryptography.fernet import Fernet from govoplan_core.core.install_config import env_template, validate_runtime_configuration class InstallConfigTests(unittest.TestCase): def test_self_hosted_validation_reports_actionable_missing_settings(self) -> None: result = validate_runtime_configuration({}, profile="self-hosted") self.assertFalse(result.ok) errors = {issue.key: issue for issue in result.errors} self.assertIn("APP_ENV", errors) self.assertIn("DATABASE_URL", errors) self.assertIn("MASTER_KEY_B64", errors) self.assertIn("ENABLED_MODULES", errors) self.assertIn("CORS_ORIGINS", errors) self.assertIn("Set DATABASE_URL", errors["DATABASE_URL"].action) def test_self_hosted_validation_accepts_explicit_postgres_configuration(self) -> None: result = validate_runtime_configuration( { "APP_ENV": "production", "GOVOPLAN_INSTALL_PROFILE": "self-hosted", "DATABASE_URL": "postgresql+psycopg://govoplan:secret@db.example.internal:5432/govoplan", "GOVOPLAN_DATABASE_URL_PGTOOLS": "postgresql://govoplan:secret@db.example.internal:5432/govoplan", "MASTER_KEY_B64": Fernet.generate_key().decode("ascii"), "ENABLED_MODULES": "access,admin,policy,audit", "CELERY_ENABLED": "true", "REDIS_URL": "redis://redis.example.internal:6379/0", "CORS_ORIGINS": "https://govoplan.example.org", "AUTH_COOKIE_SECURE": "true", "FILE_STORAGE_BACKEND": "local", "FILE_STORAGE_LOCAL_ROOT": "/var/lib/govoplan/files", }, profile="self-hosted", ) self.assertTrue(result.ok, result.to_text()) self.assertEqual([], [issue.key for issue in result.errors]) def test_production_validation_rejects_dev_bootstrap_and_sqlite(self) -> None: result = validate_runtime_configuration( { "APP_ENV": "production", "DATABASE_URL": "sqlite:////tmp/govoplan.db", "MASTER_KEY_B64": Fernet.generate_key().decode("ascii"), "ENABLED_MODULES": "access,admin", "DEV_BOOTSTRAP_ENABLED": "true", "CORS_ORIGINS": "https://govoplan.example.org", "AUTH_COOKIE_SECURE": "true", "FILE_STORAGE_BACKEND": "local", "FILE_STORAGE_LOCAL_ROOT": "/var/lib/govoplan/files", }, profile="self-hosted", ) error_keys = {issue.key for issue in result.errors} self.assertIn("DATABASE_URL", error_keys) self.assertIn("DEV_BOOTSTRAP_ENABLED", error_keys) def test_env_templates_surface_install_profiles(self) -> None: self_hosted = env_template(profile="self-hosted") production_like = env_template(profile="production-like", generate_secrets=True) self.assertIn("GOVOPLAN_INSTALL_PROFILE=self-hosted", self_hosted) self.assertIn("MASTER_KEY_B64=