Skip to content

TML-2653: Remove capabilities from defineContract; components contribute them#574

Merged
wmadden merged 11 commits into
mainfrom
onboarding-papercuts/e1-caps-on-by-default
May 27, 2026
Merged

TML-2653: Remove capabilities from defineContract; components contribute them#574
wmadden merged 11 commits into
mainfrom
onboarding-papercuts/e1-caps-on-by-default

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented May 21, 2026

At a glance

// Before
defineContract({
  family: sqlFamily,
  target: postgresPack,
  capabilities: { sql: { returning: true, foreignKeys: true } },
}, ({ model, field }) => ({ /* schema */ }));

// After
defineContract({
  family: sqlFamily,
  target: postgresPack,
}, ({ model, field }) => ({ /* schema */ }));

The capabilities argument is gone. The set of capabilities available to a contract is now derived from the components it's built on — target, extension packs, adapter, driver — instead of being enumerated by the author.

Fixes TML-2653.

The decision

defineContract no longer accepts a capabilities field. The same goes for the PSL interpreter's contract definition. Capabilities are now contributed by the framework components in the contract's stack and merged into a single matrix at build time.

Concretely:

  • ContractDefinition (both SQL and Mongo) drops capabilities. Passing it is a TypeScript error.
  • Every defineContract call site (examples/**, apps/**, fixtures) drops its capabilities: { … } block.
  • The effective capability matrix for a contract is the union of what every wired-in component declares.

Why

defineContract previously required authors to enumerate every framework capability their contract relied on, even ones the framework can always provide on a given target. First-time authors hit "requires capability" errors on flags like sql.returning that have no meaningful "off" state for a Postgres adapter, and the boilerplate added nothing the framework couldn't infer.

It was also the wrong ownership boundary. A capability is a property of the component that implements it: the Postgres adapter knows whether it supports DISTINCT ON; the pgvector extension pack knows it provides HNSW indexes; the author shouldn't need to mirror those decisions in the contract.

What this means for users

  • Contracts get shorter. Every example's capabilities: { … } block is gone.
  • New contracts work out of the box. No more "requires capability" errors from flags the framework always provides on the chosen target.
  • Capability set is wider than before in many contracts. Previously a contract's effective capability set was whatever the author typed; now it's the full set the components contribute. Generated contract.{json,d.ts} reflect this: the capabilities block grows where the example previously declared fewer flags than its components contribute, and shrinks for phantom flags no component owns.
  • profileHash stabilises. Previously profileHash was hash(definition.capabilities) — a fingerprint of the author-typed subset. With the author input gone, the hash semantics are unchanged but the input is empty, so profileHash stabilises at sha256:1a8dbe04… (Postgres-target) / sha256:c336398c… (SQLite-target) across all contracts.

What changes in the framework

  • A new generic helper mergeCapabilityMatrices in @prisma-next/contract-authoring performs structural deep-merge over capability matrices. Zero SQL or target-family knowledge. Sits in packages/1-framework/.
  • buildSqlContractFromDefinition (the path both the TS builder and the PSL interpreter lower through) merges definition.target.capabilities and every definition.extensionPacks[*].capabilities via the helper. The CLI's existing enrichContract continues to layer in adapter/driver contributions at emit time.
  • The Postgres adapter descriptor now contributes postgres.distinctOn and sql.lateral — flags the SQL builder's runtime gates on that no component previously owned.
  • Other adapter/extension contributions were already in place; nothing else moved.
  • pnpm lint:deps is clean: no @prisma-next/target-* references inside packages/1-framework/.

What changes in generated artifacts

Every contract.{json,d.ts} across examples/**, apps/**, packages/3-extensions/*/src/contract.*, and the test/fixture trees is regenerated:

  • profileHash settles at the empty-author hash per target.
  • The capabilities block reflects the merged component contributions — wider than the prior author-typed subset in most cases, narrower where the author previously declared flags nothing currently owns.

Upgrade instructions

Adds entries to skills/upgrade/prisma-next-upgrade/upgrades/0.11-to-0.12/ and skills/extension-author/prisma-next-extension-upgrade/upgrades/0.11-to-0.12/.

Test plan

  • pnpm typecheck (full monorepo) — clean.
  • pnpm lint:deps — clean; no @prisma-next/target-* references inside packages/1-framework/.
  • @prisma-next/sql-contract-ts, @prisma-next/mongo-contract-ts, @prisma-next/sql-contract-psl, @prisma-next/mongo-contract-psl, @prisma-next/sql-builder, @prisma-next/sql-orm-client, @prisma-next/contract, @prisma-next/sql-contract, @prisma-next/mongo-contract, @prisma-next/cli, @prisma-next/emitter, @prisma-next/e2e-tests — all green.
  • Negative type test in capability-defaults.test.ts confirms defineContract({ …, capabilities: { … } }) is a TypeScript error.
  • pnpm fixtures:check — regenerated assets reflect the merged-matrix shape.
  • CI Integration Tests (Postgres + Mongo) — gated by CI.

Alternatives considered

  1. Hardcode framework-wide SQL defaults (FRAMEWORK_WIDE_SQL_CAPABILITY_DEFAULTS) in packages/1-framework/. Rejected: it embeds SQL knowledge in the target-agnostic framework layer, violates the dependency direction enforced by pnpm lint:deps, and bakes in incorrect assumptions for individual targets (sql.defaultInInsert: true isn't true for SQLite).
  2. Make adapters symmetric — both Postgres and SQLite contribute the same set of caps. Rejected: capabilities are a property of each component; forcing symmetry papers over real per-target differences. Each component contributes only what it actually declares.
  3. Recompute profileHash over the merged matrix in enrichContract to preserve byte-identical output. Rejected: changes the hash's semantics for no user-visible benefit. The simpler shape — keep the hash computation as-is and accept that an empty author input produces a stable hash — was preferred.

Summary by CodeRabbit

  • New Features

    • Runtime/emit now reports additional SQL/Postgres features: DISTINCT ON, LATERAL, and explicit foreign-key support.
  • Refactor

    • Capability handling simplified: author-supplied capability overrides removed; capabilities are derived and merged from targets and extension packs.
  • Tests

    • Added tests for capability merging, defaults, propagation, and authoring-time behavior.
  • Documentation

    • Upgrade instructions added for adapting to removed authoring-time capabilities.

Review Change Stack

@wmadden wmadden requested a review from a team as a code owner May 21, 2026 14:07
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: e4f54343-bade-4ba8-be46-1d19e3cf15fa

📥 Commits

Reviewing files that changed from the base of the PR and between 2af0d19 and e9a9bf2.

📒 Files selected for processing (24)
  • packages/3-targets/6-adapters/postgres/src/core/adapter.ts
  • skills/extension-author/prisma-next-extension-upgrade/upgrades/0.11-to-0.12/instructions.md
  • skills/upgrade/prisma-next-upgrade/upgrades/0.11-to-0.12/instructions.md
  • test/integration/test/authoring/parity/callback-mode-scalars/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-bigint/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-boolean/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-date/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-double/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-json/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-string/expected.contract.json
  • test/integration/test/authoring/parity/core-surface/expected.contract.json
  • test/integration/test/authoring/parity/default-cuid-2/expected.contract.json
  • test/integration/test/authoring/parity/default-dbgenerated/expected.contract.json
  • test/integration/test/authoring/parity/default-nanoid-16/expected.contract.json
  • test/integration/test/authoring/parity/default-nanoid/expected.contract.json
  • test/integration/test/authoring/parity/default-pack-slugid/expected.contract.json
  • test/integration/test/authoring/parity/default-ulid/expected.contract.json
  • test/integration/test/authoring/parity/default-uuid-v4/expected.contract.json
  • test/integration/test/authoring/parity/default-uuid-v7/expected.contract.json
  • test/integration/test/authoring/parity/map-attributes/expected.contract.json
  • test/integration/test/authoring/parity/pgvector-named-type/expected.contract.json
  • test/integration/test/authoring/parity/relation-backrelation-list/expected.contract.json
  • test/integration/test/authoring/side-by-side/postgres/contract.json
  • test/integration/test/sql-builder/setup.ts
✅ Files skipped from review due to trivial changes (18)
  • test/integration/test/authoring/parity/default-uuid-v7/expected.contract.json
  • test/integration/test/authoring/parity/default-cuid-2/expected.contract.json
  • test/integration/test/authoring/side-by-side/postgres/contract.json
  • test/integration/test/authoring/parity/default-dbgenerated/expected.contract.json
  • test/integration/test/authoring/parity/relation-backrelation-list/expected.contract.json
  • test/integration/test/authoring/parity/default-ulid/expected.contract.json
  • test/integration/test/authoring/parity/pgvector-named-type/expected.contract.json
  • skills/upgrade/prisma-next-upgrade/upgrades/0.11-to-0.12/instructions.md
  • test/integration/test/authoring/parity/cipherstash-encrypted-json/expected.contract.json
  • test/integration/test/authoring/parity/core-surface/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-bigint/expected.contract.json
  • test/integration/test/authoring/parity/callback-mode-scalars/expected.contract.json
  • test/integration/test/authoring/parity/default-nanoid/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-double/expected.contract.json
  • test/integration/test/authoring/parity/default-pack-slugid/expected.contract.json
  • test/integration/test/authoring/parity/map-attributes/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-string/expected.contract.json
  • test/integration/test/authoring/parity/default-uuid-v4/expected.contract.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • test/integration/test/authoring/parity/default-nanoid-16/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-boolean/expected.contract.json
  • test/integration/test/authoring/parity/cipherstash-encrypted-date/expected.contract.json
  • packages/3-targets/6-adapters/postgres/src/core/adapter.ts
  • test/integration/test/sql-builder/setup.ts

📝 Walkthrough

Walkthrough

Derive contract capabilities from targets and extension packs via a new capability-matrix merge utility; remove author-declared capabilities from contract inputs; add adapter-level foreign-key capabilities; and regenerate extension, app, example, and test fixture contracts to reflect merged capability metadata.

Changes

Capability Matrix Infrastructure and Contract Capability Authoring

Layer / File(s) Summary
Capability matrix utilities
packages/1-framework/2-authoring/contract/src/capability-registry.ts, packages/1-framework/2-authoring/contract/src/index.ts, packages/1-framework/2-authoring/contract/test/capability-registry.test.ts
Introduces CapabilityMatrix type and mergeCapabilityMatrices function that deep-merges nested capability objects with later sources overriding earlier values. Test suite covers empty input, undefined handling, passthrough, cross-namespace merging, override precedence, and non-mutation guarantees.
SQL contract capability derivation
packages/2-sql/2-authoring/contract-ts/src/build-contract.ts
buildSqlContractFromDefinition now computes merged capabilities from target and extension pack sources using mergeCapabilityMatrices. Updates profileHash computation to use empty capabilities {} for hash stability, decoupling hash from capability layering.
SQL contract types and typing
packages/2-sql/2-authoring/contract-ts/src/contract-types.ts
Introduces type-level utilities and DerivedCapabilities<Definition> that computes final capabilities by defaulting target capabilities and intersecting with merged extension-pack capabilities. Updates SqlContractResult.capabilities to use derived type instead of build-time extraction.
SQL contract authoring API
packages/2-sql/2-authoring/contract-ts/src/contract-builder.ts, contract-definition.ts, contract-dsl.ts, contract-lowering.ts, test/contract-builder.constraints.test.ts
Removes Capabilities generic and optional capabilities property from ContractDefinition, ContractScaffold, ContractInput, and defineContract overloads. Updates lowering and test helpers accordingly.
SQL contract capability integration tests
packages/2-sql/2-authoring/contract-psl/test/interpreter.test.ts, packages/2-sql/2-authoring/contract-ts/test/capability-defaults.test.ts
PSL interpreter tests verify capabilities flow from target into contracts. TypeScript tests validate empty contracts, target capability propagation, extension-pack overlay, rejection of author input, and stable profileHash across different wiring configurations.
Mongo contract authoring
packages/2-mongo-family/2-authoring/contract-ts/src/contract-builder.ts
Removes Capabilities from Mongo ContractScaffold, ContractDefinition, and defineContract API. Mongo contracts now always expose empty capabilities Record<string, never>. Updates scaffold predicates and build function accordingly.
Adapter foreign-key capabilities
packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts, packages/3-targets/6-adapters/sqlite/src/core/descriptor-meta.ts, packages/3-targets/6-adapters/postgres/src/core/adapter.ts
Adds foreignKeys: true capability to Postgres and SQLite adapter descriptor metadata and updates Postgres adapter defaults (moves lateral into sql capability set and adds distinctOn).
Postgres and SQLite contract facades
packages/3-extensions/postgres/src/contract/define-contract.ts, packages/3-extensions/sqlite/src/contract/define-contract.ts, packages/3-extensions/postgres/test/contract-builder/define-contract.test-d.ts, packages/3-extensions/sqlite/test/contract-builder/define-contract.test-d.ts
Removes Capabilities generic from PostgresResult and SqliteResult types, overloads, and implementations while preserving target/targetFamily literal type overrides. Test expectations updated to validate capability inputs and model-shape inference.
Extension pack generated contracts
packages/3-extensions/cipherstash/src/contract.*, packages/3-extensions/paradedb/src/contract.*, packages/3-extensions/pgvector/src/contract.*, packages/3-extensions/postgis/src/contract.*
Regenerated extension pack contract declarations (.d.ts and .json) with new capability flags: distinctOn: true under capabilities.postgres and lateral: true under capabilities.sql.
App and example generated contracts
apps/telemetry-backend/src/prisma/contract.*, examples/*/src/prisma/contract.*, examples/*/prisma/contract.ts
Regenerated contracts across apps and examples with updated capability declarations. ParadeDB and Prisma-Next SQLite demos update profile hashes. ParadeDB, Prisma-Next demo, and React Router examples remove author-declared capabilities blocks from contract definitions.
Test fixture contracts and setup
test/integration/test/fixtures/contract.*, test/e2e/framework/test/fixtures/contract.ts, test/e2e/framework/test/sqlite/fixtures/contract.ts, test/integration/test/sql-builder/fixtures/contract.ts, test/integration/test/sql-builder/setup.ts
Integration test fixtures regenerated with new capability declarations. E2E and SQL builder test fixtures remove author-declared capabilities configuration blocks; SQL-builder setup now applies emit-time enrichment (enrichContract) before deserializing contracts used by tests.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • aqrln

Poem

🐰 Capabilities once penned by hand,
Now merge and flow across the land.
Packs and targets whisper true,
Contracts update—fresh and new.
A rabbit hops, approving you—🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: removing the capabilities field from defineContract and shifting that responsibility to framework components. It is concise and directly relates to the primary objective of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch onboarding-papercuts/e1-caps-on-by-default

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 21, 2026

Open in StackBlitz

@prisma-next/extension-author-tools

npm i https://pkg.pr.new/@prisma-next/extension-author-tools@574

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/@prisma-next/mongo-runtime@574

@prisma-next/family-mongo

npm i https://pkg.pr.new/@prisma-next/family-mongo@574

@prisma-next/sql-runtime

npm i https://pkg.pr.new/@prisma-next/sql-runtime@574

@prisma-next/family-sql

npm i https://pkg.pr.new/@prisma-next/family-sql@574

@prisma-next/extension-arktype-json

npm i https://pkg.pr.new/@prisma-next/extension-arktype-json@574

@prisma-next/extension-cipherstash

npm i https://pkg.pr.new/@prisma-next/extension-cipherstash@574

@prisma-next/middleware-cache

npm i https://pkg.pr.new/@prisma-next/middleware-cache@574

@prisma-next/mongo

npm i https://pkg.pr.new/@prisma-next/mongo@574

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/@prisma-next/extension-paradedb@574

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/@prisma-next/extension-pgvector@574

@prisma-next/extension-postgis

npm i https://pkg.pr.new/@prisma-next/extension-postgis@574

@prisma-next/postgres

npm i https://pkg.pr.new/@prisma-next/postgres@574

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/@prisma-next/sql-orm-client@574

@prisma-next/sqlite

npm i https://pkg.pr.new/@prisma-next/sqlite@574

@prisma-next/target-mongo

npm i https://pkg.pr.new/@prisma-next/target-mongo@574

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/@prisma-next/adapter-mongo@574

@prisma-next/driver-mongo

npm i https://pkg.pr.new/@prisma-next/driver-mongo@574

@prisma-next/contract

npm i https://pkg.pr.new/@prisma-next/contract@574

@prisma-next/utils

npm i https://pkg.pr.new/@prisma-next/utils@574

@prisma-next/config

npm i https://pkg.pr.new/@prisma-next/config@574

@prisma-next/errors

npm i https://pkg.pr.new/@prisma-next/errors@574

@prisma-next/framework-components

npm i https://pkg.pr.new/@prisma-next/framework-components@574

@prisma-next/operations

npm i https://pkg.pr.new/@prisma-next/operations@574

@prisma-next/ts-render

npm i https://pkg.pr.new/@prisma-next/ts-render@574

@prisma-next/contract-authoring

npm i https://pkg.pr.new/@prisma-next/contract-authoring@574

@prisma-next/ids

npm i https://pkg.pr.new/@prisma-next/ids@574

@prisma-next/psl-parser

npm i https://pkg.pr.new/@prisma-next/psl-parser@574

@prisma-next/psl-printer

npm i https://pkg.pr.new/@prisma-next/psl-printer@574

@prisma-next/cli

npm i https://pkg.pr.new/@prisma-next/cli@574

@prisma-next/cli-telemetry

npm i https://pkg.pr.new/@prisma-next/cli-telemetry@574

@prisma-next/emitter

npm i https://pkg.pr.new/@prisma-next/emitter@574

@prisma-next/migration-tools

npm i https://pkg.pr.new/@prisma-next/migration-tools@574

prisma-next

npm i https://pkg.pr.new/prisma-next@574

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/@prisma-next/vite-plugin-contract-emit@574

@prisma-next/mongo-codec

npm i https://pkg.pr.new/@prisma-next/mongo-codec@574

@prisma-next/mongo-contract

npm i https://pkg.pr.new/@prisma-next/mongo-contract@574

@prisma-next/mongo-value

npm i https://pkg.pr.new/@prisma-next/mongo-value@574

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/@prisma-next/mongo-contract-psl@574

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/@prisma-next/mongo-contract-ts@574

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/@prisma-next/mongo-emitter@574

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/@prisma-next/mongo-schema-ir@574

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/@prisma-next/mongo-query-ast@574

@prisma-next/mongo-orm

npm i https://pkg.pr.new/@prisma-next/mongo-orm@574

@prisma-next/mongo-query-builder

npm i https://pkg.pr.new/@prisma-next/mongo-query-builder@574

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/@prisma-next/mongo-lowering@574

@prisma-next/mongo-wire

npm i https://pkg.pr.new/@prisma-next/mongo-wire@574

@prisma-next/sql-contract

npm i https://pkg.pr.new/@prisma-next/sql-contract@574

@prisma-next/sql-errors

npm i https://pkg.pr.new/@prisma-next/sql-errors@574

@prisma-next/sql-operations

npm i https://pkg.pr.new/@prisma-next/sql-operations@574

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/@prisma-next/sql-schema-ir@574

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/@prisma-next/sql-contract-psl@574

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/@prisma-next/sql-contract-ts@574

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/@prisma-next/sql-contract-emitter@574

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/@prisma-next/sql-lane-query-builder@574

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/@prisma-next/sql-relational-core@574

@prisma-next/sql-builder

npm i https://pkg.pr.new/@prisma-next/sql-builder@574

@prisma-next/target-postgres

npm i https://pkg.pr.new/@prisma-next/target-postgres@574

@prisma-next/target-sqlite

npm i https://pkg.pr.new/@prisma-next/target-sqlite@574

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/@prisma-next/adapter-postgres@574

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/@prisma-next/adapter-sqlite@574

@prisma-next/driver-postgres

npm i https://pkg.pr.new/@prisma-next/driver-postgres@574

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/@prisma-next/driver-sqlite@574

commit: e9a9bf2

@SevInf
Copy link
Copy Markdown
Contributor

SevInf commented May 21, 2026

Can't we infer defaults from adapter instead? defaultInInsert will not be true for sqlite, retruning will not be true for mysql. I'd argue, flipping them to on by default makes situation worse - unless you disable them in contract, ORM will automagically try to use syntax that is not supported and sql builder will expose that option to the users.

Comment thread examples/prisma-next-demo-sqlite/src/prisma/contract.json Outdated
Copy link
Copy Markdown
Contributor Author

@wmadden wmadden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally wrong approach. Any framework component may provide capabilities, not just the family, and you can't hardcode a list of them, nor can you couple the framework domain to SQL

Additionally: this work should have no effect on the generated contract assets already in the repo. Regenerated assets should be identical.

Comment thread packages/1-framework/2-authoring/contract/src/capability-registry.ts Outdated
Comment thread packages/2-sql/2-authoring/contract-ts/src/build-contract.ts Outdated
Comment thread packages/2-sql/2-authoring/contract-ts/src/contract-types.ts Outdated
@wmadden wmadden force-pushed the onboarding-papercuts/e1-caps-on-by-default branch 2 times, most recently from 1c1558f to 8a6e9ef Compare May 22, 2026 08:55
@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented May 22, 2026

Force-pushed a correction after operator feedback: the previous force-push (06dedb02e) added sql.foreignKeys: true to the Postgres adapter for symmetry with SQLite. That was wrong — the goal here is to plumb existing capability declarations through a single contribution mechanism, not to introduce new ones. Reverted the Postgres adapter change.

New commit chain on this branch:

  • f49cf379c refactor(contract-authoring): replace SQL-aware capability defaults with a generic merge helper
  • dd4897089 feat(adapters): contribute sql.foreignKeys from sqlite descriptor
  • 8a6e9efe6 chore(fixtures): regenerate contract assets after capability contribution rework

Key changes vs the prior push:

  • Postgres adapter descriptor: unchanged from origin/main (no foreignKeys: true added).
  • SQLite adapter descriptor: still gains foreignKeys: true (legitimate move — replaces the prior hand-enumeration in examples/prisma-next-demo-sqlite/prisma/contract.ts).
  • build-contract.ts: profile hash now computed over definition.capabilities only (matching the pre-PR semantic and the Mongo path), so it doesn't drift on contracts whose author-declared caps didn't change.

Diff vs origin/main:

Source Fixtures
Postgres adapter no change no Postgres-target contract gains foreignKeys
SQLite adapter +foreignKeys: true SQLite example: only profileHash bumps (capabilities block byte-identical)
Example contracts drop redundant postgres.returning (4 files) / sql.returning + sql.foreignKeys (1 file) 5 profileHash bumps total — capabilities blocks all byte-identical

The 5 profileHash bumps land on exactly the 5 contracts whose example contract.ts dropped redundant declarations. Their resolved .capabilities blocks are unchanged because the dropped declarations now come from the adapter at CLI emit time.

@wmadden wmadden force-pushed the onboarding-papercuts/e1-caps-on-by-default branch from e1e7320 to 6ba5691 Compare May 22, 2026 12:51
@wmadden wmadden changed the title TML-2653 Default framework-wide capabilities on in TS builder + PSL TML-2653: Remove capabilities from defineContract; components contribute them May 27, 2026
wmadden added 8 commits May 27, 2026 14:43
…ith a generic merge helper

The old `resolveAuthoringCapabilities` injected hardcoded `sql.{returning, defaultInInsert, foreignKeys}` from the framework-level `@prisma-next/contract-authoring` package, which is supposed to stay target-agnostic. It also forced `defaultInInsert: true` onto every SQL target, which is wrong for SQLite.

Replace it with `mergeCapabilityMatrices(...sources)`, a pure structural deep-merge over the matrix shape with zero family or target knowledge. The SQL contract-ts builder now aggregates `definition.target.capabilities`, each `definition.extensionPacks[*].capabilities`, and the author-declared `definition.capabilities` through this helper. CLI-time `enrichContract` continues to layer in adapter/driver capabilities — this is the two-stage capability contribution model.

The SQL contract-ts result type derives `capabilities` from the same three sources via type-level intersection rather than embedding a hardcoded framework-wide shape, so authoring-time types and runtime values agree without per-family special-casing.

Tests now drive contribution semantics directly: the framework helper test exercises generic merge; the SQL test declares capabilities on target/extension pack refs and asserts they show up; the PSL interpreter test asserts that no capabilities are synthesised when the target contributes none, and that target-declared caps flow through.

Closes part of TML-2653.

Signed-off-by: Will Madden <madden@prisma.io>
The SQLite adapter always supports FOREIGN KEY constraints. Declaring `sql.foreignKeys: true` on its descriptor lets CLI-time `enrichContract` surface the capability into every contract that picks up the adapter, so authors no longer need to enumerate it.

With the capability sourced from the adapter, the example contracts drop the corresponding hand-enumerated flags: the SQLite demo no longer declares `sql.returning` or `sql.foreignKeys`, and the Postgres demos no longer declare `postgres.returning` (the Postgres adapter has always contributed it). Author-declared opt-outs still win because authoring-time capabilities are layered last in the merge.

The Postgres adapter is intentionally left untouched: `foreignKeys` was never previously declared on it nor on any Postgres example, and the goal is to plumb existing capability declarations through a single contribution mechanism rather than introduce new ones for symmetry.

Closes part of TML-2653.

Signed-off-by: Will Madden <madden@prisma.io>
…tion rework

Author-declared capability sets shrunk for the five contracts whose example `contract.ts` dropped redundant declarations now contributed by the adapter:

- `examples/paradedb-demo` (dropped `postgres.returning`)
- `examples/prisma-next-demo-sqlite` (dropped `sql.returning` and `sql.foreignKeys`)
- `packages/2-sql/4-lanes/sql-builder/test/fixtures/generated` (Postgres test fixture, dropped `postgres.returning` upstream)
- `packages/3-extensions/sql-orm-client/test/fixtures/generated` (dropped `postgres.returning` upstream)
- `test/integration/test/sql-builder/fixtures/generated` (dropped `postgres.returning` upstream)

The serialized `.capabilities` block of every regenerated contract is byte-identical to the pre-rework asset (the dropped declarations are now supplied by the adapter at CLI emit time). Only the `profileHash` field — which fingerprints the author-declared capability subset — bumps to reflect the new author input.

Signed-off-by: Will Madden <madden@prisma.io>
Picks up the new profileHash produced by the generic mergeCapabilityMatrices
helper for the postgres-target sql-builder and sql-orm-client fixtures, which
were missed in the previous fixture regen pass.

Signed-off-by: Will Madden <madden@prisma.io>
…nput

The SQL and Mongo `defineContract` factories no longer accept a
`capabilities` block. Capability flags now flow exclusively from the
configured component descriptors (target / extension packs at build
time; adapter / driver / extension layered in by `enrichContract` at
CLI emit time).

The `profileHash` computation is unchanged from `origin/main`: it
still fingerprints the author-declared capability subset. With that
input always empty after this change, the hash collapses to the
empty-author hash (`hash({})`) for every contract; the value differs
per target because `target` and `targetFamily` are also part of the
fingerprint.

Refresh the SQL `capability-defaults` test suite:

- Drop the two cases that exercised author-declared overrides (no
  longer reachable through the public surface).
- Add a `@ts-expect-error` negative-type assertion that the input
  shape rejects a `capabilities` field.
- Add a regression assertion that the build-time `profileHash` is
  stable across contracts with no author input.

Drop the now-unused `Capabilities` type parameter from the
`defineTestContract` helper in `contract-builder.constraints.test.ts`
to follow the input-shape change.

Signed-off-by: Will Madden <madden@prisma.io>
The Postgres adapter descriptor now contributes two flags it always
implies:

- `postgres.distinctOn` — gates `SelectQuery.distinctOn(...)` in the
  SQL builder runtime; previously declared by example contracts.
- `sql.lateral` — gates `lateralJoin(...)` / `outerLateralJoin(...)`
  in the SQL builder runtime; previously declared by example
  contracts. The Postgres adapter already contributes
  `postgres.lateral`; the family-namespace flag belongs on the same
  descriptor so SQL-builder gates resolve consistently for any
  Postgres-targeted contract.

After dropping `capabilities` from the `defineContract` input, the
two flags need to come from a component descriptor rather than the
example. They are honest Postgres adapter capabilities, so this is
the right home for them.

Signed-off-by: Will Madden <madden@prisma.io>
…tracts

Author-declared `capabilities: { ... }` blocks on every TS
`defineContract` call site are now removed (examples, apps,
fixtures, projects). With the field gone from the input shape, the
build-time matrix is the merge of the configured component
descriptors only.

Regenerate every emitted `contract.{json,d.ts}`:

- `profileHash` collapses to the empty-author hash for that target
  (Postgres → `1a8dbe04…`, SQLite → `c336398c…`). Same fingerprinted
  shape as before; the input subset is just always empty now.
- `capabilities` matrices reflect the merged set contributed by the
  target, adapter, driver, and any extension packs. Where examples
  had previously declared phantom flags that no component owns
  (e.g. `pgvector.hnsw`, `postgres.partialIndex`), those drop out
  of the matrix; the runtime never gated on them.

The two flags the SQL builder runtime does gate on
(`postgres.distinctOn`, `sql.lateral`) are now contributed by the
Postgres adapter descriptor in a separate commit; this regen picks
those up automatically.

Signed-off-by: Will Madden <madden@prisma.io>
Rebase onto main left ContractInput at five type parameters; align
wrapped defineContract overloads and negative tests with E1 authoring.

Signed-off-by: Will Madden <madden@prisma.io>
@wmadden wmadden force-pushed the onboarding-papercuts/e1-caps-on-by-default branch from 6ba5691 to 2af0d19 Compare May 27, 2026 12:52
wmadden added 3 commits May 27, 2026 15:14
…or postgres adapter caps

Signed-off-by: Will Madden <madden@prisma.io>
…ix and enrich in-memory contract

The Postgres adapter descriptor advertises `postgres.distinctOn` and
`sql.lateral` (added when those flags moved from author-declared to
component-contributed). The runtime `defaultCapabilities` constant
shadowed that set and lost both flags; sync the two so
`adapter.profile.capabilities` matches what the descriptor emits into
the contract (per the README invariant).

Independently, the SQL builder integration test setup builds its
contract in-memory via `defineContract` and bypasses the CLI emit
pipeline that normally folds adapter and driver capabilities in via
`enrichContract`. Run the same enrichment step in the setup so the
runtime capability gates see the merged matrix.

Signed-off-by: Will Madden <madden@prisma.io>
…es removal

Append `remove-capabilities-from-define-contract` to the user-skill 0.11-to-0.12 instructions: delete the `capabilities: { ... }` block from every `defineContract` call site and re-emit so the contributor-declared capabilities (incl. new `postgres.distinctOn` and `sql.lateral`) land in `contract.{json,d.ts}`.

Append `define-contract-drop-capabilities-generic` to the extension-skill 0.11-to-0.12 instructions: facade-style extensions drop the `Capabilities` type parameter from their `defineContract` overloads and supporting type aliases; fixture-only extensions re-emit to pick up the same auto-contributed capability keys.

Signed-off-by: Will Madden <madden@prisma.io>
@wmadden wmadden merged commit 561d3f3 into main May 27, 2026
17 checks passed
@wmadden wmadden deleted the onboarding-papercuts/e1-caps-on-by-default branch May 27, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants