## Linked issue
Closes #30153
## At a glance
SQL builder:
```ts
import type { WhereFilter } from '@prisma/orm-postgres/builder/types';
import type { Contract } from '../src/prisma/contract';
import { db } from '../src/prisma/db';
const users = db.sql.public.user.select('id', 'email', 'createdAt');
function userById(id: string): WhereFilter<Contract, 'public', 'user'> {
return (fields, operators) => operators.eq(fields.id, id);
}
users.where(userById('00000000-0000-0000-0000-000000000001'));
```
SQL ORM, with shorthand and predicate forms side by side:
```ts
import type { RelationPredicate, ShorthandWhereFilter } from '@prisma/orm-postgres/orm-client';
import { createOrmClient } from '../src/orm-client/client';
import type { Contract } from '../src/prisma/contract';
function userById(id: string): ShorthandWhereFilter<Contract, 'public', 'User'> {
return { id };
}
function userByIdPredicate(id: string): RelationPredicate<Contract, 'public', 'User'> {
return (user) => user.id.eq(id);
}
const db = createOrmClient(null as never);
const userId = '00000000-0000-0000-0000-000000000001';
db.User.where(userById(userId));
db.User.where(userByIdPredicate(userId));
```
These real integration-test examples show the new SQL builder annotation
and the namespace-qualified ORM annotations in use. In both lanes, field
mistakes are reported inside the helper body while the returned filter
passes directly to `.where()`.
## Decision
This PR ships three connected pieces:
1. A public SQL builder `WhereFilter<Contract, Namespace, Table>` type
exported from `@prisma/orm-postgres/builder/types`.
2. Namespace-precise SQL ORM standalone filters using the existing
`ShorthandWhereFilter<Contract, Namespace, Model>` and
`RelationPredicate<Contract, Namespace, Model>` names.
3. Compile-only integration coverage and RC upgrade instructions that
prove and explain the public API through the PostgreSQL facade.
## Summary
Extracting a SQL builder `where()` callback currently loses contextual
typing unless users reconstruct internal signatures or cast the result.
This change adds a supported public builder type for that pattern and
makes the existing SQL ORM reusable filter types namespace-precise,
keeping errors and autocomplete at the helper definition where they are
actionable.
## Reviewer notes
- The SQL ORM generic change is intentionally breaking: namespace is now
required and appears before model. Existing annotations need the
migration recorded in this PR.
- Relation predicates carry the target namespace from
`relation.to.namespace`; emitted branded namespace IDs are normalized
back to concrete contract namespace keys.
- Runtime query behavior and generated SQL are unchanged. The small
`find-user-by-id` cleanup removes an unnecessary ID cast discovered
while adding the public-facade integration type tests.
## How it fits together
1.
[`WhereFilter`](packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts)
binds the existing expression callback to the selected table's
`DefaultScope` and contract query context, then
[`exports/types.ts`](packages/2-sql/4-lanes/sql-builder/src/exports/types.ts)
exposes only that consumer-facing type.
2. [`types.ts`](packages/3-extensions/sql-orm-client/src/types.ts) makes
the domain namespace a required coordinate for ORM shorthand filters,
predicates, and relation filter accessors, so fields and operations
resolve against one exact model facet.
3.
[`collection.ts`](packages/3-extensions/sql-orm-client/src/collection.ts)
and
[`model-accessor.ts`](packages/3-extensions/sql-orm-client/src/model-accessor.ts)
carry that namespace through `.where()`, `.first()`, ordering, grouped
collections, and nested relation accessors.
4. Public-facade type tests in the PostgreSQL demo exercise both
authoring forms and pin negative diagnostics to nonexistent fields
inside the helper bodies.
5. The app and extension upgrade transitions explain how to migrate
existing ORM filter annotations.
## Behavior changes & evidence
- **SQL builder filters can be named, parameterized, and reused with
table-specific fields and operators.** The public surface is defined in
[`table-proxy.ts`](packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts)
and
[`exports/types.ts`](packages/2-sql/4-lanes/sql-builder/src/exports/types.ts),
with package and facade evidence in
[`where-filter.types.test-d.ts`](packages/2-sql/4-lanes/sql-builder/test/types/where-filter.types.test-d.ts)
and
[`sql-builder-filter.types.test-d.ts`](examples/prisma-8-demo/test/sql-builder-filter.types.test-d.ts).
- **SQL ORM shorthand and predicate helpers retain model-specific
autocomplete and local diagnostics.** Namespace-aware definitions live
in [`types.ts`](packages/3-extensions/sql-orm-client/src/types.ts) and
flow through
[`collection.ts`](packages/3-extensions/sql-orm-client/src/collection.ts)
and
[`model-accessor.ts`](packages/3-extensions/sql-orm-client/src/model-accessor.ts);
[`user-filter.types.test-d.ts`](examples/prisma-8-demo/test/user-filter.types.test-d.ts)
proves both forms through `@prisma/orm-postgres/orm-client`.
- **Namespace collisions resolve to the correct model facet.**
[`orm-namespace-unique-fields.types.test-d.ts`](packages/3-extensions/sql-orm-client/test/orm-namespace-unique-fields.types.test-d.ts)
proves that `public.User` and `auth.User` expose different fields and
that missing or unknown namespace coordinates fail at compile time.
- **Existing ORM filter annotations receive an explicit migration
path.** The app and extension transitions in
[`8.0.0-rc.8-to-8.0.0-rc.9`](skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.8-to-8.0.0-rc.9/instructions.md)
and its [`extension
counterpart`](skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.8-to-8.0.0-rc.9/instructions.md)
describe adding and reordering the namespace coordinate.
## Testing performed
- `pnpm --filter @internal/sql-builder test` — 13 test files, 171 tests
passed.
- `pnpm --filter @internal/sql-orm-client test` — 70 test files, 772
tests passed, no type errors.
- `pnpm --filter prisma-8-demo test` — 14 test files, 73 tests passed,
including all 26 repository integration cases.
- `pnpm --filter @internal/sql-builder typecheck`
- `pnpm --filter @internal/sql-orm-client typecheck`
- `pnpm --filter prisma-8-demo typecheck`
- `pnpm lint:deps`
- `pnpm lint:skills`
- `pnpm check:upgrade-coverage`
- `git diff --check`
## Skill update
The public ORM type signature change is recorded for both application
and extension consumers in the `8.0.0-rc.8` → `8.0.0-rc.9` upgrade
instructions. `pnpm lint:skills` and `pnpm check:upgrade-coverage` pass.
## Alternatives considered
- **Export the builder machinery directly.** Exposing `Scope`,
`QueryContext`, `ExpressionBuilder`, and `FieldProxy` would let
consumers reconstruct the callback type, but would make internal query
representation part of the supported API. `WhereFilter` supplies the
useful contract coordinate without that leakage.
- **Add `PredicateFor` and a union-shaped `WhereInput`.** `WhereFilter`
matches the method it targets, while the existing `ShorthandWhereFilter`
and `RelationPredicate` names keep the ORM's object and callback
authoring forms explicit instead of hiding them behind one broad union.
- **Keep namespace optional or after model.** Optional namespace lookup
becomes imprecise when model names collide. Requiring `<Contract,
Namespace, Model>` matches the contract coordinate order and guarantees
useful autocomplete.
- **Document `Parameters<...>` or casts as the workaround.** Those
approaches duplicate complexity at every helper and can move diagnostics
to the eventual `.where()` call. A first-class exported type keeps the
error at its source.
## Checklist
- [x] All commits are signed off (`git commit -s`) per the
[DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco).
- [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is
scoped to one logical concern.
- [x] Tests are updated.
- [x] The PR title uses the linked GitHub issue prefix because this
issue has no Linear ticket.
- [x] The **Skill update** section above is filled in.
## Notes for the reviewer
The main compatibility consideration is the intentionally required ORM
namespace coordinate; matching app and extension upgrade instructions
ship in this PR.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- SQL ORM filter and relation types now support namespace-qualified
model references.
- Added reusable, publicly available filter type support for SQL builder
workflows.
- Namespace-aware typing improves autocomplete and validation across
filtering, sorting, and relation queries.
- **Bug Fixes**
- Invalid fields and unknown namespaces are now rejected more reliably
during TypeScript checks.
- **Documentation**
- Added upgrade guidance for updating reusable ORM filter type
parameters.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Steven McClankerton <tatarintsev@prisma.io>
Co-authored-by: Steven McClankerton <tatarintsev@prisma.io>