Context
Follow-up to #97 (K8s driver — ADR #63 slice 3, closed 2026-08-27, all 6 sub-slices merged). Driver backend for k8s (K8sDriver, K8sFleetBinding/fleets-k8s.toml, k8s identity/context observation, k8s secret refs, bundle restore via pre_seed) is complete and on main. This issue tracks the next phase: console-side onboarding — today "+ New fleet" only supports AWS (Region/Credential profile/Principal); there is no UI path to onboard a k8s-driven fleet, only manual fleets-k8s.toml editing.
Design discussion: Discord thread 1537474496406233130, 2026-08-26.
Scope
Full deployment onboarding UX for k8s fleets in the desktop console, on par with the existing AWS "+ New fleet" wizard.
Design decisions (confirmed)
- Provider picker — identity form gets a provider choice (AWS / k8s) before the rest of the fields; switching provider resets the form (field semantics don't map across providers).
- k8s field group: Context, Namespace, Service account (optional). All three are
<select> (reusing the existing fillOptions pattern from the compose-library select in deploy.ts), not free-text — with a manual-entry fallback when enumeration is empty/fails.
- Namespace: new
list_namespaces tool (Api<Namespace>::list()), + free-text fallback for a namespace that doesn't exist yet.
- Service account: new
list_service_accounts(context, namespace) tool (Api<ServiceAccount>::list(namespace)) — depends on context+namespace being chosen first. If listing fails (including RBAC 403), silently fall back to leaving it blank (k8s uses the namespace's default ServiceAccount) — no error UI needed for this one.
- Service account value is stored in a new
K8sFleetBinding.expected_principal: Option<String> field — deliberately named to match the AWS side's expected_principal, since observe_k8s_identity (studio-cp/lib.rs:281) + k8s_principal_kind (:259) already provide the same verify semantics as AWS's observe_identity/identity_matches — reuse, don't reinvent.
deploy_provision gets a provider parameter and branches internally to dispatch to K8sDriver — not a separate MCP tool.
fleets-k8s.toml write path: new k8s_fleet_config_write MCP tool wired to the already-existing save_k8s_bindings_text (studio-cp/lib.rs:677 — has unit test coverage, just never wired to a tool). Client-side: new fleetsK8sToml.ts mirroring fleetToml.ts's pure text-mutation helpers (appendMember/appendFleetBlock equivalents for the k8s file).
list_aws_profiles / list_k8s_contexts failure UX — three tiers, not a single generic error:
- Config file missing / empty → actionable guidance (AWS: "run
aws configure or aws sso login"; k8s: "install OrbStack/kind/minikube for local, or merge your cloud vendor's kubeconfig into ~/.kube/config"). This is actionable because oab-mcp is a local Tauri sidecar child process (src-tauri/src/mcp.rs:1-16) reading the operator's own machine.
- Tool call itself errors (parse failure, permissions) → show the raw error, don't guess.
- Both cases: field falls back to free-text input, doesn't block the wizard.
- Admin/management agent access — no extra wiring needed.
servers_for(management, conn_id) (src-tauri/src/remote.rs:345) already declares the oab reverse-MCP server for management-bound connections; new tools are automatically reachable once built. Non-management agent consoles stay without access (least-privilege, unchanged).
New MCP tools needed
list_aws_profiles — read ~/.aws/config, return profile names (+ region if set)
list_k8s_contexts — kube::config::Kubeconfig::read(), return context names + which is current-context
list_namespaces(context) — Api<Namespace>::list()
list_service_accounts(context, namespace) — Api<ServiceAccount>::list(namespace)
k8s_fleet_config_write — wire to existing save_k8s_bindings_text
deploy_provision — extend with a provider parameter, dispatch to K8sDriver for k8s
Schema changes
K8sFleetBinding (studio-cp/lib.rs:562) — add expected_principal: Option<String>
Client changes
console/src/render.ts / deploy.ts — provider selector step in the identity form
console/src/fleetsK8sToml.ts (new) — mirrors fleetToml.ts
Explicit non-goals for this phase
Context
Follow-up to #97 (K8s driver — ADR #63 slice 3, closed 2026-08-27, all 6 sub-slices merged). Driver backend for k8s (
K8sDriver,K8sFleetBinding/fleets-k8s.toml, k8s identity/context observation, k8s secret refs, bundle restore viapre_seed) is complete and onmain. This issue tracks the next phase: console-side onboarding — today "+ New fleet" only supports AWS (Region/Credential profile/Principal); there is no UI path to onboard a k8s-driven fleet, only manualfleets-k8s.tomlediting.Design discussion: Discord thread
1537474496406233130, 2026-08-26.Scope
Full deployment onboarding UX for k8s fleets in the desktop console, on par with the existing AWS "+ New fleet" wizard.
Design decisions (confirmed)
<select>(reusing the existingfillOptionspattern from the compose-library select indeploy.ts), not free-text — with a manual-entry fallback when enumeration is empty/fails.list_namespacestool (Api<Namespace>::list()), + free-text fallback for a namespace that doesn't exist yet.list_service_accounts(context, namespace)tool (Api<ServiceAccount>::list(namespace)) — depends on context+namespace being chosen first. If listing fails (including RBAC 403), silently fall back to leaving it blank (k8s uses the namespace'sdefaultServiceAccount) — no error UI needed for this one.K8sFleetBinding.expected_principal: Option<String>field — deliberately named to match the AWS side'sexpected_principal, sinceobserve_k8s_identity(studio-cp/lib.rs:281) +k8s_principal_kind(:259) already provide the same verify semantics as AWS'sobserve_identity/identity_matches— reuse, don't reinvent.deploy_provisiongets a provider parameter and branches internally to dispatch toK8sDriver— not a separate MCP tool.fleets-k8s.tomlwrite path: newk8s_fleet_config_writeMCP tool wired to the already-existingsave_k8s_bindings_text(studio-cp/lib.rs:677— has unit test coverage, just never wired to a tool). Client-side: newfleetsK8sToml.tsmirroringfleetToml.ts's pure text-mutation helpers (appendMember/appendFleetBlockequivalents for the k8s file).list_aws_profiles/list_k8s_contextsfailure UX — three tiers, not a single generic error:aws configureoraws sso login"; k8s: "install OrbStack/kind/minikube for local, or merge your cloud vendor's kubeconfig into~/.kube/config"). This is actionable becauseoab-mcpis a local Tauri sidecar child process (src-tauri/src/mcp.rs:1-16) reading the operator's own machine.servers_for(management, conn_id)(src-tauri/src/remote.rs:345) already declares theoabreverse-MCP server for management-bound connections; new tools are automatically reachable once built. Non-management agent consoles stay without access (least-privilege, unchanged).New MCP tools needed
list_aws_profiles— read~/.aws/config, return profile names (+ region if set)list_k8s_contexts—kube::config::Kubeconfig::read(), return context names + which iscurrent-contextlist_namespaces(context)—Api<Namespace>::list()list_service_accounts(context, namespace)—Api<ServiceAccount>::list(namespace)k8s_fleet_config_write— wire to existingsave_k8s_bindings_textdeploy_provision— extend with a provider parameter, dispatch toK8sDriverfor k8sSchema changes
K8sFleetBinding(studio-cp/lib.rs:562) — addexpected_principal: Option<String>Client changes
console/src/render.ts/deploy.ts— provider selector step in the identity formconsole/src/fleetsK8sToml.ts(new) — mirrorsfleetToml.tsExplicit non-goals for this phase
pre_seed), no work needed here.