"""Re-encrypt the secrets store after SECRET_KEY was rotated. The store's encryption key is derived from SECRET_KEY, so a new key leaves ``secrets.enc`` unreadable. Put the new key in `.env` first, then hand this script the previous one: uv run python scripts/rotate_secret_key.py """ import logging import sys from app.core.config import settings from app.flow.secrets import SecretsStore, SecretsUnreadable logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def main(old_key: str) -> None: path = settings.SECRETS_FILE if not path.exists(): sys.exit(f"No secrets store at {path} — nothing to re-encrypt.") if old_key == settings.SECRET_KEY: sys.exit("Old and new key are identical — set the new SECRET_KEY first.") # The store has no bulk export; reading and writing it whole is the point. try: data = SecretsStore(path, old_key)._read() except SecretsUnreadable: sys.exit(f"{path} does not decrypt with that key — refusing to overwrite it.") SecretsStore(path, settings.SECRET_KEY)._write(data) logger.info( "Re-encrypted %d secret(s) in %s with the current SECRET_KEY", len(data), path ) if __name__ == "__main__": if len(sys.argv) != 2: sys.exit("usage: rotate_secret_key.py ") main(sys.argv[1])