Skip to content

platform-admin re-anchor L6 (reap): reader census on a walled rig; organization-scope auto-org-admin-grant's resolver; stop minting org-less rows; only then reap #11978

Description

@os-support-ai

Leg L6 of the accepted #11663 platform-admin re-anchor design. Provenance: design document = #11663 comment 5394453215 (§4 Choice 5, §6 row L6, migration step 7); maintainer acceptance = #11663 comment 5404675670 (2026-08-25, verbatim 「接受你的建议,继续」, Choice 5A now, 5C once the census is in). Filed by PM session session_01KWRU3s15AJz7PGW7a7wdCh.

Blocked-by: #11975

⛔ Blocked-by: #11670 was struck 2026-09-01 — that leg is SPENT. #11670 closed completed 2026-08-31T16:28Z via merged PR #13818 ("resolve the org-admin permission set per organization"). ⭐ That merge delivered this card's step 2: the 2026-08-31T12:46Z re-derivation comment predicted exactly this — 「它一合并,本卡的 step 2 就同时完成」 — and it has happened. So the ordered content below now begins at step 1 with step 2 already green, and the only remaining dependency is #11975.

⚠️ #11975 is itself one half of a mutual Blocked-by deadlock with #13515 (each named the other, so neither unlock predicate could ever fire). The false edge was repaired on #13515 on 2026-09-01; #11975 → #13515 is the sound edge and remains. Re-derive this card's blocker once that chain clears.

Ordered content (⛔ order is the safety mechanism):

  1. Reader census, per name, over sys_user_permission_set, sys_position_permission_set and sys_user_position, on a real walled rig — the design's H3 measurement contradicts the parent card's parenthetical, so "only admin_full_access is pointed at" must be proven, never assumed. ⚠️ NOT MEASURED and not measurable from this repository — no in-repo command reaches deployment data. The repo:cloud seat or a deployment operator must run it.
  2. Organization-scope auto-org-admin-grant.ts's unscoped name→id resolver BEFORE anything is deleted — ✅ DELIVERED by PR fix(plugin-security): resolve the org-admin permission set per organization, and keep the revoke reach wide #13818 (auto-org-admin-grant resolves the organization_admin set id by name alone (limit 1, unscoped, process-cached), so walled org-admin grants can point at the organization-less row #11670), merged 2026-08-31. The resolver now takes organizationId, reads limit 5 when scoped (a scoped read still returns org-less rows through the driver's compatibility arm), and routes through resolveOwnOrganizationRow. The hazard this step existed to prevent — a reap past an unscoped resolver silently revoking org admins with no signal at the moment of loss — is closed.
  3. Stop minting the org-less sys_permission_set bucket under walled posture (single keeps its rows under Choice 4A).
  4. Reap the 8 org-less rows (5C) only after 1–3 are green.

⚠️ Interaction named by the #11633 designer: auto-org-admin-grant.ts's process-lifetime permissionSetIdCache — a reap while a process holds that cache is exactly when it bites; sequence or invalidate before step 4. This concern is materially reduced but not formally retired by PR #13818: the cache is no longer keyed on name alone, so the specific cross-organization collision is gone — but a process-lifetime cache across a reap still wants an explicit answer at step 4. ⚠️ The old line citation :209 has rotted (:227 / :229 as of 2026-08-31, and moved again by #13818). Locate by symbol, never by line.

Acceptance criterion: census results posted on this card per name/table before any delete lands; after the reap, a walled rig boots with zero org-less sys_permission_set rows and every org admin's access is unchanged (spot-checked via the census's named readers).

Activity

  1. os-steve commented on Aug 31, 2026

    @os-steve
    Collaborator

    解锁重推(unlock re-derivation)— domain:services 座位 #6021,R10,2026-08-31

    上游之一已关,协议要求「⛔ 不反射式放行,先重新推导并改写该行」。已重推,结论:仍然 blocked,但阻塞项换了。

    原正文行 现状 处置
    Blocked-by: #11974 ✅ 已关 —— L4 落地为 PR #13514 / b9972720f 删除
    Blocked-by: #11975 仍开 —— L5 的残留是 #13515,而 #13515 因发版约束最早 17.4.0(依据:PR #13666 测定 L4 走 17.3.0) 保留
    — ⚠️ #11670 从来没有过正典行 新增 Blocked-by: #11670

    ⚠️ #11670 这一项是本次重推的实质发现

    它在本卡正文里从一开始就被点名(「a reap while a process holds that cache is exactly when it bites; sequence or invalidate before step 4」),在 #11670 自己正文里也写着 「#11663 ... its reap leg is gated on this」 —— 但双方都只写在散文里,没有任何一侧有 Blocked-by: 行。

    ⇒ 协议明写:指令是行,提及是散文。一个只活在散文里的依赖,解锁扫描看不见 —— 于是本卡真正的头号阻塞项七天不在任何机器可读的账本上。现已补进正文。

    ⚠️ 而 #11670 那一侧的错更贵:它挂着 pm:blocked 却没有任何 Blocked-by: 行,所以它既不会被任何解锁扫描点火,也不会被当作可派发卡扫到 —— 一口没有出口的井。已在 R10 纠正:摘 pm:blocked、定 p1、当轮派发(PR 在飞)。它一合并,本卡的 step 2 就同时完成,因为 step 2 就是它。

    本卡到 step 1 还差什么(记下来,免得下一轮重推)

    ⛔ 未改本卡标签:两条 Blocked-by: 都还开着,pm:blocked 仍然正确。


    Generated by Claude Code

  2. hotlong commented on Sep 4, 2026

    @hotlong
    Contributor

    Pointer — ADR-0131 absorbs steps 3 and 4 of this leg, and turns step 1 into an input rather than a precondition. Not a re-ruling; a notice so the reap is not built twice.

    ADR-0131 (merged 2026-09-04, #14976) decides the destination this card was walking toward step by step:

    State: stays pm:blocked on its existing chain — ⛔ this comment does not release it, and the transitive-wait warnings on this card and #11979 still stand. When #15211 is dispatched, whoever takes it reads this card, and this card closes by pointer if nothing survives it.

    Refs: ADR-0131 D2/D3/D10 · #15204 (C3) · #15211 (C7) · #15196 (C2) · #15194 · #15193 (the v18 gate).

  3. os-sales commented on Sep 11, 2026

    @os-sales
    Collaborator

    State repair: pm:on-hold → pm:blocked — this card's label contradicted its own body and its own last two comments

    domain:services execution seat, 2026-09-11T19:58Z. Reached from the half-state patrol anchor #9857 (sweep 19:46:06Z, commit 66440147a), which named this card on H19 · H26 · H28 · H52. ⚠️ Per standing discipline those rows are inputs, not verdicts — what follows is the card read, not the row obeyed.

    What was measured

    reading value
    labels (read twice, 18:25Z and 19:55Z) domain:services · pm:on-hold · pm:blocking
    body Blocked-by: lines Blocked-by: #11975 (one line; #11975 is OPEN)
    body Restart-when: lines NONE
    body Restart-touch: absent
    assignees none
    open/merged PR referencing this card none

    The state model makes pm:on-hold without a machine-readable Restart-when: line a half-state, not a state. A card waiting on another issue is pm:blocked + Blocked-by:; pm:on-hold is for "the decision is made and the answer is not yet", and it is legal only with a restart condition a sweep can read. This card has the Blocked-by: line and no restart condition ⇒ its declared state is the wrong one of the two.

    ⭐ The card's own record already said so, twice, and neither comment was acted on:

    • issuecomment-5478577663 (2026-08-31, the unlock re-derivation) — 「⛔ 未改本卡标签:两条 Blocked-by: 都还开着,pm:blocked 仍然正确。」
    • issuecomment-5536462985 (2026-09-04, the ADR-0131 pointer) — "State: stays pm:blocked on its existing chain — ⛔ this comment does not release it."

    ⇒ ⛔ This is not a re-derivation and ⛔ not a release. The blocker is unchanged, the work is unchanged, the ordering discipline is unchanged. Only the label is corrected to the one this card's own authors recorded.

    ⚠️ One reading recorded without an explanation, deliberately

    The issue-events API for this card returns 5 events total, 2 of them pm-label events: pm:blocked added 2026-08-25T03:32:14Z, pm:blocking added 2026-08-31T21:05:25Z. There is no event removing pm:blocked and none adding pm:on-hold — yet the live label set carries pm:on-hold and not pm:blocked. updated_at is 2026-09-07T09:45:32Z, later than every event. The same disagreement reads on #11975 (8 pm-label events, last one pm:blocked; live label pm:on-hold) and on #15556 (last event pm:queue at 2026-09-07T08:28:35Z; live label pm:blocked).

    ⛔ The mechanism is NOT established here and this seat is not going to establish it — that is a platform-behaviour question, not this card's. It is written down because it has one consequence worth knowing: a pm-state cannot be audited from the events API alone on these cards. Anyone doing forensics on "who set this state and when" should read the live label set as authority and treat the event log as possibly incomplete.

    ⚠️ Also declared: the first pass at this reading was wrong in this seat's own instrument — the pm-label filter was applied after truncating to the last 10 events, which can hide pm events behind unrelated label events. The numbers above come from the corrected pass (filter first, full page counted, Link header checked: single page for all three cards).

    Where the real "cannot move" condition lives — and why it is NOT silenced by this repair

    H26 fired on #11973 and #11979 because their Blocked-by: target (this card) wore a state that never closes. That complaint is substantively true of the chain and this repair does not erase it; it moves it to where it is declared honestly:

    #11973 / #11979  →  #11978 (this card)  →  #11975  →  #13515
       pm:blocked          pm:blocked           pm:blocked      pm:on-hold
                                                            + Restart-when: a plugin-security
                                                              minor GREATER than the one
                                                              carrying L4 (⇒ no earlier
                                                              than 17.4.0), measured 2026-08-31
    

    #13515 is correct as it stands — measured this round: it carries a real Restart-when: line with its own measurement, plus a Restart-touch:, and no Blocked-by:. A release-boundary wait is exactly what pm:on-hold is for. ⇒ The chain's genuine immobility is declared in one machine-readable place, and the three cards above it now say what they are actually doing: waiting on an issue.

    ⛔ Not done here: #11975's identical repair is being made on its own card in the same round, with its own read-back. ⛔ Nothing about ADR-0131's absorption of steps 3–4 (issuecomment-5536462985) is re-opened or re-decided.

    The write

    One label replace: pm:on-hold removed, pm:blocked added, pm:blocking and domain:services untouched, assignees passed back empty. Target set computed from the label set read immediately before the write, and diffed against union(read, delta) on read-back.


    Generated by Claude Code

  4. os-sales commented on Sep 11, 2026

    @os-sales
    Collaborator

    Addendum — scope of the Restart-when: reading, widened to both channels (⛔ conclusion unchanged)

    issuecomment-5639937182 above reported "body Restart-when: lines — NONE". That was true but scoped too narrowly to carry the legality claim: the restart condition is legal in either channel — body or a comment — and the patrol's own H9 predicate reads both (stated verbatim by the triage seat on #11453: "pm:on-hold with no Restart-when: line in either channel").

    Re-measured 2026-09-11T20:56Z over this card's full comment thread as well as its body:

    ⇒ Both cards had no restart condition in either channel, so pm:on-hold was illegal on both and the repair to pm:blocked stands exactly as written. Nothing here changes the label, the blocker, or the chain.

    ⚠️ Recorded because the instrument was wrong even though the answer was right: a body-only regex fails in the dangerous direction — it reports a legally-held card as a half-state. Measured on the two neighbours this round: #11286 carries Restart-when: closed #7497 and #11453 carries a full machine-form line, both in comments, and a body-only test calls both illegal. Neither was touched.


    Generated by Claude Code

  5. huangyiirene commented on Sep 19, 2026

    @huangyiirene
    Collaborator

    Four sites recorded for the L6 reap — surfaced by the at-tier review of PR #19136, re-measured here

    domain:services seat (#6021) · session_019hBqDVrwbijUCoK9qsss2E · written 2026-09-19T00:58Z. ⛔ Report-only: no label written, no claim taken, this card keeps pm:blocked + pm:blocking. Recorded so the reap does not have to re-derive them.

    Why these land here rather than on #18336

    PR #19136 (card #18336) retires the legacy unscoped admin_full_access anchor under a walled posture. Its declared and reviewed boundary is 「the retirement takes the anchor, not the grant」 — the row itself, and the permission-set name it puts in context.permissions, survive. Disposing of the row is this card's leg (L6 reap) and #11979's for single.

    ⇒ these four read the name or a capability, ⛔ not the anchor. ⚠️ Measured as unchanged by that diff: §6b pushes the set name on every posture for any active grant row passing the organization filter, so each arm was true before and stays true. ⛔ Not a dual-track PR #19136 opens, and correctly not fixed there.

    The sites, on origin/main

    site what it reads
    plugin-approvals/src/approval-service.ts:1402 posture === 'PLATFORM_ADMIN' || perms.includes(ADMIN_FULL_ACCESS) — the second arm survives
    plugin-sharing/src/sharing-rule-service.ts:348–352 hasPlatformAuthority — caps.includes('manage_platform_settings') OR posture === 'PLATFORM_ADMIN'
    plugin-sharing/src/sharing-plugin.ts:1188 the same manage_platform_settings capability
    plugin-security/src/security-plugin.ts:6044–6046 the capability-probe fallback for hand-built contexts

    Consequence, stated abstractly (security family — ⛔ no reproduction recipe): a walled account the derivation now grades MEMBER can still act as the approvals override actor, delete a platform-global sharing rule, and cross the wall on a hand-built context — exactly as before the diff, by design, until the row is disposed of.

    One more, log-only

    security-plugin.ts:6035–6043 — for a walled legacy holder the carried rung and the capability probe now disagree, so the ADR-0099 I4 breadcrumb fires per tenant-object operation: 「Layer 0 exemption: carried posture rung and capability probe disagree; enforcing the (narrower) carried rung」. ⭐ Correct direction (it enforces the narrower rung) and 「a breadcrumb, never a throw」 in its own words — but on a walled rig carrying a legacy row it now fires routinely rather than exceptionally. Worth knowing before someone reads the volume as a new defect.

    ⚠️ Instrument note — this seat's first reading of two of these sites was WRONG

    Checking the reviewer's list, a grep for ADMIN_FULL_ACCESS returned 0 in sharing-rule-service.ts and security-plugin.ts, which would have read as 「two of the four do not exist」. ⛔ It was an artefact: both files use the lowercase string literal — admin_full_access resolves 5 and 7 times respectively, ADMIN_FULL_ACCESS 0.

    ⭐ The control that should have caught it did not, because it lived in a different file (approval-service.ts, where the constant spelling is used). A positive control only licenses a zero when it is on the same subject as the zero — same file, same corpus, same spelling convention. ⚠️ Second time this shift a character-level guess about spelling produced a confident wrong reading; recorded here rather than quietly corrected.


    Generated by Claude Code

  6. os-steve commented on Sep 21, 2026

    @os-steve
    Collaborator

    解除停放(维护者指令,skills 席 2 代执行)— 2026-09-21T03:44Z

    出处三件(SKILL.md :149 代执行他人指令,评论带出处三件)— 谁的指令:维护者,在本席(domain:skills seat 2,session_017ETYWqMQD4qMtZzAGovWNi,席位帖 #19287)会话内的真实用户轮次。在哪说:本席会话聊天,2026-09-21,在本席呈交「停放排查」四组清单(全板 165 张停放卡:pm:blocked 64 + pm:on-hold 101;其中 38 张的停放条件已消失——正文与评论里 Blocked-by: / Restart-when: 指向的卡或 PR 全部已关或已合)之后。原话(逐字,⛔ 未翻译、未润色):「还有哪些应该解除停放的你一起排查一下」;对四组清单:「同意」。

    本卡属第一组「条件已消失、恢复排队」:本席于 2026-09-21T03:00Z 机器复核,本卡停放所指向的每个目标都已关闭或已合并(具体目标见卡面 Blocked-by: / Restart-when: 行),而卡的内容是产品面(用户可见行为、契约或数据完整性),按北极星「优先级」不属 #202 B 的工具卡关闭面。

    动作:停放状态标签一笔换回 pm:queue(assignee 为空的卡);⛔ 本席不派发——本卡回到所属车道的取卡全序,由该车道席位按序认领。若卡面 Blocked-by: 行已无效,请取卡席位在认领时一并清理。

    ⚠️ 若本卡当前带 assignee(有认领在案),本席按「跨账号 assignee 不是你 ⇒ 永不碰」只留本条评论、不改状态:持有席位见此即可续做;持有会话已不可达者,按 #19240 落地后的接管协议一笔接管。


    Generated by Claude Code

  7. huangyiirene commented on Sep 21, 2026

    @huangyiirene
    Collaborator

    Maintainer-action: 在一台真实 walled rig 上跑第 1 步的 reader census(逐 name,覆盖 sys_user_permission_set、sys_position_permission_set、sys_user_position),并把结果按卡面验收判据贴回本卡。执行方按卡面为 repo:cloud 席或部署运维;本仓无命令可达部署数据。

    状态转换:pm:queue → pm:awaiting-maintainer。阻塞已真解除,但剩下的是站外动作

    domain:services seat · session_01AhQASwqJr2Z7XfGWUdvnbF · 写于 2026-09-21T13:21Z。⛔ 未改 domain:*、未定级、未指派。

    为什么本席取到它、又为什么不派

    取到它:全序里 pm:blocking 排第二(仅次于 priority:p0,高于 p1),本卡带该标 ⇒ 队列现存三张卡中它第一。⚠️ 本席的排序脚本按「级→bug→卡龄」排,把无级的 #7401 排在了前面 —— 脚本少实现了一档,已按全序原文更正。

    阻塞已解除,本席现验:正文 Blocked-by: #11975,而 #11975 现为 closed / completed(2026-09-20T21:16Z)。⇒ 该边已清,pm:blocked 不再适用。

    但不派,理由在卡面自身:

    • 第 1 步(walled rig 上的 reader census)卡面自陈 「NOT MEASURED and not measurable from this repository — no in-repo command reaches deployment data」;
    • 验收判据要求 census 结果先贴回本卡,任何删除才能落地;
    • 卡面写明 「⛔ order is the safety mechanism」。

    ⇒ 派给本仓 dev 无法交付第 1 步,而第 4 步(reap)要求 1–3 全绿。这是站外人工动作,符合 pm:awaiting-maintainer 的定义(「只剩站外人工动作,恒带 Maintainer-action: 行」)。

    本席没有做的事

    顺带一条分诊缺口(轮报)

    本车道队列现存三张卡 全部无级(#7401、#10164、#11978)。charter 要求「无级/缺 Path: 轮报记分诊缺口」⇒ 记此一笔。本卡另有 pm:blocking,而 pm:blocking ⛔ 不手工挂,其来源应由分诊复核。


    Generated by Claude Code

  8. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    关闭(维护者裁定):剩余的第 3、4 步由 ADR-0131 v18 的 #15204 / #15211 接走,普查读数成为 #15211 的输入

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T14:28Z。维护者在分诊席的「待维护者」复核批次 ① 里答「11978 … 关闭」。本席读完了本卡全部评论。

    这张卡做到了哪一步

    关闭意味着什么

    标签:摘 pm:awaiting-maintainer、pm:blocking;domain:services 保留;以 not_planned(被吸收)关闭。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions