Skip to content

fix(web-search): bind continuations to the serving API key - #4387

Closed
luvs01 wants to merge 1 commit into
lidge-jun:devfrom
luvs01:agent/web-search-key-binding-20260912
Closed

fix(web-search): bind continuations to the serving API key#4387
luvs01 wants to merge 1 commit into
lidge-jun:devfrom
luvs01:agent/web-search-key-binding-20260912

Conversation

@luvs01

@luvs01 luvs01 commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Keep opted-in API-key Responses hosted-search continuations bound to the key selection that served the first leg. Revalidate after provider pacing and fail the bridge before another provider request if the selection, resolved credential, authentication mode, or base URL changed.
  • Preserve normal initial-dispatch reselection and the appended search result when the serving binding remains current. Document the behavior and cover both search-time and pacing-time changes.

Earlier focused verification (before this rebase)

  • Baseline regression: 6 failures reproduced an unwanted second mock-provider request when the expected request count was 1.
  • bun test tests/web-search/web-search-passthrough-bridge.test.ts — 32 passed.
  • bun test tests/providers/api-key-selection-capture.test.ts tests/usage/request-pacing.test.ts tests/lab/core-lab-boundary.test.ts — 38 passed.
  • bun test tests/web-search/web-search-passthrough-bridge.test.ts -t 'key reference with the same resolved value' — 1 passed after isolating reference drift from entry-ID drift.
  • bun run typecheck — passed.
  • bun run privacy:scan and bun run structure:check — passed.
  • cd docs-site && bun run build — passed, 425 pages. The generated provider configuration page contains the new binding and reselection guidance.
  • Validation uses mock providers and the repository test-home guard. The full suite was not run locally; hosted results are recorded below.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

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

    • Hosted web-search continuations remain tied to the API-key configuration used for the initial request.
    • Changes to credentials, authentication settings, base URL, provider selection, or availability now end the continuation with an error before another provider request is sent.
    • Continuation binding is rechecked after pacing delays.
    • Configuration changes made before the first provider request can still be applied normally.
  • Documentation

    • Added guidance across provider, transport, runtime, and integration documentation describing continuation binding and failure behavior.

Current verification (2026-09-13)

  • Rebased onto dev@dc33113a9, the latest dev commit at push time. Exact head 2a1b3c3 completed the full CI matrix green (run 34738118457, 26/26 jobs, 0 failures); gates typecheck, structure:check, privacy:scan and focused tests passed locally on that head.
    Head: 3dcc43c, rebased onto dev@17da84f89.
    Focused tests, typecheck, structure check and privacy scan passed on this rebased source:
    32 pass, 0 fail.

The previous green matrix tested an older PR head with the pending #4384 fix added. It is integration evidence only, not a passing full-suite result for this published head. Full CI readiness remains open. The current dev tip has advanced beyond this tested base; further refresh will be coordinated with the shared Windows fixture fix to avoid repeatedly queuing matrices that inherit the same failure.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 73dfc541-0ec7-4aff-ad6b-ae7ca6447688

📥 Commits

Reviewing files that changed from the base of the PR and between 107aa4f and 2a1b3c3.

📒 Files selected for processing (17)
  • docs-site/src/content/docs/reference/configuration/providers.md
  • src/server/responses/core.ts
  • structure/adapters/registry.md
  • structure/catalog.md
  • structure/clients/claude-desktop.md
  • structure/data-planes/images.md
  • structure/data-planes/inbound-compat.md
  • structure/data-planes/search.md
  • structure/gui-and-management-api.md
  • structure/ops/docs-and-release.md
  • structure/ops/service-and-sidecars.md
  • structure/providers/xai-grok.md
  • structure/runtime.md
  • structure/subagents.md
  • structure/transports/inventory.md
  • structure/transports/responses.md
  • structure/transports/streaming-health.md

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The Responses hosted-search bridge now captures the initial API-key binding and validates it before each continuation dispatch. Binding changes fail the continuation without another upstream request. Tests cover drift, pacing, and initial-request reselection. Documentation defines the contract.

Changes

Hosted-search continuation binding

Layer / File(s) Summary
Capture and validate continuation binding
src/server/responses/core.ts
The bridge captures the resolved API-key binding from the initial request. Before each continuation dispatch, it rejects missing or changed bindings instead of applying the previous OAuth override.
Validate drift, pacing, and reselection behavior
tests/web-search/web-search-passthrough-bridge.test.ts
Tests record outbound URLs and authorization headers. They cover selection mutations, disabled or removed providers, pacing-time revalidation, changes before continuation dispatch, and reselection before the first provider request.
Document the continuation contract
docs-site/src/content/docs/reference/configuration/providers.md, structure/*
Configuration and structure documentation defines the binding fields, fail-closed behavior, initial-request reselection, and related cross-references.

Priority: ⬇️ Low

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

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant webSearchBridge
  participant ProviderSelection
  participant ResponsesProvider
  Client->>webSearchBridge: send hosted-search request
  webSearchBridge->>ProviderSelection: select API key for initial dispatch
  ProviderSelection-->>webSearchBridge: return resolved binding
  webSearchBridge->>ResponsesProvider: dispatch search request
  ResponsesProvider-->>webSearchBridge: return search result
  webSearchBridge->>ProviderSelection: validate captured binding
  alt binding unchanged
    webSearchBridge->>ResponsesProvider: dispatch continuation with search result
    ResponsesProvider-->>Client: return completed response
  else binding changed or provider unavailable
    webSearchBridge-->>Client: return WEB_SEARCH_BRIDGE_ERROR_CODE
  end
Loading

Merge Risk: ⚪ Minimal · up to 2a1b3

The bridge rejects stale API-key continuations before another upstream request while preserving valid initial reselection and continuation behavior; no merge-blocking risk is evidenced.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (16 skipped: … 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 and concisely describes the main change: binding web-search continuations to the API key that served the initial request. It matches the implementation, tests, and documentation chan…
Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (16 skipped: 16 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch agent/web-search-key-binding-20260912
🧪 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.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 71 / 80

설명

이 PR은 API 키 Responses에서 hosted web-search를 켠 뒤, 첫 다리를 보낸 선택(키·인증 모드·base URL)이 이어지는 continuation에도 그대로 묶이게 합니다. 지금 dev HEAD ec065aa0csrc/server/responses/core.ts는 passthrough web-search bridge를 만들 때 providerFetch에 일반 dispatchOverride를 넘깁니다. pacing(대기) 중에 사용자가 키를 바꾸거나 pool entry/revision/환경변수가 바뀌면, 이어지는 provider 요청이 다른 키로 나갈 수 있습니다. 그러면 첫 다리에서 붙인 search 결과와 두 번째 다리의 자격이 어긋납니다.

패치는 첫 다리 이후 requestBindings에서 실제로 쓴 API-key binding을 캡처하고, continuation dispatch 직전에 providerApiKeySelectionIsCurrent로 같은지 검사합니다. 바뀌었으면 provider 요청을 다시 만들기 전에 에러로 끊습니다. 초기 dispatch의 재선택은 그대로 두고, binding이 유효하면 검색 결과 append도 유지합니다. 문서와 structure에 계약을 적고, 선택 revision·키 참조·entry id·환경변수·authMode·baseUrl·disabled·삭제, 그리고 pacing 중 변경까지 테스트합니다. 관련 런타임은 #4350 continuation replay, #4368 quota avoid와 이웃하지만 파일 충돌은 거의 없습니다. draft이고 hosted CI는 아직 대기입니다.

라인 - 이게 무슨 문제다

src/server/responses/core.ts webSearchBridgeBinding / beforeDispatch - "첫 다리 이후 binding을 고정한다"는 방향이 맞습니다. 다만 에러가 일반 Error("API key selection changed...")라서 클라이언트에 어떤 코드/상태로 보이는지(취소 가능한 실패인지, 재시도하면 또 터지는지) 한 번만 확인하세요.

providerApiKeySelectionIsCurrent - revision·참조·resolved value·entry id·authMode·baseUrl까지 보는 범위는 본문 테스트와 맞습니다. "값은 같고 참조만 다른" 케이스와 "참조는 같고 값만 다른" 케이스를 나눈 것도 좋습니다.

pacing 중 변경 테스트 - waitForProviderRequestSlot / pacing runtime 훅으로 검색 직후·다음 provider 요청 전에 설정을 바꿉니다. 스케줄에 민감하면 flake 후보입니다. Cross-platform에서 이 describe만 먼저 보면 좋습니다.

structure 다수 파일 한 줄 갱신 - inventory/responses/search 등에 같은 문장을 복제합니다. #4388/#4389와 같이 올리면 conflict 납니다. 계약 문장은 structure/data-planes/search.md 중심으로 두는 편이 낫습니다.

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

  • 키 변경 거절을 soft fail(검색 결과 버리고 새 키로 재시작)로 할지, 지금처럼 hard fail로 할지
  • structure 복제를 이 PR에서 모두 갱신할지, search/responses 두 파일만 남길지
  • draft에서 focused web-search suite + hosted CI로 충분한지

너의 추천
보안·정확도 경계가 분명하니, web-search 테스트와 Cross-platform이 초록이면 draft 해제 후 머지하세요. structure conflict가 싫으면 문서 복제만 후속으로 줄이세요. soft-retry로 바꾸지 말고, 지금은 "같은 키로만 continuation" 계약을 유지하는 편이 낫습니다.

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

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

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@luvs01

luvs01 commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

Exact-head CI for a6a3403 completed with failure: https://github.com/luvs01/opencodex/actions/runs/34681035244

The recorded assertion groups concern Cline inventories (#4386), injection/journal fixtures (#4380), all three Devin path cases (#4384), and pnpm shims (#4379). No web-search/key-binding assertion failure was identified in the inspected logs. This is evidence for separating the shared failure groups from this patch, not a proof that the entire matrix passed or that every failure cause is settled. Draft remains pending integration and exact-head validation.

@luvs01

luvs01 commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

Correction to my previous status comment, for completeness rather than a changed conclusion. Full enumeration of all eleven failing test jobs in that run adds two clusters I did not name:

With those included, every failure in the run is accounted for by open baseline work, and nothing touches the web-search key-binding path in this PR. Please read this comment together with the previous one; the earlier list was incomplete, not inaccurate.

@github-actions

github-actions Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

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

What to do

  • Tick all four boxes in the PR description once you're done (currently 3/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.

3/4 boxes ticked.

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

@luvs01
luvs01 force-pushed the agent/web-search-key-binding-20260912 branch 2 times, most recently from c321680 to 107aa4f Compare September 12, 2026 23:09
@luvs01
luvs01 marked this pull request as ready for review September 13, 2026 02:15
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-13T06:01:15.789905Z 2a1b3c3 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions
github-actions Bot marked this pull request as draft September 13, 2026 02:41
@luvs01
luvs01 force-pushed the agent/web-search-key-binding-20260912 branch from 107aa4f to 3dcc43c Compare September 13, 2026 03:08
@luvs01
luvs01 force-pushed the agent/web-search-key-binding-20260912 branch from 3dcc43c to 2a1b3c3 Compare September 13, 2026 04:31
@luvs01
luvs01 marked this pull request as ready for review September 13, 2026 05:56
@github-actions
github-actions Bot marked this pull request as draft September 13, 2026 05:57
lidge-jun added a commit that referenced this pull request Sep 13, 2026
Lane R of the contributor carry train, the serialized responses/core lane: code-mode view_image through unified exec (#4455 by jeongjin0, also carrying the duplicate #4171 by rrmlima), routed effort ladders from models.dev with a refused-rung replay (#4409 by yxr1995-maker), and web-search continuations bound to the serving API key (#4387 by luvs01).

Cross-platform CI run 34746891233 concluded success on 2c28886, the exact head merged here, and it covers every link because the lane is cumulative. #4475 and #4488 carry no ci check of their own; their head commits carry [skip ci] by design, under the owner-authorized tip-only CI economy for this batch.

The fourth planned link, #4086 by Eleven-is-cool, is not here because it is already on dev as d6723f7 with its own Co-authored-by trailer. The lane attempted the carry first and found a modify/delete conflict on structure/04_transports-and-sidecars.md, which the #4276 SSOT restructure had removed; the landed version is a superset of the branch.

All four source authors are credited by Co-authored-by trailers in the landed commits.
@lidge-jun

Copy link
Copy Markdown
Owner

Closing as landed: binding web-search continuations to the serving API key is on dev via #4489 (merge commit 3f76ce4, verified as an ancestor of origin/dev).

Your authorship is preserved by a Co-authored-by trailer in the landed commit itself rather than only in the pull request body, so it counts on your contributor graph.

The carry folded the review findings already on this pull request. If you think something from this branch did not make it to dev, say so and I will reopen.

@lidge-jun lidge-jun closed this Sep 13, 2026
S0RYUASUKA pushed a commit to S0RYUASUKA/opencodex that referenced this pull request Sep 13, 2026
A hosted-search continuation is not a new turn. It is the first leg plus the
search the proxy just executed, and it has to reach the account that already
served that leg. The continuation went out through the ordinary dispatch
override instead, so a selection change during the search could send the
search-bearing body under a different key -- or rebuild the request from the
original turn and drop the search result entirely.

The bridge now captures the request binding that served the first leg, after
any permitted initial reselection, and rechecks it after provider pacing on
every continuation dispatch. The binding must still be an API-key selection
matching the configured entry, reference, revision, resolved key, auth mode and
base URL; a disabled or removed provider fails the same check. Drift ends the
turn with the bridge's failed terminal and issues no further provider request.
Initial dispatch keeps its normal reselection policy.

Carries lidge-jun#4387 by luvs01 onto current dev.

The branch documents this in fifteen structure/ files. Four are kept:
structure/runtime.md carries the contract itself, and transports/responses.md,
data-planes/search.md and transports/streaming-health.md own the transport, the
search data plane and the post-pacing check. The other eleven received the same
cross-reference sentence pasted into documents that own none of the changed
source -- data-planes/images.md, providers/xai-grok.md and subagents.md among
them, with ops/service-and-sidecars.md a character-identical copy of the
data-planes/search.md insertion. structure/AGENTS.md makes these documents a
source-ownership map, so a pointer in a document that owns nothing here adds a
maintenance edge without adding a fact.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants