Skip to content

Cover HEAD preservation, interim answers and the SOCKS response timeout - #5225

Merged
lidge-jun merged 4 commits into
devfrom
codex/transport-head-and-informational-coverage
Sep 20, 2026
Merged

lidge-jun merged 4 commits into
devfrom
codex/transport-head-and-informational-coverage

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Sep 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

Three coverage gaps the acceptance audit found in the raw outbound transports work for #5109 and #5110. No production change: each case exercises a branch that is already there and was not asserted.

  • HEAD preservation ([Bug]: Return null bodies for 204 and 205 in raw outbound transports #5109). A HEAD answer carries the headers the GET would have carried, including the length of a body it will never send; a transport that read that many bytes would park on a body that is not coming with the answer already in hand. The SOCKS case asserts a null body, the advertised content-length surviving in the headers where a caller is entitled to it, and the tunnel released even though the peer asked to keep it alive.
  • Interim informational answers ([Bug]: Settle SOCKS5 streaming uploads on cancellation and early final responses #5110). A peer may answer 100 and 103 before the request body is finished, and those are not the answer. The peer sends both mid-upload and the caller receives the final 200, with upload continuity witnessed by the peer receiving the rest of the body including its terminating chunk.
  • The response timeout during a stalled body read ([Bug]: Settle SOCKS5 streaming uploads on cancellation and early final responses #5110). The branch that matters runs while the upload is parked on a chunk the caller will never produce. The timer is observed as the transport arms it and the transport's own callback is invoked once the peer has witnessed the stall, so the real branch runs without waiting out a three-minute budget. Settlement, release of the caller's stream and teardown of the socket are each witnessed.
Path Change
tests/lib/transport-null-body.test.ts Adds the SOCKS HEAD case beside the existing null-body statuses, reusing that file's proxy, keep-alive peer and destroyed-socket helpers.
tests/lib/socks5-upload-lifecycle.test.ts Adds the interim-answer and response-timeout cases, reusing its stalling body, upload observer and settlement helpers.

The timeout budget is mirrored in the test rather than exported from src/lib/socks5-fetch.ts. The value is what identifies the transport's own timer among the several this exchange arms, and a test is not a reason to widen that module's surface; if the budget changes there, the assertion stops finding it and says so.

Verification

Hosted CI on this branch at exact head. local checks: NOT RUN — no repository suite, focused test, typecheck, build, install or runtime command was run in this lane.

These are test-only additions against branches of the transports that already exist, so the evidence that matters is that they pass without any production change.

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.

Summary by CodeRabbit

  • Tests
    • Added coverage confirming uploads continue successfully after interim 100 and 103 responses.
    • Added coverage for request timeouts during stalled response-body reads, including body cancellation, tunnel destruction, and timeout errors.
    • Added coverage ensuring HEAD responses remain bodyless when an unavailable response length is advertised.
    • Verified advertised headers are preserved and connections are cleaned up after incomplete body responses.
    • Confirmed these scenarios complete without leaving connections waiting indefinitely.

…sponse timeout

Three coverage gaps the acceptance audit found in the transports work. No
production change: each case exercises a branch that is already there and was
not asserted.

HEAD (#5109). A HEAD answer carries the headers the GET would have carried,
including the length of a body it will never send. The SOCKS transport now has a
case proving it answers with a null body, keeps the advertised length in the
headers where a caller is entitled to it, and releases a tunnel whose peer asked
to stay alive.

Interim answers (#5110). A peer may answer 100 and 103 before the request body
is finished, and those are not the answer. The new case has the peer send both
mid-upload and asserts the caller receives the final 200, with upload continuity
witnessed by the peer receiving the rest of the body including its terminating
chunk.

The response timeout (#5110). The branch that matters runs while the upload is
parked on a chunk the caller will never produce. Waiting out the real budget
would make this a three-minute test, so the timer is observed as the transport
arms it and its own callback is invoked once the peer has witnessed the stall.
The budget asserted is the transport's, mirrored in the test rather than
exported from the module. Settlement, reader release and socket teardown are
each witnessed.

local checks: NOT RUN
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 19, 2026 22:50
@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 19, 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-19T22:53:29.768025Z f43cc0f PR opened
ℹ️ 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 added the chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature). label Sep 19, 2026
@coderabbitai

coderabbitai Bot commented Sep 19, 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: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 617c99ac-4345-4c6d-bc56-4fe39165e40a

📥 Commits

Reviewing files that changed from the base of the PR and between 899c57c and 9e3ee90.

📒 Files selected for processing (1)
  • tests/lib/socks5-upload-lifecycle.test.ts

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


📝 Walkthrough

Walkthrough

The pull request adds SOCKS5 transport tests for interim upload responses, stalled response-timeout cleanup, and HEAD responses with null bodies and unsent Content-Length values.

Changes

Transport lifecycle coverage

Layer / File(s) Summary
Upload response and timeout lifecycle
tests/lib/socks5-upload-lifecycle.test.ts
The tests add the Socket import and response-timeout budget. They verify that 100 Continue and 103 Early Hints are consumed before upload completion. They also verify timeout rejection, body cancellation, socket destruction, and timer restoration during a stalled response read.
Null-body response handling
tests/lib/transport-null-body.test.ts
The test verifies that a HEAD response returns status 200, a null body, and the advertised content-length header while destroying the held connection.

Priority: ⬇️ Low

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

Change: Other

🚥 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%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three test areas: HEAD response preservation, interim SOCKS responses, and the response-timeout path. It is concise and specific.
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f43cc0f6e9

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tests/lib/socks5-upload-lifecycle.test.ts Outdated
@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 36 / 80

이 PR은 돌아가는 코드를 바꾸지 않습니다. SOCKS로 요청을 보낼 때 빠졌던 확인 세 가지를, 테스트만 넣어서 채웁니다.

HEAD부터입니다. 상대는 "본문이 128바이트"라고 길이를 적어 줍니다. HEAD 답에는 그 본문이 없습니다. 적힌 숫자만큼 읽으면, 오지 않을 본문을 기다리다 멈춥니다. 새 테스트는 본문이 비어 있는지, 128이 헤더에 남는지, 상대가 연결을 살려 두자고 해도 터널을 닫는지 봅니다.

업로드가 끝나기 전에도 상대는 100과 103을 보낼 수 있습니다. 둘 다 최종 답이 아닙니다. 테스트는 마지막 상태가 200이고 본문이 posted인지를 확인합니다.

마지막은 올리는 쪽이 멈춘 경우입니다. 다음 조각을 영원히 안 주면 답도 오지 않습니다. 제한 시간은 200초라, 테스트는 그 시간을 기다리지 않습니다. 타이머가 200초로 켜지는지만 보고, SOCKS 코드가 타이머에 넣어 둔 함수를 직접 실행합니다. 에러로 끝나는지, 멈추던 스트림이 풀리는지, 소켓이 닫히는지를 각각 봅니다.

베이스는 dev입니다. 이 변경과 겹쳐서 닫을 중복 PR은 없습니다.

라인 - tests/lib/socks5-upload-lifecycle.test.ts:314 - 100과 103 테스트가 본문을 start() 안에서 두 덩어리 다 넣고 바로 닫습니다. 그래서 100이 나가기 전에, 본문 전체와 끝 표시 0\r\n\r\n이 이미 보내진 뒤일 수 있습니다. 받은 글에 hello , socks, 끝 표시가 있는지만 검사해서, 100을 본 다음 업로드를 멈추는 코드도 통과할 수 있습니다. 마지막 상태가 200인지는 잡습니다. "100을 받아도 나머지를 계속 올린다"는 아직 잡지 못합니다.

메인테이너의 판단이 필요한 지점
제한 시간 테스트는 시계를 200초 돌리지 않습니다. 넣어 둔 함수가 정리를 하는지만 봅니다. 이 타협을 그대로 둘지 정해 주십시오. 리눅스 테스트 조각은 이 커밋에서 통과했습니다. macOS 두 조각은 댓글을 쓰는 시점에 아직 끝나지 않았습니다.

너의 추천
100과 103 테스트만 고치고 머지하면 됩니다. 본문은 한 덩어리만 먼저 보내고, 상대가 100과 103을 쓴 뒤에 나머지와 끝 표시를 내보내게 하면 됩니다. HEAD 테스트와 제한 시간 테스트는 지금 그대로 두어도 됩니다. 제품 코드는 건드릴 필요가 없습니다.

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

The case enqueued the whole request body up front, so the upload could finish
before the peer ever sent 100 and 103 and the claim that the rest of the body
went out after them was not causal.

The peer now answers the request head before any body byte, and the caller's
stream withholds its last chunk and the end of the body until that has happened.
Upload continuity is measured against the moment the interim answers were sent
rather than against the whole exchange, so the terminator arriving afterwards
says what it appears to say.

The transport-side receipt is the final answer itself: reading 200 with its body
is only possible for something that consumed both interim heads and went on
reading, where a transport that stopped at the first would have handed the caller
an empty 100. The exchange is also required to end on its own, before the
fixture tears any peer down.

No production change, and every existing assertion is kept.

local checks: NOT RUN
…f the tunnel

The previous version released the rest of the body once the peer had written 100
and 103, which says the bytes were sent, not that the transport had them. The
release now waits until both complete interim heads have arrived on the client
side of the tunnel and the reader has had a native scheduling turn to consume
them, and it records that the fetch is still pending and the body uncancelled at
that moment, which is what says neither head was taken for the answer.

The socket is observed through the timer the transport already arms, with a
passive data listener; the reader is in flowing mode, so it observes the same
chunks and consumes none. No production seam and no sleep.

Upload continuity is still measured from the moment the interim answers were
sent, the final answer and its body are still the receipt that both were read
past, and the exchange must still end on its own before the fixture tears any
peer down.

local checks: NOT RUN
@lidge-jun

Copy link
Copy Markdown
Owner Author

추가 리뷰 · 우선순위 30 / 80

지난 리뷰에서 100과 103 테스트가 순서를 못 잡는다고 적었습니다. 그 뒤 커밋 둘이 그 구멍을 막았습니다. 돌아가는 코드는 그대로입니다.

먼저 나가는 본문은 hello 뿐입니다. socks와 끝 표시는 붙잡아 둡니다. 100과 103이 이쪽 터널에 도착하고, 읽는 쪽이 그 헤더를 처리할 시간을 한 번 가진 뒤에야 풀립니다. 푸는 순간 요청은 아직 안 끝나 있어야 하고, 본문도 취소되면 안 됩니다. 상대가 100을 보낸 다음에 받은 글에는 socks와 끝 표시가 있어야 합니다. 호출자가 받는 마지막 상태는 200이고, 본문은 posted입니다.

100을 최종 답으로 보고 업로드를 끊으면 여기서 실패합니다. socks가 그때까지 나가지 않기 때문입니다.

HEAD 확인과 제한 시간 확인은 이번 푸시에서 안 바뀌었습니다.

라인 - 새로 고칠 줄은 없습니다.

메인테이너의 판단이 필요한 지점
macOS 1/2가 빨갛습니다. 이 PR 때문이 아닙니다. 실패한 곳은 tests/codex-integration/codex-runtime.test.ts이고, 기대한 버전이 비어 있었습니다. 같은 조각에서 이 PR의 HEAD 테스트는 통과했습니다. 리눅스 네 조각과 macOS 2/2도 통과했습니다. 제한 시간 테스트는 여전히 200초를 기다리지 않고 넣어 둔 함수를 직접 부릅니다. 그 타협은 지난 리뷰와 같습니다.

너의 추천
이 PR은 이대로 머지하면 됩니다. 제품 코드는 건드릴 필요가 없습니다. macOS 빨간 표시는 이 변경과 따로 보시면 됩니다.

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

The held tail lived in a stream pull that awaited a receipt which, if it never
arrived, would park the fetch until the runner's own deadline. The finally block
restoring the global Socket prototype would not have run by then, and the data
observer was anonymous, so nothing could remove it either.

The tail is now held by the test body with bounded waits on the receipt, the
outcome and the response, the observer is named and removed, and the fetch is
owned by an AbortController the fixture aborts on the way out. The prototype is
restored first, before anything else in teardown.

Every causal assertion is kept and two more are added: at the moment the
remainder is released, the peer has not yet seen it or the terminator, which
makes the ordering the assertions rely on visible rather than assumed. The
timeout constant and the response and closure checks are unchanged.

local checks: NOT RUN
@lidge-jun

Copy link
Copy Markdown
Owner Author

Maintainer integration into dev under MAINTAINERS.md at reviewed head 9e3ee90f930d6f7ebaf94f3a2dd2425a6f7ce332.

This focused test-only follow-up completes original #5109/#5110 verification requirements. Independent review accepted real HEAD/null-body settlement and cleanup, controlled100/103 processing before the remaining upload, the real response-timeout callback while a read is stalled, and bounded failure cleanup. No production behavior, timeout constant or existing assertion was weakened.

Exact-head hosted run35477114410 attempt1 completed successfully with all applicable jobs and aggregate. Actual macOS logs105988178081/105988178063 show all three named cases passing. Both jobs checked out a81daf8. Change-inapplicable jobs and unrequested Windows full shards are not counted as executions. No local tests, typecheck, builds or runtime were run.

The public finding is resolved. Current merge candidate is tree088e56b6379cd5dbf6b28fd5db8f682bd362a468, native membership is absent, and maintainer preflight passed. Re-closure follows actual dev ancestry verification; previous implementation receipts remain preserved.

@lidge-jun
lidge-jun merged commit 3f9fe3f into dev Sep 20, 2026
31 checks passed
@lidge-jun
lidge-jun deleted the codex/transport-head-and-informational-coverage branch September 20, 2026 00:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Maintenance, CI, tests, refactors, or build changes (not a user-facing bug or feature).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant