docs(driver-sql): isOrganizationScopedUnique judges the FIELD-level unique only - #8512
Conversation
… `unique` only (#8463) The JSDoc claimed the helper governed "either spelling (field-level `unique` or a declared index's `unique`)". It does not: both call sites pass `field.unique`, while `normalizeDeclaredIndex` scopes a declared index with a strict `idx?.unique === 'organization'` instead — so a declared index's bare `true` is taken verbatim as global. The corrected JSDoc states the field-level scope plainly, points at `normalizeDeclaredIndex` and the parked question on #5082, and records why unifying the two paths is rejected (option 1 of #8323, maintainer ruling 2026-08-13): 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. Comment-only: no behaviour, signature or type change. Patch-bumped because the helper is a top-level export and the text ships in `dist/index.d.ts`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VoxQqG5FiUHZKCST7KDoZC
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 8 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also reference the affected code. These are read-only:
|
Fixes #8463
Comment-only correction. No behaviour change —
normalizeDeclaredIndex, the helper body, and every call site are untouched.The defect
The exported helper's JSDoc claimed it judged organization scope "on either spelling (field-level
uniqueor a declared index'sunique)". It does not, and never did.origin/main@e474853schema-drift.ts:82-84—return unique === true || unique === 'organization';:933—isOrganizationScopedUnique(field.unique):1102—if (!isOrganizationScopedUnique(field.unique)) continue;:987—} else if (idx?.unique === 'organization' && tenantField) {— a strict equality, not the helperBoth call sites are field-level. A declared index's bare
unique: trueis therefore taken verbatim as global.Why the code is right and the comment was wrong
The divergence is deliberate — the #4986 answer, ADR-0120 D1 — and it is already pinned and documented elsewhere (both verified, not assumed):
packages/lint/src/data-model-rules.ts:101shipsunique/unscoped-declared-index, and itsindexUniqueScopeat:137-141states the declared-index contract.packages/spec/src/data/object.zod.ts:401—IndexSchema.unique'sdescribe()says baretrueis the deprecated positional spelling of'global'.sql-driver-declared-index-organization-respelling.test.ts:161pins that a declared baretruetakes the listed columns verbatim, with no tenant column.The hazard was that the comment invited the obvious tidy-up — routing the declared-index branch through the helper so code and comment agree. That edit is option 1 of #8323, ruled out by the maintainer on 2026-08-13, and it pre-empts the bare-spelling question parked on #5082. It would silently reinterpret every existing declared
unique: trueon deployed databases as organization-scoped: an unannounced index migration, landing a release before #5082 refuses the bare spelling.Neither #8323 nor #5082 is addressed here; both remain open.
What the new JSDoc does
States the field-level scope plainly; names the declared-index path's strict-equality requirement and the verbatim-global reading of bare
true;{@link normalizeDeclaredIndex}; points at #5082 for the parked question; and records the rejected-unification reasoning so the next reader learns why the disagreement is correct rather than re-deriving the hazard.Changeset:
patchJudged on this package's own evidence rather than by copying the
driver-sqlprecedent in #8283 / PR #8488 (aprotectedmember). Stronger case here:isOrganizationScopedUniqueis a top-level export atsrc/index.ts:86, the package is published (noprivate),typesisdist/index.d.ts,declaration: trueis set in both the package and base tsconfig, and noremoveCommentsexists anywhere. Verified empirically by building — the corrected text appears verbatim atdist/index.d.ts:39-65.Verification
pnpm --filter '@objectstack/driver-sql' test— 90 files / 1457 tests passed, 4 files / 52 skipped.typecheckclean. Gates green:check:nul-bytes,check:driver-conformance,check:test-source-alias,check:type-source-resolution,check:empty-changeset(re-run post-commit:1 declaring changeset(s) added),check:changeset-gate-self-tests,check:objectui-changeset,check-adr-0087-registration,check-changeset-no-major.check:objectui-pin-freshandcheck-dev-prereqsare known-ambient.Reverse verification does not apply to a comment-only change — there is no behaviour to invert. Each claim the new text makes was instead checked against the code it describes, at the file:line above.
Generated by Claude Code