mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
109 lines
4.6 KiB
TypeScript
109 lines
4.6 KiB
TypeScript
import { mkdtempSync, readFileSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import nacl from 'tweetnacl'
|
|
import { beforeAll, describe, expect, it, vi } from 'vitest'
|
|
import { encodeDeviceProofMessage } from '../../../src/shared/remote-runtime/pairing/device-key-proof'
|
|
import { DeviceRegistry } from '../../../src/main/runtime/rpc/server/pairing/device-registry'
|
|
import { SimulatedMobileE2EEV2Peer } from '../../../src/main/runtime/mobile-cloud-relay/testing/simulated-mobile-e2ee-v2-peer'
|
|
import {
|
|
importReleaseCheckoutModule,
|
|
materializeReleaseCheckout,
|
|
resolveBaselineReleaseRef
|
|
} from './release-checkout'
|
|
|
|
// Across downgrade, preserve keyed rows inertly and keep token auth; refuse unsupported key auth with bad_auth so clients retain their keys.
|
|
const SUITE_TIMEOUT_MS = 180_000
|
|
|
|
type RegistryLike = {
|
|
validateToken(token: string): { deviceId: string } | null
|
|
updateLastSeen(deviceId: string): void
|
|
listDevices(): readonly Record<string, unknown>[]
|
|
}
|
|
type ChannelLike = { handleRawMessage(raw: string): void }
|
|
|
|
let ReleasedRegistry: new (userDataPath: string) => RegistryLike
|
|
let ReleasedChannel: new (ws: unknown, options: Record<string, unknown>) => ChannelLike
|
|
|
|
beforeAll(async () => {
|
|
const checkout = await materializeReleaseCheckout(resolveBaselineReleaseRef())
|
|
const [registryModule, channelModule] = await Promise.all([
|
|
importReleaseCheckoutModule(checkout, 'src/main/runtime/rpc/server/pairing/device-registry.ts'),
|
|
importReleaseCheckoutModule(checkout, 'src/main/runtime/rpc/e2ee-channel.ts')
|
|
])
|
|
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the pinned release's DeviceRegistry class; a changed shape fails the assertions below.
|
|
ReleasedRegistry = registryModule.DeviceRegistry as typeof ReleasedRegistry
|
|
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the pinned release's E2EEChannel class; a changed shape fails the assertions below.
|
|
ReleasedChannel = channelModule.E2EEChannel as typeof ReleasedChannel
|
|
}, SUITE_TIMEOUT_MS)
|
|
|
|
describe('cross-version: device keys against a released host', () => {
|
|
it('a released registry keeps keyed rows intact and inert, and token rows working', () => {
|
|
const userDataPath = mkdtempSync(join(tmpdir(), 'orca-xv-device-key-'))
|
|
const current = new DeviceRegistry(userDataPath)
|
|
const legacy = current.addDevice('Phone', 'mobile')
|
|
current.updateLastSeen(legacy.deviceId)
|
|
const keyB64 = Buffer.from(nacl.sign.keyPair().publicKey).toString('base64')
|
|
const forked = current.forkDeviceKey(legacy.deviceId, keyB64, 'Phone (key)')
|
|
|
|
const released = new ReleasedRegistry(userDataPath)
|
|
expect(released.validateToken(legacy.token)?.deviceId).toBe(legacy.deviceId)
|
|
expect(released.validateToken('undefined')).toBeNull()
|
|
released.updateLastSeen(legacy.deviceId)
|
|
|
|
const reread = new DeviceRegistry(userDataPath)
|
|
expect(reread.getDevice(forked.deviceId)).toMatchObject({
|
|
credentialKind: 'device-key',
|
|
devicePublicKeyB64: keyB64,
|
|
forkedFrom: legacy.deviceId
|
|
})
|
|
expect(reread.lookupDeviceKey(forked.deviceId)).toMatchObject({ kind: 'found' })
|
|
expect(JSON.parse(readFileSync(join(userDataPath, 'orca-devices.json'), 'utf-8'))).toHaveLength(
|
|
2
|
|
)
|
|
})
|
|
|
|
it('a released host refuses key auth with bad_auth (not unauthorized)', () => {
|
|
const desktop = nacl.box.keyPair()
|
|
const sent: string[] = []
|
|
const ws = {
|
|
OPEN: 1,
|
|
readyState: 1,
|
|
bufferedAmount: 0,
|
|
send: (data: string) => sent.push(data),
|
|
close: vi.fn()
|
|
}
|
|
const onError = vi.fn()
|
|
const channel = new ReleasedChannel(ws, {
|
|
serverSecretKey: desktop.secretKey,
|
|
resolveAuthenticatedDevice: () => null,
|
|
onReady: vi.fn(),
|
|
onError
|
|
})
|
|
const peer = new SimulatedMobileE2EEV2Peer(nacl.box.keyPair(), desktop.publicKey, null)
|
|
channel.handleRawMessage(JSON.stringify(peer.hello))
|
|
expect(peer.acceptReady(JSON.parse(sent[0]!))).toBe(true)
|
|
const key = nacl.sign.keyPair()
|
|
const proof = nacl.sign.detached(
|
|
encodeDeviceProofMessage('auth', Buffer.from(peer.transcriptHashB64, 'base64')),
|
|
key.secretKey
|
|
)
|
|
channel.handleRawMessage(
|
|
peer.sealText(
|
|
JSON.stringify({
|
|
type: 'e2ee_auth',
|
|
v: 2,
|
|
transcriptHashB64: peer.transcriptHashB64,
|
|
deviceId: 'keyed',
|
|
deviceProofB64: Buffer.from(proof).toString('base64')
|
|
})
|
|
)
|
|
)
|
|
expect(JSON.parse(peer.openText(sent[1]!)!)).toEqual({
|
|
type: 'e2ee_error',
|
|
error: { code: 'bad_auth' }
|
|
})
|
|
expect(onError).toHaveBeenCalledWith(4001, 'Invalid e2ee_auth')
|
|
})
|
|
})
|