diff --git a/backend/tests/test_delivery.py b/backend/tests/test_delivery.py index b47b279..af35f17 100644 --- a/backend/tests/test_delivery.py +++ b/backend/tests/test_delivery.py @@ -392,6 +392,7 @@ def postgres_recovery_settings_shape(): values = recovery_identity.recovery_settings() rows = [{"name": key, "setting": value, "unit": None} for key, value in values.items()] normalized = { + "archive_command": ("(disabled)", None), "shared_buffers": ("8192", "8kB"), "work_mem": ("1024", "kB"), "maintenance_work_mem": ("32768", "kB"), @@ -416,6 +417,7 @@ def test_postgres_recovery_readback_compares_effective_units_instead_of_cli_stri recovered = recovery_identity.check_settings(rows) assert recovered["listen_addresses"]["setting"] == "" assert recovered["unix_socket_permissions"]["setting"] == "0700" + assert recovered["archive_command"]["setting"] == "(disabled)" for row in rows: if row["name"] == "shared_buffers": row["setting"] = "16384" @@ -423,6 +425,24 @@ def test_postgres_recovery_readback_compares_effective_units_instead_of_cli_stri recovery_identity.check_settings(rows) +@pytest.mark.parametrize( + ("name", "setting"), + [ + ("archive_mode", "on"), + ("archive_library", "unapproved_library"), + ("archive_command", "/bin/true"), + ("archive_command", ""), + ], +) +def test_postgres_recovery_disabled_display_requires_disabled_archiving(name, setting): + rows = postgres_recovery_settings_shape() + for row in rows: + if row["name"] == name: + row["setting"] = setting + with pytest.raises(policy.DeliveryError): + recovery_identity.check_settings(rows) + + def recovery_receipts_shape(): # Pure closed-contract example; no PG connection, Root or Linux acceptance. prepared = { diff --git a/scripts/release/recovery_database.py b/scripts/release/recovery_database.py index e487064..9d89dfa 100644 --- a/scripts/release/recovery_database.py +++ b/scripts/release/recovery_database.py @@ -373,7 +373,7 @@ def recover_locked(recovery_id: str, data_sha: str, password_file: Path, passwor "RestrictAddressFamilies": "AF_UNIX", "RuntimeDirectory": recovery_identity.RUNTIME.name, "RuntimeDirectoryMode": "0700", - "ReadWritePaths": str(dependency_initialize.DATA), + "ReadWritePaths": str(dependency_initialize.DATA.parent), }.items(): command.append("--property=" + key + "=" + setting) command += [ diff --git a/scripts/release/recovery_identity.py b/scripts/release/recovery_identity.py index f1ca3e5..00a3b82 100644 --- a/scripts/release/recovery_identity.py +++ b/scripts/release/recovery_identity.py @@ -180,6 +180,14 @@ def check_settings(rows) -> dict: good = unit is None and int(value, 8 if value.startswith("0") else 10) == 0o700 elif key == "temp_file_limit": good = unit == "kB" and value == expected + elif key == "archive_command": + # PostgreSQL's show hook masks the empty command while archiving is off. + good = ( + unit is None + and value == "(disabled)" + and actual["archive_mode"] == ("off", None) + and actual["archive_library"] == ("", None) + ) else: good = unit is None and value == expected if not good: