Merge remote-tracking branch 'origin/main' into feat/removed-flag-env-migration
CI / Lint (ruff) (pull_request) Successful in 11s
CI / Tests (py3.12 / windows-latest) (pull_request) Successful in 23s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 14s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 17s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 14s
CI / Catalog signature (pull_request) Successful in 9s

# Conflicts:
#	tests/test_core.py
This commit is contained in:
the_og
2026-08-12 06:12:19 +00:00
4 changed files with 858 additions and 0 deletions
+172
View File
@@ -3206,3 +3206,175 @@ def test_ssh_membermatters_end_to_end():
]
assert new["env"] == {"SSH_MCP_PASSWORD": "topsecret"}
assert notes
# --------------------------------------------------------------------------- #
# Move to environment variable (issue #83)
# --------------------------------------------------------------------------- #
@pytest.mark.parametrize(
"raw,expected",
[
("API_KEY", "API_KEY"),
("api-key", "API_KEY"),
("x.y z", "X_Y_Z"),
("2fa", "_2FA"),
("", "VAR"),
("***", "VAR"),
("clé", "CL_"), # non-ASCII becomes _
],
)
def test_sanitize_env_var_name(raw, expected):
assert c.sanitize_env_var_name(raw) == expected
def test_shell_export_lines_quote_safely():
lines = c.shell_export_lines("TOKEN", "ab'cd")
assert lines["posix"] == "export TOKEN='ab'\\''cd'"
assert lines["windows"] == 'setx TOKEN "ab\'cd"'
def test_can_move_gate_requires_secret_and_expanding_client():
desktop = c.Profile(label="d", path="/x/Claude/claude_desktop_config.json", config_exists=True)
code = c.Profile(label="c", path=Path.home() / ".claude.json", config_exists=True)
# real secret on an expanding client -> offer
assert c.can_move_value_to_env_ref("API_KEY", "ghp_abc", code) is True
assert c.can_move_value_to_env_ref("API_KEY", "ghp_abc", None) is True
# non-secret key -> no
assert c.can_move_value_to_env_ref("REGION", "us-east-1", code) is False
# already a reference -> no
assert c.can_move_value_to_env_ref("API_KEY", "${API_KEY}", code) is False
# non-expanding client (Claude Desktop) -> refuse even a real secret
assert c.can_move_value_to_env_ref("API_KEY", "ghp_abc", desktop) is False
def test_move_env_value_replaces_with_reference_and_returns_secret():
data = {"command": "x", "env": {"API_KEY": "ghp_secret", "REGION": "us"}}
conv = c.move_value_to_env_ref(data, field="env", key="API_KEY")
assert conv is not None
assert conv.var_name == "API_KEY"
assert conv.reference == "${API_KEY}"
assert conv.secret == "ghp_secret"
assert conv.data["env"]["API_KEY"] == "${API_KEY}"
# non-secret row untouched
assert conv.data["env"]["REGION"] == "us"
# input never mutated
assert data["env"]["API_KEY"] == "ghp_secret"
def test_move_derives_and_sanitises_var_name_from_key():
data = {"headers": {"x-api-key": "sekret"}}
conv = c.move_value_to_env_ref(data, field="headers", key="x-api-key")
assert conv.var_name == "X_API_KEY"
assert conv.data["headers"]["x-api-key"] == "${X_API_KEY}"
def test_move_honours_explicit_var_name():
data = {"env": {"tok": "sekret"}}
conv = c.move_value_to_env_ref(data, field="env", key="tok", var_name="GITHUB_TOKEN")
assert conv.reference == "${GITHUB_TOKEN}"
assert conv.data["env"]["tok"] == "${GITHUB_TOKEN}"
def test_move_args_by_index():
data = {"command": "x", "args": ["--token", "ghp_secret"]}
conv = c.move_value_to_env_ref(data, field="args", index=1, var_name="GH_TOKEN")
assert conv.secret == "ghp_secret"
assert conv.data["args"] == ["--token", "${GH_TOKEN}"]
def test_move_returns_none_on_missing_or_nonstring_or_already_ref():
data = {"env": {"API_KEY": "${API_KEY}", "N": 5}}
assert c.move_value_to_env_ref(data, field="env", key="ABSENT") is None
assert c.move_value_to_env_ref(data, field="env", key="N") is None # not a string
assert c.move_value_to_env_ref(data, field="env", key="API_KEY") is None # already a ref
assert c.move_value_to_env_ref({}, field="bogus") is None
assert c.move_value_to_env_ref({"args": ["a"]}, field="args", index=9) is None
def test_is_env_var_set():
assert c.is_env_var_set("FOO", {"FOO": "x"}) is True
assert c.is_env_var_set("FOO", {"FOO": ""}) is False
assert c.is_env_var_set("FOO", {}) is False
# --------------------------------------------------------------------------- #
# Args secret indices + suggested var name (issue #83, args surface)
# --------------------------------------------------------------------------- #
def test_secret_arg_indices_flags_token_and_flag_value():
args = ["--port", "8080", "ghp_deadbeef", "--token", "sk-abc", "--flag=val"]
idxs = c.secret_arg_indices(args)
assert 2 in idxs # ghp_ token prefix
assert 4 in idxs # value following --token
assert 1 not in idxs # 8080
assert 5 not in idxs # --flag=val inline pair
def test_secret_arg_indices_flags_embedded_url_credentials():
args = ["postgres://user:pass@host/db"]
assert c.secret_arg_indices(args) == [0]
def test_secret_arg_indices_excludes_existing_references():
args = ["--token", "${GH_TOKEN}"]
assert c.secret_arg_indices(args) == []
def test_suggested_env_var_for_arg_uses_preceding_flag():
args = ["--api-key", "sk-secret"]
assert c.suggested_env_var_for_arg(args, 1) == "API_KEY"
def test_suggested_env_var_for_arg_falls_back_when_no_flag():
args = ["ghp_secret"]
assert c.suggested_env_var_for_arg(args, 0) == "SECRET"
# --------------------------------------------------------------------------- #
# Referenced-variables readout + args->env relocation (issue #83, "both")
# --------------------------------------------------------------------------- #
def test_referenced_env_vars_dedupes_and_reports_status():
data = {
"command": "npx",
"args": ["--token", "${GH_TOKEN}", "${GH_TOKEN}"],
"env": {"API_KEY": "${API_KEY}", "REGION": "${REGION:-us-east-1}"},
}
usages = c.referenced_env_vars(data, environ={"GH_TOKEN": "x"})
by = {u.name: u for u in usages}
assert set(by) == {"GH_TOKEN", "API_KEY", "REGION"}
# GH_TOKEN appears only in args, deduped to one entry, set in env -> resolved
assert by["GH_TOKEN"].fields == ("args",)
assert by["GH_TOKEN"].resolved is True
# API_KEY not set, no default -> unresolved
assert by["API_KEY"].resolved is False
# REGION has a default -> resolved regardless of environment
assert by["REGION"].has_default is True
assert by["REGION"].resolved is True
# sorted by name
assert [u.name for u in usages] == sorted(u.name for u in usages)
def test_referenced_env_vars_empty_when_no_refs():
assert c.referenced_env_vars({"command": "npx", "args": ["-y", "pkg"]}) == []
def test_move_arg_to_env_block_removes_flag_and_value():
data = {"command": "x", "args": ["--api-key", "sk-secret", "run"], "env": {"KEEP": "1"}}
out = c.move_arg_to_env_block(data, 1)
assert out["args"] == ["run"] # flag + value both gone
assert out["env"]["API_KEY"] == "sk-secret"
assert out["env"]["KEEP"] == "1" # existing env preserved
# input not mutated
assert data["args"] == ["--api-key", "sk-secret", "run"]
def test_move_arg_to_env_block_bare_positional_keeps_no_flag():
data = {"command": "x", "args": ["ghp_secret", "serve"]}
out = c.move_arg_to_env_block(data, 0, var_name="GITHUB_TOKEN")
assert out["args"] == ["serve"]
assert out["env"] == {"GITHUB_TOKEN": "ghp_secret"}
def test_move_arg_to_env_block_none_on_bad_target():
assert c.move_arg_to_env_block({"args": ["a"]}, 5) is None
assert c.move_arg_to_env_block({"args": ["${REF}"]}, 0) is None # already a ref
assert c.move_arg_to_env_block({}, 0) is None