From b285e581eae226eb623bbadfa8f3807c0692b713 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sat, 24 Oct 2026 18:42:36 -0500 Subject: [PATCH] fixture fix, untested --- packages/harness/tests/proxy-bundle.test.mjs | 94 +++++++++++++++++++ packages/plugins/tests/proxy-harness.test.mjs | 65 +++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 packages/harness/tests/proxy-bundle.test.mjs create mode 100644 packages/plugins/tests/proxy-harness.test.mjs diff --git a/packages/harness/tests/proxy-bundle.test.mjs b/packages/harness/tests/proxy-bundle.test.mjs new file mode 100644 index 000000000..35ea19ef5 --- /dev/null +++ b/packages/harness/tests/proxy-bundle.test.mjs @@ -0,0 +1,94 @@ +// P3: generate real harness config through buildBundle; credentials never enter disk artifacts. +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { mkdirSync, readFileSync, statSync } from 'node:fs'; +import { join } from 'node:path'; +import { buildBundle } from '../src/bundle.mjs'; +import { HARNESS, REPO_SKILLS, resolvedFor, scratch } from './helpers.mjs'; + +const models = { + a: { provider: 'proxy', model: 'claude-fixture', route: 'anthropic' }, + z: { provider: 'proxy', model: 'glm-fixture', route: 'glm' }, + g: { provider: 'proxy', model: 'gpt-fixture', route: 'codex' }, +}; +function build(t, selection, proxy, declared = models) { + const root = scratch(t, 'p332-'), runDir = join(root, 'run'); + mkdirSync(runDir, { mode: 0o700 }); + const resolved = resolvedFor(t, 'pm', doc => { + doc.roles.pm.vars = { ...doc.roles.pm.vars, harness: 'pi', model: selection }; + }); + const bundle = buildBundle({ + dir: join(runDir, 'bundle'), resolved, models: declared, + contract: '# Fixture\n', harness: HARNESS.pi, harnessVersion: 'fixture', + skillsDir: REPO_SKILLS, proxy, + session: { run: 'r332', launchedBy: 'chief', workspace: join(root, 'ws'), + toolSocket: join(runDir, 'tools.sock'), turnMarker: join(runDir, 'turn.done') }, + }); + const file = join(runDir, 'home', '.pi', 'agent', 'models.json'); + return { ...bundle, file, runDir, text: readFileSync(file, 'utf8') }; +} +function assertSafe(value) { + if (typeof value === 'string') assert.ok(!value.startsWith('!'), value); + else if (value && typeof value === 'object') for (const item of Object.values(value)) assertSafe(item); +} + +test('P3 Anthropic route uses messages at proxy root and the declared model id', t => { + const b = build(t, 'a', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }); + const { anthropic } = JSON.parse(b.text).providers; + assert.equal(anthropic.api, 'anthropic-messages'); + assert.equal(anthropic.baseUrl, 'http://127.0.0.1:12345'); + assert.deepEqual(anthropic.models.map(m => m.id), ['claude-fixture']); + assert.equal(b.env.PI_PROVIDER, 'anthropic'); + assert.equal(b.env.PI_MODEL, 'claude-fixture'); +}); + +test('P3 GLM route uses completions at proxy /v1 with explicit z.ai compatibility', t => { + const b = build(t, 'z', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }); + const glm = JSON.parse(b.text).providers['mosaic-proxy-glm']; + assert.equal(glm.api, 'openai-completions'); + assert.equal(glm.baseUrl, 'http://127.0.0.1:12345/v1'); + assert.deepEqual(glm.models.map(m => m.id), ['glm-fixture']); + assert.equal(glm.compat.thinkingFormat, 'zai'); + assert.equal(glm.compat.zaiToolStream, true); + assert.equal(b.env.PI_PROVIDER, 'mosaic-proxy-glm'); +}); + +test('P3 GPT route selects a stack-owned provider instead of pi Codex OAuth', t => { + const b = build(t, 'g', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }); + const providers = JSON.parse(b.text).providers; + assert.equal(Object.hasOwn(providers, 'openai-codex'), false); + const gpt = providers['mosaic-proxy-codex']; + assert.equal(gpt.baseUrl, 'http://127.0.0.1:12345/v1'); + assert.deepEqual(gpt.models.map(m => m.id), ['gpt-fixture']); + assert.equal(b.env.PI_PROVIDER, 'mosaic-proxy-codex'); + // Assert the one chosen API after the authorized pinned-binary probe, before this file first runs. +}); + +test('P3 models file is private, references the one session key, and stores no executable values or keys', t => { + const key = 'fx332-agent-a'; + const b = build(t, 'a', { baseUrl: 'http://127.0.0.1:12345', key }); + const document = JSON.parse(b.text); + assert.deepEqual(Object.keys(document.providers).sort(), ['anthropic', 'mosaic-proxy-codex', 'mosaic-proxy-glm']); + for (const provider of Object.values(document.providers)) assert.equal(provider.apiKey, '$ANTHROPIC_API_KEY'); + assertSafe(document); + assert.ok(!b.text.includes(key)); + assert.equal(b.env.ANTHROPIC_API_KEY, key); + assert.equal(statSync(b.file).mode & 0o777, 0o600); + for (const dir of ['home', 'home/.pi', 'home/.pi/agent']) assert.equal(statSync(join(b.runDir, dir)).mode & 0o777, 0o700); + for (const file of Object.values(b.files)) assert.ok(!readFileSync(file, 'utf8').includes(key), file); + assert.ok(!JSON.stringify(b.manifest).includes(key)); +}); + +test('P3 every launch regenerates proxy port, declared models and own key without caching', t => { + const first = build(t, 'a', { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' }); + const second = build(t, 'a', { baseUrl: 'http://127.0.0.1:23456', key: 'fx332-agent-b' }, { + a: { provider: 'proxy', model: 'changed-model-id', route: 'anthropic' }, + }); + assert.equal(second.env.ANTHROPIC_API_KEY, 'fx332-agent-b'); + assert.ok(!JSON.stringify(second).includes('fx332-agent-a')); + const { providers } = JSON.parse(second.text); + assert.deepEqual(Object.keys(providers), ['anthropic']); + assert.equal(providers.anthropic.baseUrl, 'http://127.0.0.1:23456'); + assert.deepEqual(providers.anthropic.models.map(m => m.id), ['changed-model-id']); + assert.equal(JSON.parse(first.text).providers.anthropic.baseUrl, 'http://127.0.0.1:12345'); +}); diff --git a/packages/plugins/tests/proxy-harness.test.mjs b/packages/plugins/tests/proxy-harness.test.mjs new file mode 100644 index 000000000..b862bb98c --- /dev/null +++ b/packages/plugins/tests/proxy-harness.test.mjs @@ -0,0 +1,65 @@ +// P3: run real harness exports through the plug-in loader, with made-up session keys only. +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { chmodSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { createLoader } from '../src/loader.mjs'; +import { sessionEnv } from '../../seat/src/session.mjs'; + +async function harness(name) { + const loader = createLoader({ log() {} }); + const result = await loader.load({ harness: [name] }); + assert.deepEqual(result.refused, []); + return loader.modules('harness')[0]; +} +function scratch(t) { + const root = mkdtempSync(join(tmpdir(), 'p332-')); + t.after(() => rmSync(root, { recursive: true, force: true })); + return root; +} +const policy = { tools: [], typed: [] }; +const session = { model: 'claude-fixture', thinking: 'low' }; + +test('P3 Claude env receives the session proxy URL and key, without another agent or host credential', async () => { + const claude = await harness('claude-code'); + const host = { CLAUDE_CODE_OAUTH_TOKEN: 'fx332-host', OPENAI_API_KEY: 'fx332-upstream' }; + for (const [run, key] of [['r332a', 'fx332-agent-a'], ['r332b', 'fx332-agent-b']]) { + const proxy = { baseUrl: 'http://127.0.0.1:12345', key }; + const env = { ...sessionEnv(host, run, proxy), ...claude.env({ files: {}, policy, session, proxy }) }; + assert.equal(env.ANTHROPIC_BASE_URL, 'http://127.0.0.1:12345'); + assert.equal(env.ANTHROPIC_AUTH_TOKEN, key); + assert.equal(Object.hasOwn(env, 'CLAUDE_CODE_OAUTH_TOKEN'), false); + assert.equal(Object.hasOwn(env, 'OPENAI_API_KEY'), false); + const other = run === 'r332a' ? 'fx332-agent-b' : 'fx332-agent-a'; + assert.ok(!Object.values(env).includes(other)); + } +}); + +test('P3 Claude preflight accepts a proxy key without a host provider credential', async t => { + const claude = await harness('claude-code'); + const root = scratch(t), binary = join(root, 'claude'); + writeFileSync(binary, '#!/bin/sh\nexit 0\n'); + chmodSync(binary, 0o700); + assert.equal(claude.preflight({ env: { MOSAIC_CLAUDE_BIN: binary }, proxy: { + baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a', + } }), null); +}); + +test('P3 pi refuses no-session-credential with no provider key', async () => { + const pi = await harness('pi'); + assert.equal(pi.preflight({ env: {} })?.code, 'no-session-credential'); +}); + +test('P3 pi refuses no-session-credential with only a Claude OAuth token', async () => { + const pi = await harness('pi'); + assert.equal(pi.preflight({ env: { CLAUDE_CODE_OAUTH_TOKEN: 'fx332-oauth' } })?.code, 'no-session-credential'); +}); + +test('P3 pi accepts its own provider key or a session proxy key', async () => { + const pi = await harness('pi'); + for (const name of ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'OPENROUTER_API_KEY', 'ZAI_API_KEY']) { + assert.equal(pi.preflight({ env: { [name]: 'fx332-own' } }), null, name); + } + assert.equal(pi.preflight({ env: {}, proxy: { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' } }), null); +});