Skip to content

Support multiple simultaneous connections (multi-account) per provider integration #5430

Description

@julianmesa-gitkraken

Description

IntegrationService / ConfiguredIntegrationService (packages/plus/integrations) currently model at most one connected account per provider per domain. There is no per-connection identity and no way to have two accounts for the same provider (e.g. two GitHub.com accounts) connected at the same time, with one designated as the "primary" and used by default.

This blocks a consumer (Kepler, GitKraken's desktop dev tool) from migrating its provider-connection management off the gk CLI onto @gitkraken/core-gitlens, because the CLI/backend already support genuine multi-account connections and Kepler's UI/data model depends on that.

Current behavior (verified against 177e3bb2 on main)

  • ConfiguredIntegrationDescriptor has no connection/session identifier and no primary flag:

    // packages/plus/integrations/src/authentication/models.ts:82-88
    export interface ConfiguredIntegrationDescriptor {
      readonly cloud: boolean;
      readonly integrationId: IntegrationIds;
      readonly scopes: string;
      readonly domain?: string;
      readonly expiresAt?: string | Date;
    }
  • ConfiguredIntegrationService dedupes/overwrites by (integrationId, domain, cloud) — a second account for the same provider+domain silently replaces the first rather than coexisting:

    • addOrUpdateConfigured (configuredIntegrationService.ts:123-154) finds an "existing" descriptor by domain === descriptor.domain && integrationId === descriptor.integrationId && cloud === descriptor.cloud, and replaces it.
    • removeConfigured (configuredIntegrationService.ts:156-184) removes by the same (domain, cloud) key, so there's no way to target one of several connections.
  • Session storage mirrors this: the secret key is integration.auth[.cloud]:{id}|{domain} and ProviderAuthenticationSession.id is literally set to descriptor.domain (configuredIntegrationService.ts:366-368, used at integrationAuthenticationProvider.ts:266) — i.e. the "id" is not a real per-connection identifier, just the domain.

  • IntegrationAuthenticationProvider.deleteSession/getSession (integrationAuthenticationProvider.ts:31-40, impl at :64 and :91) operate on a {domain, scopes} descriptor, so they can only ever address "the" session for that domain — there's nothing to disambiguate between two accounts on the same domain.

  • IntegrationService.getConfigured() (integrationService.ts:443-448) just forwards to the above, so it inherits the same one-session-per-domain ceiling.

  • There is no primary/default-connection setter anywhere in packages/plus/integrations today.

I confirmed with a repo-wide grep that there's no existing tracking issue or TODO for this ("multi-account", "multiple connections", etc. all return zero hits), so filing fresh.

Why this matters

GitKraken's account/token backend and the gk CLI already support connecting multiple accounts to the same provider simultaneously, with a real per-connection identity and an explicit primary/default selection that can be switched or removed independently per connection (removing the primary promotes a secondary). This is a shipped, paid-tier capability today — @gitkraken/core-gitlens is the odd one out in not modeling it.

Concretely, Kepler's provider DTO already expects this shape end-to-end (ProviderConnection[] with tokenId/primary per connection, sourced from the CLI), and cannot adopt @gitkraken/core-gitlens as its provider backend for connection management until this exists — see internal tracking: gitkraken/kepler#1325 (part of gitkraken/kepler#1322).

Proposed API surface

  • ConfiguredIntegrationDescriptor gains a stable per-connection identifier (e.g. id/tokenId) and a primary: boolean field, and ConfiguredIntegrationService stops deduping by (integrationId, domain, cloud) alone — it should support an array of connections per (integrationId, domain).
  • IntegrationService/IntegrationAuthenticationService gain connection-identity-aware operations, roughly:
    • getConfigured(id?) returns all connections for a provider, each with its identifier and primary flag (superset of today's behavior when there's only one).
    • connectSecondary(id, ...) / an "add without replacing the existing primary" connect flow.
    • setPrimaryConnection(id, connectionId) to switch which connection is used by default.
    • deleteConnection(id, connectionId) to remove one specific connection (as opposed to deleteAllSessions(), which already exists and clears everything for a provider).
  • Whatever backs this should be able to represent "no secondary support" gracefully for any provider/plan where GitKraken's backend doesn't offer it, since this is presumably gated by entitlement server-side already.

I'm intentionally not prescribing the exact wire format here since the team maintaining the account/token backend already knows the existing contract the CLI talks to — happy to pair on this if useful.

Acceptance criteria

  • Two accounts can be connected to the same provider (e.g. GitHub) at the same time without one silently overwriting the other's stored session/config.
  • Each connection is addressable by a stable identifier distinct from the domain.
  • There is a way to read which connection is currently primary/default, and to switch it.
  • Removing the primary connection when a secondary exists promotes the secondary (or at least leaves the provider in a well-defined connected state), rather than leaving the provider fully disconnected.
  • deleteConnection/equivalent only removes the targeted connection, not every session for that provider.

Additional context

  • Internal motivating issue: gitkraken/kepler#1325 (part of epic gitkraken/kepler#1322).
  • Checked against @gitkraken/core-gitlens@0.4.0 / vscode-gitlens@177e3bb2.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions