You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The server-timeout configuration (webjs.requestTimeoutMs / headersTimeoutMs / keepAliveTimeoutMs, #237) has cross-runtime coverage on Node only. The node test packages/server/test/body-limit/server-timeouts.test.js asserts server.requestTimeout / headersTimeout / keepAliveTimeout (node:http-specific) and is DENYLISTED from the Bun matrix (scripts/run-bun-tests.js) for that reason. On the Bun shell, startBunListener maps the configured requestTimeout to Bun.serve's single idleTimeout via a private bunIdleTimeout() (#511), but that mapping has no test on either runtime and no test/bun script asserts the Bun shell honors the configured timeout. So the Bun side of this feature shipped unverified.
This was surfaced by an audit of the run-bun-tests.js DENYLIST for "Bun parity missed" gaps. It is the ONLY genuine gap found: every other denylisted entry cites real Bun coverage (listener.mjs, compression.mjs, file-storage.mjs, smoke.mjs, dev-hot-reload.mjs) or is runtime-agnostic (importmap test-ordering, redis env, docs-content app-boot).
Design / approach
Add a cross-runtime assertion for the Bun timeout mapping. Two complementary pieces:
Export bunIdleTimeout from listener-bun.js and add a unit test for the pure mapping (ms to seconds; the documented clamp so the idle timeout stays above the 25s SSE keepalive; the default when no config is set). A unit test on the exported function runs under the Bun matrix automatically, so it is proven on both runtimes.
Assert the wiring: that startBunListener passes the configured requestTimeoutMs through to Bun.serve({ idleTimeout }). Either extend test/bun/listener.mjs (it already boots a real Bun.serve socket) to assert the configured value is applied, or add a focused test/bun/timeouts.mjs.
Alternative considered: leaving it to the node test only. Rejected, because the whole point of #508 parity is that a runtime-specific mapping (node requestTimeout to Bun idleTimeout) is exactly where the two diverge and must be pinned.
Implementation notes (for the implementing agent)
Where to edit:
packages/server/src/listener-bun.js: bunIdleTimeout(timeouts) is the private mapping (~L346-352); it is consumed at the Bun.serve({ idleTimeout: bunIdleTimeout(timeouts) }) call (~L66). Export bunIdleTimeout so it is unit-testable.
Unit test: packages/server/test/body-limit/ (alongside server-timeouts.test.js), or a new listener-bun test. Assert the ms to seconds conversion, the >= 25s SSE-keepalive clamp, and the no-config default.
Cross-runtime: extend test/bun/listener.mjs (it boots startServer on a real socket and runs under BOTH node and bun) to assert the configured timeout reached the shell, OR add test/bun/timeouts.mjs wired into the CI bun job + scripts/run-bun-tests.js expectations.
Landmines:
bunIdleTimeout is currently private; exporting it is the cleanest way to get matrix (cross-runtime) coverage of the mapping logic without booting a socket.
Do NOT un-denylist server-timeouts.test.js from the matrix; it asserts node:http server fields that do not exist on Bun.serve. The Bun coverage is the NEW mapping test, not that file.
Bun.serveidleTimeout is in SECONDS and is a single value (no separate headers/keepAlive); the node side is three millisecond fields. The mapping is intentionally lossy; the test asserts the documented contract, not field-for-field equality.
bunIdleTimeout is exported and unit-tested (ms to seconds, the >= 25s clamp, the default), so the mapping runs under the Bun matrix.
A cross-runtime test (test/bun/listener.mjs extension or test/bun/timeouts.mjs) asserts the Bun shell applies the configured requestTimeoutMs to Bun.serveidleTimeout.
The new test fails if the mapping is reverted (counterfactual).
Problem
The server-timeout configuration (
webjs.requestTimeoutMs/headersTimeoutMs/keepAliveTimeoutMs, #237) has cross-runtime coverage on Node only. The node testpackages/server/test/body-limit/server-timeouts.test.jsassertsserver.requestTimeout/headersTimeout/keepAliveTimeout(node:http-specific) and is DENYLISTED from the Bun matrix (scripts/run-bun-tests.js) for that reason. On the Bun shell,startBunListenermaps the configuredrequestTimeouttoBun.serve's singleidleTimeoutvia a privatebunIdleTimeout()(#511), but that mapping has no test on either runtime and notest/bunscript asserts the Bun shell honors the configured timeout. So the Bun side of this feature shipped unverified.This was surfaced by an audit of the
run-bun-tests.jsDENYLIST for "Bun parity missed" gaps. It is the ONLY genuine gap found: every other denylisted entry cites real Bun coverage (listener.mjs,compression.mjs,file-storage.mjs,smoke.mjs,dev-hot-reload.mjs) or is runtime-agnostic (importmap test-ordering, redis env, docs-content app-boot).Design / approach
Add a cross-runtime assertion for the Bun timeout mapping. Two complementary pieces:
bunIdleTimeoutfromlistener-bun.jsand add a unit test for the pure mapping (ms to seconds; the documented clamp so the idle timeout stays above the 25s SSE keepalive; the default when no config is set). A unit test on the exported function runs under the Bun matrix automatically, so it is proven on both runtimes.startBunListenerpasses the configuredrequestTimeoutMsthrough toBun.serve({ idleTimeout }). Either extendtest/bun/listener.mjs(it already boots a realBun.servesocket) to assert the configured value is applied, or add a focusedtest/bun/timeouts.mjs.Alternative considered: leaving it to the node test only. Rejected, because the whole point of #508 parity is that a runtime-specific mapping (node
requestTimeoutto BunidleTimeout) is exactly where the two diverge and must be pinned.Implementation notes (for the implementing agent)
packages/server/src/listener-bun.js:bunIdleTimeout(timeouts)is the private mapping (~L346-352); it is consumed at theBun.serve({ idleTimeout: bunIdleTimeout(timeouts) })call (~L66). ExportbunIdleTimeoutso it is unit-testable.packages/server/test/body-limit/(alongsideserver-timeouts.test.js), or a newlistener-buntest. Assert the ms to seconds conversion, the >= 25s SSE-keepalive clamp, and the no-config default.test/bun/listener.mjs(it bootsstartServeron a real socket and runs under BOTH node and bun) to assert the configured timeout reached the shell, OR addtest/bun/timeouts.mjswired into the CIbunjob +scripts/run-bun-tests.jsexpectations.bunIdleTimeoutis currently private; exporting it is the cleanest way to get matrix (cross-runtime) coverage of the mapping logic without booting a socket.server-timeouts.test.jsfrom the matrix; it asserts node:http server fields that do not exist onBun.serve. The Bun coverage is the NEW mapping test, not that file.Bun.serveidleTimeoutis in SECONDS and is a single value (no separate headers/keepAlive); the node side is three millisecond fields. The mapping is intentionally lossy; the test asserts the documented contract, not field-for-field equality..claude/hooks/require-bun-parity-with-runtime-src.sh, which would now BLOCK alistener-bun.jschange with notest/buntest). Invariant release: bump core/server/cli versions, honest engines fields #11 in any new prose.Acceptance criteria
bunIdleTimeoutis exported and unit-tested (ms to seconds, the >= 25s clamp, the default), so the mapping runs under the Bun matrix.test/bun/listener.mjsextension ortest/bun/timeouts.mjs) asserts the Bun shell applies the configuredrequestTimeoutMstoBun.serveidleTimeout.nodeandbun.