Skip to content

fix(images): support custom image relay providers - #551

Merged
lidge-jun merged 3 commits into
lidge-jun:devfrom
iF2007:fix/image-relay-custom-provider
Jul 27, 2026
Merged

fix(images): support custom image relay providers#551
lidge-jun merged 3 commits into
lidge-jun:devfrom
iF2007:fix/image-relay-custom-provider

Conversation

@iF2007

@iF2007 iF2007 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an explicit images.provider setting for Codex's standalone /v1/images/generations and /v1/images/edits relay.

  • Selects a custom API-key openai-responses provider only for Images requests.
  • Preserves the existing ChatGPT/OpenAI fallback when images.provider is omitted.
  • Fails closed when the selected provider is missing, disabled, registry-managed, incompatible, or has no usable key.
  • Keeps registry-managed provider endpoints protected, so a custom gateway cannot repurpose the official openai-apikey tier.
  • Documents configuration and updates translated image-generation guidance.

Fixes #549

Validation

  • bun test tests/server-images.test.ts tests/server-live.test.ts
  • bun run typecheck
  • bun run privacy:scan
  • bun run test (4839 passed before rebasing this single commit onto current dev)

Security Notes

The configured provider key replaces the caller bearer before the upstream Images request. Existing provider destination validation, data-plane authentication, request limits, cancellation, and response-size protections remain unchanged.

Summary by CodeRabbit

  • New Features
    • Added images configuration to explicitly select a custom OpenAI-compatible Images provider for built-in image generation.
    • Documented standalone Images relay options, including per-request timeout.
  • Bug Fixes
    • Explicit provider selection now fails closed with clear 400 errors and no fallback to other paid upstreams.
  • Documentation
    • Updated the Codex integration guides and the configuration reference with provider-selection rules and JSON examples (multi-language).
  • Tests
    • Added coverage for provider selection/validation, correct forwarding, admission behavior, and fail-closed error cases.

@github-actions github-actions Bot added the bug Something isn't working label Jul 27, 2026
@coderabbitai

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as outdated.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The feature is worthwhile and the current implementation is focused. I verified the current head (35fb1f8b) locally: bun test tests/server-images.test.ts passes 26/26 and bun run typecheck passes. The duplicate-json review note is already stale on this head.

Two blockers remain before merge:

  1. handleImages() calls validateForwardAdmissionCredential() before selecting the explicit keyed Images provider. On a non-loopback proxy, a client using the supported Authorization: Bearer <OpenCodex admission key> form therefore gets 401 even though the keyed provider path replaces that header with the provider key before fetch. Keep the admission secret fail-closed for ChatGPT/forward relays, but allow the explicit keyed path after selection and add a regression covering Bearer admission plus images.provider while asserting the proxy secret never reaches upstream.
  2. structure/04_transports-and-sidecars.md says compatible multipart edits are forwarded unchanged, but the handler always uses readJsonRequestBody() and JSON.stringify(body). Please narrow the invariant/docs to JSON Images requests in this PR unless multipart preservation is implemented and tested.

Once those are corrected and CI is green, this should be mergeable.

iF2007 added 2 commits July 27, 2026 22:15
Allow standalone Images requests to explicitly select a custom API-key openai-responses provider while preserving the existing ChatGPT/OpenAI fallback. Fail closed for invalid selections and keep registry-managed provider endpoints protected.
@iF2007

iF2007 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Addressed both blockers in 050347f1:

  1. handleImages() now resolves the Images provider before applying the forward-only admission guard. A valid explicit keyed images.provider accepts Authorization: Bearer <OpenCodex admission key> because the outbound request replaces caller authorization with the configured provider key. Default ChatGPT/forward relays retain the existing fail-closed guard. The new non-loopback regression verifies the request succeeds, the provider key reaches upstream, and the proxy admission secret appears in no upstream header.
  2. The transport invariant now documents only bounded JSON generation/edit requests and no longer claims multipart bodies are forwarded unchanged.

Validation: bun test tests/server-images.test.ts (27/27), bun run typecheck, bun run privacy:scan, and the full suite (5058/5058). CodeRabbit incremental review is also green.

@lidge-jun
lidge-jun force-pushed the fix/image-relay-custom-provider branch from 050347f to ab652af Compare July 27, 2026 13:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/server/images.ts (1)

51-70: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Return explicit-provider configuration errors before the forward-admission check.

On a non-loopback bind, an invalid images.provider plus Authorization: Bearer <OPENCODEX_API_AUTH_TOKEN> reaches Lines 53-58 first and returns 401, hiding the intended 400 invalid_request_error from Lines 69-71. No upstream can be selected in this case, so the anti-forwarding guard is unnecessary. Check candidates.error immediately after selection, before admission validation, and add the remote-bearer regression case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server/images.ts` around lines 51 - 70, Move the candidates.error check
in the image request flow immediately after selectImagesProvider(config), before
validateForwardAdmissionCredential in the admission guard. Return the existing
400 invalid_request_error response for invalid explicit-provider configuration
before any authentication check, while preserving normal admission validation
for valid configurations. Add a regression case covering a non-loopback request
with an invalid images.provider and a bearer token.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/server/images.ts`:
- Around line 51-70: Move the candidates.error check in the image request flow
immediately after selectImagesProvider(config), before
validateForwardAdmissionCredential in the admission guard. Return the existing
400 invalid_request_error response for invalid explicit-provider configuration
before any authentication check, while preserving normal admission validation
for valid configurations. Add a regression case covering a non-loopback request
with an invalid images.provider and a bearer token.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6e143c2a-376f-4992-bda7-8069a33ec45d

📥 Commits

Reviewing files that changed from the base of the PR and between 050347f and ab652af.

📒 Files selected for processing (12)
  • docs-site/src/content/docs/guides/codex-integration.md
  • docs-site/src/content/docs/ja/guides/codex-integration.md
  • docs-site/src/content/docs/ko/guides/codex-integration.md
  • docs-site/src/content/docs/reference/configuration.md
  • docs-site/src/content/docs/ru/guides/codex-integration.md
  • docs-site/src/content/docs/zh-cn/guides/codex-integration.md
  • src/providers/openai-sidecar.ts
  • src/server/images.ts
  • src/types.ts
  • structure/01_runtime.md
  • structure/04_transports-and-sidecars.md
  • tests/server-images.test.ts

@iF2007

iF2007 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the configuration-error ordering in f51b64ae:

  • handleImages() now returns the existing 400 invalid_request_error immediately after selectImagesProvider() reports an explicit-provider configuration error, before the forward-only admission guard runs. Valid explicit keyed providers and all default/forward paths retain their existing admission behavior.
  • Added a non-loopback regression with Authorization: Bearer <OpenCodex admission key> plus an invalid images.provider; it asserts the stable 400 response, invalid_request_error type, and validation message.

Validated with bun test tests/server-images.test.ts (28/28), bun run typecheck, and bun run privacy:scan.

@lidge-jun
lidge-jun merged commit 14ae6fe into lidge-jun:dev Jul 27, 2026
1 of 2 checks passed
@iF2007
iF2007 deleted the fix/image-relay-custom-provider branch July 27, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants