feat(polli-cli): polli harness codex + claude-code via pinned routers - #15241
afanasevmylife wants to merge 3 commits into
Conversation
Quest pollinations#15218. Two router-backed harness adapters (codex via Codex Router 5e1b49e/v0.6.0, claude-code via Claude Code Router 3.1.1): documented router commands only, dedicated child keys, WAL journal recovery, ownership markers, read-only CCR sqlite verification, fail-closed version gates, exit codes 0/2/3/4, opt-in --smoke. 24 new tests; 169/169 green; biome clean.
Strix Security ReviewWarning This pull request has 6 commits after the last Strix review ( No security issues found. Updated for Reviewed by Strix |
- interprocess lock (mkdir mutex) around codex on/off and claude-code on/off - reconcile never deletes a pre-existing credential file - off rebuilds ownership baseline from a committed tx journal - claude-code on re-mints and repairs when the stored key stops validating - saved CCR ids re-validated against config shape; off requires context - spawnCommand for Windows .cmd shims; key never printed on non-TTY - router not-found matched on exact stderr text; pin enforced on mutations - regression tests for all of the above (173 tests green)
|
Cross-review round completed (independent reviewer pass over the full diff). All 11 findings were real and are fixed in 62cc1d6: High
Medium
Low
Regression tests added for the credential-preservation, committed-tx recovery, key-repair, and no-context-off paths. Full suite: 173/173 green locally; biome clean on all touched files. |
|
@strix-security re-run review please - 6 commits landed since the last pass at 2b6ef4e (merge with upstream main at 1d7fde2). Current head is the same code as the reviewed diff plus upstream sync; CI is green (11/11 check runs). |
Fixes #15218.
Adds
polli harness codex on|off|statusandpolli harness claude-code on|off|status, driving the two community routers the quest names - Codex Router and Claude Code Router - each pinned to an exact version so the integration cannot drift under us.Codex (
src/harnesses/codex.ts)~/.pollinations/harnesses/codex/codex-router, pinned to commit5e1b49e(v0.6.0); any other version is refused, not driven.providers generic add/show/enable/disable/remove,curate-models --models/--remove --apply,credential ... status,doctor). polli never edits router state files.generic-provider-credentials/pollinations.keyusing the router's own protocol (temp file + rename,0o600), because the router'scredential setreads only from a hidden TTY prompt. The write is verified afterwards withproviders generic credential pollinations status; mismatch = stop, no guessing.polli-harness-codex(child key), like the other adapters.fetchHarnessModels);--model <id>picks the active one.tx.json) records intent before each mutation; an interruptedonis reconciled on the next run - rollback removes only what the journal proves we created (conditional on themanaged-by: polli-cli harness codexdescription marker). After the commit boundary (key publication)ononly continues idempotently.offremoves our curated models, the credential file, disables/removes the provider only per first-run facts (a provider that existed before us, or was enabled before us, is left in its previous state), verifies absence, then revokes the child key(s) by name.Claude Code (
src/harnesses/claude-code.ts)CCR's only supported way to create providers/profiles is its management UI (
config.sqliteis "do not edit live"; the management RPC is undocumented), so this adapter is an honest semi-automatic path:@musistudio/claude-code-router@3.1.1if missing (any other installed version → refused), requires Claude Code major 2, starts the service.http://127.0.0.1:3458with exact values: providerpollinations→https://gen.pollinations.ai/v1(OpenAI Chat) + a freshly minted child key (printed once, never stored by polli), then an agent profile (provider + model + enabled).config.sqlite(SELECT value_json FROM app_config WHERE key='default', SQLite openedreadOnly: true, never written) until the new entries verify. Ownership is proven against a pre-state id snapshot taken before the intent - a provider that existed before ouronis never claimed.awaiting-provider/awaiting-profile); re-runningonresumes,statusshows the lifecycle state (router-missing/client-missing/not-configured/awaiting-*/key-valid/key-invalid).offasks the user to delete the two entries in the UI, verifies their absence read-only, then revokes the child key and clears state (manual-pending, exit 3, while entries remain).Shared
status). New--smokeflag sends one billable request after setup (smoke-test <model> --yes --jsonfor Codex; gateway health + guidance for CCR, whose billable gateway call needs a UI-created client key).HarnessOnOptions.smoke,HarnessResult.state/exitCode/notes, exportedkeyIsValid, andrevokeHarnessKeys(delete by name - the key endpoint enforces no name uniqueness).CODING_HARNESSES.mdsections for both adapters, README + SKILL.md adapter lists.Tests
24 new tests (169/169 green in
packages/polli-cli): fresh/existing/foreign configs, crash-recovery journal, byte-preserving off for pre-existing providers, ownership exclusion via pre-state, version-gate refusals, key-valid/key-invalid lifecycle, manual-pending off. Biome clean on all touched files.Honest limits