Skip to content

context.unsafe.raw/.sql degrade to object through the context seam, so a migration script cannot type them #1206

Description

@borisno2

Parent

#1122 — build spec 2 of the Prisma 8 architecture spec. Lands on the prisma-8 integration branch, not main.

Surfaced while fixing #1204 (which implemented #1144). Flagged by the implementer as a real ergonomic gap, out of that PR's scope.

Problem

context.unsafe.raw and context.unsafe.sql are typed as object when reached through the structural UnsafeCapableClient that the context uses to cross the seam. So the raw tag is untypeable from application code without a cast — and casts are banned by this repo's conventions.

The concrete symptom: examples/rag-openai-chatbot/scripts/install-pgvector.ts is exactly the migration-script use case the Unsafe surface exists to serve, and it could not route through context.unsafe. It now opens its own pg client against DATABASE_URL instead — which works, but means the stack's own example bypasses the surface the stack just built for that purpose.

This undercuts two of the spec's user stories directly:

  • "As an app developer writing a migration script, I want the Unsafe surface to hand me Prisma's typed SQL builder and raw tag untouched, so that I have total fidelity with the cost stated." Untouched at runtime, yes — but not usably typed through the context.
  • "As an app developer, I want query(plan) on the Unsafe surface to return Prisma's streaming result, so that a bulk re-embed can consume rows with a cursor." A bulk re-embed is precisely a script that needs the raw tag.

The surface's own tests do not catch this because they build over a concrete client type, where the lanes are precise. Only a consumer reaching it through StackContext sees object.

What to build

Key the Unsafe surface's lanes to the app's emitted contract so sql and raw keep Prisma's own types through the context, rather than degrading to object at the structural boundary. packages/core/src/unsafe.ts carries a Known limits entry describing this as awaiting spec 3's contract keying — confirm whether spec 3 (#1123) actually closes it, and if so, close this as part of that work rather than duplicating it.

Whatever the mechanism, it must not reintroduce a cast: the surface is currently cast-free and that is worth preserving.

Acceptance criteria

  • A migration script reaching context.unsafe.raw / .sql gets Prisma's own types, with no cast and no any
  • examples/rag-openai-chatbot/scripts/install-pgvector.ts routes through context.unsafe rather than opening its own pg client
  • The Known limits entry in packages/core/src/unsafe.ts is removed rather than left describing a fixed defect
  • The surface stays cast-free

Notes

Related: #1123 (spec 3, the secured surface's reads and the contract keying), #1129 (spec 9, examples and docs conversion).

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

    ready-for-agentFully specified, ready for an AFK agent

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions