"""Vault secret resolver + file IO + rsync command build.""" from __future__ import annotations import stat from pathlib import Path from claire import vault def test_write_read_roundtrip_and_0600(tmp_path: Path) -> None: p = vault.write_vault_file("s.txt", "hunter2", vault_dir=tmp_path) assert vault.read_vault_file("s.txt", vault_dir=tmp_path) == "hunter2" assert stat.S_IMODE(p.stat().st_mode) == 0o600 assert stat.S_IMODE(tmp_path.stat().st_mode) == 0o700 def test_read_missing_returns_none(tmp_path: Path) -> None: assert vault.read_vault_file("nope.txt", vault_dir=tmp_path) is None def test_resolve_prefers_vault_over_fallback(tmp_path: Path) -> None: vault.write_vault_file("claire-sync-secret.txt", "VAULTSECRET", vault_dir=tmp_path) assert vault.resolve_sync_secrets("CONFIGSECRET", vault_dir=tmp_path) == ["VAULTSECRET"] def test_resolve_falls_back_to_config_when_no_vault(tmp_path: Path) -> None: assert vault.resolve_sync_secrets("CONFIGSECRET", vault_dir=tmp_path) == ["CONFIGSECRET"] def test_resolve_empty_when_nothing(tmp_path: Path) -> None: assert vault.resolve_sync_secrets(None, vault_dir=tmp_path) == [] def test_resolve_includes_prev_during_rotation(tmp_path: Path) -> None: vault.write_vault_file("claire-sync-secret.txt", "NEW", vault_dir=tmp_path) vault.write_vault_file("claire-sync-secret.prev.txt", "OLD", vault_dir=tmp_path) assert vault.resolve_sync_secrets(None, vault_dir=tmp_path) == ["NEW", "OLD"] def test_resolve_dedupes_prev_equal_current(tmp_path: Path) -> None: vault.write_vault_file("claire-sync-secret.txt", "SAME", vault_dir=tmp_path) vault.write_vault_file("claire-sync-secret.prev.txt", "SAME", vault_dir=tmp_path) assert vault.resolve_sync_secrets(None, vault_dir=tmp_path) == ["SAME"] def test_rsync_cmd_flags(tmp_path: Path) -> None: cmd = vault._rsync_cmd(tmp_path, "apricot:.vault/", delete=False, ts="T") assert "--no-inplace" in cmd assert "--exclude=*.prev.txt" in cmd # rotation prev stays plum-local assert "--backup-dir=../.vault-backups/T/" in cmd assert "--delete" not in cmd assert cmd[-2:] == [f"{tmp_path}/", "apricot:.vault/"] def test_rsync_cmd_delete_opt_in(tmp_path: Path) -> None: assert "--delete" in vault._rsync_cmd(tmp_path, "h:.vault/", delete=True, ts="T")