Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .changeset/org-scoped-unique-jsdoc-field-level.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
"@objectstack/driver-sql": patch
---

docs(driver-sql): `isOrganizationScopedUnique` documents the FIELD-level spelling only

The exported helper's JSDoc claimed it judged organization scope "on either
spelling (field-level `unique` or a declared index's `unique`)". It does not,
and never did: both of its call sites pass `field.unique`, while
`normalizeDeclaredIndex` scopes a declared index with a strict
`idx?.unique === 'organization'` — so a declared index's bare `unique: true`
is taken verbatim as global.

That divergence is deliberate (the #4986 answer, ADR-0120 D1), but the comment
invited the tidy-up that would erase it — routing the declared-index branch
through the helper, which is option 1 of #8323 (⛔ rejected by the maintainer,
2026-08-13) and pre-empts the bare-spelling question parked on #5082. The
corrected JSDoc states what the helper actually judges, points at
`normalizeDeclaredIndex` and #5082, and records why unifying the two paths is
rejected: it would silently reinterpret every existing declared `unique: true`
on deployed databases as organization-scoped.

Documentation only — no behaviour, signature or type change. Shipped as a patch
because the helper is a top-level export of the package entry point and
`declaration: true` with no `removeComments` puts this text in the published
`dist/index.d.ts` a consumer reads.
28 changes: 25 additions & 3 deletions packages/drivers/driver-sql/src/schema-drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,31 @@ export function isUniqueScopeDeclared(unique: unknown): boolean {
}

/**
* The organization-scoped spellings: field-level `true` (unchanged since
* #3696) and the explicit `'organization'` synonym (ADR-0120 D1) — on either
* spelling (field-level `unique` or a declared index's `unique`).
* The organization-scoped spellings of a FIELD-level `unique`: bare `true`
* (the positional synonym, unchanged since #3696) and the explicit
* `'organization'` word (ADR-0120 D1). Pass a field's `unique`; do NOT pass a
* declared index's.
*
* This is NOT the scope judgment for a declared index, and it must not be
* reached for there. {@link normalizeDeclaredIndex} decides with a strict
* `idx?.unique === 'organization'` instead, so a declared index's bare `true`
* is taken VERBATIM as global — the `'global'` arm. That the two paths judge
* the same token differently is the answer to #4986, not an oversight: the
* spellings were authored under different contracts, and both halves are
* pinned (`sql-driver-declared-index-organization-respelling.test.ts`).
*
* Routing the declared-index branch through this predicate so code and comment
* agree is REJECTED — maintainer ruling 2026-08-13, option 1 of #8323. It
* would silently reinterpret every existing declared `unique: true` on
* deployed databases as organization-scoped: an unannounced index migration,
* landing a release BEFORE #5082 refuses the bare spelling — the
* two-migrations-with-contradictory-meanings sequence that ruling exists to
* avoid. Whether a declared index's bare `true` should be refused at all is
* PARKED on #5082 (v18 D2: bare `true` → `'global'` plus a loud refusal).
* Until that lands the divergence stays, surfaced to authors rather than
* silently repaired: lint `unique/unscoped-declared-index` warns on it
* (`packages/lint/src/data-model-rules.ts`) and `IndexSchema.unique`'s
* `describe()` states it (`packages/spec/src/data/object.zod.ts`).
*/
export function isOrganizationScopedUnique(unique: unknown): boolean {
return unique === true || unique === 'organization';
Expand Down
Loading