Skip to content

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

Closed

Description

@objectstack-fleet

Ruled: 6028793924 · letter B · 2026-10-07T01:23Z

Filing gate: ② a decision only the maintainer can make. Filed by the triage seat (objectstack-wide, seat post #6015, session_01AavokzJ5DndAwitDXvKy4U) at the maintainer's instruction 「需要我决裁的问题,立决策卡」. ⛔ Not a claim. The ruling is recorded on this card and on the parent, then this card closes.

Parents: #15196 (C2) and #15204 (C3), both target:v18. Found by triage's pre-opening re-verification (6018633315). The contradiction was already in the cards at the cut.

维护者速读

v18 要把"职位、权限集、能力"这些目录统一改为从注册表读取。C2 负责改读法,C3 负责删掉旧的目录表,并给"职位"加一个"包含哪些权限集"的字段。但 C2 改读法时就需要这个字段,而按执行表,C3 又要等 C2 做完,两张卡互相等。

  • A:字段提前到 C2 加,C3 只搬数据、删旧表。过渡期同一个事实有两个来源(新字段和旧的关联表),C2 要同时读两边。
  • B:C2 对"职位→权限集"这一条暂时仍读旧关联表,其余都改从注册表读。C3 再一起完成:加字段、搬数据、切换读法、删旧表。字段和它唯一的读者同时落地。
  • C:把 C2 和 C3 合成一张大卡,一个 PR。

推荐 B。回一个字母:A / B / C。

四棱(os-decision-facets)

  • ① 项目长远合理性:三个选项的终态相同;B 在任何时刻都只有一个来源,A 有一段"两个来源"的特例期。
  • ② 实际业务拉动:职位所含的权限集决定每个用户的权限,今天每次权限计算都会读。
  • ③ 防 AI 犯错:A 的过渡期里新字段和旧表可能不一致,读哪边会悄悄影响结果;B 没有这个窗口。
  • ④ 创业阶段不扩散:B 不增加过渡代码;A 要写合并两边的读法,之后再删;C 一次改动最大,评审风险最高。

Prior rulings read: ADR-0131 §8 (C3 after C1 + C2), D2, D3, D4, D13; spec/src/identity/position.zod.ts:51 (today's closed-shape refusal of the key); thread: #15196, #15204.

一句话问题

"职位包含哪些权限集"这个新字段,什么时候加、由哪张卡读,才能解开 C2 和 C3 互相等待?

选项 × 代价

选项 做什么 代价
A C2 加 PositionSchema.permissionSets(替换第 51 行的拒收说明),并在读取时合并关联表的行;C3 迁移数据、退役关联表 过渡期有两个来源,需要合并的读法和对应测试
B C2 对这一条关系保留读 sys_position_permission_set;C3 加字段、迁移、切换读取、退役关联表 C2 的"目录全部从注册表读"在 C3 之前差这一条
C C2 和 C3 合并 一个超大 PR(XL),评审和回滚都更难

推荐 + 回退 + 置信缺口

  • 推荐 B。 两年后,职位所含的权限集只写在职位定义里,读取只有一个来源。这与 Salesforce Permission Set Group 把成员关系写在定义里的建模一致。
  • 回退 C。
  • 置信缺口: 两张卡都还要按复核意见改,体量估计未实测。
  • 只看①选 B;②③④ 是否翻转:否。

裁后执行


Generated by Claude Code

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:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they land
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    on Oct 6, 2026
  2. objectstack-fleet commented on Oct 7, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #283 item 4 · letter B · maintainer 「其他同意」 2026-10-07T01:17Z

    Director seat, summon #35, session_01VYToj6PQehTEKNrjGM9akg (GitHub os-zhuang; written as objectstack-fleet[bot] via the relay). Batch #283 was presented in chat with this card's options A / B / C; the maintainer answered 「其他同意」 for the four cards of the batch whose recommendation stood, this one among them, which takes B. Freshness gate: the body (no comments) and both parents' threads (#15196: re-verification 6018633315; #15204: re-verification 6018622568) were re-read before this record; nothing newer exists. Thread-read: none on this card.

    The ruling

    B. C2 (#15196) moves every catalog read to the registry EXCEPT the position-to-permission-set relation, which keeps reading sys_position_permission_set until C3. C3 (#15204) then lands the field and its only reader together: PositionSchema.permissionSets replaces the closed-shape refusal at packages/spec/src/identity/position.zod.ts:51, the rows migrate into the position definitions, the read switches, and the join table retires. ADR-0131 §8 keeps its order (C3 after C1 and C2). ⛔ Not taken: A (the field lands in C2 and the read merges two sources for a transition window, where the two can disagree and silently change a permission result) and C (one XL change set that is harder to review and to roll back).

    Why B: the end state is the same under all three, and under B there is never a moment with two sources of truth for which permission sets a position carries, a relation read on every permission computation. It matches Salesforce's Permission Set Group modelling, where the membership lives in the definition.

    State


    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 7, 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:engineRetired 2026-10-22, alias of domain:server (engine surface); in-flight cards keep it until they landpriority: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