Skip to content

TursoDriverConfig.timeout is still accepted beside an UPPERCASE WSS:// url in forced remote mode — the client lowercases the scheme, the driver's two readers do not #16637

Description

@os-musk

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions