Skip to content

fix(server): allow alpha search on loopback listener - #3193

Closed
alan7629 wants to merge 1 commit into
lidge-jun:devfrom
alan7629:fix-alpha-search-loopback
Closed

alan7629 wants to merge 1 commit into
lidge-jun:devfrom
alan7629:fix-alpha-search-loopback

Conversation

@alan7629

@alan7629 alan7629 commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Problem:
Native Codex Web Search via the unauthenticated loopback listener fails with 404 Unknown endpoint. (Fixes #3192)

Root cause:
The /v1/alpha/search handler exists in src/server/index.ts but was omitted from the loopbackRouteAllowed() allowlist, causing the loopback listener to reject the request before it reaches the handler.

Fix:
Add /v1/alpha/search for POST method to loopbackRouteAllowed().

Tests:
Added a focused regression test in loopback-listener-integration.test.ts that ensures /v1/alpha/search passes the loopback admission gate (which then correctly fails inside the handler for missing ChatGPT auth instead of a generic 404).

Manual E2E evidence:
Native Codex Web Search changed from 404 to 200, successfully routing the upstream relay.

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.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

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

github-actions Bot commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (0/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 0/4).

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.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

Hygiene

✅ Deterministic PR hygiene checks passed.

@github-actions
github-actions Bot marked this pull request as draft September 1, 2026 17:52
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 71 / 80

지금 dev HEAD는 88c427522 이고 package.json은 2.40.0입니다. 제목은 feat(combo): adapt reasoning effort to target capabilities (#2731) (#3190)입니다. 인증 없이 켜 두는 루프백 리스너는 길을 기본으로 막습니다. src/server/index.ts 의 loopbackRouteAllowed 는 허용 목록에 없는 경로는 전부 404입니다. 지금 HEAD 792줄 근처에서 통과하는 것은 POST나 웹소켓 /v1/responses, POST /v1/responses/compact, GET /v1/models, 웹소켓 /v1/realtime 과 /v1/live 뿐입니다. /v1/alpha/search 는 없습니다.

공개 쪽 처리기는 이미 이 길을 알고 있습니다. 같은 파일 1647줄 근처에서 경로가 /v1/alpha/search 이고 메서드가 POST이면 handleSearch 로 보냅니다. 그 함수는 src/server/search.ts 에 있습니다. Codex가 직접 띄운 네이티브 웹 검색은 주입된 base_url, 곧 이 루프백으로 POST를 보냅니다. 허용 목록에 없어서 처리기에 닿기도 전에 404 Unknown endpoint가 납니다. 검색 중계가 실패한 것이 아니라, 문 앞에서 거절당한 것입니다.

이 PR이 하려는 고침은 한 줄입니다. loopbackRouteAllowed 안에 if (path === "/v1/alpha/search") return req.method === "POST"; 를 넣습니다. 공개 처리기가 이미 받는 길만 루프백에도 열어 주는 것입니다. 테스트 tests/loopback-listener-integration.test.ts 는 거부 목록에서 POST /v1/alpha/search 를 빼고, 공개 리스너는 여전히 opencodex API key required 로 401이 나고, 루프백은 그 문장이 아닌 401이 나는지 보는 새 테스트를 넣었습니다. 허용되면 404가 아니라 처리기 안의 실패가 나와야 한다는 뜻입니다.

다만 handleSearch 는 여전히 ChatGPT 포워드 제공자가 필요합니다. listOpenAiForwardSidecarCandidates 로 후보를 찾고, ChatGPT 인증이 없으면 401 web search relay needs ChatGPT auth (Authorization header) 를 돌립니다. 제공자 자체가 없으면 400으로, 라우트된 제공자나 API 키 제공자는 이 끝점을 못 받습니다. 이 PR은 이슈 #2730을 구현하지 않습니다. #2730은 ChatGPT 포워드 인증 없이 설정한 웹 검색 백엔드입니다. 허용 목록만 고치면, 예전처럼 가짜 404가 아니라 처리기가 내는 진짜 401이 보입니다. 그게 이 고침의 범위입니다.

머지를 막는 것은 그 한 줄이 아니라 파일 전체가 깨진 것입니다. src/server/index.ts 주석 수십 곳에서 유니코드 줄표가 ?? 로 바뀌었습니다. 시작 로그의 로켓, 경고, 자물쇠 이모지도 깨져서 ?? 나 이상한 글자가 되었습니다. 어떤 주석은 줄표가 있던 자리에서 두 줄이 한 줄로 붙기도 했습니다. 테스트 파일 주석에도 같은 ?? 가 있습니다. 이건 고침이 아니라 인코딩이 깨진 것입니다. HEAD의 바이트를 되돌리기 전에는 머지하면 안 됩니다. types.ts는 이미 나눠서 다시 내보내기만 하는 통이고, 이 PR은 types.ts/config.ts를 합치지 않으므로 close-don't-rebase 대상이 아닙니다.

이 PR은 alan7629의 초안이고 베이스는 dev 입니다. 체크리스트 네 칸이 전부 비어 있고 mergeStateStatus는 BLOCKED입니다. 이슈 #3192는 이미 닫혀 있습니다. 새 테스트는 같은 부정 검사를 두 번 적었고, search.ts 가 실제로 내는 문구는 한 번도 확인하지 않습니다. 들여쓰기도 WebSocket 테스트 옆에 깨져 붙어 있습니다.

src/server/index.ts:281 - 유니코드 줄표가 ?? 로 깨진 문제입니다. 이 파일 주석 수십 곳이 같은 방식으로 깨졌고, 어떤 곳은 두 줄이 한 줄로 붙었습니다. 의도한 고침이 아닙니다.
src/server/index.ts:2274 - 시작 로그의 로켓 이모지가 ?? 로 깨진 문제입니다. 2286줄 경고와 2294줄 자물쇠도 깨졌습니다. 주석 바이트를 HEAD와 같게 되돌리기 전에는 머지하면 안 됩니다.
tests/loopback-listener-integration.test.ts:399 - opencodex API key required 가 아니라는 검사를 400줄에서 한 번 더 반복한 문제입니다. 같은 문장이 두 번입니다.
tests/loopback-listener-integration.test.ts:399 - search.ts 가 실제로 내는 메시지(web search relay needs ChatGPT auth (Authorization header) 또는 포워드 제공자가 없을 때의 400 문구)를 한 번도 확인하지 않는 문제입니다. 부정 검사만 있으면 다른 401도 통과합니다.
tests/loopback-listener-integration.test.ts:376 - 새 테스트가 앞 테스트 다음에 들여쓰기가 깨진 채 붙어 있고, 405줄 WebSocket 테스트도 같은 자리로 밀린 문제입니다. describe 블록 정리가 깨져 보입니다.
PR 본문 체크리스트 - 네 칸이 전부 비어 있고, 초안이며 mergeStateStatus는 BLOCKED인 문제입니다.

메인테이너의 판단이 필요한 지점

  • 인코딩이 깨진 초안을 지금 머지할지, 주석과 로그를 HEAD와 같게 되돌린 뒤에 머지할지 정해야 합니다. 허용 목록 한 줄은 맞습니다.
  • ChatGPT 포워드 없이 설정한 웹 검색 백엔드([Feature]: Allow /v1/alpha/search to use a configured web-search backend without ChatGPT forward auth #2730)를 이 고침 다음에 따로 할지 정해야 합니다. 이 PR의 범위가 아닙니다.
  • 이미 닫힌 #3192에 더 손댈 일이 있는지 정해야 합니다. 지금은 닫혀 있고, 이 PR이 그 404만 고칩니다.

너의 추천
지금 상태로 머지하지 마세요. 주석과 로그 바이트를 HEAD와 같게 되돌리고, 허용 목록 한 줄과 거부 목록에서 빼는 테스트는 남기세요. 루프백 401은 search.ts 가 내는 실제 문구를 검사하고, 같은 부정 검사는 한 번만 남기세요. 들여쓰기를 고치고 체크리스트 네 칸을 채운 뒤에 머지하면 됩니다. types.ts/config.ts 분리는 이 PR에 해당하지 않습니다.

이 댓글은 grok-bot이 작성했습니다

lidge-jun added a commit that referenced this pull request Sep 1, 2026
)

The unauthenticated loopback listener admits routes through an allowlist
in loopbackRouteAllowed(). /v1/alpha/search - the native Codex web-search
relay - was never on it, so a directly-spawned codex app-server got 404
for every web search (#3192).

Admit POST on that path. The handler runs its own admission
(resolveApiAuth + validateForwardAdmissionCredential), so a loopback
caller without a ChatGPT credential is still refused inside the relay;
only the listener's 404 goes away. The public listener is unchanged.

Clean reimplementation of #3193, whose branch was byte-corrupted by an
encoding round-trip (em-dashes and emoji in ~30 unrelated comment lines).

Supersedes #3193. Fixes #3192.

Co-authored-by: jun <jun@lidge.dev>
Co-authored-by: alan7629 <alan7629@gmail.com>
@lidge-jun

Copy link
Copy Markdown
Owner

Thanks @alan7629 — the diagnosis and the fix were exactly right. The branch itself could not be merged as-is: an encoding round-trip rewrote every em-dash to ?? and the warning emoji to mojibake across ~30 unrelated comment lines in src/server/index.ts and the test file, and the new test carried a duplicated expect.

Rather than ask for another round, I landed a clean reimplementation with you credited as co-author: #3205 → 53c09a247 on dev. Same one-line allowlist change, a focused test for POST /v1/alpha/search on the loopback listener, and the docs-site allowlist paragraph updated. #3192 is resolved by that commit.

Closing this PR in favour of #3205. If your editor writes files in a non-UTF-8 code page, setting it to UTF-8 (no BOM) will keep future PRs clean.

@lidge-jun lidge-jun closed this Sep 1, 2026
@lidge-jun lidge-jun added the landed-via-maintainer Original PR closed after landing via a maintainer merge train label Sep 1, 2026
tarunravi pushed a commit to tarunravi/opencodex that referenced this pull request Sep 14, 2026
…dge-jun#3205)

The unauthenticated loopback listener admits routes through an allowlist
in loopbackRouteAllowed(). /v1/alpha/search - the native Codex web-search
relay - was never on it, so a directly-spawned codex app-server got 404
for every web search (lidge-jun#3192).

Admit POST on that path. The handler runs its own admission
(resolveApiAuth + validateForwardAdmissionCredential), so a loopback
caller without a ChatGPT credential is still refused inside the relay;
only the listener's 404 goes away. The public listener is unchanged.

Clean reimplementation of lidge-jun#3193, whose branch was byte-corrupted by an
encoding round-trip (em-dashes and emoji in ~30 unrelated comment lines).

Supersedes lidge-jun#3193. Fixes lidge-jun#3192.

Co-authored-by: jun <jun@lidge.dev>
Co-authored-by: alan7629 <alan7629@gmail.com>
agentHits pushed a commit to agentHits/opencodex that referenced this pull request Sep 17, 2026
…dge-jun#3205)

The unauthenticated loopback listener admits routes through an allowlist
in loopbackRouteAllowed(). /v1/alpha/search - the native Codex web-search
relay - was never on it, so a directly-spawned codex app-server got 404
for every web search (lidge-jun#3192).

Admit POST on that path. The handler runs its own admission
(resolveApiAuth + validateForwardAdmissionCredential), so a loopback
caller without a ChatGPT credential is still refused inside the relay;
only the listener's 404 goes away. The public listener is unchanged.

Clean reimplementation of lidge-jun#3193, whose branch was byte-corrupted by an
encoding round-trip (em-dashes and emoji in ~30 unrelated comment lines).

Supersedes lidge-jun#3193. Fixes lidge-jun#3192.

Co-authored-by: jun <jun@lidge.dev>
Co-authored-by: alan7629 <alan7629@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working landed-via-maintainer Original PR closed after landing via a maintainer merge train

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants