from __future__ import annotations import re from pathlib import Path ROOT = Path(__file__).resolve().parents[3] SCRIPT = ROOT / "scripts" / "backup" / "backup-awoooi.sh" FREQUENT_SCRIPT = ROOT / "scripts" / "backup" / "backup-awoooi-frequent.sh" def test_daily_backup_has_no_hardcoded_database_password() -> None: text = SCRIPT.read_text(encoding="utf-8") assignment = re.search(r"^AWOOOI_DB_PASS=(.+)$", text, re.MULTILINE) assert assignment is not None assert assignment.group(1) == '"${AWOOOI_DB_PASS:-}"' assert "PGPASSWORD='${AWOOOI_DB_PASS}'" not in text assert 'PGPASSFILE="$pgpass"' in text assert "pg_dump --no-password" in text def test_daily_backup_resolves_runtime_database_url_and_fails_closed() -> None: text = SCRIPT.read_text(encoding="utf-8") assert "resolve_database_url()" in text assert "load_database_config()" in text assert "AWOOOI_BACKUP_DATABASE_URL BACKUP_DATABASE_URL DATABASE_URL" in text assert "無法解析 AWOOOI DATABASE_URL;拒絕使用舊硬編密碼" in text assert "base64 -d" in text assert 'printf \'%s\\n\' "${decoded}"' in text def test_daily_and_frequent_backups_fail_closed_without_mutating_rls() -> None: for script in (SCRIPT, FREQUENT_SCRIPT): text = script.read_text(encoding="utf-8") assert "logical_backup_preflight()" in text assert "dump_database_fail_closed()" in text assert "rolsuper" in text assert "rolbypassrls" in text assert "backup role must not be superuser or global BYPASSRLS" in text assert "forced_rls_tables=${forced_rls_count}" in text assert "physical/WAL backup with isolated restore verifier is required" in text assert "return 78" in text assert 'PGOPTIONS="-c statement_timeout=0 -c max_parallel_workers_per_gather=0"' in text assert "ALTER TABLE" not in text assert "NO FORCE" not in text assert "collect_force_rls_sql" not in text assert "apply_remote_sql" not in text assert "restore_force_rls" not in text def test_daily_backup_routes_every_database_through_fail_closed_dump() -> None: text = SCRIPT.read_text(encoding="utf-8") assert text.count("if dump_database_fail_closed \\") == 3 assert 'dump_database_fail_closed \\\n "awoooi_prod"' in text assert 'dump_database_fail_closed \\\n "awoooi_dev"' in text assert 'dump_database_fail_closed \\\n "k3s_datastore"' in text def test_frequent_backup_routes_production_database_through_fail_closed_dump() -> None: text = FREQUENT_SCRIPT.read_text(encoding="utf-8") assert 'dump_database_fail_closed "awoooi_prod"' in text