import assert from 'node:assert/strict' import { test } from 'vitest' import { normalizeRegistry, REGISTRY_VERSION } from './connection-registry' import { resolveDesktopRemoteRoute } from './desktop-remote-route' const tokenA = { encoding: 'plain', value: 'token-a' } const tokenB = { encoding: 'plain', value: 'token-b' } function registry(primary: string, connections: Record[]) { return normalizeRegistry({ version: REGISTRY_VERSION, primary, connections: [{ id: 'local', kind: 'local', label: 'This device' }, ...connections] }) } test('profile remote wins precedence and carries one exact registry id', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'remote', remote: { url: 'https://global.test', authMode: 'token', token: tokenB }, profiles: { worker: { mode: 'remote', url: 'https://worker.test/', authMode: 'token', token: tokenA } } }, env: { url: 'https://env.test', token: 'env-token' }, profile: 'worker', registry: registry('global', [ { id: 'global', kind: 'remote', label: 'Global', url: 'https://global.test', token: tokenB }, { id: 'worker', kind: 'remote', label: 'Worker', url: 'https://worker.test', token: tokenA } ]) }) assert.equal(route?.kind, 'remote') assert.equal(route?.source, 'profile') assert.equal(route?.connectionId, 'worker') }) test('environment route wins over global but never claims a registry id', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'remote', remote: { url: 'https://global.test', token: tokenB } }, env: { url: 'https://env.test', token: 'token-a' }, registry: registry('env', [{ id: 'env', kind: 'remote', label: 'Env', url: 'https://env.test', token: tokenA }]) }) assert.equal(route?.source, 'env') assert.equal(route?.connectionId, undefined) assert.equal(route?.kind === 'remote' ? route.url : null, 'https://env.test') }) test('environment URL without its token keeps the existing error', () => { assert.throws( () => resolveDesktopRemoteRoute({ config: { mode: 'local' }, env: { url: 'https://env.test' }, registry: registry('local', []) }), /HERMES_DESKTOP_REMOTE_TOKEN is not/ ) }) test('global remote uses exact primary provenance when another row is identical', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'remote', remote: { url: 'https://gateway.test/', authMode: 'token', token: tokenA } }, registry: registry('gateway-primary', [ { id: 'gateway-primary', kind: 'remote', label: 'Primary', url: 'https://gateway.test', token: tokenA }, { id: 'gateway-copy', kind: 'remote', label: 'Copy', url: 'https://gateway.test', token: tokenA } ]) }) assert.equal(route?.source, 'settings') assert.equal(route?.connectionId, 'gateway-primary') }) test('global route fails closed when primary differs, even if another row matches', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'remote', remote: { url: 'https://gateway.test', authMode: 'token', token: tokenA } }, registry: registry('other', [ { id: 'other', kind: 'remote', label: 'Other', url: 'https://other.test', token: tokenB }, { id: 'matching', kind: 'remote', label: 'Matching', url: 'https://gateway.test', token: tokenA } ]) }) assert.equal(route?.connectionId, undefined) }) test('profile SSH identity includes port, key, paths, and remote profile', () => { const ssh = { mode: 'ssh', host: 'box.test', user: 'hermes', port: 2222, keyPath: '/keys/a', remoteHermesPath: '/srv/hermes', remoteProfile: 'worker' } const route = resolveDesktopRemoteRoute({ config: { mode: 'local', profiles: { worker: ssh } }, profile: 'worker', registry: registry('local', [ { id: 'wrong-port', kind: 'ssh', label: 'Wrong port', ...ssh, port: 22 }, { id: 'worker-ssh', kind: 'ssh', label: 'Worker SSH', ...ssh } ]) }) assert.equal(route?.kind, 'ssh') assert.equal(route?.connectionId, 'worker-ssh') }) test('profile SSH route fails closed when any dial field differs', () => { const ssh = { mode: 'ssh', host: 'box.test', user: 'hermes', port: 2222, keyPath: '/keys/a', remoteHermesPath: '/srv/hermes', remoteProfile: 'worker' } const variants = [ { ...ssh, port: 2200 }, { ...ssh, keyPath: '/keys/b' }, { ...ssh, remoteHermesPath: '/opt/hermes' }, { ...ssh, remoteProfile: 'default' }, { ...ssh, user: 'other' } ] for (const [index, variant] of variants.entries()) { const route = resolveDesktopRemoteRoute({ config: { mode: 'local', profiles: { worker: ssh } }, profile: 'worker', registry: registry('local', [{ id: `ssh-${index}`, kind: 'ssh', label: `SSH ${index}`, ...variant }]) }) assert.equal(route?.connectionId, undefined) } }) test('global SSH treats an omitted port as 22 and checks the primary route', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'ssh', remote: { mode: 'ssh', host: 'box.test', user: 'hermes' } }, registry: registry('ssh-primary', [ { id: 'ssh-primary', kind: 'ssh', label: 'SSH primary', host: 'box.test', user: 'hermes', port: 22 } ]) }) assert.equal(route?.kind, 'ssh') assert.equal(route?.connectionId, 'ssh-primary') }) test('profile route omits identity when two registry entries match exactly', () => { const block = { mode: 'remote', url: 'https://worker.test', authMode: 'token', token: tokenA } const route = resolveDesktopRemoteRoute({ config: { mode: 'local', profiles: { worker: block } }, profile: 'worker', registry: registry('local', [ { id: 'worker-a', kind: 'remote', label: 'Worker A', ...block }, { id: 'worker-b', kind: 'remote', label: 'Worker B', ...block } ]) }) assert.equal(route?.connectionId, undefined) }) test('kind, auth material, headers, and Cloud org stay part of route identity', () => { const cloud = { mode: 'cloud', url: 'https://cloud.test', authMode: 'oauth', headers: { 'CF-Access': { encoding: 'plain', value: 'a' } }, org: 'org-a' } const route = resolveDesktopRemoteRoute({ config: { mode: 'cloud', remote: cloud }, registry: registry('cloud', [ { id: 'cloud', kind: 'cloud', label: 'Cloud', ...cloud }, { id: 'remote', kind: 'remote', label: 'Remote', ...cloud }, { id: 'other-org', kind: 'cloud', label: 'Other org', ...cloud, org: 'org-b' } ]) }) assert.equal(route?.kind, 'cloud') assert.equal(route?.connectionId, 'cloud') }) test('URL route fails closed for different token, headers, kind, or Cloud org', () => { const cases = [ { config: { mode: 'remote', remote: { url: 'https://gateway.test', token: tokenA } }, primary: { kind: 'remote', url: 'https://gateway.test', token: tokenB } }, { config: { mode: 'remote', remote: { url: 'https://gateway.test', token: tokenA, headers: { 'CF-Access': { encoding: 'plain', value: 'a' } } } }, primary: { kind: 'remote', url: 'https://gateway.test', token: tokenA, headers: { 'CF-Access': { encoding: 'plain', value: 'b' } } } }, { config: { mode: 'remote', remote: { url: 'https://gateway.test', token: tokenA } }, primary: { kind: 'cloud', url: 'https://gateway.test', token: tokenA } }, { config: { mode: 'cloud', remote: { url: 'https://gateway.test', authMode: 'oauth', org: 'a' } }, primary: { kind: 'cloud', url: 'https://gateway.test', authMode: 'oauth', org: 'b' } } ] for (const [index, item] of cases.entries()) { const route = resolveDesktopRemoteRoute({ config: item.config, registry: registry('primary', [{ id: 'primary', label: `Primary ${index}`, ...item.primary }]) }) assert.equal(route?.connectionId, undefined) } }) test('profile remote wins over a registry-backed global SSH route', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'ssh', remote: { mode: 'ssh', host: 'global-box.test', user: 'hermes' }, profiles: { worker: { mode: 'remote', url: 'https://worker.test', authMode: 'token', token: tokenA } } }, profile: 'worker', registry: registry('global-ssh', [ { id: 'global-ssh', kind: 'ssh', label: 'Global SSH', host: 'global-box.test', user: 'hermes' }, { id: 'worker-remote', kind: 'remote', label: 'Worker', url: 'https://worker.test', token: tokenA } ]) }) assert.equal(route?.kind, 'remote') assert.equal(route?.source, 'profile') assert.equal(route?.connectionId, 'worker-remote') }) test('profile SSH wins over a different registry primary SSH route', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'ssh', remote: { mode: 'ssh', host: 'global-box.test', user: 'hermes' }, profiles: { worker: { mode: 'ssh', host: 'worker-box.test', user: 'hermes' } } }, profile: 'worker', registry: registry('global-ssh', [ { id: 'global-ssh', kind: 'ssh', label: 'Global SSH', host: 'global-box.test', user: 'hermes' }, { id: 'worker-ssh', kind: 'ssh', label: 'Worker SSH', host: 'worker-box.test', user: 'hermes' } ]) }) assert.equal(route?.kind, 'ssh') assert.equal(route?.source, 'profile') assert.equal(route?.connectionId, 'worker-ssh') }) test('environment remote wins over a registry-backed global SSH route', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'ssh', remote: { mode: 'ssh', host: 'global-box.test', user: 'hermes' } }, env: { url: 'https://env.test', token: 'env-token' }, registry: registry('global-ssh', [ { id: 'global-ssh', kind: 'ssh', label: 'Global SSH', host: 'global-box.test', user: 'hermes' } ]) }) assert.equal(route?.kind, 'remote') assert.equal(route?.source, 'env') assert.equal(route?.connectionId, undefined) }) test('local route does not inherit an unrelated registry SSH connection', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'local' }, registry: registry('local', [ { id: 'unused-ssh', kind: 'ssh', label: 'Unused SSH', host: 'box.test', user: 'hermes' } ]) }) assert.equal(route, null) }) test('local config without overrides returns null', () => { assert.equal(resolveDesktopRemoteRoute({ config: { mode: 'local' }, registry: registry('local', []) }), null) }) // --- Registry-primary transport gating (#91564 / #90316) --- // // "Make primary" on a registered remote gateway only writes connections.json; // the v1 config.mode stays 'local'. The route resolver must still expose that // remote transport, or startHermes() spawns a loopback `hermes serve` the // desktop never uses (duplicated MCP sets, port squat, respawn-on-poll). test('falls back to a REMOTE registry primary when the v1 mode is local (#91564/#90316)', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'local' }, profile: null, registry: registry('gw-b', [ { id: 'gw-b', kind: 'remote', label: 'Gateway B', url: 'https://gw-b.test', authMode: 'token', token: tokenB } ]) }) assert.equal(route?.kind, 'remote') assert.equal(route?.source, 'registry') assert.equal(route?.connectionId, 'gw-b') assert.equal((route as any)?.url, 'https://gw-b.test') assert.deepEqual((route as any)?.token, tokenB) }) test('falls back to a CLOUD registry primary when the v1 mode is local', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'local' }, profile: null, registry: registry('cloud-1', [ { id: 'cloud-1', kind: 'cloud', label: 'Hermes Cloud', url: 'https://agent.hermes.cloud', authMode: 'oauth', org: 'nous' } ]) }) assert.equal(route?.kind, 'cloud') assert.equal(route?.source, 'registry') assert.equal((route as any)?.authMode, 'oauth') assert.equal((route as any)?.org, 'nous') }) test('falls back to an SSH registry primary when the v1 mode is local', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'local' }, profile: null, registry: registry('spark', [ { id: 'spark', kind: 'ssh', label: 'Spark', host: 'spark1', user: 'tek', port: 2222, token: tokenA } ]) }) assert.equal(route?.kind, 'ssh') assert.equal(route?.source, 'registry') assert.equal(route?.connectionId, 'spark') assert.equal((route as any)?.ssh?.host, 'spark1') assert.equal((route as any)?.ssh?.port, 2222) }) test('a LOCAL registry primary keeps resolving local (null route)', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'local' }, profile: null, registry: registry('local', [ { id: 'gw-b', kind: 'remote', label: 'Gateway B', url: 'https://gw-b.test', authMode: 'token', token: tokenB } ]) }) assert.equal(route, null) }) test('the v1 global remote still outranks the registry primary', () => { const route = resolveDesktopRemoteRoute({ config: { mode: 'remote', remote: { url: 'https://global.test', authMode: 'token', token: tokenA } }, profile: null, registry: registry('gw-b', [ { id: 'global', kind: 'remote', label: 'Global', url: 'https://global.test', token: tokenA }, { id: 'gw-b', kind: 'remote', label: 'Gateway B', url: 'https://gw-b.test', authMode: 'token', token: tokenB } ]) }) assert.equal(route?.source, 'settings') assert.equal((route as any)?.url, 'https://global.test') })