feat(settings): add Codex link controls and authenticated phone bridge

This commit is contained in:
yilsem committed 2026-10-09 11:55:16 +03:00
1 parent 1acb5dd90f
commit 55a1beaf9d
22 files changed
+2857 -3

No files matched your search

@@ -271,6 +271,63 @@ async function startProxy(over: Record<string, unknown> = {}) {
return { proxy, port, identity, clock, logs, saved, ended, pair, ca: identity.cert }
}
describe('LAN proxy: narrow Codex control', () => {
const route = '/api/aiturk/codex-link/control'
const body = { contract_version: 'codex-link/1', kind: 'settings_get', request_id: 'phone-read-1', operation_id: 'phone-op-1' }
it('requires pairing before invoking local control and never starts a backend', async () => {
const calls: unknown[] = []
const t = await startProxy({ codexLinkControl: async request => { calls.push(request); return { ...request, kind: 'control_error', settings_revision: 0, error: { code: 'pending', message: 'Not ready', recovery_action: 'none' } } } })
const before = resolveCalls
try {
expect((await call(t.port, 'POST', route, { ca: t.ca, body })).status).toBe(401)
expect(calls).toHaveLength(0)
const phone = await t.pair()
const result = await call(t.port, 'POST', route, { ca: t.ca, token: phone.token, body })
expect(result.status).toBe(200)
expect(calls).toEqual([body])
expect(resolveCalls).toBe(before)
expect(JSON.stringify(calls)).not.toContain(phone.token)
} finally { await t.proxy.stop() }
})
it('rejects runtime commands, extra paths, duplicate keys and large bodies', async () => {
let calls = 0
const t = await startProxy({ codexLinkControl: async () => { calls++; throw new Error('must not execute') } })
try {
const phone = await t.pair()
for (const rawBody of [
JSON.stringify({ ...body, kind: 'runtime_attach' }),
JSON.stringify({ ...body, path: 'C:\\private' }),
JSON.stringify(body).replace('"kind":"settings_get"', '"kind":"settings_get","kind":"status_get"'),
'x'.repeat(65537)
]) {
expect((await call(t.port, 'POST', route, { ca: t.ca, token: phone.token, rawBody })).status).toBe(400)
}
expect(calls).toBe(0)
} finally { await t.proxy.stop() }
})
it('returns a fixed unknown-outcome code without leaking CLI diagnostics', async () => {
const t = await startProxy({ codexLinkControl: async () => { throw new Error('private-key-and-path') } })
try {
const phone = await t.pair()
const result = await call(t.port, 'POST', route, { ca: t.ca, token: phone.token, body })
expect(result.status).toBe(503)
expect(result.json).toEqual({ error: 'codex_link_outcome_unknown' })
expect(result.text).not.toContain('private-key')
} finally { await t.proxy.stop() }
})
it('rejects revoked phones and unsupported methods', async () => {
let calls = 0
const t = await startProxy({ codexLinkControl: async () => { calls++; return {} } })
try {
const phone = await t.pair()
expect((await call(t.port, 'GET', route, { ca: t.ca, token: phone.token })).status).toBe(405)
await t.proxy.revoke(phone.deviceId)
expect((await call(t.port, 'POST', route, { ca: t.ca, token: phone.token, body })).status).toBe(401)
expect(calls).toBe(0)
} finally { await t.proxy.stop() }
})
})
describe('LAN proxy: pairing (hello / claim)', () => {
it('hello is unauthenticated and reports whether pairing is open', async () => {
const t = await startProxy()