From 8daf21370bd5ebb7a6ed0c5210622c00026422d8 Mon Sep 17 00:00:00 2001 From: vam Date: Wed, 21 Oct 2026 17:37:11 +0800 Subject: [PATCH] fix: preserve case-sensitive SSH usernames in host picker --- docs/site/content/docs/ssh.mdx | 2 +- src/main/ssh/config/ssh-config-host-picker.test.ts | 10 ++++++++++ src/shared/ssh-config-alias.test.ts | 7 +++++-- src/shared/ssh-config-alias.ts | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/site/content/docs/ssh.mdx b/docs/site/content/docs/ssh.mdx index e61342c889f..4e081918611 100644 --- a/docs/site/content/docs/ssh.mdx +++ b/docs/site/content/docs/ssh.mdx @@ -21,7 +21,7 @@ Orca can drive agents on remote machines over SSH — useful for long-running bu Dirty add/edit forms ignore outside clicks so an accidental click away does not discard your fields; use Escape, Cancel, or × to discard. -The OpenSSH config picker's **In Orca** badge also recognizes a saved target with the same configured hostname, port, and user, even when its label differs from the config alias. A different port or user remains a separate target; entries without `HostName` are matched by alias only. +The OpenSSH config picker's **In Orca** badge also recognizes a saved target with the same configured hostname, port, and user, even when its label differs from the config alias. Hostnames are compared case-insensitively, but SSH usernames preserve case. A different port or user remains a separate target; entries without `HostName` are matched by alias only. ## Host key verification diff --git a/src/main/ssh/config/ssh-config-host-picker.test.ts b/src/main/ssh/config/ssh-config-host-picker.test.ts index 029ded7bbf2..5d6d1441d1f 100644 --- a/src/main/ssh/config/ssh-config-host-picker.test.ts +++ b/src/main/ssh/config/ssh-config-host-picker.test.ts @@ -77,6 +77,16 @@ describe('SSH config host picker search', () => { expect(result.newHostCount).toBe(0) }) + it('keeps case-distinct SSH users on the same machine separate', () => { + const result = searchSshConfigHosts( + [{ host: 'admin-account', hostname: 'BOX', user: 'Admin' }], + [{ configHost: 'saved-account', label: 'Saved', host: 'box', port: 22, username: 'admin' }] + ) + + expect(result.hosts[0]).toMatchObject({ alias: 'admin-account', alreadyInOrca: false }) + expect(result.newHostCount).toBe(1) + }) + it('leaves a different machine unflagged', () => { const result = searchSshConfigHosts( [{ host: 'aimp', hostname: '172.16.203.131', user: 'chanmuzi' }], diff --git a/src/shared/ssh-config-alias.test.ts b/src/shared/ssh-config-alias.test.ts index ecd942978b6..8a026392b99 100644 --- a/src/shared/ssh-config-alias.test.ts +++ b/src/shared/ssh-config-alias.test.ts @@ -30,8 +30,11 @@ describe('sshEndpointIdentity', () => { ) }) - it('folds host and user case but keeps a different user distinct', () => { - expect(sshEndpointIdentity({ host: 'BOX', port: 22, username: 'Me' })).toBe( + it('folds hostname case but preserves case-sensitive SSH usernames', () => { + expect(sshEndpointIdentity({ host: 'BOX', port: 22, username: 'me' })).toBe( + sshEndpointIdentity({ host: 'box', port: 22, username: 'me' }) + ) + expect(sshEndpointIdentity({ host: 'box', port: 22, username: 'Me' })).not.toBe( sshEndpointIdentity({ host: 'box', port: 22, username: 'me' }) ) expect(sshEndpointIdentity({ host: 'box', port: 22, username: 'me' })).not.toBe( diff --git a/src/shared/ssh-config-alias.ts b/src/shared/ssh-config-alias.ts index 594a5d82226..c9fcd711d6c 100644 --- a/src/shared/ssh-config-alias.ts +++ b/src/shared/ssh-config-alias.ts @@ -25,5 +25,5 @@ export function sshEndpointIdentity(target: { target.port <= 65_535 ? target.port : 22 - return `${host}\u0000${port}\u0000${target.username?.trim().toLowerCase() ?? ''}` + return `${host}\u0000${port}\u0000${target.username?.trim() ?? ''}` }