from pathlib import Path from pyra.utils.paths import pyra_home class VaultAccessError(PermissionError): pass class PyraSecurityError(RuntimeError): pass VAULT_PATH: Path = pyra_home() / "vault" BLOCKED_PREFIXES: list[Path] = [VAULT_PATH] def assert_safe_path(path: Path) -> None: """Raise VaultAccessError if path resolves into a blocked prefix.""" resolved = path.resolve() for blocked in BLOCKED_PREFIXES: blocked_resolved = blocked.resolve() try: resolved.relative_to(blocked_resolved) raise VaultAccessError( f"Access denied: '{resolved}' is inside the protected vault. " "The vault is never accessible to the AI." ) except ValueError: pass def check_vault_lock() -> None: """Raise PyraSecurityError if the vault sentinel is missing.""" lock = VAULT_PATH / ".vault_lock" if not lock.exists(): raise PyraSecurityError( f"Vault sentinel missing: {lock}\n" "This may indicate tampering. Refusing to start.\n" "Run 'pyra setup' to reinitialise the vault." )