From 3b003b850d9d3d521769a01f9723faa5472edcca Mon Sep 17 00:00:00 2001 From: jenkins Date: Sun, 16 Aug 2026 08:39:45 -0300 Subject: [PATCH] hermes: preserve Vault CLI credentials for workers --- services/hermes/scripts/cli_lane_runner.py | 7 +++++-- testing/tests/test_hermes_cli_lanes.py | 13 +++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/services/hermes/scripts/cli_lane_runner.py b/services/hermes/scripts/cli_lane_runner.py index d2984e8d..8ee96516 100644 --- a/services/hermes/scripts/cli_lane_runner.py +++ b/services/hermes/scripts/cli_lane_runner.py @@ -428,12 +428,15 @@ def _terminate_worker_process(process: subprocess.Popen[str]) -> None: def _base_env() -> dict[str, str]: + """Build a worker environment while preserving Vault-backed CLI homes.""" env = os.environ.copy() env.update( { "HOME": str(DATA_ROOT / "home"), - "CODEX_HOME": str(DATA_ROOT / "home/.codex"), - "CLAUDE_CONFIG_DIR": str(DATA_ROOT / "home/.claude"), + "CODEX_HOME": os.environ.get("CODEX_HOME", "/runtime-access/codex"), + "CLAUDE_CONFIG_DIR": os.environ.get( + "CLAUDE_CONFIG_DIR", "/runtime-access/claude" + ), "GIT_TERMINAL_PROMPT": "0", } ) diff --git a/testing/tests/test_hermes_cli_lanes.py b/testing/tests/test_hermes_cli_lanes.py index fcf76182..60b9de24 100644 --- a/testing/tests/test_hermes_cli_lanes.py +++ b/testing/tests/test_hermes_cli_lanes.py @@ -151,6 +151,19 @@ def test_cross_provider_retry_passes_failed_provider_to_switchyard(): assert "codex provider failed or exhausted capacity" in content +def test_worker_environment_preserves_vault_backed_cli_homes(monkeypatch): + """Kanban workers must not fall back to credential-free persistent homes.""" + monkeypatch.setenv("CODEX_HOME", "/runtime-access/codex") + monkeypatch.setenv("CLAUDE_CONFIG_DIR", "/runtime-access/claude") + + env = lanes._base_env() + + assert env["HOME"] == str(lanes.DATA_ROOT / "home") + assert env["CODEX_HOME"] == "/runtime-access/codex" + assert env["CLAUDE_CONFIG_DIR"] == "/runtime-access/claude" + assert env["GIT_TERMINAL_PROMPT"] == "0" + + def test_claude_session_is_reserved_before_first_process(tmp_path: Path, monkeypatch): state: dict = {} state_file = tmp_path / "state.json"