Skip to content

fix(auth): pin forwarded Codex credentials to ChatGPT - #1471

Open
luvs01 wants to merge 2 commits into
lidge-jun:devfrom
luvs01:agent/pin-forwarded-codex-credentials
Open

fix(auth): pin forwarded Codex credentials to ChatGPT#1471
luvs01 wants to merge 2 commits into
lidge-jun:devfrom
luvs01:agent/pin-forwarded-codex-credentials

Conversation

@luvs01

@luvs01 luvs01 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • forward caller OAuth/Codex metadata and runtime pool credentials only to the canonical ChatGPT Codex endpoint
  • prevent noncanonical Responses gateways from receiving caller bearer tokens, ChatGPT account/session identifiers, or runtime account overrides
  • pin accepted canonical URL variants before Responses, web-search, vision, image, live, and native-compact requests are constructed
  • preserve explicitly configured static provider headers and ordinary canonical forward behavior
  • require a Codex pool account only for canonical credential-bearing destinations, so a noncanonical gateway can continue with its configured URL and static headers

Previously, every openai-responses provider using authMode: "forward" copied FORWARD_HEADERS and any _codexAccountOverride into its upstream request. A custom or changed baseUrl could therefore become a credential destination even though it was not the canonical ChatGPT backend.

The adapter now uses the existing canonical-provider predicate as the authorization boundary for dynamic credentials and the pool-required invariant. Canonical trailing-slash spellings are pinned to the exact ChatGPT base before credential-bearing sidecars and compact/live paths append endpoints. Noncanonical gateways still receive their explicitly configured static headers, but never inherit caller or pool-account credentials.

Verification

  • Bun 1.4.0-canary.1: the four exact maintainer-requested credential/native-metadata regressions passed (4/4, 17 assertions)
  • Bun 1.3.14: the same four exact regressions passed (4/4, 17 assertions)
  • Bun 1.3.14: full passthrough, custom-tool, and override adapter files passed (85/85, 302 assertions)
  • Bun 1.4.0-canary.1: broader three-file run passed every changed regression, including canonical custom tools and synthesized session_id; three unrelated existing Windows ACL/teardown cases failed and are recorded separately rather than treated as PR regressions
  • Bun 1.4.0-canary.1: TypeScript 7.0.2 tsc --noEmit passed on the exact latest-dev head
  • Bun 1.3.14: TypeScript 7.0.2 tsc --noEmit passed on the exact latest-dev head
  • bun run privacy:scan passed
  • git diff --check passed
  • latest-dev rebase preserved the exact validated patch-id
  • independent read-only production and test reviews found no remaining P0-P3 findings

Focused affected-surface tests, dual-runtime typecheck, privacy, diff, and independent review satisfy the local CI gate. Unrelated environment failures are not attributed to this change, and the same GitHub CI workload is not duplicated locally.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed. This tightens an existing internal credential-destination invariant without changing user-facing configuration.
  • Security-sensitive changes were reviewed for credential destinations, runtime overrides, canonical URL normalization, sidecar routing, and static-header compatibility.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Bug Fixes

    • Improved request forwarding for supported OpenAI-compatible connections.
    • Standardized endpoint routing by removing extra trailing slashes.
    • Preserved configured URLs and credentials for nonstandard providers.
    • Improved authentication and account handling for supported Codex connections.
    • Fixed live, compact, vision, image, and web-search requests to reach the correct endpoints.
  • Tests

    • Added coverage for URL normalization, credential handling, authentication, and request routing across supported services.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b7b2a333-1f87-4349-b97d-7ee832f1f366

📥 Commits

Reviewing files that changed from the base of the PR and between 80aeb36 and 52fe372.

📒 Files selected for processing (4)
  • src/server/responses/compact.ts
  • tests/claude-messages-endpoint.test.ts
  • tests/responses-compaction-routing.test.ts
  • tests/web-search.test.ts

📝 Walkthrough

Walkthrough

Canonical OpenAI forward providers now use CODEX_FORWARD_BASE_URL and receive forwarded caller or runtime credentials. Noncanonical providers retain configured URLs and credentials. Sidecar, compact, live, and related test paths normalize trailing slashes and endpoint paths.

Changes

Canonical Codex routing

Layer / File(s) Summary
Forward adapter routing and credentials
src/adapters/openai-responses.ts, tests/openai-responses-passthrough.test.ts, tests/codex-metadata-integrity.test.ts, tests/passthrough-override.test.ts, tests/responses-custom-tool-repair.test.ts
Canonical providers use the fixed Codex URL and receive caller or runtime credentials. Noncanonical providers retain configured URLs and exclude caller and runtime credentials. Tests cover credential filtering, override precedence, URL selection, and request forwarding.
Sidecar, compact, and relay endpoint normalization
src/providers/openai-sidecar.ts, src/server/responses/compact.ts, src/server/live.ts, tests/responses-compaction-routing.test.ts, tests/server-images.test.ts, tests/server-live.test.ts, tests/vision-sidecar-e2e.test.ts, tests/web-search.test.ts
Sidecar and compact requests pin canonical providers to the Codex URL. Live relay construction removes all trailing slashes. Tests cover compact, image, live, vision, and web-search routing.
Native endpoint integration coverage
tests/claude-messages-endpoint.test.ts
The native endpoint test redirects canonical Codex requests to the mock upstream, rejects unexpected paths, and restores the global fetch implementation during cleanup.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: lidge-jun, wibias, ingwannu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: restricting forwarded Codex credentials to the canonical ChatGPT endpoint.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Aug 11, 2026
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

This pull request has been marked Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently. If no CodeRabbit review appears, comment @coderabbitai review to request one.
Maintainers notified: @lidge-jun @Ingwannu @Wibias

@luvs01
luvs01 force-pushed the agent/pin-forwarded-codex-credentials branch 2 times, most recently from 392873c to 3725a3c Compare August 11, 2026 13:35

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the credential-destination changes. I did not find an additional blocker in this head. The canonical-provider predicate rejects userinfo/query/hash/noncanonical destinations, dynamic caller and pool credentials are gated on that predicate, and canonical trailing-slash variants are pinned before credential-bearing endpoint construction.

I am not approving this head because GitHub currently reports it as not mergeable against the latest dev. Please rebase/resolve the conflicts and request re-review so the final credential boundary can be checked on the integrated diff.

@Wibias
Wibias force-pushed the agent/pin-forwarded-codex-credentials branch from 3725a3c to 8abf036 Compare August 11, 2026 19:34
@Wibias
Wibias marked this pull request as ready for review August 11, 2026 19:42
@Wibias
Wibias marked this pull request as draft August 11, 2026 19:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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/adapters/openai-responses.ts (1)

1174-1195: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Gate the required-account error on canonical providers.

Line 1185 throws when any forward provider has _codexAccountRequired: true without an override. This includes noncanonical providers. Those providers must use their configured URL and static headers without requiring a Codex pool account.

Require mayForwardCallerCredentials in this condition. Add a regression case with a noncanonical provider, _codexAccountRequired: true, and no _codexAccountOverride.

Proposed fix
-        if (runtimeProvider._codexAccountRequired && !runtimeProvider._codexAccountOverride) {
+        if (
+          mayForwardCallerCredentials
+          && runtimeProvider._codexAccountRequired
+          && !runtimeProvider._codexAccountOverride
+        ) {
           throw new Error("Codex pool account auth is required but unavailable");
         }

This conflicts with the PR objective that noncanonical gateways retain static-header operation without caller or pool credentials.

🤖 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/adapters/openai-responses.ts` around lines 1174 - 1195, Update the
`_codexAccountRequired` validation in the response request flow so it throws
only when `mayForwardCallerCredentials` is true and no `_codexAccountOverride`
exists. Preserve noncanonical providers’ configured URL and static-header
behavior without requiring pool credentials, and add a regression case covering
a noncanonical provider with `_codexAccountRequired: true` and no override.
🤖 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/adapters/openai-responses.ts`:
- Around line 1174-1195: Update the `_codexAccountRequired` validation in the
response request flow so it throws only when `mayForwardCallerCredentials` is
true and no `_codexAccountOverride` exists. Preserve noncanonical providers’
configured URL and static-header behavior without requiring pool credentials,
and add a regression case covering a noncanonical provider with
`_codexAccountRequired: true` and no override.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 46121151-b40d-49a3-837b-152da073e2d8

📥 Commits

Reviewing files that changed from the base of the PR and between d91ca60 and 8abf036.

📒 Files selected for processing (12)
  • src/adapters/openai-responses.ts
  • src/providers/openai-sidecar.ts
  • src/server/live.ts
  • src/server/responses/compact.ts
  • tests/codex-metadata-integrity.test.ts
  • tests/openai-responses-passthrough.test.ts
  • tests/passthrough-override.test.ts
  • tests/responses-compaction-routing.test.ts
  • tests/server-images.test.ts
  • tests/server-live.test.ts
  • tests/vision-sidecar-e2e.test.ts
  • tests/web-search.test.ts

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Requesting changes for two regressions plus one remaining credential-boundary bug:

  1. The PR currently breaks existing Responses behavior. The suite reports:

    • (fail) routed Responses custom-tool compatibility > handleResponses leaves custom tools native for forward-auth passthrough
    • (fail) native openai-responses route carries prompt_cache_key + synthesized session_id header

    These failures are in code paths changed by this PR's canonical/noncanonical forward-provider classification. Please update the implementation and/or now-obsolete fixtures as appropriate, but the full affected behavior needs to remain covered and green before merge. In particular, make sure legitimate canonical native Responses requests still preserve their expected metadata/header behavior while noncanonical gateways do not inherit caller credentials.

  2. Major: gate _codexAccountRequired on the canonical credential destination. In src/adapters/openai-responses.ts, the current condition throws for any authMode: "forward" provider with _codexAccountRequired: true and no _codexAccountOverride:

if (runtimeProvider._codexAccountRequired && !runtimeProvider._codexAccountOverride) {
  throw new Error("Codex pool account auth is required but unavailable");
}

That still includes noncanonical providers. It conflicts with this PR's objective that noncanonical gateways continue operating with their configured URL and static headers, without caller or pool credentials.

Please require mayForwardCallerCredentials in this condition, e.g. conceptually:

if (
  mayForwardCallerCredentials &&
  runtimeProvider._codexAccountRequired &&
  !runtimeProvider._codexAccountOverride
) {
  throw new Error("Codex pool account auth is required but unavailable");
}

Add a regression case with a noncanonical provider, _codexAccountRequired: true, no _codexAccountOverride, and static configured headers. It should build/send against the configured noncanonical URL without requiring a Codex pool account and without forwarding caller credentials.

@luvs01
luvs01 force-pushed the agent/pin-forwarded-codex-credentials branch from 8abf036 to d2bd0f0 Compare August 12, 2026 02:49
@Ingwannu

Copy link
Copy Markdown
Owner

Re-review on exact head d2bd0f0b2c3438184d83c28a08651bba94e2725b against current dev@37139818d2d3fe7b033e958ccf87080e4be2b4b7.

The blockers from the previous review are addressed on this head:

  • _codexAccountRequired is now enforced only when the resolved provider is the canonical ChatGPT Codex credential destination;
  • noncanonical forward gateways retain only their configured URL and static headers, without caller/pool credentials or runtime account overrides;
  • canonical trailing-slash variants are pinned before Responses, compact, live, image, vision, and web-search endpoint construction;
  • the two previously regressed canonical paths now have updated coverage for native custom tools and synthesized session_id/prompt-cache metadata.

I traced the destination predicate through the adapter, sidecar, compact, and live paths and found no additional credential-boundary blocker. Exact-head validation under a 2-CPU/8-GB cap:

  • affected paths excluding the known flaky Claude replay case: 281 passed, 0 failed;
  • bun run typecheck: passed;
  • bun run privacy:scan: passed.

tests/claude-messages-endpoint.test.ts still has the existing Claude replay owns optional main enrichment... timing/state failure (39 passed, 1 failed) when run alone; the same failure reproduces on the current dev baseline and is unrelated to this diff.

I am not approving or merging while the PR remains draft with the author's local-CI and ready-for-review boxes open. From the credential-destination and affected-path review, I found no remaining code blocker at this head; please complete the readiness/CI gate and request final review without changing the head.

@luvs01
luvs01 force-pushed the agent/pin-forwarded-codex-credentials branch from d2bd0f0 to 787db40 Compare August 12, 2026 04:13
@github-actions
github-actions Bot marked this pull request as ready for review August 12, 2026 04:15
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@github-actions[bot] The readiness gate is complete. I will review the current ready head 787db40d9411388b00c24a634f754e121a1f643c before approval.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.
⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== HEAD and merge base =='
git rev-parse HEAD
git rev-parse dev
git merge-base HEAD dev

echo '== Changed files relative to dev =='
git diff --name-status dev...HEAD

echo '== Changed TypeScript outlines =='
git diff --name-only dev...HEAD -- '*.ts' |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --type function,class,interface,type --view compact || true
  done

echo '== Exact diff =='
git diff --find-renames --find-copies --unified=80 dev...HEAD -- \
  src/adapters/openai-responses.ts \
  src/providers/openai-sidecar.ts \
  src/server/live.ts \
  src/server/responses/compact.ts \
  tests/openai-responses-passthrough.test.ts \
  tests/responses-compaction-routing.test.ts \
  tests/web-search.test.ts \
  tests/server-live.test.ts \
  tests/server-images.test.ts \
  tests/vision-sidecar-e2e.test.ts \
  tests/codex-metadata-integrity.test.ts \
  tests/passthrough-override.test.ts

Length of output: 1538


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr_number="1471"

echo '== Available refs =='
git branch -a
git show-ref --heads --remotes || true

echo '== Pull request metadata =='
gh pr view "$pr_number" --repo "$repo" \
  --json number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,mergeCommit,reviewDecision,statusCheckRollup \
  --jq '{
    number,
    state,
    isDraft,
    baseRefName,
    baseRefOid,
    headRefName,
    headRefOid,
    mergeCommit: (.mergeCommit.oid // null),
    reviewDecision,
    checks: [.statusCheckRollup[]? | {name, conclusion, status}]
  }'

base_sha="$(gh pr view "$pr_number" --repo "$repo" --json baseRefOid --jq '.baseRefOid')"
echo "== Diff summary from base $base_sha =="
git diff --stat "$base_sha...HEAD"
git diff --name-status "$base_sha...HEAD"

echo '== Relevant source outlines =='
for file in \
  src/adapters/openai-responses.ts \
  src/providers/openai-sidecar.ts \
  src/server/live.ts \
  src/server/responses/compact.ts; do
  echo "--- $file"
  ast-grep outline "$file" --items all --view compact
done

echo '== Relevant source and test diff =='
git diff --find-renames --find-copies --unified=100 "$base_sha...HEAD" -- \
  src/adapters/openai-responses.ts \
  src/providers/openai-sidecar.ts \
  src/server/live.ts \
  src/server/responses/compact.ts \
  tests/openai-responses-passthrough.test.ts \
  tests/responses-compaction-routing.test.ts \
  tests/web-search.test.ts \
  tests/server-live.test.ts \
  tests/server-images.test.ts \
  tests/vision-sidecar-e2e.test.ts \
  tests/codex-metadata-integrity.test.ts \
  tests/passthrough-override.test.ts

Length of output: 5957


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base_sha="49887650eb2c7efa5c90996ec5108c8a7cfd129b"

echo '== Changed source outlines =='
for file in \
  src/adapters/openai-responses.ts \
  src/providers/openai-sidecar.ts \
  src/server/live.ts \
  src/server/responses/compact.ts; do
  echo "--- $file"
  ast-grep outline "$file" --items all --view signatures
done

echo '== Full PR diff =='
git diff --find-renames --find-copies --unified=55 "$base_sha...HEAD" -- \
  src/adapters/openai-responses.ts \
  src/providers/openai-sidecar.ts \
  src/server/live.ts \
  src/server/responses/compact.ts \
  tests/claude-messages-endpoint.test.ts \
  tests/codex-metadata-integrity.test.ts \
  tests/openai-responses-passthrough.test.ts \
  tests/passthrough-override.test.ts \
  tests/responses-compaction-routing.test.ts \
  tests/responses-custom-tool-repair.test.ts \
  tests/server-images.test.ts \
  tests/server-live.test.ts \
  tests/vision-sidecar-e2e.test.ts \
  tests/web-search.test.ts

echo '== Canonical-forward predicate and canonical-base references =='
rg -n -C 5 --glob '*.ts' \
  'CODEX_FORWARD_BASE_URL|isCanonical.*Codex|canonical.*Codex|is.*Forward.*Provider' \
  src

echo '== Response and sidecar URL construction contexts =='
rg -n -C 6 --glob '*.ts' \
  'new URL\(|/responses|/responses/compact|/realtime/calls|forwardLiveUrl|runWebSearch' \
  src/adapters src/providers src/server

Length of output: 192052


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base_sha="49887650eb2c7efa5c90996ec5108c8a7cfd129b"

echo '== Canonical provider predicate =='
nl -ba src/providers/openai-tiers.ts | sed -n '1,65p'

echo '== Forward request construction =='
nl -ba src/adapters/openai-responses.ts | sed -n '1200,1255p'

echo '== Sidecar selection and pinning =='
nl -ba src/providers/openai-sidecar.ts | sed -n '35,90p'

echo '== Native compact and live URL construction =='
nl -ba src/server/responses/compact.ts | sed -n '345,425p'
nl -ba src/server/live.ts | sed -n '155,180p'

echo '== Source-only PR diff =='
git diff --unified=25 "$base_sha...HEAD" -- \
  src/adapters/openai-responses.ts \
  src/providers/openai-sidecar.ts \
  src/server/responses/compact.ts \
  src/server/live.ts

echo '== Focused test changes =='
git diff --unified=22 "$base_sha...HEAD" -- \
  tests/openai-responses-passthrough.test.ts \
  tests/responses-compaction-routing.test.ts \
  tests/web-search.test.ts \
  tests/server-live.test.ts \
  tests/server-images.test.ts \
  tests/vision-sidecar-e2e.test.ts \
  tests/responses-custom-tool-repair.test.ts \
  tests/claude-messages-endpoint.test.ts \
  tests/codex-metadata-integrity.test.ts \
  tests/passthrough-override.test.ts

Length of output: 1609


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base_sha="49887650eb2c7efa5c90996ec5108c8a7cfd129b"

echo '== Canonical provider predicate =='
sed -n '1,65p' src/providers/openai-tiers.ts

echo '== Forward request construction =='
sed -n '1200,1255p' src/adapters/openai-responses.ts

echo '== Sidecar selection and pinning =='
sed -n '35,90p' src/providers/openai-sidecar.ts

echo '== Native compact and live URL construction =='
sed -n '345,425p' src/server/responses/compact.ts
sed -n '155,180p' src/server/live.ts

echo '== Source-only PR diff =='
git diff --unified=25 "$base_sha...HEAD" -- \
  src/adapters/openai-responses.ts \
  src/providers/openai-sidecar.ts \
  src/server/responses/compact.ts \
  src/server/live.ts

echo '== Focused test changes =='
git diff --unified=22 "$base_sha...HEAD" -- \
  tests/openai-responses-passthrough.test.ts \
  tests/responses-compaction-routing.test.ts \
  tests/web-search.test.ts \
  tests/server-live.test.ts \
  tests/server-images.test.ts \
  tests/vision-sidecar-e2e.test.ts \
  tests/responses-custom-tool-repair.test.ts \
  tests/claude-messages-endpoint.test.ts \
  tests/codex-metadata-integrity.test.ts \
  tests/passthrough-override.test.ts

Length of output: 74725


@github-actions[bot] Review complete for ready head 787db40d9411388b00c24a634f754e121a1f643c.

I found no new blocker.

The implementation now applies the canonical destination predicate before it forwards caller credentials, enforces pool-account availability, or applies runtime account overrides in src/adapters/openai-responses.ts.

Noncanonical forward providers retain only configured static headers. They do not receive caller bearer tokens, ChatGPT account IDs, session metadata, or pool credentials.

The canonical URL is pinned for Responses, sidecars, compact requests, and downstream image, vision, web-search, and live paths. The focused tests cover these paths and the trailing-slash variants.

The PR gate is complete, and GitHub reports the required gate checks as successful. I did not execute tests in this restricted inspection sandbox.

To approve through CodeRabbit, post the explicit top-level command: @coderabbitai approve.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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/adapters/openai-responses.ts (1)

579-640: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add regression tests for batch normalization.

Lines 579-640 change request ordering when requiresAdjacentResponsesToolResults is enabled. Add adapter coverage for a reasoning turn with parallel calls, an interleaved non-tool item, and ordered outputs. Assert that the result is calls → outputs → intervening item. Add cases that leave duplicate, missing, backward, and reversed outputs unchanged.

As per path instructions, “A behavior change in src/ should come with a focused regression test near the existing tests for that subsystem.”

🤖 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/adapters/openai-responses.ts` around lines 579 - 640, Add focused
regression tests near the existing OpenAI Responses adapter tests for
requiresAdjacentResponsesToolResults: verify a reasoning turn with parallel
calls, an interleaved non-tool item, and ordered outputs normalizes to calls →
outputs → intervening item. Also verify duplicate, missing, backward, and
reversed output mappings return the original input unchanged.

Source: Path instructions

🤖 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/adapters/openai-responses.ts`:
- Around line 579-640: Add focused regression tests near the existing OpenAI
Responses adapter tests for requiresAdjacentResponsesToolResults: verify a
reasoning turn with parallel calls, an interleaved non-tool item, and ordered
outputs normalizes to calls → outputs → intervening item. Also verify duplicate,
missing, backward, and reversed output mappings return the original input
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 74b95024-1d20-4939-8a3c-7d31088e180f

📥 Commits

Reviewing files that changed from the base of the PR and between 8abf036 and 787db40.

📒 Files selected for processing (5)
  • src/adapters/openai-responses.ts
  • tests/claude-messages-endpoint.test.ts
  • tests/openai-responses-passthrough.test.ts
  • tests/responses-custom-tool-repair.test.ts
  • tests/web-search.test.ts

@luvs01
luvs01 requested a review from Wibias August 12, 2026 04:36

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-review on current head 787db40d9411388b00c24a634f754e121a1f643c.

The earlier credential-boundary blockers are fixed on this head. Dynamic caller/pool credentials are gated on the canonical ChatGPT Codex destination, canonical trailing-slash variants are pinned before endpoint construction, _codexAccountRequired is now gated on that same canonical boundary, and the previously failing canonical metadata/custom-tool regressions have been updated. I did not find a new code blocker in the current diff. The later CodeRabbit batch-normalization note is outside this PR's behavioral change and comes from base history, not this credential patch.

The remaining blocker is integration. This head is now 10 commits behind current dev@70d2e175 after #1464 merged, with overlap in tests/claude-messages-endpoint.test.ts. Exact-head Cross-platform CI and React Doctor are action_required, and the Cross-platform run executed zero jobs.

Please rebase onto current dev and obtain an executed exact-head CI signal, then request re-review. No additional credential-scope changes are requested from my review.

@luvs01
luvs01 force-pushed the agent/pin-forwarded-codex-credentials branch from 787db40 to fa87583 Compare August 12, 2026 05:21
@github-actions
github-actions Bot marked this pull request as draft August 12, 2026 05:22
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@github-actions[bot] The readiness gate is complete for reviewed head 787db40d9411388b00c24a634f754e121a1f643c.

The checklist and hygiene checks passed. The prior review found no remaining code blocker on this head.

Post @coderabbitai approve as a top-level PR comment to request approval.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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.

Inline comments:
In `@tests/claude-messages-endpoint.test.ts`:
- Around line 653-660: Update the fetch shim around the canonical Codex routing
condition to fail closed for any request whose origin is https://chatgpt.com and
whose pathname is not exactly /backend-api/codex/responses: reject it instead of
passing it to originalFetch. Preserve the existing rewrite for the exact
canonical path and normal passthrough for non-canonical origins.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0e0b3036-01a7-4deb-9ea1-13cad4398394

📥 Commits

Reviewing files that changed from the base of the PR and between 787db40 and fa87583.

📒 Files selected for processing (1)
  • tests/claude-messages-endpoint.test.ts

Comment thread tests/claude-messages-endpoint.test.ts
@Wibias
Wibias marked this pull request as ready for review August 12, 2026 05:58
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
previous_head="fa87583f243e3ae5bac073572a81a76f897b713c"
current_head="80aeb36aa0d0f55276f4f42132f14ae71925db14"

echo '== Current PR metadata and checks =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,headRefOid,baseRefOid,reviewDecision,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    baseRefOid,
    reviewDecision,
    checks: [.statusCheckRollup[]? | {name, status, conclusion}]
  }'

echo '== Head relationship =='
git merge-base --is-ancestor "$previous_head" "$current_head" \
  && echo 'previous_head_is_ancestor=true' \
  || echo 'previous_head_is_ancestor=false'
git merge-base --is-ancestor "$current_head" HEAD \
  && echo 'current_head_is_checked_out=true' \
  || echo 'current_head_is_checked_out=false'

echo '== Commits after the previous reviewed head =='
git log --oneline "${previous_head}..${current_head}"

echo '== Changed files after the previous reviewed head =='
git diff --name-status "${previous_head}..${current_head}"

echo '== Incremental diff =='
git diff --find-renames --find-copies --unified=60 "${previous_head}..${current_head}"

Length of output: 10325


@github-actions[bot] I reviewed the incremental change on head 80aeb36aa0d0f55276f4f42132f14ae71925db14.

No code blocker was introduced. tests/claude-messages-endpoint.test.ts now rejects every canonical https://chatgpt.com path except /backend-api/codex/responses. This test fails if a future change routes a native Codex request to another canonical path.

The READY message is premature. GitHub currently shows these checks as IN_PROGRESS on the same head:

  • test 1/4 through test 4/4
  • gates
  • macos
  • keyring ubuntu
  • keyring windows
  • several npm-global jobs

GitHub also reports CHANGES_REQUESTED. Do not approve until the required checks complete successfully on 80aeb36aa0d0f55276f4f42132f14ae71925db14.

I used the existing readiness-gate guidance: readiness status must correspond to the exact PR head.


🧠 Learnings used
Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
previous_head="fa87583f243e3ae5bac073572a81a76f897b713c"
gate_head="80aeb36aa0d0f55276f4f42132f14ae71925db14"

echo '== Current PR state and checks =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,headRefOid,baseRefOid,reviewDecision,statusCheckRollup,labels \
  --jq '{
    state,
    isDraft,
    headRefOid,
    baseRefOid,
    reviewDecision,
    labels: [.labels[].name],
    checks: [.statusCheckRollup[]? | {name, status, conclusion}]
  }'

echo '== Gate head availability and ancestry =='
git cat-file -e "${gate_head}^{commit}"
git merge-base --is-ancestor "$previous_head" "$gate_head" \
  && echo 'previous_head_is_ancestor_of_gate_head=true' \
  || echo 'previous_head_is_ancestor_of_gate_head=false'
git merge-base --is-ancestor "$gate_head" HEAD \
  && echo 'gate_head_is_checked_out=true' \
  || echo 'gate_head_is_checked_out=false'

echo '== Commits after previous reviewed head =='
git log --oneline "${previous_head}..${gate_head}"

echo '== Changed files after previous reviewed head =='
git diff --name-status "${previous_head}..${gate_head}"

echo '== Changed TypeScript outlines =='
git diff --name-only "${previous_head}..${gate_head}" -- '*.ts' |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

echo '== Incremental diff =='
git diff --find-renames --find-copies --unified=60 "${previous_head}..${gate_head}"

Length of output: 12968


@github-actions[bot] I reviewed current head 80aeb36aa0d0f55276f4f42132f14ae71925db14.

I found no new code blocker.

tests/claude-messages-endpoint.test.ts now rejects every https://chatgpt.com request except /backend-api/codex/responses. This test fails closed if a future change sends Codex credentials to an unexpected canonical path.

GitHub still reports these checks as IN_PROGRESS:

  • test 1/4 through test 4/4
  • gates
  • macos
  • keyring windows
  • npm-global windows-latest

Do not approve until these checks complete successfully.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@Wibias Wibias left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-review on current head fa87583f243e3ae5bac073572a81a76f897b713c against current dev@bd5bc566d33f37682ffbf636e909243ba388caca.

The production credential-boundary changes still look correct. I re-checked the security-sensitive path rather than relying on the previous review:

  • isCanonicalOpenAiForwardProvider() rejects userinfo, query, fragment, wrong origin/path, and only accepts the normalized canonical ChatGPT Codex destination.
  • Caller FORWARD_HEADERS, _codexAccountOverride, and the _codexAccountRequired invariant are all gated on that canonical destination.
  • Canonical trailing-slash variants are pinned to CODEX_FORWARD_BASE_URL before credential-bearing Responses/sidecar/compact endpoint construction.
  • Noncanonical forward providers keep only their explicitly configured static headers and URL; caller and runtime Codex credentials are not injected.
  • Native compact only resolves/forwards Codex account credentials inside supportsNativeResponsesCompactEndpoint(), so arbitrary Responses-shaped gateways do not reach that credential-bearing branch.

I did not find a new production auth/security blocker in the current patch.

The new unresolved CodeRabbit thread in tests/claude-messages-endpoint.test.ts is valid test-harness hardening: the fetch shim should fail closed for unexpected https://chatgpt.com/backend-api/codex/* paths instead of falling through to the real network. I do not treat the current fixture as evidence of a production credential leak—the test uses an isolated CODEX_HOME and this request does not carry a real bearer—but the regression harness should still never permit accidental external ChatGPT requests.

Two merge blockers remain:

  1. Rebase/integration: this head is ahead 1 / behind 10 current dev, with merge-base d6673675. Since that base, dev changed overlapping/adjacent surfaces including src/server/responses/compact.ts, tests/claude-messages-endpoint.test.ts, tests/responses-compaction-routing.test.ts, and tests/web-search.test.ts. Please rebase and preserve both this credential boundary and the newer dev behavior.
  2. Exact-head CI is not green: React Doctor run 31566300187 succeeded. Cross-platform run 31566300191 executed substantially and the gates/typecheck/privacy plus all four Linux test shards succeeded, but the workflow ultimately concluded cancelled; macOS and npm-global Windows were cancelled and the final ci aggregation job failed because not every required job completed successfully. Please obtain a complete green run on the rebased head.

The older batch-normalization CodeRabbit note remains outside this PR's credential change and is not a blocker from my review.

@Wibias
Wibias marked this pull request as draft August 12, 2026 06:01
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

gh pr view 1471 --repo lidge-jun/opencodex \
  --json state,isDraft,headRefOid,reviewDecision,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    reviewDecision,
    checks: [
      .statusCheckRollup[]? |
      {
        name,
        status,
        conclusion,
        isRequired: (.isRequired // null)
      }
    ]
  }'

Length of output: 4308


@github-actions[bot] The READY comment references the current head 80aeb36aa0d0f55276f4f42132f14ae71925db14.

I cannot approve yet.

  • The PR is still a draft.
  • GitHub reports CHANGES_REQUESTED.
  • test 2/4 is IN_PROGRESS.
  • macos is IN_PROGRESS.

The completed checks, including gates and hygiene, report success. Mark the PR ready for review and wait for test 2/4 and macos to complete successfully on this same head.


🧠 Learnings used
Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@luvs01
luvs01 force-pushed the agent/pin-forwarded-codex-credentials branch from 80aeb36 to cd5b3b7 Compare August 12, 2026 07:02
@luvs01
luvs01 requested a review from Wibias August 12, 2026 07:02
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

gh pr view 1471 --repo lidge-jun/opencodex \
  --json state,isDraft,headRefOid,reviewDecision,labels,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    reviewDecision,
    labels: [.labels[].name],
    checks: [
      .statusCheckRollup[]? |
      {
        name,
        status,
        conclusion,
        isRequired: (.isRequired // null)
      }
    ]
  }'

Length of output: 1038


🏁 Script executed:

#!/bin/bash
set -euo pipefail

previous_head="80aeb36aa0d0f55276f4f42132f14ae71925db14"
current_head="cd5b3b766dd2c713804963babfb3ba60976b05b1"

echo '== Head ancestry =='
git cat-file -e "${previous_head}^{commit}"
git cat-file -e "${current_head}^{commit}"
git merge-base --is-ancestor "$previous_head" "$current_head" \
  && echo 'previous_head_is_ancestor=true' \
  || echo 'previous_head_is_ancestor=false'

echo '== Commits after the gate-completed head =='
git log --oneline "${previous_head}..${current_head}"

echo '== Changed files after the gate-completed head =='
git diff --name-status "${previous_head}..${current_head}"

echo '== Changed TypeScript outlines =='
git diff --name-only "${previous_head}..${current_head}" -- '*.ts' |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

echo '== Incremental diff =='
git diff --find-renames --find-copies --unified=70 "${previous_head}..${current_head}"

Length of output: 104589


🏁 Script executed:

#!/bin/bash
set -euo pipefail

previous_head="80aeb36aa0d0f55276f4f42132f14ae71925db14"
current_head="cd5b3b766dd2c713804963babfb3ba60976b05b1"

echo '== Incremental commits =='
git log --format='%H%n%s%n%b%n---' "${previous_head}..${current_head}"

echo '== Incremental diff statistics =='
git diff --stat "${previous_head}..${current_head}"
git diff --shortstat "${previous_head}..${current_head}"

echo '== Changed production files =='
git diff --name-status "${previous_head}..${current_head}" -- src

echo '== Changed workflow and package files =='
git diff --name-status "${previous_head}..${current_head}" -- .github package.json bun.lockb

echo '== Outlines of changed production files =='
git diff --name-only "${previous_head}..${current_head}" -- src |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

Length of output: 98372


@github-actions[bot] I cannot approve this PR.

The READY gate is stale. It completed at head 80aeb36aa0d0f55276f4f42132f14ae71925db14. GitHub now reports head cd5b3b766dd2c713804963babfb3ba60976b05b1.

The current head adds 12 commits after the gate-completed head. It changes 76 files with 3,482 additions and 211 deletions. The changes include local management authorization, direct local HTTP transport, reasoning replay identity, OAuth account handling, Codex usage attribution, request logging, and CLI diagnostics.

The PR is still a draft. GitHub reports CHANGES_REQUESTED. The review-ready label is absent. GitHub lists only resolve-pr, label, hygiene, and enforce-target as successful. It does not list the test and platform workflows for the current head.

Mark the PR ready for review. Run the required checks on cd5b3b766dd2c713804963babfb3ba60976b05b1. Request a complete review of the new changes after the checks succeed.


🧠 Learnings used
Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@github-actions
github-actions Bot marked this pull request as ready for review August 12, 2026 07:11
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

gh pr view 1471 --repo lidge-jun/opencodex \
  --json state,isDraft,headRefOid,reviewDecision,labels,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    reviewDecision,
    labels: [.labels[].name],
    checks: [
      .statusCheckRollup[]? |
      {
        name,
        status,
        conclusion,
        isRequired: (.isRequired // null)
      }
    ]
  }'

Length of output: 1369


@github-actions[bot] The readiness gate applies to the current head cd5b3b766dd2c713804963babfb3ba60976b05b1.

The PR is open, not a draft, and has the review-ready label.

GitHub still reports CHANGES_REQUESTED. The visible check rollup shows successful gate and hygiene checks, but it does not show the test or platform workflows. I cannot verify those workflow results from the current rollup.

The current head also requires a complete code review before approval.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/server/responses/core.ts:2311-2313
Timestamp: 2026-08-10T09:11:23.594Z
Learning: In `src/server/responses/core.ts`, routed custom-tool restoration is enabled only for non-forward passthrough providers because `routedCustomToolNames` is empty for forward-auth requests. Therefore, `createGithubCopilotResponsesBlockRewrite` cannot coexist with `createRoutedCustomToolRestoreBlockRewrite`. In `src/server/responses-snapshot-repair.ts`, snapshot repair only synthesizes closure events for `message` and `reasoning` items and does not synthesize function or custom-tool lifecycles.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@luvs01
luvs01 force-pushed the agent/pin-forwarded-codex-credentials branch from cd5b3b7 to 52fe372 Compare August 12, 2026 08:43
@github-actions
github-actions Bot marked this pull request as draft August 12, 2026 08:44
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
previous_head="80aeb36aa0d0f55276f4f42132f14ae71925db14"
current_head="cd5b3b766dd2c713804963babfb3ba60976b05b1"

echo '== PR state and checks =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,headRefOid,baseRefOid,reviewDecision,labels,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    baseRefOid,
    reviewDecision,
    labels: [.labels[].name],
    checks: [.statusCheckRollup[]? | {name,status,conclusion,isRequired}]
  }'

echo '== Head verification =='
git rev-parse HEAD
git cat-file -e "${previous_head}^{commit}"
git cat-file -e "${current_head}^{commit}"
git merge-base --is-ancestor "$previous_head" "$current_head" \
  && echo 'previous_head_is_ancestor=true' \
  || echo 'previous_head_is_ancestor=false'
git merge-base --is-ancestor "$current_head" HEAD \
  && echo 'current_head_is_checked_out=true' \
  || echo 'current_head_is_checked_out=false'

echo '== Incremental commits =='
git log --format='%H %s' "${previous_head}..${current_head}"

echo '== Incremental files =='
git diff --name-status "${previous_head}..${current_head}"

echo '== Changed production-file outlines =='
git diff --name-only "${previous_head}..${current_head}" -- src |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

echo '== Incremental production diff =='
git diff --find-renames --find-copies --unified=45 "${previous_head}..${current_head}" -- src

echo '== Incremental tests and workflow diff =='
git diff --find-renames --find-copies --unified=35 "${previous_head}..${current_head}" -- tests .github package.json bun.lockb

Length of output: 105522


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
previous_head="80aeb36aa0d0f55276f4f42132f14ae71925db14"
current_head="cd5b3b766dd2c713804963babfb3ba60976b05b1"

echo '== Current PR status and checks =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,headRefOid,reviewDecision,labels,statusCheckRollup \
  --jq '{
    state, isDraft, headRefOid, reviewDecision,
    labels: [.labels[].name],
    checks: [.statusCheckRollup[]? | {name,status,conclusion,isRequired}]
  }'

echo '== Changed production files =='
git diff --name-status "${previous_head}..${current_head}" -- src

echo '== Candidate source files =='
fd -t f . src | rg \
  'local-management-capability|local-management-attestation|management-auth|auth-cors|direct.*transport|local.*transport|reasoning-replay-cache|responses/core|openai-chat|request-log|usage/(log|summary)|account-label'

echo '== Local management capability implementation and uses =='
rg -n -C 8 \
  'LOCAL_MANAGEMENT_CAPABILITY|createLocalManagementReadCapability|verifyLocalManagementReadCapability|local-read-capability|LOCAL_MANAGEMENT_READ_PATHS' \
  src

echo '== Local direct transport implementation and uses =='
rg -n -C 8 \
  'attestationSecret|readRuntimePort|findLiveProxy|management.*fetch|managementHeaders|LOCAL_ATTESTATION|local management' \
  src/cli src/server src/lib

echo '== Reasoning replay cache implementation and scope binding =='
ast-grep outline src/responses/reasoning-replay-cache.ts --items all --view signatures
rg -n -C 8 \
  'reasoningReplay(Key|OAuth|Codex)CredentialIdentity|reasoningReplayDestinationIdentity|bindReasoningReplayScope|_reasoningReplayScope' \
  src

echo '== Focused implementation diffs =='
git diff --unified=50 "${previous_head}..${current_head}" -- \
  src/lib/local-management-capability.ts \
  src/server/management-auth.ts \
  src/server/auth-cors.ts \
  src/responses/reasoning-replay-cache.ts \
  src/server/responses/core.ts \
  src/adapters/openai-chat.ts \
  src/server/request-log.ts \
  src/usage/log.ts \
  src/usage/summary.ts \
  src/codex/account-label.ts

Length of output: 111230


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Local capability module outline =='
ast-grep outline src/lib/local-management-capability.ts --items all --view expanded

echo '== Local capability module =='
cat -n src/lib/local-management-capability.ts

echo '== Management authentication enforcement =='
rg -n -C 16 \
  'local-read-capability|verifyLocalManagementReadCapability|requireManagementAuth|managementPrincipal' \
  src/server/management-auth.ts src/server/auth-cors.ts

echo '== CLI capability generation and management request transport =='
rg -n -C 16 \
  'createLocalManagementReadCapability|LOCAL_MANAGEMENT_READ_PATHS|readRuntimePortImpl|attestationSecret|managementHeaders|management.*fetch' \
  src/cli

echo '== Terminal continuation variable and bridge context =='
rg -n -C 20 \
  'nextParsed|fetchTerminalGuardContinuation|bindRouteReasoningReplayScope\(|replayCacheScope:' \
  src/server/responses/core.ts

echo '== Replay cache module =='
cat -n src/responses/reasoning-replay-cache.ts

echo '== Account label source and request-log serialization =='
cat -n src/codex/account-label.ts
rg -n -C 12 \
  'accountLogLabel|sealRequestAttemptIdentity|addFinalRequestLog|requestLogErrorCode' \
  src/server/request-log.ts src/server/responses/core.ts

Length of output: 120789


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Terminal guard implementation =='
ast-grep outline src/server/responses/terminal-guard.ts --items all --view expanded
cat -n src/server/responses/terminal-guard.ts

echo '== Parsed request type and copy sites =='
rg -n -C 12 \
  'OcxReasoningReplayScopeRef|_reasoningReplayScope|structuredClone\(.*parsed|\.{3}parsed|Object\.assign\(.*parsed|nextParsed' \
  src tests

echo '== OpenAI Chat replay lookup =='
rg -n -C 18 \
  'peekReasoningForCall|_reasoningReplayScope|reasoning_content|tool_calls' \
  src/adapters/openai-chat.ts

echo '== Existing terminal-continuation tests =='
rg -n -C 12 \
  'terminal.*continuation|terminal guard|end_turn|key-429|reasoning.*replay' \
  tests

Length of output: 197602


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Terminal guard source =='
cat -n src/server/responses/terminal-guard.ts

echo '== Terminal continuation failover test =='
sed -n '125,180p' tests/terminal-guard-server.test.ts

echo '== Current head and check rollup =='
gh pr view 1471 --repo lidge-jun/opencodex \
  --json headRefOid,state,isDraft,reviewDecision,labels,statusCheckRollup \
  --jq '{
    headRefOid, state, isDraft, reviewDecision,
    labels: [.labels[].name],
    checks: [.statusCheckRollup[]? | {name,status,conclusion,isRequired}]
  }'

Length of output: 16067


@github-actions[bot] I cannot approve this PR.

The READY gate completed at cd5b3b766dd2c713804963babfb3ba60976b05b1.

GitHub now reports head 52fe372c0e354af2082a9fa503483054aeb8c786.

The PR is also a draft. GitHub reports CHANGES_REQUESTED. The review-ready label is absent.

The current check rollup shows only resolve-pr, label, hygiene, and enforce-target. It does not show test or platform workflow results for the current head.

I reviewed the local management capability implementation. It binds the capability to the exact GET path, PID, port, expiry, and a one-time HMAC. I found no blocker in that path. I also verified that terminal-continuation requests share the same reasoning replay scope holder.

Mark the PR ready for review. Run the required checks on 52fe372c0e354af2082a9fa503483054aeb8c786. Then request a complete review of the current diff.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@github-actions
github-actions Bot marked this pull request as ready for review August 12, 2026 08:46
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
gate_head="52fe372c0e354af2082a9fa503483054aeb8c786"

echo '== Pull request state and checks =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,headRefOid,baseRefOid,reviewDecision,labels,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    baseRefOid,
    reviewDecision,
    labels: [.labels[].name],
    checks: [
      .statusCheckRollup[]? |
      {name, status, conclusion, isRequired: (.isRequired // null)}
    ]
  }'

current_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq -r '.headRefOid')"

echo '== Head relationship =='
printf 'gate_head=%s\ncurrent_head=%s\n' "$gate_head" "$current_head"
git cat-file -e "${gate_head}^{commit}"
git cat-file -e "${current_head}^{commit}"
git merge-base --is-ancestor "$gate_head" "$current_head" \
  && echo 'gate_head_is_ancestor_of_current_head=true' \
  || echo 'gate_head_is_ancestor_of_current_head=false'

echo '== Commits after gate-completed head =='
git log --oneline "${gate_head}..${current_head}"

echo '== Changed files after gate-completed head =='
git diff --name-status "${gate_head}..${current_head}"

echo '== Changed source outlines =='
git diff --name-only "${gate_head}..${current_head}" -- 'src/**/*.ts' |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

echo '== Incremental source and test diff =='
git diff --find-renames --find-copies --unified=50 "${gate_head}..${current_head}" -- src tests

Length of output: 2811


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
head="52fe372c0e354af2082a9fa503483054aeb8c786"

echo '== Workflow runs for the exact head =='
gh run list --repo "$repo" --commit "$head" --limit 100 \
  --json databaseId,name,workflowName,status,conclusion,event,headSha,url,createdAt,updatedAt \
  --jq 'sort_by(.workflowName, .databaseId) | .[] | {
    databaseId,
    workflowName,
    name,
    status,
    conclusion,
    event,
    headSha,
    url,
    createdAt,
    updatedAt
  }'

echo '== Required workflow run summary =='
gh run list --repo "$repo" --commit "$head" --limit 100 \
  --json workflowName,status,conclusion \
  --jq 'group_by(.workflowName) | map({
    workflowName: .[0].workflowName,
    runs: map({status, conclusion})
  })'

echo '== Head and gate commit relationship =='
git rev-parse HEAD
git cat-file -e "${head}^{commit}"
git merge-base --is-ancestor "$head" HEAD \
  && echo 'gate_head_is_ancestor_of_checked_out_head=true' \
  || echo 'gate_head_is_ancestor_of_checked_out_head=false'

echo '== Commits after the gate-completed head =='
git log --oneline "${head}..HEAD"

Length of output: 4094


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
run_id="31579662202"
head="52fe372c0e354af2082a9fa503483054aeb8c786"

echo '== React Doctor run details =='
gh run view "$run_id" --repo "$repo" --json \
  databaseId,name,workflowName,status,conclusion,event,headSha,url,createdAt,updatedAt,jobs \
  --jq '{
    databaseId,
    workflowName,
    name,
    status,
    conclusion,
    event,
    headSha,
    url,
    createdAt,
    updatedAt,
    jobs: [
      .jobs[]? | {
        databaseId,
        name,
        status,
        conclusion,
        startedAt,
        completedAt,
        steps: [
          .steps[]? | {name, status, conclusion, number}
        ]
      }
    ]
  }'

echo '== Recent pull-request workflow runs =='
gh run list --repo "$repo" --branch "$(gh pr view "$pr" --repo "$repo" --json headRefName --jq '.headRefName')" --limit 100 \
  --json databaseId,workflowName,name,status,conclusion,event,headSha,createdAt,url \
  --jq '.[] | select(.event == "pull_request" or .event == "pull_request_target") | {
    databaseId,
    workflowName,
    name,
    status,
    conclusion,
    event,
    headSha,
    createdAt,
    url
  }'

echo '== Workflow files that define test or platform jobs =='
fd -t f -e yml -e yaml .github/workflows -x sh -c \
  'if rg -n -i "test [1-4]/4|macos|keyring|npm-global|workflow_dispatch|pull_request" "$1" >/dev/null; then
     echo "--- $1"
     rg -n -i -C 2 "test [1-4]/4|macos|keyring|npm-global|workflow_dispatch|pull_request" "$1"
   fi' sh {}

Length of output: 30852


@github-actions[bot] The readiness gate applies to the current head 52fe372c0e354af2082a9fa503483054aeb8c786. No commits were added after the gate-completed head.

I cannot confirm full CI success from GitHub Actions.

  • Enforce PR target branch, PR Labeler, and PR hygiene succeeded.
  • React Doctor run 31579662202 completed with action_required and no job details.
  • GitHub Actions shows no Cross-platform CI, test-shard, or platform workflow run for this head.

A maintainer must resolve or explain the React Doctor status and the missing CI workflow runs before approval. I used the existing readiness-gate guidance: readiness must correspond to the exact PR head.

I will complete a review of the current head.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/server/responses/core.ts:2311-2313
Timestamp: 2026-08-10T09:11:23.594Z
Learning: In `src/server/responses/core.ts`, routed custom-tool restoration is enabled only for non-forward passthrough providers because `routedCustomToolNames` is empty for forward-auth requests. Therefore, `createGithubCopilotResponsesBlockRewrite` cannot coexist with `createRoutedCustomToolRestoreBlockRewrite`. In `src/server/responses-snapshot-repair.ts`, snapshot repair only synthesizes closure events for `message` and `reasoning` items and does not synthesize function or custom-tool lifecycles.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@luvs01
luvs01 force-pushed the agent/pin-forwarded-codex-credentials branch from 52fe372 to 875a694 Compare August 12, 2026 08:51
@github-actions
github-actions Bot marked this pull request as draft August 12, 2026 08:51
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
gate_head="52fe372c0e354af2082a9fa503483054aeb8c786"
previous_reviewed_head="80aeb36aa0d0f55276f4f42132f14ae71925db14"

echo '== PR state and status checks =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,headRefOid,baseRefOid,reviewDecision,labels,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    baseRefOid,
    reviewDecision,
    labels: [.labels[].name],
    checks: [.statusCheckRollup[]? | {name,status,conclusion,isRequired}]
  }'

current_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq -r .headRefOid)"
printf '\n== Head verification ==\ngate_head=%s\ncurrent_head=%s\n' "$gate_head" "$current_head"
git merge-base --is-ancestor "$gate_head" "$current_head" \
  && echo 'gate_head_is_ancestor_of_current_head=true' \
  || echo 'gate_head_is_ancestor_of_current_head=false'

echo '== Commits after prior reviewed head =='
git log --oneline "${previous_reviewed_head}..${current_head}"

echo '== Full changed-file list after prior reviewed head =='
git diff --name-status "${previous_reviewed_head}..${current_head}"

echo '== Changed source outlines =='
git diff --name-only "${previous_reviewed_head}..${current_head}" -- 'src/**/*.ts' |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

echo '== Full production diff after prior reviewed head =='
git diff --find-renames --find-copies --unified=40 \
  "${previous_reviewed_head}..${current_head}" -- src

echo '== Full test and workflow diff after prior reviewed head =='
git diff --find-renames --find-copies --unified=35 \
  "${previous_reviewed_head}..${current_head}" -- tests .github package.json bun.lockb

echo '== Workflow runs for the current head =='
gh run list --repo "$repo" --commit "$current_head" --limit 100 \
  --json databaseId,workflowName,status,conclusion,event,headSha,url \
  --jq 'sort_by(.workflowName, .databaseId) | .[] | {databaseId,workflowName,status,conclusion,event,headSha,url}'

Length of output: 3052


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
gate_head="52fe372c0e354af2082a9fa503483054aeb8c786"
current_head="875a694f473ec6403130f5ab73185560679c6823"

echo '== Head graph =='
git log --oneline --decorate -25 "$current_head"
echo '== Commit range after gate head =='
git log --format='%H%n%s%n%b%n---' "${gate_head}..${current_head}"

echo '== Changed files after gate head =='
git diff --name-status "${gate_head}..${current_head}"
git diff --stat "${gate_head}..${current_head}"

echo '== Changed production files and outlines =='
git diff --name-only "${gate_head}..${current_head}" -- src |
  while IFS= read -r file; do
    echo "--- $file"
    ast-grep outline "$file" --items all --view signatures || true
  done

echo '== Incremental production diff =='
git diff --find-renames --find-copies --unified=50 \
  "${gate_head}..${current_head}" -- src

echo '== Incremental tests, workflows, and package diff =='
git diff --find-renames --find-copies --unified=40 \
  "${gate_head}..${current_head}" -- tests .github package.json bun.lockb

echo '== Workflow runs for the current head =='
gh run list --repo "$repo" --commit "$current_head" --limit 100 \
  --json databaseId,workflowName,status,conclusion,event,headSha,url,createdAt,updatedAt \
  --jq 'sort_by(.workflowName, .databaseId) | .[] | {databaseId,workflowName,status,conclusion,event,headSha,url,createdAt,updatedAt}'

Length of output: 17381


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"

echo '== Current changed workflow lines =='
nl -ba .github/workflows/release.yml | sed -n '135,195p'

echo '== Current changed test lines =='
nl -ba tests/ci-workflows.test.ts | sed -n '585,640p'

for run_id in 31580237649 31580237765; do
  echo "== Workflow run ${run_id} =="
  gh run view "$run_id" --repo "$repo" \
    --json databaseId,workflowName,status,conclusion,event,headSha,url,jobs \
    --jq '{
      databaseId,
      workflowName,
      status,
      conclusion,
      event,
      headSha,
      url,
      jobs: [
        .jobs[]? | {
          name,
          status,
          conclusion,
          startedAt,
          completedAt,
          steps: [.steps[]? | {name,status,conclusion}]
        }
      ]
    }' || true
done

echo '== Check suite details for the current head =='
gh api "repos/lidge-jun/opencodex/commits/875a694f473ec6403130f5ab73185560679c6823/check-suites" \
  --jq '.check_suites[] | {app: .app.slug, status, conclusion, head_sha, url: .url}' || true

Length of output: 1434


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"

echo '== Current changed workflow lines =='
awk 'NR >= 135 && NR <= 195 { printf "%6d  %s\n", NR, $0 }' .github/workflows/release.yml

echo '== Current changed test lines =='
awk 'NR >= 585 && NR <= 640 { printf "%6d  %s\n", NR, $0 }' tests/ci-workflows.test.ts

for run_id in 31580237649 31580237765; do
  echo "== Workflow run ${run_id} =="
  gh run view "$run_id" --repo "$repo" \
    --json databaseId,workflowName,status,conclusion,event,headSha,url,jobs \
    --jq '{
      databaseId,
      workflowName,
      status,
      conclusion,
      event,
      headSha,
      url,
      jobs: [
        .jobs[]? | {
          name,
          status,
          conclusion,
          startedAt,
          completedAt,
          steps: [.steps[]? | {name,status,conclusion}]
        }
      ]
    }' || true
done

echo '== Check suites for the current head =='
gh api "repos/lidge-jun/opencodex/commits/875a694f473ec6403130f5ab73185560679c6823/check-suites" \
  --jq '.check_suites[] | {app: .app.slug, status, conclusion, head_sha, url: .url}' || true

Length of output: 10167


@github-actions[bot] Review complete for current head 875a694f473ec6403130f5ab73185560679c6823.

I found no code blocker in the incremental diff.

In .github/workflows/release.yml, Lines 145-153 now filter the gh run list JSON results for conclusion == "success". This replaces the unsupported --status success argument. The change preserves the exact commit, branch, and push event constraints.

tests/ci-workflows.test.ts, Lines 595-617, verifies the new filtering for both the Cross-platform CI lookup and the Service lifecycle lookup.

I used the existing readiness-gate guidance. The READY state is stale because it completed at 52fe372c0e354af2082a9fa503483054aeb8c786, not at the current head.

I cannot approve this PR yet.

  • Cross-platform CI run 31580237649 is action_required.
  • React Doctor run 31580237765 is action_required.
  • Both runs expose no job details through GitHub Actions.
  • GitHub previously reported this PR as a draft with CHANGES_REQUESTED.

A maintainer must resolve or explain both action_required runs. Run the required checks on 875a694f473ec6403130f5ab73185560679c6823. Then complete the readiness gate again for this exact head.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

@github-actions
github-actions Bot marked this pull request as ready for review August 12, 2026 08:53
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
pr="1471"
gate_head="875a694f473ec6403130f5ab73185560679c6823"

echo '== Pull request state and check rollup =='
gh pr view "$pr" --repo "$repo" \
  --json state,isDraft,headRefOid,baseRefOid,reviewDecision,labels,statusCheckRollup \
  --jq '{
    state,
    isDraft,
    headRefOid,
    baseRefOid,
    reviewDecision,
    labels: [.labels[].name],
    checks: [
      .statusCheckRollup[]? |
      {name, status, conclusion, isRequired: (.isRequired // null)}
    ]
  }'

echo '== Gate-head relationship =='
current_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq -r .headRefOid)"
printf 'gate_head=%s\ncurrent_head=%s\n' "$gate_head" "$current_head"
git cat-file -e "${gate_head}^{commit}"
git cat-file -e "${current_head}^{commit}"
git merge-base --is-ancestor "$gate_head" "$current_head" \
  && echo 'gate_head_is_ancestor_of_current_head=true' \
  || echo 'gate_head_is_ancestor_of_current_head=false'
git log --oneline "${gate_head}..${current_head}"

echo '== GitHub Actions runs for the gate head =='
gh run list --repo "$repo" --commit "$gate_head" --limit 100 \
  --json databaseId,workflowName,name,status,conclusion,event,headSha,url,createdAt,updatedAt \
  --jq 'sort_by(.workflowName, .databaseId) | .[] | {
    databaseId, workflowName, name, status, conclusion, event, headSha, url, createdAt, updatedAt
  }'

echo '== Check suites for the gate head =='
gh api "repos/${repo}/commits/${gate_head}/check-suites" \
  --jq '.check_suites[] | {
    app: .app.slug,
    status,
    conclusion,
    head_sha,
    url: .html_url
  }'

Length of output: 2905


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="lidge-jun/opencodex"
head="875a694f473ec6403130f5ab73185560679c6823"

echo '== GitHub Actions workflow runs for the exact head =='
gh run list --repo "$repo" --commit "$head" --limit 100 \
  --json databaseId,workflowName,name,status,conclusion,event,headSha,url,createdAt,updatedAt \
  --jq 'sort_by(.workflowName, .databaseId) | .[] | {
    databaseId,
    workflowName,
    name,
    status,
    conclusion,
    event,
    headSha,
    url,
    createdAt,
    updatedAt
  }' || true

echo '== Check suites for the exact head =='
gh api "repos/${repo}/commits/${head}/check-suites" \
  --jq '.check_suites[] | {
    app: .app.slug,
    status,
    conclusion,
    head_sha,
    url: .html_url
  }' || true

echo '== Check runs for the exact head =='
gh api "repos/${repo}/commits/${head}/check-runs?per_page=100" \
  --jq '.check_runs[] | {
    name,
    app: .app.slug,
    status,
    conclusion,
    details_url
  }' || true

Length of output: 5617


@github-actions[bot] The readiness gate applies to the current head 875a694f473ec6403130f5ab73185560679c6823.

I cannot approve the PR yet.

GitHub Actions reports two completed workflows with action_required on this exact head:

GitHub also reports CHANGES_REQUESTED.

The successful checks are limited to the target, label, hygiene, and resolve workflows. The API does not show successful test-shard or platform-job results for this head.

A maintainer must resolve or explain both action_required workflows before approval.


🧠 Learnings used
Learnt from: harryzhou2000
Repo: lidge-jun/opencodex PR: 0
File: :0-0
Timestamp: 2026-08-03T12:43:51.638Z
Learning: For PR `#865`, residual full-suite shard-2 failures in server-auth WebSocket upgrade/auth statuses, active-registry WebSocket test 129, Claude Messages 502-versus-503 handling, and OpenAI compact transport reproduced on both upstream/dev commit 6a7351b4 and pre-fix merge head 528b4550 under a loaded machine. Treat these failures as pre-existing environment flakes unless a later change provides contrary evidence.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/adapters/openai-responses.ts:1249-1251
Timestamp: 2026-08-10T09:09:40.785Z
Learning: In the TypeScript resolver `src/server/adapter-resolve.ts`, `resolveWireProtocolOverride()` changes only the provider `adapter` through a shallow copy and preserves `authMode`, credentials, and `baseUrl`. Reviews must not treat `route.provider.authMode` and the resolved adapter provider's `authMode` as divergent through this resolver.

Learnt from: Eleven-is-cool
Repo: lidge-jun/opencodex PR: 616
File: src/config.ts:499-549
Timestamp: 2026-07-29T02:47:48.815Z
Learning: In `src/router.ts`, registry-backed providers derive an effective `canonicalAuthMode` before request handling. For registry entries with `authKind` other than `forward` or `oauth` (including `openai-apikey`), a persisted `authMode: "forward"` is normalized to `undefined`; reviews of adapters must use this routed provider state rather than assume raw persisted `authMode` reaches the adapter.

Learnt from: baileyh8
Repo: lidge-jun/opencodex PR: 1361
File: src/server/responses/core.ts:2311-2313
Timestamp: 2026-08-10T09:11:23.594Z
Learning: In `src/server/responses/core.ts`, routed custom-tool restoration is enabled only for non-forward passthrough providers because `routedCustomToolNames` is empty for forward-auth requests. Therefore, `createGithubCopilotResponsesBlockRewrite` cannot coexist with `createRoutedCustomToolRestoreBlockRewrite`. In `src/server/responses-snapshot-repair.ts`, snapshot repair only synthesizes closure events for `message` and `reasoning` items and does not synthesize function or custom-tool lifecycles.

Learnt from: Wibias
Repo: lidge-jun/opencodex PR: 986
File: .github/workflows/enforce-pr-target.yml:631-636
Timestamp: 2026-08-04T06:41:30.089Z
Learning: For the PR readiness gate in `.github/workflows/enforce-pr-target.yml`, the required scope is to bind contributor checklist completion and maintainer notification to the exact PR head SHA, then reset them after a new head commit. Maintainer approval staleness is separate from this gate and should be enforced by GitHub branch protection, such as `dismiss-stale-reviews` or `require_last_push_approval`, when configured for `dev`.

You are interacting with an AI system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants