Repository navigation
ADR-0005 的租户可定制白名单表说 flow/workflow/approval 一律 ❌ per-org override,注册表却写着 allowOrgOverride: true——反转没有走 ADR(Prime Directive #13) #6191
Description
Activity
Triage:
needs-user-decision+domain:spec+target:v17.Classification
Not a defect card — it asks whether an accepted ADR's recorded decision stands or is superseded. Reversing (or ratifying the reversal of) ADR-0005's tenant-customizable whitelist is a public-contract call on the maintainer's desk, not something a dev agent may guess. Both routes the body lists are legitimate and they are mutually exclusive, so no dispatch is possible until the direction is picked. Filed to the decision inbox unchanged.
Routing rationale (landing site, not title vocabulary)
domain:spec. The authoritative flag isMetadataTypeRegistryEntry.allowOrgOverrideinpackages/spec/src/kernel/metadata-plugin.zod.ts(schema at :216,DEFAULT_METADATA_TYPE_REGISTRYentries at :604-:778) — verified onorigin/main. Every listed route lands there: route 2 edits the flags directly, and route 3 ("whichever route is chosen") stamps the ADR id onto those same entries.packages/metadata-protocol/src/protocol.ts:6860only derivesOVERLAY_ALLOWED_TYPESfrom the flag, so it is a consumer, not the fix site. Per the skill's "shared contract surfaces have one owner", anything touchingpackages/specbelongs to the spec seat regardless of who needs it.Premise check — the drift is real, but the affected set is wrong in both directions
The body's claimed set ("8 types … object/field/flow/workflow/agent/permission/role/profile") is quoted from
packages/objectql/src/overlay-precedence.test.ts:19, which describes the state at commitba252da0b. That note has since gone stale. Measured againstorigin/maintoday, entry by entry:ADR-0005 says live allowOrgOverrideverdict object,field❌false,falseno drift — flipped back since ba252da0bhook❌falseno drift datasource❌falseno drift agent❌falseno drift — contra the body flow❌trueDRIFT (:649) permission❌trueDRIFT (:777) — the one security type still drifted tool,skill❌true,trueDRIFT — not named in the body page,app,action❌** true**×3DRIFT — not named in the body view,dashboard,report,email_template,translation✅true×5no drift Two corrections that change the card's scope before anyone prices it:
- The live drift set is 7 types —
flow,permission,tool,skill,page,app,action— not the 8 the body names. Three of the body's eight (object,field,agent) are already back tofalse; five of the live seven (tool,skill,page,app,action) are not in the body at all. The security exposure the body leads with ("three security types") is in fact one:permission.roleandprofileare not registry types (see 2). - A second, independent staleness in the ADR itself:
validation,workflow,approval,profile,roleappear in the ADR-0005 table but do not exist inDEFAULT_METADATA_TYPE_REGISTRYat all (full live type list: action, agent, api, app, book, dashboard, dataset, datasource, doc, email_template, external_catalog, field, flow, hook, job, mapping, object, page, permission, position, report, seed, skill, tool, translation, view). So the table names five types that were retired or never landed — whichever route is chosen, the amendment has to reconcile those rows too, not just the flags. - Also unlisted by the ADR while carrying
allowOrgOverride: true:dataset,book,position. New types default tofalseper the ADR's closing rule, so these three are additions the table never recorded.
None of this changes the body's core claim — the reversal did happen without an ADR, Prime Directive #13 applies — but it shrinks the security surface, moves five types onto the list, and adds a table-vs-registry membership gap the body does not mention.
Dedup
Full-text scan of all open issues and PRs across the three repos for
allowOrgOverride/ADR-0005/OVERLAY_ALLOWED_TYPES/ba252da0b: no existing dispatch entry for this drift. Nearest neighbours are context, not duplicates — #6155 (the ruling whose main path rests on this card's outcome), #6190 (the concrete defect this gates), #5992 (ADR numbering ambiguity, a different governance defect). Cross-repo: nothing in objectui/cloud.Release board
target:v17on criterion ②: a published document declares seven types cannot be per-org overridden while the runtime accepts exactly those writes — declared ≠ enforced on a contract we ship. It also gates #6190, itself a v17 board item; a blocked blocker with no visible gate makes the board lie.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- The live drift set is 7 types —
os-project-manager commented
on Aug 7, 2026 CollaboratorMore actionsMaintainer ruling — 2026-08-07. The maintainer reviewed the PM's three-axis analysis of the decision inbox and accepted the recommendations (「你帮我综合评估,我接受你的建议」). Recorded by the PM session;
needs-user-decisioncomes off with this comment.Decision: split the eight flipped types into two halves.
- Revert to the ADR table —
allowOrgOverride: false— for the six types with no argued case:workflow,approval(automation row;flowis already ruled back to false via Schedule 触发器不携带任何 org 上下文——定时 runAs:'system' 清扫在多组织部署里仍会产出 organization_id=NULL 的行(#5494 的用户缺席半边) #6155 Q1=B, transfer card [转移·spec] flow 的allowOrgOverride:true回滚为 false——#6155 Q1=B 裁决的契约半边,同步了结 #6191 #6283) andpermission,role,profile(the trio the ADR itself flags as "Authorization correctness; overlays would create silent privilege drift"). Include a migration assessment for any org-scoped overlay rows already stored under these types. object/fieldkeeptrue— the flip is the substance of project mode, i.e. real shipped pull — but the reversal must be legitimized by an ADR-0005 revision section that addresses the ADR's three named risks (physical schema divergence / execution side-effects / privilege drift) specifically for these two types. Until that section merges, the ADR remains the stated authority.
Both halves: leave the governing ADR id on the touched
DEFAULT_METADATA_TYPE_REGISTRYlines and register them inscripts/adr-anchors.json— the reason this flip happened silently is that the edited lines named no ADR (PD #13 corollary).Rationale: PD #13 — reversing a recorded decision is itself a decision needing an ADR; the split follows the evidence — object/field have a shipped feature behind them, the other six never received an argument.
Generated by Claude Code
- Revert to the ADR table —
发现于 #6155 的前提核验(未在该 PR 内修,按 Prime Directive #10 单开)。
两处直接冲突
ADR-0005(accepted,
docs/adr/0005-metadata-customization-overlay.md,§"Tenant-customizable type whitelist (shared-DB tenancy invariant)")的表格原文:flow,workflow,approval同一节还写明「The authoritative whitelist lives on
MetadataTypeRegistryEntry.allowOrgOverride」「The runtime validator (OVERLAY_ALLOWED_TYPES) derives its set from that flag — there is no parallel allowlist」。代码(
packages/spec/src/kernel/metadata-plugin.zod.ts,DEFAULT_METADATA_TYPE_REGISTRY):OVERLAY_ALLOWED_TYPES(metadata-protocol/src/protocol.ts:6860)照此派生,于是saveMetaItem({ type:'flow', organizationId })放行。仓内已有的packages/objectql/src/overlay-precedence.test.ts:18-22把这次反转当既成事实记了下来:为什么是缺陷而不是文档陈旧
Prime Directive #13:「An accepted ADR binds until a superseding ADR says otherwise. Reversing a recorded decision is itself a decision: it needs a new ADR(或旧 ADR 上的修订状态行),not a changeset that quietly does the opposite.」这次反转把 ADR 表里点名为 ❌ 的 8 个类型(object/field/flow/workflow/agent/permission/role/profile,含 ADR 明确写「Authorization correctness; overlays would create silent privilege drift」的三个安全类型)一次性翻成 ✅,ADR 正文与状态行都没动。今天读 ADR-0005 的人得到的是与运行时相反的答案,而 ADR 自称是权威。
已经付出的代价
建议(不越权,只列选项)
allowOrgOverride: false(需评估已在库的 overlay 行的迁移)。DEFAULT_METADATA_TYPE_REGISTRY的相关条目留下 ADR id(Prime Directive [WIP] Add Chinese version of the documentation #13 的推论:实现某个 ADR 决定时把 id 留在代码里),并考虑登记进scripts/adr-anchors.json——本次反转之所以能悄悄发生,正是因为被编辑的那一行没有点名管辖它的 ADR。Refs:#6155、#6190、ADR-0005、
packages/objectql/src/overlay-precedence.test.ts:18、commitba252da0b。