docs(adr): ADR-0120 draft — explicit unique-scope vocabulary (organization/global) and NULL-safe per-organization uniqueness (#4986, #5030) - #5054
Draft
os-zhuang wants to merge 6 commits into
Conversation
…-safe tenant uniqueness (#4986, #5030) Proposed-status draft for maintainer review. Records the amendment of the #3696 verbatim-declared-index decision into an explicit 'global' | 'tenant' scope vocabulary (D1), a lossless ADR-0087 D2 conversion for stored metadata (D2), NULL-safe COALESCE tenant key parts fixing #5030 (D3), the duplicate-pre-flight migration ceremony (D4), authoring gates (D5), the five-surface truth sweep (D6), 17.x -> 18 staging (D7), and the freeze on unilateral driver-sql changes until acceptance (D8). Docs-only: no code semantics change in this PR. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Akrzh2mHi2siSNVPPtfTw7
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
…nstraint Maintainer requirement from #4986 review: one metadata app must run unmodified under single-org and multi-org deployment; the author states the business boundary of a unique constraint, never the topology. Adds the governing principle, a dedicated Mode portability section with the declaration x mode matrix and both mode-transition stories (single->multi relaxes with zero migration; multi->single tightens through the D4 ceremony), matrix row S13, a D1 anchor line, and the dual-mode conformance requirement in Acceptance tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Akrzh2mHi2siSNVPPtfTw7
…portability Maintainer review round 2 on #4986. Two corrections from review: 1. The authorable word 'tenant' was ambiguous — the platform has a second tenancy sense (database-per-customer environments) besides row-level organization scoping. The scope tokens are now 'organization' and 'company'; 'tenant' is not accepted even as an alias, and a Terminology section records why. 2. Multi-org splits into group (one corporate family) and isolated (organizations are separate customers) postures per ADR-0105 D1, which makes 'company-wide unique' posture-VARIANT: installation-wide under group, per-organization under isolated. A third scope word 'company' is added, resolved to one of the two existing physical shapes at registration where the posture is known; posture transitions re-resolve it through the D4 ceremony. New matrix row S14, reworked Posture portability section with the declaration x posture table and the acquisition/consolidation transition stories, acceptance coverage for all three postures, and two new open questions (token name; where the isolated-posture 'global' advisory lives). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Akrzh2mHi2siSNVPPtfTw7
This was referenced Aug 4, 2026
Maintainer ruling on #4986 review round 3: a posture change is a planned re-platforming event, expected to be rare; the platform's obligation is a well-defined target state and a trustworthy migrate plan, not built-in transition machinery. Per ADR-0087's operating assumption the migrator is an AI agent that writes the upgrade script from the D4 plan (including the duplicate probe report). Transition acceptance coverage slimmed to one smoke assertion; D1 and Consequences reworded to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Akrzh2mHi2siSNVPPtfTw7
…deployment-seam handling for S14 Maintainer ruling round 4: a posture-resolved third word is the only token in the vocabulary that cannot be used without first understanding the posture spectrum — too easy for AI authors to confuse — and the scenario it served is rare. Vocabulary stays 'global' | 'organization'. The S14 residual (company-wide keys in a posture-portable app) moves to the deployment seam: author 'global', and under isolated posture os doctor / migrate plan surface each 'global' business unique as an explicit decision point (confirm or rewrite to 'organization', AI-authored install adjustment). Posture flips now have zero automatic schema consequences by construction. The rejected design is recorded in Alternatives #6 per PD #13; open questions renumbered (now four). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Akrzh2mHi2siSNVPPtfTw7
…ecisions) Q1: COALESCE literal is '__global__' (flipped from '') — self-describing constraint-violation errors for AI ops triage, and one vocabulary with the autonumber GLOBAL_TENANT; org creation reserves the token, storage stays NULL. Q2: field-level bare true stays valid indefinitely; examples and scaffolding emit 'organization' as non-normative guidance. Q3: D3 ships in 17.x — waiting compounds the duplicate sets the D4 probe must report, and the protocol-18 wave is physically empty either way. Q4: the isolated- posture decision point is a hard install-time gate with recorded confirmations (new D5e); doctor/plan keep the advisory form for pre-gate installs and posture changes. Open-questions section converted to a resolved-decisions record. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Akrzh2mHi2siSNVPPtfTw7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这是什么
#4986 维护者裁定后的 ADR-0120 完整草案(Status: Proposed),一张 ADR 同时覆盖 #4986(表级声明唯一索引的组织语义岔路)与 #5030(NULL 组织行上复合唯一约束蒸发)。本 PR 仅新增 ADR 文档,零代码语义改动 —— D8 明确:ADR 被接受前,driver-sql / spec / lint 均不动。
已含五轮维护者评审:①「app 元数据姿态可移植」为总纲(
single | group | isolated,ADR-0105;每客户单库 = 环境级选择);② 词汇弃用'tenant';③ 姿态切换罕见、不自动化,执行交 AI 写升级脚本;④ 第三词'company'被否(记入 Alternatives #6),S14 改部署接缝处理;⑤ 四个遗留评审问题全部裁决(见下),Open questions 节已转为 Resolved 决策记录。决定摘要(D1–D8)
unique: 'global' | 'organization'两种写法通用,两词均不依赖姿态;声明索引裸true弃用(17.x 警告 → 协议 18 拒绝);字段级true永久合法,官方示例/脚手架一律输出'organization'(非规范性引导)。true → 'global',存量库零漂移;九个 engine-owned 幂等键钉死不变。COALESCE(organization_id, '__global__')—— 报错自述平台桶、与 autonumber 的 GLOBAL_TENANT 同词;组织创建保留该 token,存储仍为 NULL;17.x 落地。recreate_index+ 重复数据预检,预检不净永不自动应用。'global'业务唯一装进isolated环境逐索引确认/改写,留痕不复问;doctor/plan 兜底存量与姿态变更)。true。四个评审问题的裁决(2026-08-04,详见 ADR §Resolved review questions)
'__global__'(从''翻转):事故现场报错自述性 + 子系统词汇统一(多租户缺陷:unique 物化为全局唯一索引、无视 tenancy,与按租户分裂的 autonumber 序列自相矛盾(跨租户必然撞号 + 存在性探测泄露) #3696 教训)。true永久合法:无歧义无陷阱,弃用只买 churn 不买安全;示例引导显式写法。isolated决策点 = 安装期硬门 + 留痕:危险方向(跨客户唯一墙 + 存在性泄露)永不静默落地;advisory 只兜历史存量。ADR 已无未决问题,可评审定稿(Proposed → Accepted)后拆实现波次。
Refs #4986, #5030 · Amends #3696 · Relates #4698, #4884, ADR-0105
🤖 Generated with Claude Code
https://claude.ai/code/session_01Akrzh2mHi2siSNVPPtfTw7