feat(desktop): provider-tagged, hermetic oab-mcp target (backend) - #60
Merged
Conversation
Root-fix the credential/region drift behind the AccessDenied: the desktop spawned oab-mcp with only OAB_CLUSTER, so the sidecar inherited the host's ambient AWS default chain and could point at the wrong account/region. - config.rs (new): `McpTarget` is a **provider-tagged** enum (Ecs today; k8s etc. add a variant). `hermetic_env()` builds the child env **from empty** — a small base allow-list (HOME/PATH/TMPDIR/locale/certs) carried over if present, then exactly the target's vars. No ambient AWS_*/KUBECONFIG leaks, and one provider's vars can't bleed into another's sidecar. Persisted to `mcp-target.json`; env-seeded default so behaviour is unchanged until saved. - mcp.rs: `spawn(target)` uses `.env_clear().envs(target.hermetic_env())`; `child: Option` + `shutdown()` (kill) so the core can be reloaded. - lib.rs: `start_core` spawns from the persisted target; new commands `mcp_target_get` / `mcp_target_set` (persist + reload the core onto the new target, no app restart). Supersedes #10's approach (blacklist strip AWS_*, AWS-shaped config) with the provider-tagged + whitelist-hermetic design. Config-tab UI is a follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brettchien
pushed a commit
that referenced
this pull request
Aug 15, 2026
The UI half for #60: a Config tab (cluster / AWS profile / region) that reads the persisted target via `mcp_target_get`, and on save calls `mcp_target_set` (persist + reload the core onto the new hermetic env), then refreshes the roster. Browser build disables the form. Ports #10's UI onto #60's provider-tagged `McpTarget` shape ({ provider: "ecs", cluster, profile?, region? }). Verified locally: `tsc --noEmit && vite build` clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brettchien
added a commit
that referenced
this pull request
Aug 15, 2026
#62) The UI half for #60: a Config tab (cluster / AWS profile / region) that reads the persisted target via `mcp_target_get`, and on save calls `mcp_target_set` (persist + reload the core onto the new hermetic env), then refreshes the roster. Browser build disables the form. Ports #10's UI onto #60's provider-tagged `McpTarget` shape ({ provider: "ecs", cluster, profile?, region? }). Verified locally: `tsc --noEmit && vite build` clean. Co-authored-by: brettchien <orca@openab.dev> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finishes #10's intent with the provider-tagged + whitelist-hermetic design we settled on (this is the backend slice; the Config-tab UI follows).
Why
The
AccessDeniedondeploy_listwas credential/region drift, not IAM: the desktop spawnedoab-mcpwith onlyOAB_CLUSTER, so the sidecar inherited the host's ambient AWS default chain and could point at the wrong account/region (e.g.916371022086/ap-southeast-1instead of504190915686/ap-east-2).Design (why not #10's approach)
#10 stripped
AWS_*from an inherited env (a blacklist) and used an AWS-shaped config. That (a) isn't hermetic — everything non-AWS still leaks — and (b) doesn't generalise: a staleKUBECONFIGwould bleed into an ECS sidecar, and the{cluster,profile,region}shape doesn't fit k8s. Instead:McpTargetis an enum (Ecstoday). Adding k8s is a new variant + its own env arm; the spawn path is provider-agnostic.hermetic_env()builds the child env from empty: a small base allow-list (HOME/PATH/TMPDIR/locale/cert vars) carried over if present, then exactly the target's vars. No ambient credential/region leaks; no cross-provider bleed. (EKS's AWS dependency, when k8s lands, gets declared explicitly in that arm — not inherited by accident.)Changes
config.rs(new):McpTargetenum +hermetic_env()+ persist (mcp-target.json) + env-seeded default (behaviour unchanged until saved).mcp.rs:spawn(target)→.env_clear().envs(target.hermetic_env());child: Option+shutdown()for reload.lib.rs:start_corespawns from the persisted target; commandsmcp_target_get/mcp_target_set(persist + reload the core onto the new target, no app restart).Verification
rustfmtparses clean;tauri_plugin_shellCommand::{env_clear,envs}confirmed present. Full compile is the bundle-macos gate (this box has no GTK).start_core(persisted-or-default target), so the drift fix lands even before the UI;mcp-target.jsonis hand-editable meanwhile.Follow-up
🤖 Generated with Claude Code