Files
orca/src/shared/runtime-environment-managed-orcad-store.test.ts
T
38c2d1dcb9 feat(ssh): update, roll back, recover and stop a managed orcad server (#16741 T6-5 follow-up) (#24463)
* feat(ssh): update, roll back, recover and stop a managed orcad server (#16741 T6-5 follow-up)

Builds managed-server maintenance on T6-2's deploy, rollback and recovery and
T6-4's journaled decommission. Each step reads a terminal census through the
server's tunnel; orcad answers it through a new capability-gated
orcad.terminalCensus RPC, and an older host or lost answer is unverifiable.
Update defers over live or uncounted terminals and status reports the last
deferral. A stop unlinks the server (deployment record, tunnel, SSH claim)
only after a proven exit. Inert until the T6-6 settings UI.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(rpc): load the orcad terminal census lazily so the dispatcher does not pull in the xterm window polyfill

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 15:53:24 -07:00

134 lines
5.0 KiB
TypeScript

import { mkdtempSync, readFileSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import { encodePairingOffer } from './pairing'
import {
getEnvironmentStorePath,
listEnvironments,
removeEnvironment,
updateEnvironmentFromPairingCode
} from './runtime-environment-store'
import {
addManagedOrcadEnvironment,
refreshManagedOrcadPairing,
removeManagedOrcadEnvironment
} from './runtime-environment-managed-orcad-store'
import { getRuntimeEnvironmentSidecarPath } from './runtime-environment-sidecar'
import { getRuntimeSshAccess } from './runtime-environments'
import { shippedBuildRewrite } from './runtime-environment-shipped-store-fixture'
const deployment = {
sshTargetId: 'ssh-1',
sshTargetGeneration: 4,
localPort: 46_768,
remotePort: 6_768
}
const pairingCode = (endpoint = 'ws://127.0.0.1:46768') =>
encodePairingOffer({
v: 2,
endpoint,
deviceToken: 'private-device-token',
publicKeyB64: Buffer.alloc(32, 1).toString('base64')
})
describe('managed orcad environment store', () => {
let userDataPath: string
beforeEach(() => {
userDataPath = mkdtempSync(join(tmpdir(), 'orca-managed-orcad-store-'))
})
afterEach(() => rmSync(userDataPath, { recursive: true, force: true }))
const add = (overrides: Partial<Parameters<typeof addManagedOrcadEnvironment>[1]> = {}) =>
addManagedOrcadEnvironment(userDataPath, {
id: 'environment-1',
name: 'Managed',
pairingCode: pairingCode(),
orcadDeployment: deployment,
now: 100,
...overrides
})
it('keeps the deployment link out of the file shipped builds rewrite', () => {
const environment = add()
expect(environment.orcadDeployment).toEqual(deployment)
expect(getRuntimeSshAccess(environment)).toEqual(deployment)
const persisted = readFileSync(getEnvironmentStorePath(userDataPath), 'utf8')
expect(persisted).not.toContain('orcadDeployment')
expect(persisted).toContain('"connectionDependency":"ssh-tunnel"')
expect(readFileSync(getRuntimeEnvironmentSidecarPath(userDataPath), 'utf8')).not.toContain(
'private-device-token'
)
})
it('survives a downgraded build rewriting orca-environments.json', () => {
add()
shippedBuildRewrite(userDataPath, (environments) => {
environments[0]!.lastUsedAt = 500
})
const [restored] = listEnvironments(userDataPath)
expect(restored?.orcadDeployment).toEqual(deployment)
expect(restored?.lastUsedAt).toBe(500)
})
it('drops the link when a downgraded build re-pairs the server elsewhere', () => {
add()
shippedBuildRewrite(userDataPath, (environments) => {
environments[0]!.pairingRevision = 200
})
expect(listEnvironments(userDataPath)[0]?.orcadDeployment).toBeUndefined()
})
it('refuses a pairing that does not point at the deployment tunnel', () => {
expect(() => add({ pairingCode: pairingCode('ws://127.0.0.1:1234') })).toThrow(
'does not point at its SSH tunnel'
)
expect(() => add({ pairingCode: pairingCode('wss://server.example') })).toThrow()
expect(listEnvironments(userDataPath)).toEqual([])
})
it('refuses duplicate ids and names', () => {
add()
expect(() => add({ name: 'Other' })).toThrow('already exists')
expect(() => add({ id: 'environment-2' })).toThrow('already exists')
})
it('keeps a managed server from being removed or re-paired outside its lifecycle', () => {
add()
expect(() => removeEnvironment(userDataPath, 'Managed')).toThrow('managed by Orca over SSH')
expect(() =>
updateEnvironmentFromPairingCode(userDataPath, 'Managed', { pairingCode: pairingCode() })
).toThrow('managed by Orca over SSH')
expect(listEnvironments(userDataPath)).toHaveLength(1)
})
it('removes the server and its deployment record together once it is unlinked', () => {
add()
removeManagedOrcadEnvironment(userDataPath, 'environment-1')
expect(listEnvironments(userDataPath)).toEqual([])
expect(readFileSync(getRuntimeEnvironmentSidecarPath(userDataPath), 'utf8')).not.toContain(
'environment-1'
)
})
it('leaves an unchanged pairing alone and re-binds the link when the offer rotates', () => {
const environment = add()
expect(refreshManagedOrcadPairing(userDataPath, 'environment-1', pairingCode())).toEqual(
environment
)
const rotated = encodePairingOffer({
v: 2,
endpoint: 'ws://127.0.0.1:46768',
deviceToken: 'rotated-token',
publicKeyB64: Buffer.alloc(32, 1).toString('base64')
})
const refreshed = refreshManagedOrcadPairing(userDataPath, 'environment-1', rotated, 500)
expect(refreshed.endpoints[0]?.deviceToken).toBe('rotated-token')
expect(refreshed.pairingRevision).toBe(500)
expect(refreshed.orcadDeployment).toEqual(deployment)
expect(() =>
refreshManagedOrcadPairing(userDataPath, 'environment-1', pairingCode('ws://127.0.0.1:1'))
).toThrow('does not point at its SSH tunnel')
})
})