feat(kubernetes): add multi-source service discovery#621
feat(kubernetes): add multi-source service discovery#621guanzhousongmicrosoft wants to merge 86 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a Kubernetes-based service discovery provider with multi-source kubeconfig management, context aliases, and improved connection/port-forward behavior across discovery and saved connections.
Changes:
- Introduces a new Kubernetes discovery provider (tree + wizard) with multi-source kubeconfig storage/migration and context display aliases.
- Adds port-forward metadata plumbing and lifecycle handling (reconnect behavior, copy-connection-string tweaks, provider deactivation cleanup).
- Improves collection-view navigation (open from collection node + reuse existing tabs) and expands related command routing/retry behavior.
Reviewed changes
Copilot reviewed 65 out of 66 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| webpack.config.ext.js | Marks Kubernetes optional deps as externals and tweaks bundling behavior for dynamic imports. |
| test/util/classifyCommand.test.ts | Updates classifyCommand test import path and normalizes section comments. |
| src/tree/documentdb/CollectionItem.ts | Adds a TreeItem command to open the collection view directly from a collection node. |
| src/tree/documentdb/CollectionItem.test.ts | Adds unit tests for the new collection node command and children retention. |
| src/tree/documentdb/ClusterItemBase.ts | Adds a hook to prepare infrastructure before reusing cached clients (e.g., port-forward). |
| src/tree/connections-view/DocumentDBClusterItem.ts | Ensures Kubernetes port-forward is established when using saved connections (including cached-client reuse). |
| src/services/discoveryServices.ts | Extends discovery provider interface with activation-time setup and deactivation cleanup hooks. |
| src/plugins/service-kubernetes/sources/sourceStore.ts | Implements StorageService-backed multi-source kubeconfig persistence (default/file/inline), hiding, and caching. |
| src/plugins/service-kubernetes/sources/sourceStore.test.ts | Adds tests for sourceStore CRUD, ordering, hidden IDs, and inline secret behavior. |
| src/plugins/service-kubernetes/sources/migrationV2.ts | Adds migration from legacy globalState/secret storage to the new StorageService layout. |
| src/plugins/service-kubernetes/sources/migrationV2.test.ts | Adds tests validating migration behavior, cleanup, seeding, and idempotency. |
| src/plugins/service-kubernetes/sources/aliasStore.ts | Adds StorageService-backed context alias persistence with caching and pruning helpers. |
| src/plugins/service-kubernetes/sources/aliasStore.test.ts | Adds tests for alias CRUD, scoping, trimming, and malformed entry filtering. |
| src/plugins/service-kubernetes/promptForLocalPort.ts | Adds a port prompt for ClusterIP port-forward scenarios. |
| src/plugins/service-kubernetes/portForwardMetadata.ts | Adds structured port-forward metadata stored on connections and readers/identity helpers. |
| src/plugins/service-kubernetes/ensureKubernetesPortForward.ts | Implements friendly-source errors and ensures port-forward tunnels are (re)started as needed. |
| src/plugins/service-kubernetes/ensureKubernetesPortForward.test.ts | Adds tests for friendly missing-source errors and successful tunnel startup. |
| src/plugins/service-kubernetes/discovery-wizard/SelectServiceStep.ts | Adds wizard step to select a discovered DocumentDB service within a chosen context. |
| src/plugins/service-kubernetes/discovery-wizard/SelectContextStep.ts | Adds wizard step to select a Kubernetes context across all sources (with alias support). |
| src/plugins/service-kubernetes/discovery-wizard/KubernetesExecuteStep.ts | Resolves endpoints, starts tunnels for ClusterIP, sets connection properties, and auto-resolves credentials where possible. |
| src/plugins/service-kubernetes/discovery-wizard/KubernetesExecuteStep.test.ts | Adds tests covering endpoint kinds, port-forward metadata, and credential auto-resolution behavior. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesServiceItem.ts | Adds a discovery leaf that can authenticate/connect and open collections; includes port-forward reconnect handling. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesRootItem.ts | Adds Kubernetes discovery root node reading migrated multi-source configuration and hidden-source filtering. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesRootItem.test.ts | Adds tests for migration gating, hidden-source behavior, and recovery nodes. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesNamespaceItem.ts | Adds namespace node listing DocumentDB services with retry/error children on failures and telemetry. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesNamespaceItem.test.ts | Adds tests for service listing, preloading, retry nodes, and telemetry measurements. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesKubeconfigSourceItem.ts | Adds per-source node loading contexts, showing recovery actions, and pruning aliases. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesContextItem.ts | Adds context node listing namespaces with bounded concurrency prescan and alias-aware labeling/tooltip. |
| src/plugins/service-kubernetes/discovery-tree/KubernetesContextItem.test.ts | Adds tests for alias rendering, error handling, sorting, and concurrency caps. |
| src/plugins/service-kubernetes/config.ts | Adds provider constants, labels/descriptions, multi-source config types, and legacy keys for migration. |
| src/plugins/service-kubernetes/commands/renameKubernetesContext.ts | Adds command to set/clear per-source context display aliases and refresh the discovery tree. |
| src/plugins/service-kubernetes/commands/renameKubernetesContext.test.ts | Adds tests for alias set/clear/cancel/error behavior and refresh invocation. |
| src/plugins/service-kubernetes/commands/renameKubeconfigSource.ts | Adds command to rename a kubeconfig source and refresh the discovery tree. |
| src/plugins/service-kubernetes/commands/removeKubeconfigSource.ts | Adds command to remove a source, stop its tunnels, clear aliases, and refresh. |
| src/plugins/service-kubernetes/commands/refreshKubernetesRoot.ts | Adds helper to reset cached error state for the Kubernetes root and refresh the discovery tree. |
| src/plugins/service-kubernetes/commands/manageKubeconfigSources.ts | Adds QuickPick-based manage UI for hiding/removing sources and refreshing. |
| src/plugins/service-kubernetes/commands/manageKubeconfigSources.test.ts | Adds tests for selection persistence, hidden IDs, and default-source remove-button behavior. |
| src/plugins/service-kubernetes/commands/addKubeconfigSource.ts | Adds flow to add default/file/inline kubeconfig sources with validation and telemetry. |
| src/plugins/service-kubernetes/KubernetesDiscoveryProvider.ts | Registers Kubernetes discovery provider (tree + wizard), configures manage flow, and adds deactivate cleanup. |
| src/plugins/service-kubernetes/KubernetesDiscoveryProvider.test.ts | Adds tests for provider wiring, configureCredentials flow, refresh behavior, and deactivation cleanup. |
| src/documentdb/ClustersExtension.ts | Registers Kubernetes provider and wires Kubernetes-specific commands; adds disposal cleanup for tunnels. |
| src/commands/retryAuthentication/retryAuthentication.ts | Improves retry routing by inferring view from tree id when context tokens are missing. |
| src/commands/retryAuthentication/retryAuthentication.test.ts | Adds tests for retry routing via tree id inference and Azure branch token routing. |
| src/commands/removeDiscoveryRegistry/removeDiscoveryRegistry.ts | Calls provider deactivation hook before removing provider from active state. |
| src/commands/removeDiscoveryRegistry/removeDiscoveryRegistry.test.ts | Adds tests for deactivation invocation and removal behavior with/without cleanup. |
| src/commands/openCollectionView/openCollectionView.ts | Adds reuse of existing collection tabs and a keyed controller cache; strengthens reveal behavior. |
| src/commands/openCollectionView/openCollectionView.test.ts | Adds tests verifying reuse and proper cleanup when a tab is disposed. |
| src/commands/newConnection/NewConnectionWizardContext.ts | Adds connectionProperties to carry non-secret provider-specific connection metadata. |
| src/commands/newConnection/ExecuteStep.ts | Incorporates port-forward identity into duplicate detection and persists provider connection properties on save. |
| src/commands/copyConnectionString/copyConnectionString.ts | Offers include-password prompt for Kubernetes discovery nodes and adds telemetry about copy origin/password inclusion. |
| src/commands/copyConnectionString/copyConnectionString.test.ts | Adds coverage for connections-view vs Kubernetes discovery copy behaviors and telemetry fields. |
| src/commands/addDiscoveryRegistry/ExecuteStep.ts | Adds duplicate prevention and provider activation-time credential configuration before persisting active state. |
| src/commands/addDiscoveryRegistry/ExecuteStep.test.ts | Adds tests for activation-time configure flow, cancellation/error propagation, and duplicate prevention. |
| src/commands/addConnectionFromRegistry/addConnectionFromRegistry.ts | Persists provider connection properties when saving registry connections and improves duplicate checks for port-forwarded targets. |
| scripts/k8s-test-teardown.sh | Adds helper teardown script for local kind-based Kubernetes discovery testing. |
| scripts/k8s-test-setup.sh | Adds helper setup script to create a kind cluster and deploy DKO + a test DocumentDB resource. |
| package.json | Adds Kubernetes client dependency and wires new Kubernetes commands/menus/contribution conditions. |
| docs/user-manual/service-discovery.md | Updates service discovery docs list and improves formatting/wording. |
| docs/user-manual/service-discovery-kubernetes.md | Adds Kubernetes discovery provider documentation (sources, aliases, port-forwarding, RBAC, troubleshooting). |
Comments suppressed due to low confidence (9)
src/plugins/service-kubernetes/sources/sourceStore.ts:1
- renameSource() rewrites the persisted
orderusing the record’s current array index rather than the storedproperties.order. This can change ordering semantics (e.g., the default source is inserted with order -1 but would become 0 on rename, potentially colliding with other entries and losing its guaranteed sort position). Preserve the existing stored order by reading the item’s currentproperties.order(or by extendingreadSecretsForExistingItem()to also return the current order) and reusing that value when calling pushItem().
src/plugins/service-kubernetes/sources/sourceStore.ts:1 - The cache/inflight logic can resurrect stale data: if
ensureCache()is awaitinginflightLoadwhile another call mutates storage and callsinvalidateCache(), the original await will still setcache = loadedafter invalidation. A simple fix is to version the cache (generation counter) or capture the current inflight promise and only commit results if it still matches the latest inflight value after awaiting.
src/plugins/service-kubernetes/sources/sourceStore.ts:1 - The cache/inflight logic can resurrect stale data: if
ensureCache()is awaitinginflightLoadwhile another call mutates storage and callsinvalidateCache(), the original await will still setcache = loadedafter invalidation. A simple fix is to version the cache (generation counter) or capture the current inflight promise and only commit results if it still matches the latest inflight value after awaiting.
src/plugins/service-kubernetes/sources/aliasStore.ts:1 - aliasStore has the same stale-cache race as sourceStore: an in-flight read can repopulate
cacheafterinvalidate()has been called by a writer. Consider the same mitigation (generation counter / promise identity check) so an outdated read result cannot overwrite a post-mutation invalidation.
src/plugins/service-kubernetes/sources/aliasStore.ts:1 - aliasStore has the same stale-cache race as sourceStore: an in-flight read can repopulate
cacheafterinvalidate()has been called by a writer. Consider the same mitigation (generation counter / promise identity check) so an outdated read result cannot overwrite a post-mutation invalidation.
src/plugins/service-kubernetes/promptForLocalPort.ts:1 parseInt()will accept inputs like\"10260abc\"(parsing them as 10260), so invalid user input can pass validation and be used as a port. Validate that the entire string is a base-10 integer (e.g., viaNumber(...)+Number.isInteger+ a strict digits-only check) before accepting it, and ensure the returned value matches what was validated.
src/plugins/service-kubernetes/promptForLocalPort.ts:1parseInt()will accept inputs like\"10260abc\"(parsing them as 10260), so invalid user input can pass validation and be used as a port. Validate that the entire string is a base-10 integer (e.g., viaNumber(...)+Number.isInteger+ a strict digits-only check) before accepting it, and ensure the returned value matches what was validated.
src/plugins/service-kubernetes/portForwardMetadata.ts:1- getKubernetesPortForwardMetadata() validates integer-ness but not port ranges. Persisted metadata with
servicePort/localPortoutside 1–65535 would still be accepted and could lead to failures later when establishing tunnels or building connection strings. Add explicit bounds checks for both ports.
src/plugins/service-kubernetes/config.ts:1 - The TSDoc link target appears incorrect:
sourceStoredoes not exportStorageItem(it imports that type fromservices/storageService). This makes the doc link misleading/broken. Consider linking to../../../services/storageService’sStorageItemtype (or removing the link if it can’t be referenced cleanly from here).
|
Plugin boundary: custom inline "+" command Location: The Kubernetes plugin introduced a custom The correct approach is to extend the discovery plugin API with a first-class Note: "add a kubeconfig source" is fundamentally what a user is mentally doing. It is closer to "add connection" semantics than credential management, so the right API to introduce is something like |
0742eba to
e74f81d
Compare
|
@guanzhousongmicrosoft we'll have to carefully review the PR on the code level. I noticed that some changes made on |
My bad, I didn't pull, forget it :) |
2c64958 to
5e771be
Compare
📦 Build Size Report
Download artifact · updated automatically on each push. |
…matting Three related fixes surfaced by PR #621 multi-agent review: * portForwardTunnel: do not leak the per-connection PassThrough error stream when forward.portForward() rejects (e.g. backend pod flap). errStream is now declared in outer scope so the catch block releases it via cleanupErrorStream() instead of letting it accumulate in tunnel.errorStreams. * portForwardTunnel: stop treating EACCES like EADDRINUSE. EACCES (privileged port / sandbox restriction) has no existing tunnel to fall through to, so emit an explicit permission-denied error with a recovery hint instead of offering Use existing and building a connection string against an unbindable port. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add Kubernetes service discovery with kubeconfig source management, context aliases, connection-string copy prompts, port-forward lifecycle handling, and the supporting tests and user documentation. Signed-off-by: Guanzhou Song <guanzhousong@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Guanzhou Song <guanzhousong@microsoft.com>
Scope Kubernetes port-forward tunnel identity by kubeconfig source, surface unexpected DKO discovery failures, align Default source docs with implementation, and harden GKE provider URL inference against substring matches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Guanzhou Song <guanzhousong@microsoft.com>
…cker - Change `description` to `detail` so explanatory text renders on a full-width line instead of being truncated inline - Add ThemeIcon iconPath to each picker item: key (default), file (custom file), clippy (clipboard paste) - Add tests validating picker item configuration Fixes #9 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Guanzhou Song <guanzhousong@microsoft.com>
- Remove inline@2 registration for removeSource in package.json (#1) Destructive actions should only be accessible via context menu. - Add always-visible 'Add a kubeconfig source...' action to SelectContextStep picker, following Azure SelectSubscriptionStep pattern (#12). Eliminates the dead-end when no contexts exist. - Add SelectContextStep.test.ts with 6 tests covering zero-source, all-sources-fail, action-invocation, property-setting, and separator. - Update l10n bundle for new strings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Guanzhou Song <guanzhousong@microsoft.com>
Signed-off-by: Guanzhou Song <guanzhousong@microsoft.com>
…ssages
Replace generic 'Failed to connect. Click to retry.' with classified
error summaries (401/403/ECONNREFUSED/DNS/timeout/cert) and actionable
hints shown as description text. Full error details available in tooltip.
Tree now shows two children on failure:
[warning] Authentication failed (401 Unauthorized)
Credentials may have expired...
[refresh] Retry
Applied to both KubernetesContextItem (namespace listing) and
KubernetesNamespaceItem (service listing) error paths.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Guanzhou Song <guanzhousong@microsoft.com>
…-facing strings (§9.5)
… into grouped tooltip (§9.6)
… standard cluster menu (§9.4)
…forwarded targets Keep the clear 'Copy connection string…' entry point but, for Kubernetes ClusterIP targets reached through a port-forward tunnel, show a grouped quick pick: a 'Connection string' group (with/without password) plus a 'Kubernetes' group exposing the reproducing kubectl port-forward command and a Learn more docs entry. Non-port-forward nodes keep the exact prior behavior (no regression). Adds copyAction telemetry. Extends tests to cover the grouped picker variants.
…s follow-up and issue #734
…de tooltip Prefix the tooltip 'Reachability' line with one theme icon encoding the connection-string portability spectrum: globe (direct/portable), server (cluster-routed via node port), plug (machine-local port-forward) and warning (pending / not directly reachable). Exactly one glyph per tooltip, on the line where it carries meaning; node icon stays the DocumentDB cluster icon. Enables supportThemeIcons on the MarkdownString.
…le tooltip glyph decision (§11.3)
… word; tooltip teaches it Reduce the always-visible grey description to a single connectivity caveat word (direct shows none, plus node-routed/pending/port-forward/unsupported). 'pending' mirrors kubectl's EXTERNAL-IP <pending>; 'unsupported' replaces 'not directly supported'. Move provenance (Source: DKO/Generic) and service type into the tooltip key-info group. The tooltip Reachability line now echoes the exact description word before the longer explanation, so it doubles as a legend that teaches what the terse node shortcut means.
…mentDB Local node icon)
Dedicated cluster-named copies of vscode-documentdb-icon-{light,dark}-themes.svg
so the Kubernetes discovery cluster node can reuse the DocumentDB brand mark
without coupling to the 'DocumentDB Local' node's own asset.
…e; reachability first in tooltip - Discovery cluster node now uses the DocumentDB brand mark (same icon as the 'DocumentDB Local' node) via the new cluster-named SVGs, instead of the generic server-environment ThemeIcon. - Move the reachability group to the top of the tooltip (it's the signal users care about most) and drop the em dash from the label (now 'Reachability (`word`):'). - Tests: mock Uri.file + utils/icons, assert the themed cluster icon path.
…hability; add §12 next-iteration backlog
… / 'No DocumentDB targets found' Promote the noun to the label (the children are namespaces) and use neutral, vocabulary-consistent wording for the reason. Replaces 'Others' / 'DocumentDB not detected', which was contentless and faintly alarming (failures are a separate retry/error node).
- Add a 'How this review was run' intro: iterative, phase-by-phase review (person steering + AI assistant), each phase closed out before the next to keep both the assistant's working context and the reviewer's attention lean. - Drop the product reference (Lens/k8slens) and its doc link; describe the naming as common/field-standard Kubernetes tooling convention instead. - Soften the recorded review feedback: replace blunt verbatim directive quotes with neutral reported feedback and use 'reviewer'/'review feedback' framing. - Sync the §1 tree example with the 'Other namespaces' wording.
…icher tooltip The grouping bucket no longer shows a grey description (it made the row long). The meaning now lives in a MarkdownString tooltip that explains these namespaces were scanned but had no DocumentDB target and are grouped to keep the list of connectable namespaces uncluttered. No em dashes in the generated string. Tests assert no description + tooltip explanation.
- Copy quick pick 'Learn more' -> https://aka.ms/vscode-documentdb-kubernetes-port-forward (forwards to the new Copy Connection String manual page). - Kubernetes discovery provider getLearnMoreUrl -> https://aka.ms/vscode-documentdb-discovery-providers-kubernetes (consistent with the other discovery providers' aka.ms slugs).
…ing page - Kubernetes manual: rename root to 'Kubernetes Clusters'; 'Add Kubeconfig…'; replace the removed manage-dialog section with the right-click context menu (Refresh / Rename… / Open in Editor / Remove…); document the discovered-target node (connectivity word + tooltip + DocumentDB icon); drop the 'Other namespaces' inline description (now a tooltip); correct the port-forward settings ids. - New 'Copy Connection String' page covering the grouped quick pick for Kubernetes port-forwarded targets (with/without password, kubectl command, sharing). Linked from the docs index. - No em dashes in the Kubernetes manual or the new page.
Drop the region from the always-visible context description (it can be a raw hostname token rather than a real region for some clusters, e.g. an AKS DNS hash). The description now shows just the inferred provider, falling back to the server host when no provider is detected. Region is still shown in the tooltip.
KubernetesKubeconfigSourceItem.getChildren() was the one discovery-tree load
path with no telemetry: a failed kubeconfig load only went to the output channel.
Wrap it in callWithTelemetryAndErrorHandling('kubernetes-discovery.loadKubeconfigSource')
and load the config inside a rethrowing sub-step
('kubernetes-discovery.loadKubeconfigSource.load', errorHandling.rethrow=true,
suppressDisplay=true) so the telemetry library records the failure (result=Failed,
error name + message) automatically while the outer event still renders the
recovery UI. Adds kubeconfigSourceKind + kubeconfigLoadResult properties,
contextsInSource measurement, and threads journeyCorrelationId. journeyCorrelationId
stays generated per getChildren (matches the Azure discovery-root funnel pattern).
…ror types Measurements: - dkoResourcesCount / genericServicesCount on listServices (DKO adoption vs the generic-service fallback). - portForwardLocalPort + portForwardDurationMs (time to establish a started tunnel) on both the discovery-tree connect and the New Connection execute step. - portForwardStrategy + portForwardPortChanged + portSelectionResult, recorded by promptForLocalPort via an optional IActionContext (port numbers are not sensitive). Error classification (additive, alongside the existing boolean flags): - namespaceFetchErrorType, namespaceServiceFetchErrorType (KubernetesContextItem), serviceFetchErrorType (KubernetesNamespaceItem) capture the error name so failures can be triaged (auth/timeout/etc). These spots intentionally catch to render retry/recovery nodes, so they classify the error rather than rethrow; the new kubeconfig-load path (separate commit) relies on the library's built-in failure logging via a rethrowing sub-step.
Summary
Adds first-class Kubernetes service discovery to the DocumentDB VS Code extension: users can connect to DocumentDB clusters running in Kubernetes (DKO operator-managed or generic DocumentDB-API services) without manually building connection strings or running
kubectl port-forward.Supersedes #617.
What ships
Discovery flow
Connectivity
portForwardTunnel.ts) with:showWarningMessage, pre-register).ensureKubernetesPortForwardlives inDocumentDBClusterItem.beforeCachedClientConnect, so re-opening a saved K8s cluster transparently re-establishes the tunnel.Settings (scoped subset of #20)
documentDB.serviceDiscovery.kubernetes.portForward.localPortStrategy—matchRemote(default) orautoSelect.documentDB.serviceDiscovery.kubernetes.portForward.localPortBase— default27100.autoSelectuses bind-attempt scan on127.0.0.1, capped at 100 candidates, falls back to the remote service port.Cross-cutting changes that landed alongside
discoveryProviderVisibility.ts): inverted from a "what to show" allowlist to a hidden-providers denylist, with one-time migration from the legacyactiveDiscoveryProviderIdsand theazure-discovery→azure-mongo-vcore-discoveryrename normalization. Unknown provider ids are preserved in storage so plugin registration timing changes never silently drop a user's hide preference.BaseExtendedTreeDataProvider.failedChildrenCache— error/recovery nodes are cached so Refresh returns the same recovery tree; only explicit Retry/Reload/mutating commands clear the cache viaresetNodeErrorState.DocumentDBShellPty.writeLinenormalizes bare\nto\r\nso multi-line error output no longer staircases in the pseudoterminal.webpack.config.ext.jsno longer externalizessocks— the transitive@kubernetes/client-nodedep is now bundled, fixing the TDZ at K8s import time.Coverage — bug-bash repo
tnaum-ms/vscode-documentdb-bugbash-090All 30 closed issues were verified through this branch:
Verification was done in two full passes: an initial 30-issue × 5-model review (150 verdicts), then a corrected re-verification on the 6 issues that warranted a second look (30 more verdicts). All findings are recorded.
Review history
This PR went through two rounds of independent multi-agent code review (5 models per round: gpt-5.4, gpt-5.5, claude-opus-4.6, 4.7, 4.8).
Round 1 surfaced 15 findings against the pre-rebase state. All 11 worth fixing pre-merge were addressed and committed:
c12412f5portForwardTunnel: leak-freeerrStreamcleanup + explicit EACCES errordd950d1fkubernetesClient: IPv6 brackets, multi-entry KUBECONFIG,createCoreApimutation doccfc4b24bsourceStore/aliasStore: rename-order preservation, inline-add race protection, ensureCache invalidate-during-load race, alias write serialization15311649treeIdaligned withclusterIdsuffix;removeKubeconfigSourceresets the failed-children cache for the removed node;discoveryProviderVisibilitypreserves unknown idsRound 2 (run against the rebased branch): 4 of 5 reviewers completed (gpt-5.4 was cancelled before starting); the 4 completed reviewers verified every round-1 fix at HEAD and returned unanimous READY-TO-MERGE / Approve with zero blockers and zero should-fix. Findings explicitly deferred (filed as future-issue candidates rather than blockers): inline-add cosmetic ordering between unrelated adds, kubectl-share snippet (#21), exec-auth trust prompt for pasted/dropped kubeconfigs (matches kubectl industry norm), per-reconnect storage-read perf hint.
Validation
All five required steps pass cleanly at HEAD:
Testing matrix
sourceStore+aliasStorerace semanticsPromise.allSettled × 3concurrent-add cases + globalState fault injectionportForwardTunnellifecycle, cancellation, EADDRINUSE retry, EACCES errorKubernetesServiceItemreachability tooltip + copy semanticstreeId↔clusterIdalignmentfindClusterNodeByClusterIdlookup test%USERPROFILE%, KUBECONFIG splitting)path.sep-tolerant Jest assertionsazure-discoveryrenameNot exercised in CI (manual smoke required for full sign-off): live
kubectlagainst a real cluster, SOCKS-proxied connection through the newly-bundledsocksmodule.Known intentional non-goals
KUBECONFIG-style path-list merging (kubectl's full merge semantics). We follow the operationally-equivalent "first existing entry wins" +loadFromDefaultfallback. Matches@kubernetes/client-nodebehavior, not full kubectl semantics.kubectl port-forward …share-snippet from #21 — metadata is now persisted to enable this as a follow-up enhancement.namespaceScanConcurrency,additionalPorts,showEmptyNamespaces, DKO CRD version escape hatch) — deferred to separate design issues.