TML-2916: un-namespaced PG models default to public namespace per ADR 223#838
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (19)
📒 Files selected for processing (125)
✅ Files skipped from review due to trivial changes (73)
🚧 Files skipped from review as they are similar to previous changes (44)
📝 WalkthroughWalkthroughUn-namespaced models now resolve to ChangesConditional namespace defaults and regenerated artifacts
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/extension-supabase
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/emitter
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
size-limit report 📦
|
… 223
The contract authoring pipeline injected an empty `__unbound__` storage
namespace into every Postgres contract, in violation of ADR 223 — which
makes `target.defaultNamespaceId` ("public" for Postgres) the static,
target-owned default. Two sites are guarded on `defaultNamespaceId ===
UNBOUND_NAMESPACE_ID` so only SQLite and Mongo (whose default is the
unbound sentinel) keep the slot:
1. `build-contract.ts` — the `ensureUnboundNamespaceSlot` call site at
the end of `buildSqlContractFromDefinition` (the build path both the
PSL interpreter and the TS DSL converge on).
2. `sql-contract-serializer-base.ts` — `hydrateSqlStorage` previously
re-injected the slot on every deserialize round-trip, defeating the
build-time fix during emit. An `abstract get defaultNamespaceId():
string` was added to the base class and implemented in the PG, SQLite,
and Mongo (`SqlContractSerializer` fallback) subclasses.
Regenerates the affected fixtures and baked extension-pack contracts
(pgvector, paradedb, postgis, supabase, audit, feature-flags) to drop
the spurious `__unbound__` slot. Updates the contract-builder.namespaces
tests that encoded the bug as expected behavior. Adds an IR-level test
in interpreter.namespaces that pins the un-namespaced PG → public
invariant end-to-end.
The diamond fixture chain under examples/prisma-next-demo/fixtures/* is
not regenerated by this PR: it has no per-step contract.prisma source
so the regen script cannot rebuild it, and a `grep` of the codebase
shows zero consumers. Left stale; follow-up to add a regen mechanism.
Extends `regen-extension-migrations.mjs` to cover the
multi-extension-monorepo sub-extension packages (audit, feature-flags)
that also carry on-disk migrations + head refs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…struction declarations - postgres-contract-serializer.test.ts: RegistryDispatchProbeSerializer needs to implement the new abstract defaultNamespaceId getter. - skills/upgrade + skills/extension-author 0.13-to-0.14/instructions.md: add TML-2916 incidental-substrate-diff markers so per-pr-declaration CI gate sees the upgrade-instruction files were touched. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
…-2918 Post-rebase regen: TML-2918 (#837) landed schema-qualified op ids (`column.${schema}.${table}.${column}`) for the PG AddColumn op. The prisma-next-demo migration ops.json files now carry `column.public.*` ids; migrationHash updates accordingly. Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
85695a1 to
99d8dc6
Compare
Main shipped the 0.14.0 publish bump (#843) and several follow-ups (TML-2916 #838, TML-2503 #839, TML-2787 #683, TML-2893 #849, ci-fix #847) while slice 1 was in review. Merge to pick them up. Resolution: - `skills/extension-author/.../0.13-to-0.14/instructions.md` — union of the slice's TML-2919 entry and main's TML-2916 entry as two distinct HTML-comment blocks, matching the file's per-ticket convention. Per the skill spec's rebase scenario (lines 122-130): existing entries in the just-shipped 0.13-to-0.14 directory may stay in place; we do not relocate the TML-2919 entry to 0.14-to-0.15. - Lockfile + example fixtures + apps + all other non-slice files — take main's side cleanly (the branch hadn't touched them; auto-merge resolved to main's content). `pnpm install` confirms the lockfile is consistent. - No `src/` conflicts — only the one instructions.md conflict above. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
At a glance
Postgres contracts were emitting an empty
__unbound__storage namespace slot alongsidepublicon every contract — in violation of ADR 223 — Target-owned default namespace, which makestarget.defaultNamespaceId(="public"for Postgres) the static, target-owned default. Surfaced during the #825 (TML-2889) review.The decision
Two sites in the authoring/emit pipeline injected the spurious slot. Both are now gated on
defaultNamespaceId === UNBOUND_NAMESPACE_ID— descriptor-driven, notargetId === 'postgres'branch anywhere (per ADR 223). Only SQLite and Mongo (whose default IS unbound) keep the slot.packages/2-sql/2-authoring/contract-ts/src/build-contract.ts:748— end ofbuildSqlContractFromDefinition, the path both the PSL interpreter and the TS DSL converge onensureUnboundNamespaceSlotcall ondefaultNamespaceId === UNBOUND_NAMESPACE_ID.packages/2-sql/9-family/src/core/ir/sql-contract-serializer-base.ts—hydrateSqlStoragere-injected the slot on every deserialize round-trip, defeating site 1 during emitprotected abstract get defaultNamespaceId(): stringtoSqlContractSerializerBase; implemented in PG, SQLite, and theSqlContractSerializerfamily-level fallback (which preserves legacy behaviour for callers without a target descriptor). Mongo uses its own base class and is unaffected.Why two sites
D1 (diagnosis dispatch) identified site 1 only; the in-memory contract built via the TS DSL was already clean (only
public). D2's emit traced throughexecuteContractEmit→familyInstance.deserializeContract(enrichedIR)→hydrateSqlStorage, where the round-trip re-introduced the slot. Sites 1 and 2 are independent; both need the gate.What's regenerated
src/contract.json+.d.tslose the__unbound__slot; their migrationhead.jsonrefs andmigration.tshashes are rewritten bymigrations:regen.scripts/regen-extension-migrations.mjswas extended to walk these (they live underexamples/multi-extension-monorepo/packages/*, outside the script's originalpackages/3-extensions/walk).apps/telemetry-backend,examples/{bundle-size, paradedb-demo, prisma-next-cloudflare-worker, multi-extension-monorepo/app, prisma-next-demo, prisma-next-postgis-demo}— emitted contracts + migration chains lose the slot; migration hashes update.packages/2-sql/4-lanes/sql-builder/test/fixtures/generated/,packages/3-extensions/sql-orm-client/test/fixtures/generated/,test/e2e/framework/test/fixtures/generated/,test/integration/test/{fixtures,namespaced-accessors/fixtures/generated}/— same.What was NOT regenerated
The diamond + 6 sibling fixture chains under
examples/prisma-next-demo/fixtures/*/migrations/app/. The regen script (regen-example-migrations.mjs) requires a per-stepcontract.prismafor each migration directory to recompute the end-state contract; these chains store onlymigration.tsper step plus a single rootcontract.prismafor the final state. Agrep -rln "fixtures/diamond"(excludingnode_modules,dist,.json,.d.ts) returns zero hits outside the slice's own docs — no test or script reads these fixtures. Left stale on this branch; follow-up to add a regen mechanism or rewrite them.Tests
packages/2-sql/2-authoring/contract-psl/test/interpreter.namespaces.test.ts— a baremodel user { id String @id }interpreted against the PG target producesdomain.namespaces.public.models.user+storage.namespaces.public, with no__unbound__namespace. Goes red onmainwithout the fix at site 1.packages/2-sql/2-authoring/contract-ts/test/contract-builder.namespaces.test.tsthat asserted__unbound__was present in PG storage — flipped to assert post-fix shape with a// TML-2916marker.packages/3-extensions/pgvector/test/descriptor.test.ts:100asserted the install-vector pre/postcheck SQL contained literalextname = 'vector'. The regen produces parameterised SQL ("extname" = \$1+params: ["vector"]), a downstream effect of TML-2889's typed-AST routing of verification queries. Test updated to assert both the parameter placeholder and the params array.ADR-223 grep gate
Returns the same 3 hits as before — all input validation guards rejecting reserved namespace names. No new namespace-defaulting branches.
Related
MigrationPG methods require explicitschema). This PR is the planner/interpreter half.Closes TML-2916.
Summary by CodeRabbit
Release Notes
Refactor
publicnamespace where applicable.Chores
Tests
Documentation