Surfaced by the contract review of PR #16616 (card #16378), not by its implementation — the review's width check went looking for a refusal wider than the gap and found the opposite: one corner of the gap the refusal does not reach. ⛔ Filed bare and unassigned; domain:*, type and priority are triage's, and this seat does not produce them. ⛔ Deliberately not ridden on PR #16616 — a refusal that is narrower than the gap is not a defect in that diff.
Contract text
TursoDriverConfig.timeout (packages/drivers/driver-turso/src/turso-driver.ts): "Operation timeout in milliseconds for remote operations." PR #16616 landed the enforcement for the WebSocket schemes: a timeout beside a wss:// / ws:// url in remote mode is refused at construction with VALIDATION_ERROR / 400, because @libsql/client's ws arm has no seam to carry a window (measured: 0 timeout hits across @libsql/hrana-client@0.10.0's lib-esm/ws/*.js and lib-esm/index.js).
The corner, measured
The two readers the driver uses are case-sensitive; the client's own config expansion is not.
@libsql/core@0.17.4 lib-esm/config.js:26 lowercases the scheme before routing. Executed by the review: expandConfig({ url: 'WSS://db.example.turso.io' }, true).scheme === 'wss', and 'Ws://127.0.0.1:8080' → 'ws'. ⇒ an uppercase-scheme url does reach the WebSocket client, which has no window seam.
ridesWebSocketTransport (turso-driver.ts, the new module-level helper) matches the wss:// / ws:// prefixes literally; detectMode is case-sensitive in the same way.
⇒ The one composition that still constructs with an undelivered window is:
new TursoDriver({ url: 'WSS://db.example.turso.io', mode: 'remote', timeout: 30000 })
⚠️ The forced mode: 'remote' is load-bearing and is why this is narrow. Without it, an uppercase url already falls through detectMode to 'local' — behaviour that predates PR #16616 and is unchanged by it. So this is not a regression the refusal introduced; it is the residue of the same case-sensitivity, visible only now that the surrounding case is refused.
⚠️ This also corrects a statement in the director seat's review note on #16378 (comment 5571605362), which reads the client's switch as matching "the literal lowercase". The switch does — but expandConfig runs before it and has already lowercased, so the switch never sees the original casing. The correction is why this card exists rather than the corner being dismissed.
Not measured
Whether any deployment spells a Turso url with an uppercase scheme. The OS_DATABASE_URL boot path forwards only url and authToken (packages/runtime/src/standalone-stack.ts:639–640), and the datasource seam's buildTursoDriverConfig maps an authored timeoutMs — neither normalises case. ⇒ reachable in principle from both, unmeasured in practice. ⛔ No claim about external deployments.
Options (none recommended here)
- (a) fold the case at the driver's two readers — lowercase the scheme in
ridesWebSocketTransport and detectMode before matching, so both agree with the client they hand the url to. Smallest, and makes detectMode's pre-existing uppercase → 'local' fall-through go away too, which is a behaviour change beyond this card and must be argued, not slipped in;
- (b) fold the case only in
ridesWebSocketTransport, leaving detectMode exactly as it is — closes this corner and touches nothing else, at the cost of two readers of the same url disagreeing on purpose;
- (c) refuse an unrecognised scheme outright rather than falling through to
'local' — the widest, and a separate ADR-0049 question about detectMode's whole fall-through, not about timeout.
⚠️ (a) and (c) both move detectMode, which is pinned by turso-driver.test.ts; (b) does not.
Related
#16378 (the card PR #16616 delivers) · PR #16616 · #16617 — the sibling residue of the same ADR-0049 declared-but-unenforced shape, one composition over (timeout reaches nothing when a pre-configured client is supplied). ⭐ These are now three cards in one family; whoever rates this one may want to rate it against #16617 rather than alone. · #16024 · ADR-0049
Surfaced by the contract review of PR #16616 (card #16378), not by its implementation — the review's width check went looking for a refusal wider than the gap and found the opposite: one corner of the gap the refusal does not reach. ⛔ Filed bare and unassigned;
domain:*, type and priority are triage's, and this seat does not produce them. ⛔ Deliberately not ridden on PR #16616 — a refusal that is narrower than the gap is not a defect in that diff.Contract text
TursoDriverConfig.timeout(packages/drivers/driver-turso/src/turso-driver.ts): "Operation timeout in milliseconds for remote operations." PR #16616 landed the enforcement for the WebSocket schemes: atimeoutbeside awss:///ws://url in remote mode is refused at construction withVALIDATION_ERROR/ 400, because@libsql/client's ws arm has no seam to carry a window (measured: 0timeouthits across@libsql/hrana-client@0.10.0'slib-esm/ws/*.jsandlib-esm/index.js).The corner, measured
The two readers the driver uses are case-sensitive; the client's own config expansion is not.
@libsql/core@0.17.4lib-esm/config.js:26lowercases the scheme before routing. Executed by the review:expandConfig({ url: 'WSS://db.example.turso.io' }, true).scheme === 'wss', and'Ws://127.0.0.1:8080'→'ws'. ⇒ an uppercase-scheme url does reach the WebSocket client, which has no window seam.ridesWebSocketTransport(turso-driver.ts, the new module-level helper) matches thewss:///ws://prefixes literally;detectModeis case-sensitive in the same way.⇒ The one composition that still constructs with an undelivered window is:
mode: 'remote'is load-bearing and is why this is narrow. Without it, an uppercase url already falls throughdetectModeto'local'— behaviour that predates PR #16616 and is unchanged by it. So this is not a regression the refusal introduced; it is the residue of the same case-sensitivity, visible only now that the surrounding case is refused.5571605362), which reads the client's switch as matching "the literal lowercase". The switch does — butexpandConfigruns before it and has already lowercased, so the switch never sees the original casing. The correction is why this card exists rather than the corner being dismissed.Not measured
Whether any deployment spells a Turso url with an uppercase scheme. The
OS_DATABASE_URLboot path forwards onlyurlandauthToken(packages/runtime/src/standalone-stack.ts:639–640), and the datasource seam'sbuildTursoDriverConfigmaps an authoredtimeoutMs— neither normalises case. ⇒ reachable in principle from both, unmeasured in practice. ⛔ No claim about external deployments.Options (none recommended here)
ridesWebSocketTransportanddetectModebefore matching, so both agree with the client they hand the url to. Smallest, and makesdetectMode's pre-existing uppercase →'local'fall-through go away too, which is a behaviour change beyond this card and must be argued, not slipped in;ridesWebSocketTransport, leavingdetectModeexactly as it is — closes this corner and touches nothing else, at the cost of two readers of the same url disagreeing on purpose;'local'— the widest, and a separate ADR-0049 question aboutdetectMode's whole fall-through, not abouttimeout.detectMode, which is pinned byturso-driver.test.ts; (b) does not.Related
#16378 (the card PR #16616 delivers) · PR #16616 · #16617 — the sibling residue of the same ADR-0049 declared-but-unenforced shape, one composition over (
timeoutreaches nothing when a pre-configuredclientis supplied). ⭐ These are now three cards in one family; whoever rates this one may want to rate it against #16617 rather than alone. · #16024 · ADR-0049