feat(#83): offer move-to-env on args rows; explain the gate instead of an empty menu
CI / Lint (ruff) (pull_request) Successful in 19s
CI / Tests (py3.12 / windows-latest) (pull_request) Successful in 24s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 29s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 29s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 31s
CI / Catalog signature (pull_request) Successful in 22s
CI / Lint (ruff) (pull_request) Successful in 19s
CI / Tests (py3.12 / windows-latest) (pull_request) Successful in 24s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 29s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 29s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 31s
CI / Catalog signature (pull_request) Successful in 22s
Two things surfaced testing the GUI:
1. Args rows showed the secret warning but no move action -- the args
editor is a free-text widget, not a table, and was deliberately left out
of the first cut. Wired it up: ArgsEdit gains a context menu that offers
"Move to environment variable…" on exactly the args that look like a
credential. New pure core: secret_arg_indices (which args are secrets,
mirroring args_secret_warning per-index) and suggested_env_var_for_arg
(default var name from the preceding flag -- `--api-key <secret>` ->
API_KEY, else SECRET). The move replaces that one arg line with ${VAR}
and copies the secret to the clipboard, same contract as the tables.
2. On a Claude Desktop profile (or any non-expanding client) the menu showed
NOTHING, so it read as broken. Now a real stored secret always shows the
item -- enabled on a client that expands references, or disabled with the
reason ("unavailable for Claude Desktop -- it doesn't expand ${VAR}") so
the gate is visible rather than silent. Applies to env, headers and args.
Not a change: after converting, env_ref_warnings still notes a variable that
isn't set in the environment. That's #82's advisory doing its job -- the user
runs the export line the dialog handed them; auto-adding a ':-default' would
bake a fallback back into the config and defeat moving the secret out.
Tests: +5 core (secret_arg_indices for token/flag-value/embedded-URL/
reference-excluded, suggested_env_var_for_arg with and without a flag).
483 passed, ruff clean. GUI wiring (context menus) remains untestable in CI.
Refs #83
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKwBecy6N83jnqQmw8ezwE
This commit is contained in:
@@ -3148,3 +3148,35 @@ 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"
|
||||
|
||||
Reference in New Issue
Block a user