feat(#91): sidecar config detection + precedence + verified paths
CI / Tests (py3.12 / windows-latest) (pull_request) Failing after 23s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 46s
CI / Catalog signature (pull_request) Successful in 8s
CI / Lint (ruff) (pull_request) Successful in 36s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 15s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 16s
CI / Tests (py3.12 / windows-latest) (pull_request) Failing after 23s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 46s
CI / Catalog signature (pull_request) Successful in 8s
CI / Lint (ruff) (pull_request) Successful in 36s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 15s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 16s
ssh-mcp v2 reads a TOML sidecar and only falls back to CLI args when that file
is ABSENT — so BCC's managed --host/--user args can be completely inert while
the real config lives in a file BCC never looks at. This adds read-only
truth-telling for that (no sidecar writing).
Core (pure, fully injectable platform/environ/home/exists/read for testing):
- sidecar_path(spec): VERIFIED per-platform TOML location from the package source,
NOT the README (macOS → ~/Library/Application Support/ssh-mcp, Windows → %APPDATA%,
else → ${XDG_CONFIG_HOME:-~/.config}). sidecar_doc_path() is the README path.
- sidecar_status(): resolves exists / has_managed_args / args_inert / wrong_path.
- sidecar_warnings(): mirrors removed_flag_warnings' shape. Reports:
* precedence — "these arguments are inert; the server reads <real path>"
* wrong-path — a TOML at the README path the server never actually reads
* #11 credential scoping — an unprefixed SSH_MCP_PASSWORD shared across 2+
profiles in a multi-profile sidecar (count_toml_profiles is a documented
3.10-safe heuristic; unscoped_credential_warning gates on it).
GUI: a read-only advisory label in the stdio editor (mirrors the removed-flag
label; no fix button — editing the sidecar is a separate deliberate action).
Uses the real platform/env/filesystem so it reflects this machine.
pytest green, ruff + format clean. Closes #91. Part of epic #94.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e087107710
commit
8c51c25211
@@ -899,6 +899,15 @@ class ServerEditor(QFrame):
|
||||
rf_row.addWidget(self.removed_flag_warn, 1)
|
||||
rf_row.addWidget(self.removed_flag_fix_btn)
|
||||
v.addLayout(rf_row)
|
||||
# Shown when a server reads a config sidecar (ssh-mcp's TOML): the args
|
||||
# may be inert, or a file may sit at the README path the server never
|
||||
# reads. Read-only advisory (#91) — no auto-fix; editing the sidecar is
|
||||
# a separate, deliberate action.
|
||||
self.sidecar_warn = QLabel("")
|
||||
self.sidecar_warn.setStyleSheet(f"color: {WARN};")
|
||||
self.sidecar_warn.setWordWrap(True)
|
||||
self.sidecar_warn.hide()
|
||||
v.addWidget(self.sidecar_warn)
|
||||
v.addWidget(self._lbl("Environment variables"))
|
||||
self.env = KeyValueTable(
|
||||
"Variable", "Value", on_change=self._emit, before_change=self._before_change
|
||||
@@ -1000,6 +1009,7 @@ class ServerEditor(QFrame):
|
||||
self.secret_warn.hide()
|
||||
self.removed_flag_warn.hide()
|
||||
self.removed_flag_fix_btn.hide()
|
||||
self.sidecar_warn.hide()
|
||||
self._loading = False
|
||||
return
|
||||
self.setEnabled(True)
|
||||
@@ -1089,6 +1099,7 @@ class ServerEditor(QFrame):
|
||||
self.secret_warn.hide()
|
||||
self.removed_flag_warn.hide()
|
||||
self.removed_flag_fix_btn.hide()
|
||||
self.sidecar_warn.hide()
|
||||
return
|
||||
_, notes = core.split_suspicious_args(self._current_arg_lines())
|
||||
if notes:
|
||||
@@ -1121,6 +1132,14 @@ class ServerEditor(QFrame):
|
||||
else:
|
||||
self.removed_flag_warn.hide()
|
||||
self.removed_flag_fix_btn.hide()
|
||||
# Sidecar precedence / wrong-path / credential-scoping (#91). Uses the
|
||||
# real platform + environment + filesystem so it reflects this machine.
|
||||
sc_warnings = core.sidecar_warnings(stdio)
|
||||
if sc_warnings:
|
||||
self.sidecar_warn.setText("⚠ " + "\n\n".join(sc_warnings))
|
||||
self.sidecar_warn.show()
|
||||
else:
|
||||
self.sidecar_warn.hide()
|
||||
|
||||
def _fix_args(self):
|
||||
if self._before_change:
|
||||
|
||||
Reference in New Issue
Block a user