Skip to content

K8s fleet onboarding — console UX for provider selection ('+ New fleet') #104

Description

@brettchien

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)

  1. 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).
  2. 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.
  3. deploy_provision gets a provider parameter and branches internally to dispatch to K8sDriver — not a separate MCP tool.
  4. 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).
  5. 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.
  6. 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_contextskube::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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions