Repository navigation
Description
发现于 #6155 的前提核验(未在该 PR 内修,按 Prime Directive #10 单开)。
两处直接冲突
ADR-0005(accepted,docs/adr/0005-metadata-customization-overlay.md,§"Tenant-customizable type whitelist (shared-DB tenancy invariant)")的表格原文:
| Domain | Type | Per-org override? | Why |
|---|---|---|---|
| automation | flow, workflow, approval |
❌ | Carry execution side-effects (events, jobs, audit). Per-org variants are a deployment, not an overlay. |
同一节还写明「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):
{ type: 'flow', label: 'Flow', …, supportsOverlay: false, allowOrgOverride: true, allowRuntimeCreate: true, … }OVERLAY_ALLOWED_TYPES(metadata-protocol/src/protocol.ts:6860)照此派生,于是 saveMetaItem({ type:'flow', organizationId }) 放行。仓内已有的 packages/objectql/src/overlay-precedence.test.ts:18-22 把这次反转当既成事实记了下来:
Note: object, field, flow, workflow, agent, permission, role, and profile all flipped to
allowOrgOverride: truein commit ba252da (feat: add project mode, metadata forms, and org overlays). The invariant now pins the execution/wiring-layer types that MUST stay false.
为什么是缺陷而不是文档陈旧
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 自称是权威。
已经付出的代价
- org 作用域的 flow overlay 只在「本进程内发布后」绑定触发器,重启后静默失绑——冷启动两条读路径都把 organization_id 非空的行滤掉了 #6190(同批开):org 归属的 flow overlay 因此可写,但两条冷启动读路径都把它滤掉,重启后静默失绑。
- Schedule 触发器不携带任何 org 上下文——定时 runAs:'system' 清扫在多组织部署里仍会产出 organization_id=NULL 的行(#5494 的用户缺席半边) #6155:维护者裁决的主路径建立在「org overlay 里的流程天然归属其 org」之上——该前提是否成立,恰恰取决于本单的定性(若 ADR 表仍然有效,org flow overlay 本就不该存在,主路径就没有主体)。
建议(不越权,只列选项)
- 修 ADR:给 ADR-0005 加修订段,逐类型说明为什么这 8 类可以 per-org override,以及 ADR 原文点名的三条风险(物理表 schema 分叉 / 执行副作用 / 权限静默漂移)各自如何被消解;这也是 Schedule 触发器不携带任何 org 上下文——定时 runAs:'system' 清扫在多组织部署里仍会产出 organization_id=NULL 的行(#5494 的用户缺席半边) #6155 主路径成立所需要的那段论证。
- 修代码:把 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、commit ba252da0b。
Activity
claude commentedon Aug 7, 2026
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:allowOrgOverrideobject,field❌false,falseba252da0bhook❌falsedatasource❌falseagent❌falseflow❌truepermission❌truetool,skill❌true,truepage,app,action❌true**×3view,dashboard,report,email_template,translation✅true×5Two corrections that change the card's scope before anyone prices it:
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).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.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
os-project-manager commentedon Aug 7, 2026
Maintainer 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.
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