Skip to content

feat(desktop): provider-tagged, hermetic oab-mcp target (backend) - #60

Merged
brettchien merged 1 commit into
mainfrom
feat/mcp-target-hermetic
Aug 15, 2026
Merged

feat(desktop): provider-tagged, hermetic oab-mcp target (backend)#60
brettchien merged 1 commit into
mainfrom
feat/mcp-target-hermetic

Conversation

@brettchien

Copy link
Copy Markdown
Contributor

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 AccessDenied on deploy_list was credential/region drift, not IAM: 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 (e.g. 916371022086/ap-southeast-1 instead of 504190915686/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 stale KUBECONFIG would bleed into an ECS sidecar, and the {cluster,profile,region} shape doesn't fit k8s. Instead:

  • Provider-taggedMcpTarget is an enum (Ecs today). Adding k8s is a new variant + its own env arm; the spawn path is provider-agnostic.
  • Hermetic envhermetic_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): McpTarget enum + 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_core spawns from the persisted target; commands mcp_target_get / mcp_target_set (persist + reload the core onto the new target, no app restart).

Verification

  • rustfmt parses clean; tauri_plugin_shell Command::{env_clear,envs} confirmed present. Full compile is the bundle-macos gate (this box has no GTK).
  • The hermetic spawn takes effect immediately via start_core (persisted-or-default target), so the drift fix lands even before the UI; mcp-target.json is hand-editable meanwhile.

Follow-up

🤖 Generated with Claude Code

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
brettchien merged commit f1952c0 into main Aug 15, 2026
2 checks passed
@brettchien
brettchien deleted the feat/mcp-target-hermetic branch August 15, 2026 14:33
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant