Skip to content

[Decision] ADR-0131 剩余部分(C2 余下阶段 + C3):继续分段、合并成一次切换,还是改成「registry 支撑的对象」 #22601

Closed

Description

@objectstack-fleet

Ruled: 6094045326 · letter B · 2026-10-10T05:08Z

Filing gate ②:只有维护者能做的决定。分诊席(seat post #6015,session_01AavokzJ5DndAwitDXvKy4U)按维护者在本会话的要求立卡:

  • 「需要我决裁的问题,立决策卡」;
  • 维护者问 C2 为什么这么大:「这么小的需求怎么搞出这么大这么复杂的开发?没有更简单的通用方案吗?」;
  • 「是否做一个『registry 支撑的对象』也应该卡决策卡」;
  • 「C3 才真正撤掉四张表和种子器,这个风险更大吧,是否也要决裁?」

本卡按维护者新定的规矩,每个选项都带开发工作量:「以后总监决裁的时候还应该适当评估开发工作量。」(落实卡 #22597)。⛔ 不是认领。读者:总监席呈报,然后由执行车道落地。 Ruled B (6094045326); the execution carriers are #15196, #15204, objectui#7611 and the triage seat.

一句话问题

「岗位、权限集、能力只存在 registry 里」这件事已经做了 3 天、16 个 PR,还剩 C2 的 4 段和整个 C3(撤四张表和种子器,风险最大的一段)。剩下的部分是按原计划逐段过渡,还是合并成一次切换,还是换一条路:四张表不撤,改成读写都落在 registry 的「虚对象」?

背景(实测,objectstack main 99801d831f,objectui main d758f2f20d)

Governing text

  • ADR-0131 D2–D4(目录只有一个家,按名引用,resolution 只读 registry),D7(Setup 和选择器读 registry),D13(四个对象退役),D14(分期:除一处 17.3 前的列修正外,全在 v18 线)。
  • ADR-0094 D1/D3:权限集早已是「数据门写入重定向到元数据,再投影成行」,也就是一个单类型的「registry 支撑对象」。ADR-0131 D2 裁定这个投影不再需要。
  • 决策框架:「过渡也从紧 —— 创业阶段不渐进」,「新增门禁默认否」,「长远合理性权重恒 ≥50%」。

协议声明

  • A 和 B 不改已裁的终态,只改分期,需要修订 ADR-0131 D14 的分期段。
  • C 改终态(四个对象不退役,改为 registry 支撑),需要修订 ADR-0131 D2/D13,而且新增一个公开的对象能力(Clause-②: yes)。

选项 × 真实代价 × 开发工作量

选项 做什么 客户能感知的后果 开发工作量(按已落地同类 PR 估)
A 继续分段 C2 余下 4 段逐段落地,每段 main 可用、授权不变(双读、回退读行、关联表 id 桥接留到 C3);然后 C3 撤表撤种子器;C7 迁移;C8 删 id 列 发布前无感;v18 发布时一次升级 C2 余:4 个 PR、3 个车道,约 4.5–6k 行(S5a/S5b 读者切换各约 1.9k)。C3:5–8 个 PR、3 个车道加 objectui,约 8–12k 行(删约 5.2k 源码,改约 270 个测试文件)。按近期节奏,到 C7 落地约 5–8 天
B 合并切换(终态同 A) 把 S8a/S8b/S9 和 C3 合成一次切换:读者切到 registry 与撤表、撤种子器、撤投影器同批落地。可以是一组 PR,在短窗口内连续合并,不再做只为中间状态存在、随后又要删掉的过渡件。C7 迁移不变 同 A 比 A 的「C2 余 + C3」少约 20–35%,约少 2–3 个 PR、3–5k 行。置信度低:未逐段实测
C registry 支撑的对象(终态改变) 四张表不撤,改成没有行的对象:数据门的读来自 registry,写转到元数据门(把 ADR-0094 D3 推广成通用机制,不要投影)。Setup 和 objectui 继续走数据门 发布前无感;Setup 不用改 新增 objectql 通用机制约 3–5k 行(参照:单类型的投影加同步写约 2.3k)。可省 objectui 6 个文件的改动和 S8b 的一部分;种子器、投影器、逐组织目录照删。总量与 A 相近或略少,但留下一个要长期维护的新机制。另需修订 ADR

子问题 Q(S8b 前必须裁,三个选项都需要): single 下两个组织同名岗位:

  • (a) 岗位名全部署唯一,第二个持有者被明确拒绝(席位倾向;属于收紧);
  • (b) 其他规则。

业务含义

  • A: 稳妥地边开车边换轮子,但每换一个零件都要先装一个临时支架,事后再拆。
  • B: 车还没上路(v18 没发布),直接在车库里一次换完。
  • C: 不拆旧仪表盘,把它的线改接到新引擎上;以后多了一个转接盒要一直维护。Salesforce 的 PermissionSet、Profile 就是这种「一份存储,两扇门」。

四轴(从业务看)

  • 项目长远合理性: A 和 B 的终态一样:定义归元数据门,记录归数据门,一类东西一扇门(D7:界面不在服务端合并来源)。C 的终态是一份存储两扇门,主流平台有先例,但它恢复了 ADR-0131 已经退役的数据门入口,并新增一个通用机制。
  • 实际业务拉动: 今天的拉动是 3 个目录类型(岗位、权限集、能力),加上 objectui 的 6 个文件。没有其他元数据类型在等「以数据门读写」。C 的通用性目前没有第二个用户。
  • 防 AI 犯错: A 和 B 让 AI 只学一条路(目录都走元数据门)。C 的「看起来是表其实不是表」,会让 AI 写出关联查询、报表、批量写,必须一一响亮拒绝,否则就是静默错误。
  • 创业阶段不扩散: B 最少(不造过渡件),A 次之。C 新增一个永久机制,违背「无拉动不扩散」。

维护者速读

「岗位和权限只存在一个地方」这件事已经做了 3 天、16 个 PR,还剩最难的一段:把旧的四张表和种子器撤掉(C3)。剩下的有三条路:A 照原计划一段一段过渡,每段都装临时支架再拆;B v18 还没发布、没人在用,直接一次切换,省掉临时支架,工作量大约少两到三成;C 不撤旧表,改成「读写都落在新位置的虚表」,Setup 页面不用改,但平台从此多一个要长期维护的通用机制。另有一个子问题 Q:同一个岗位名被两个组织都用了怎么办,推荐 (a) 全部署唯一、第二个被明确拒绝;没有异议就按 (a) 执行。

选 A、B 还是 C?

os-decision-facets

  • ① 项目长远合理性:A=B 的终态缩小特例(一类东西一扇门);C 增生一个通用机制,并恢复已退役的数据门入口。
  • ② 实际业务拉动:3 个目录类型加 objectui 6 个文件;C 的通用性零额外拉动。
  • ③ 防 AI 犯错:A/B 结构上只有一条路;C 需要逐项响亮拒绝「表的错觉」。
  • ④ 创业阶段不扩散:B 不造过渡件,最省;C 新增永久义务。

Prior rulings read: ADR-0131 D2/D3/D4/D7/D13/D14; ADR-0094 D1/D3; #22006 B (6028793924); #15196 Q3 A · Q4 A (6050490870); S7 A (6075437096); thread: none on this question.

推荐:B,回退 A;子问题 Q 推荐 (a)。

  • 只看①:A、B 终态相同且优于 C,所以①选 A/B 的终态。
  • ②③④ 只调分期:④和新定的工作量规矩都偏向不造过渡件,所以取 B。
  • 自检:只看①选 A/B 终态;②③④ 是否翻转:否,只决定分期取 B。

置信缺口:

  • B 能省多少没有逐段实测;
  • C 的通用机制在 RLS/FLS、审计、回收站、触发器上的完整语义未实测;
  • objectui 的 6 个文件能否先改为读元数据门:GET /api/v1/meta/position 在 v17 也存在,未逐个核实。

裁后执行(你只需裁方向)

  • 选 B:
    • C2 的 S5c 照常(三个选项都需要)。
    • S8a/S8b/S9 不再单独落地,与 C3 合并:由分诊重核 C3 清单(它已 DRIFTED),出一份「切换批」的阶段计划,列 PR 序列、车道和每段的授权等价测试,以及先落 objectui 6 个文件的改读卡。
    • 修订 ADR-0131 D14 的分期段。
    • 子问题 Q 按所裁执行。
  • 选 A: 按现计划继续;S8b 等子问题 Q 的裁决。
  • 选 C: 先立 ADR 修订和通用机制的契约卡(domain:spec + domain:engine);C3 改为「替换四个对象的存储」;S8b 的一部分取消。

相关: #15196(C2)、#15204(C3)、#15211(C7)、#22006、#22597(工作量规矩)、cloud#2709。

Activity

  1. added
    priority:p1High: required for production / M2
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    on Oct 10, 2026
  2. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #309 item 1 · letter B · maintainer 「同意」 2026-10-10T05:05Z

    Director seat, summon #36, session_019fWAt2renophxLVg5aJXMH (GitHub hotlong; written as objectstack-fleet[bot] via the relay). Batch #309 was presented in chat as this card alone, on the maintainer's instruction 「先处理 22601」, with this seat's own readings (below) and the recommendation B, fallback A, sub-question Q (a); the maintainer answered 「同意」, which takes the recommendation whole. Freshness gate: the body (10,393 bytes, unedited since filing) and the comment list (none) were re-read before this record; #15196's newest comment is 6093457233 and #15204's is 6093460731, both the triage pointers to this card; nothing newer exists. Thread-read: none on this card.

    The ruling

    • B — one cutover. C2's remaining reader switch (S8a, S8b, S9) and C3 (refactor(plugin-security,platform-objects,spec): retire the catalog seeders, the per-organization catalog machinery and the four catalog objects; Setup creation is an environment write under single and refused under a wall (ADR-0131 D2/D3/D5/D13) #15204: the seven seeders, the permission-set projector, the per-organization catalog machinery, the four catalog objects, PositionSchema.permissionSets with the junction-row migration and the read switch) land as ONE cutover batch: a sequence of PRs merged in a short window, each green on its own and leaving main usable, with ⛔ no transition piece built for an intermediate state the batch itself removes — no position projector, no metadata-first dual write replacing S7's write-through, no row fallback read, no junction id bridge. S5c (domain:cli: verify reads the name column) proceeds now as planned; every option needs it. C7 (feat(objectql,cli): inventory + migration — four fates per object, mirrors deleted only after the id→name rewrite is verified, per-table boot report (ADR-0131 D10) #15211) follows the cutover unchanged; C8 unchanged. The end state is ADR-0131 D2/D3/D4/D7/D13 as written.
    • Sub-question Q → (a). Under single a position name is unique per deployment: a second holder (a second organization's row of the same name) is refused loudly at the write door, extending the S10 refusal; the C3/C7 migration treats an existing same-name pair as conflicting and REPORTS it for the operator (D10 fate 4: never guessed, never merged); the S7 write-through's last-write-wins over such a pair is not carried forward. This is the direct consequence of Q4 A (6050490870: one namespace per deployment for the three security catalog types), recorded here so S8b and C3 do not return to the decision box.
    • ⛔ Not taken: A (stage by stage, each stage carried by dual reads, row fallbacks and id bridges that C3 then deletes — transition pieces for an intermediate state no deployment runs: cloud is pinned at 56bf27affb on the v17 line and waits for C7, cloud#2709 B) and C (the four objects kept as registry-backed virtual objects: a new generic objectql mechanism with no second consumer, a revision of D2/D3/D7/D13, and a table-that-is-not-a-table that every AI-authored app would have to be refused on, join by join and trigger by trigger).

    Why B on the first axis

    A and B share the end state, and that end state is a strict narrowing: definitions behind the metadata door, records behind the data door, one kind of thing behind one door; four objects, one projector and one per-organization copy machinery fewer. C restores the data-door entrance ADR-0131 retired and adds a generic mechanism whose semantics (RLS/FLS, audit, trash, triggers, joins, reports, schema sync) would each need defining and refusing. Between A and B only the staging differs, and D14's own reason — no dual columns and no registry-first-then-rows resolution carried for a shape nobody has used — applies inside the v18 line as much as across releases. The workload rule (#22597) points the same way: B skips the enumerable pieces A would build and then delete (a position projector with a metadata-first dual write, the row fallback reads, the junction bridge; roughly 2–4k lines and 2–3 PRs by the S7 and projector precedents, not measured stage by stage).

    Readings this seat took (objectstack origin/main 3e72f93, objectui 1b2d016, cloud 37c706b)

    • The seven seeders, permission-set-projection.ts (1766 lines) and per-organization-catalog.ts (694 lines) are as the card states; bindBaselineToEveryone is a closure in security-plugin.ts (from line 4643), not a module.
    • The card's objectui count of 6 files is low: at least 10 objectui source files read the four tables through the data door (AssignedUsersSection, CapabilityMultiSelectField, RecipientPickerField, useApproverDirectory, approverIdentity, decisionOutputParams, recordDelete, permission-set-clone-dispatch, the data-objectstack special case, RecordDetailView's slot, PermissionMatrixEditor's capability read), and the Setup position and permission-set pages are generic ObjectViews over the data door (the AppContent routes). That is C9 (ADR-0131 §8, objectui#7611), owed under A and B alike, with D7's parity criterion.
    • ADR text: D14 fixes only C1–C6 before C7 before C8; §8 has C3 blocked by C1 and C2. The S1–S10 staging is the services seat's census plan (6038897018), not ADR text. So A needs no ADR change; B needs one execution-plan note in §8/D14 (C2's reader switch and C3 land as one cutover, still before C7), Tier H; C would have needed D2/D3/D7/D13 revised and a new spec key. §5 never considered C: it is a new proposal, not a rejected one, and it conflicts with D13.
    • Q4 A (6050490870) already gives the three catalog types one namespace per deployment; decision: ADR-0131 C2/C3 order — C2 must read positions' permission sets, which only C3 adds, while §8 makes C3 wait on C2. Which way is the knot cut? #22006 B (6028793924) rejected one XL change set and keeps the field and its only reader landing together. Both hold under this B: the cutover is a sequence of PRs, and the field still lands with its only reader.

    Prior rulings read: ADR-0131 D2/D3/D4/D7/D13/D14/§8; ADR-0094 D1/D3; #22006 B (6028793924); #15196 Q3 A · Q4 A (6050490870); S7 A (6075437096, whose item 2 is Q); C3 re-verification DRIFTED (6018622568); cloud#2709 B (6081163069); thread: none on this card. 自检:只看①选 A/B 终态;②③④是否翻转:否,只定分期取 B。

    State and execution


    Generated by Claude Code

  3. removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Oct 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landedpriority:p1High: required for production / M2target:v18

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions