Skip to content

turso: the bound secret is never read, so post-#8078 a new turso datasource cannot be authenticated by any supported route #8152

Description

@huangyiirene

Split out of #8081 scope item 4 by the domain:services PM seat, on the dev's explicit recommendation ("on my reading it is a live P1, not a nice-to-have"). ⛔ Not graded by me; no domain:* label — the fix I believe is right lands in service-datasource, but that is exactly the judgement triage should make rather than inherit from me.

The finding — measured, and wider than #8081's card said

#8081 framed item 4 as "turso encryptionKey is credential-shaped, still writable, and the binder has only one slot." The measurement found something larger: spec.secret is never read on the turso path at all.

TURSO_CONFIG_READERS.authToken reads only config.authToken (turso-driver-config.ts:115); resolveTursoUrl reads only config.url. The connect path resolves exactly one ref → one spec.secret (datasource-connection-service.ts:581), and nothing hands it to the turso builder:

buildTursoDriverConfig({driver:'turso', config:{url:'libsql://my-db.turso.io'},
secret:'THE-BOUND-JWT', external:{credentialsRef:'sys_secret:abc'}})
→ { url: 'libsql://my-db.turso.io' } // no authToken. The bound secret is dropped.

Why this is a release-facing problem, not a gap

After #8078, config.authToken is refused at every authoring door (z.never()). The supported alternative — bind the credential, reference it — resolves a secret the turso builder never reads. So:

A new turso remote datasource cannot be authenticated by any supported route.

Existing stored rows still work, because stored config bypasses the parse. That is what makes it invisible: nothing that already works breaks, and only new authoring is dead. turso-driver-config.test.ts contains no case for secret, so nothing pins the gap.

The cheap fix is not the one #8081 named

The dev's recommendation, cheapest first — and note item 4's "Option B (multi-slot binder)" is not the cheap one:

  1. Read spec.secret into authToken in the turso builder — ~5 lines, entirely in service-datasource, no spec change, no new mechanism. It is exact parity with what postgres/mysql/mongo already do (spec.secret ? {password: spec.secret} : …). It restores turso's primary credential to the one slot that already exists, and shrinks the remaining question to encryptionKey alone.
  2. Then decide encryptionKey, if it still needs deciding. Two multi-slot shapes exist: external.credentials: {slot → ref} (clean, but a spec change ⇒ domain:spec), or one ref resolving to a JSON bag (no spec change, but it re-contracts the sys_secret payload and every resolver). ⛔ Neither is worth building until (1) lands and shows whether one slot plus a URL is enough in practice.

The dev deliberately did not implement (1): it is outside #8081's items 1–2 and he declined to take the decision unasked. Correct call — recording it so the next agent does not read the omission as an oversight.

Acceptance, if this is graded for dispatch

Provenance: #8081 dev report (comment 5269923121, §④) and my ACCEPT receipt (#8081 comment 5270102954). Related: #7990 (class card), #8078 (the spec half that closed the inline door).

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions