fix: unconditionally clear ANTHROPIC_TOKEN on v8→v9 migration
No conditional checks — just clear it. The new auth flow doesn't use this env var. Anyone upgrading gets it wiped once, then it's done.
This commit is contained in:
parent
e9f1a8e39b
commit
1c61ab6bd9
2 changed files with 17 additions and 91 deletions
|
|
@ -828,29 +828,15 @@ def migrate_config(interactive: bool = True, quiet: bool = False) -> Dict[str, A
|
||||||
tz_display = config["timezone"] or "(server-local)"
|
tz_display = config["timezone"] or "(server-local)"
|
||||||
print(f" ✓ Added timezone to config.yaml: {tz_display}")
|
print(f" ✓ Added timezone to config.yaml: {tz_display}")
|
||||||
|
|
||||||
# ── Version 8 → 9: clear stale ANTHROPIC_TOKEN when better creds exist ──
|
# ── Version 8 → 9: clear ANTHROPIC_TOKEN from .env ──
|
||||||
|
# The new Anthropic auth flow no longer uses this env var.
|
||||||
if current_ver < 9:
|
if current_ver < 9:
|
||||||
try:
|
try:
|
||||||
old_token = get_env_value("ANTHROPIC_TOKEN")
|
old_token = get_env_value("ANTHROPIC_TOKEN")
|
||||||
if old_token:
|
if old_token:
|
||||||
has_api_key = bool(get_env_value("ANTHROPIC_API_KEY"))
|
save_env_value("ANTHROPIC_TOKEN", "")
|
||||||
has_claude_code = False
|
if not quiet:
|
||||||
try:
|
print(" ✓ Cleared ANTHROPIC_TOKEN from .env (no longer used)")
|
||||||
from agent.anthropic_adapter import (
|
|
||||||
read_claude_code_credentials,
|
|
||||||
is_claude_code_token_valid,
|
|
||||||
)
|
|
||||||
cc_creds = read_claude_code_credentials()
|
|
||||||
has_claude_code = bool(
|
|
||||||
cc_creds and is_claude_code_token_valid(cc_creds)
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
if has_api_key or has_claude_code:
|
|
||||||
save_env_value("ANTHROPIC_TOKEN", "")
|
|
||||||
if not quiet:
|
|
||||||
source = "ANTHROPIC_API_KEY" if has_api_key else "Claude Code credentials"
|
|
||||||
print(f" ✓ Cleared stale ANTHROPIC_TOKEN (using {source} instead)")
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -316,92 +316,32 @@ class TestSanitizeEnvLines:
|
||||||
assert fixes == 0
|
assert fixes == 0
|
||||||
|
|
||||||
|
|
||||||
class TestStaleAnthropicTokenMigration:
|
class TestAnthropicTokenMigration:
|
||||||
"""Test that migrate_config clears stale ANTHROPIC_TOKEN."""
|
"""Test that config version 8→9 clears ANTHROPIC_TOKEN."""
|
||||||
|
|
||||||
def _write_config_version(self, tmp_path, version):
|
def _write_config_version(self, tmp_path, version):
|
||||||
"""Write a config.yaml with a specific _config_version."""
|
|
||||||
config_path = tmp_path / "config.yaml"
|
config_path = tmp_path / "config.yaml"
|
||||||
import yaml
|
import yaml
|
||||||
config = {"_config_version": version}
|
config_path.write_text(yaml.safe_dump({"_config_version": version}))
|
||||||
config_path.write_text(yaml.safe_dump(config, sort_keys=False))
|
|
||||||
|
|
||||||
def test_clears_stale_token_when_api_key_exists(self, tmp_path):
|
def test_clears_token_on_upgrade_to_v9(self, tmp_path):
|
||||||
"""ANTHROPIC_TOKEN cleared when ANTHROPIC_API_KEY is also set."""
|
"""ANTHROPIC_TOKEN is cleared unconditionally when upgrading to v9."""
|
||||||
self._write_config_version(tmp_path, 8)
|
self._write_config_version(tmp_path, 8)
|
||||||
env_file = tmp_path / ".env"
|
(tmp_path / ".env").write_text("ANTHROPIC_TOKEN=old-token\n")
|
||||||
env_file.write_text(
|
|
||||||
"ANTHROPIC_API_KEY=sk-ant-real-key\n"
|
|
||||||
"ANTHROPIC_TOKEN=old-stale-token\n"
|
|
||||||
)
|
|
||||||
with patch.dict(os.environ, {
|
with patch.dict(os.environ, {
|
||||||
"HERMES_HOME": str(tmp_path),
|
"HERMES_HOME": str(tmp_path),
|
||||||
"ANTHROPIC_API_KEY": "sk-ant-real-key",
|
"ANTHROPIC_TOKEN": "old-token",
|
||||||
"ANTHROPIC_TOKEN": "old-stale-token",
|
|
||||||
}):
|
}):
|
||||||
migrate_config(interactive=False, quiet=True)
|
migrate_config(interactive=False, quiet=True)
|
||||||
|
assert load_env().get("ANTHROPIC_TOKEN") == ""
|
||||||
env = load_env()
|
|
||||||
assert env.get("ANTHROPIC_TOKEN") == ""
|
|
||||||
assert env.get("ANTHROPIC_API_KEY") == "sk-ant-real-key"
|
|
||||||
|
|
||||||
def test_clears_stale_token_when_claude_code_available(self, tmp_path):
|
|
||||||
"""ANTHROPIC_TOKEN cleared when Claude Code credentials exist."""
|
|
||||||
self._write_config_version(tmp_path, 8)
|
|
||||||
env_file = tmp_path / ".env"
|
|
||||||
env_file.write_text("ANTHROPIC_TOKEN=old-stale-token\n")
|
|
||||||
|
|
||||||
fake_creds = {"accessToken": "valid-token", "expiresAt": 0}
|
|
||||||
with patch.dict(os.environ, {
|
|
||||||
"HERMES_HOME": str(tmp_path),
|
|
||||||
"ANTHROPIC_TOKEN": "old-stale-token",
|
|
||||||
}):
|
|
||||||
with patch(
|
|
||||||
"agent.anthropic_adapter.read_claude_code_credentials",
|
|
||||||
return_value=fake_creds,
|
|
||||||
), patch(
|
|
||||||
"agent.anthropic_adapter.is_claude_code_token_valid",
|
|
||||||
return_value=True,
|
|
||||||
):
|
|
||||||
migrate_config(interactive=False, quiet=True)
|
|
||||||
|
|
||||||
env = load_env()
|
|
||||||
assert env.get("ANTHROPIC_TOKEN") == ""
|
|
||||||
|
|
||||||
def test_preserves_token_when_no_alternative(self, tmp_path):
|
|
||||||
"""ANTHROPIC_TOKEN kept when no API key or Claude Code creds exist."""
|
|
||||||
self._write_config_version(tmp_path, 8)
|
|
||||||
env_file = tmp_path / ".env"
|
|
||||||
env_file.write_text("ANTHROPIC_TOKEN=only-auth-method\n")
|
|
||||||
|
|
||||||
with patch.dict(os.environ, {
|
|
||||||
"HERMES_HOME": str(tmp_path),
|
|
||||||
"ANTHROPIC_TOKEN": "only-auth-method",
|
|
||||||
}):
|
|
||||||
os.environ.pop("ANTHROPIC_API_KEY", None)
|
|
||||||
with patch(
|
|
||||||
"agent.anthropic_adapter.read_claude_code_credentials",
|
|
||||||
return_value=None,
|
|
||||||
):
|
|
||||||
migrate_config(interactive=False, quiet=True)
|
|
||||||
|
|
||||||
env = load_env()
|
|
||||||
assert env.get("ANTHROPIC_TOKEN") == "only-auth-method"
|
|
||||||
|
|
||||||
def test_skips_on_version_9_or_later(self, tmp_path):
|
def test_skips_on_version_9_or_later(self, tmp_path):
|
||||||
"""Migration doesn't fire when already at config version 9+."""
|
"""Already at v9 — ANTHROPIC_TOKEN is not touched."""
|
||||||
self._write_config_version(tmp_path, 9)
|
self._write_config_version(tmp_path, 9)
|
||||||
env_file = tmp_path / ".env"
|
(tmp_path / ".env").write_text("ANTHROPIC_TOKEN=current-token\n")
|
||||||
env_file.write_text(
|
|
||||||
"ANTHROPIC_API_KEY=sk-ant-real-key\n"
|
|
||||||
"ANTHROPIC_TOKEN=should-stay\n"
|
|
||||||
)
|
|
||||||
with patch.dict(os.environ, {
|
with patch.dict(os.environ, {
|
||||||
"HERMES_HOME": str(tmp_path),
|
"HERMES_HOME": str(tmp_path),
|
||||||
"ANTHROPIC_API_KEY": "sk-ant-real-key",
|
"ANTHROPIC_TOKEN": "current-token",
|
||||||
"ANTHROPIC_TOKEN": "should-stay",
|
|
||||||
}):
|
}):
|
||||||
migrate_config(interactive=False, quiet=True)
|
migrate_config(interactive=False, quiet=True)
|
||||||
|
assert load_env().get("ANTHROPIC_TOKEN") == "current-token"
|
||||||
env = load_env()
|
|
||||||
assert env.get("ANTHROPIC_TOKEN") == "should-stay"
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue