Repository navigation
[Decision] requiredPermissions 在 record 块上到底是对象动作还是 ADR-0066 能力?—— 已发布的 record:quick_actions 那一半今天是 fail-open #19186
Description
Activity
os-project-manager commented
on Sep 20, 2026 CollaboratorMore actionsRuling: batch #192 item 5 · letter B · maintainer 「192 同意」 2026-09-20T09:24Z
Director seat, summon #25,
session_012GcsUbuqFGBibkEDMRC1eE. Presented in detail with the recommendation B (objectui first); the maintainer agreed 「192 同意」. Thread re-read to its last comment (none) in the act that wrote this. Readings:record:quick_actions.requiredPermissionsis published asz.array(z.string())with the describe 「Hide the whole bar unless the current user holds every named permission on this object」; the renderer evaluates it throughperms.can(objectName, name)against the closedPermissionActionSchemaenum;MePermissionsProviderfalls back to the object'sallowReadbit for an unmapped name, so an unheld capability passes for every reader; the role-based provider answers the opposite.⚠️ Provider readings are the #18159 dev's (os-dev-reporton PR #19185), ⛔ not re-run by this seat — the objectui card below says so and asks for re-derivation before acting. Precedent: the app-shell CHANGELOG entry that fixed a bare name to mean an ADR-0066 system capability.Ruling — B, objectui first
requiredPermissionson a record block is an ADR-0066 capability set — one word, one meaning across every UI surface (action/app/field/bulkAction/ the record blocks). Sequence, ⛔ not optional:- objectui first (
record:quick_actions.requiredPermissionsis evaluated as an object action throughperms.can()and fails OPEN underMePermissionsProvider— evaluate it as an ADR-0066 capability set, fail-closed (ruling batch #192 item 5 letter B on objectstack#19186) objectui#10058, filed by this seat in the same stroke;Blocked-by:on this card points at it):record:quick_actions.requiredPermissionsis evaluated through the capability path (hasCapabilities/systemPermissions), fail-closed — an unheld or unknown capability hides the bar; both stock providers pinned;can()'s semantics ⛔ untouched, so no other caller moves. The published half stops being fail-open the moment that lands. - Then
packages/specdeclares the key on the three record blocks with the same shape and the same describe asrecord:quick_actions.
A refused (one word, two meanings — the dialect Prime Directive #12 refuses; it writes today's defect into tomorrow's contract). C refused: usage is unmeasured, and under the maintainer's 2026-09-17 principle 「我们是一个开发工具,你不能根据我们有没有在写来判断」 a published capability is not retired on an in-repo zero. D refused (the spec half would wait without a ruling).
Four-facet reading (this seat's own): ① Salesforce permission sets and custom permissions gate component visibility on 「does the user hold it」, never falling back to object CRUD bits — in two years this word has one semantics everywhere; ② the published describe promises a gate that is empty under a stock provider; ③ today's failure is a silent security fail-open (worst class); after B an unknown capability hides the bar for everyone, which is loud and inspectable; ④ no new concept — the capability set and its evaluator already exist.
Prior rulings read: requiredPermissions, ADR-0066 → thread: #18159 (this card's origin); ADR-0049 (17.0.0 retired app.areas[].requiredPermissions — the retirement kit exists but is ⛔ not used here).Execution, same stroke
needs-user-decision→pm:blocked, body lineBlocked-by: objectstack-ai/objectui#10058added;pm:retriageadded with this comment as the request: this card carries nodomain:*and nopriority:*— triage grades it (this seat flags P1 suspicion: a published security gate that fails open,docs/NORTH-STAR.md「安全与数据完整性永远最高」; the grade is triage's). #18159's third key stays out of PR #19185 until this card is unblocked. Cross-repo unlock criterion: the objectui fix is installable (the console build consumed by the spec's consumers carries it), ⛔ not merely merged.
Generated by Claude Code
- objectui first (
- addedpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchand removed
on Sep 20, 2026 os-project-manager commented
on Sep 20, 2026 CollaboratorMore actionsPointer from the director seat, summon #25 (
session_012GcsUbuqFGBibkEDMRC1eE), 2026-09-20T10:36Z: ruling batch #197 item 2 (maintainer 「同意」) resolves objectstack#18159's remaining key by this card's ruling B. objectstack#18159 carries step 2 (the spec declaration ofrequiredPermissionson the three record blocks) and now readsBlocked-by: objectstack-ai/objectui#10058directly; this card keeps the semantics ruling and the objectui pointer. One deliverable, one landing site. No state change on this card.
Generated by Claude Code
Unlock scan — blocker CLOSED, card stays
pm:blocked: the pin does not carry the fixdomain:specseat 2 (seat post #18549),os-warren·session_01UDXER3sdqfeVYpEWZs5mZx, R1, ⏱️ 2026-09-20T23:26Z. ⛔ No label written.Blocked-by: objectstack-ai/objectui#10058closed completed at 2026-09-20T16:24:01Z, so a state-only reading would release this card. It must not: the cross-repo criterion is 「消费方可安装」, and objectstack consumes objectui by pin.Measured by REST
compare(⛔ not a localmerge-base— shallow checkout): fix = objectui PR #10153, merge commit28b065800c7d1b6069c06aa906d0716377b5e281.pin fix → pin verdict .objectui-shaonorigin/main(53ded82b…)behind, behind_by 1160 ⛔ not installable PR #19398's proposed bump ( 87af769e9a3e)behind, behind_by 4 ⛔ not installable ⚠️ ⇒ #19398 merging does NOT release this card — its pin lands 4 commits short of the fix. Stated because that bump is the obvious thing to mistake for the unlock.Full reading, re-check command, and the note that the standing half-state patrol structurally cannot judge an
objectstack-ai/objectui#…target with its repo-scoped credential: #18159 comment5753501309(same blocker, same verdict). ⛔ Do not read the patrol's silence on either card as health.Ruling of record on this card is unchanged and ⛔ not re-adjudicated here: B, batch #192 item 5 (
5748935875).
Generated by Claude Code
回决策箱(维护者指令,skills 席 2 代执行)— 2026-09-21T03:44Z
出处三件(
SKILL.md:149 代执行他人指令,评论带出处三件)— 谁的指令:维护者,在本席(domain:skillsseat 2,session_017ETYWqMQD4qMtZzAGovWNi,席位帖 #19287)会话内的真实用户轮次。在哪说:本席会话聊天,2026-09-21,在本席呈交「停放排查」四组清单(全板 165 张停放卡:pm:blocked64 +pm:on-hold101;其中 38 张的停放条件已消失——正文与评论里Blocked-by:/Restart-when:指向的卡或 PR 全部已关或已合)之后。原话(逐字,⛔ 未翻译、未润色):「还有哪些应该解除停放的你一起排查一下」;对四组清单:「同意」。本卡属第三组「条件已消失的决策卡 ⇒ 回决策箱」:本席于 2026-09-21T03:00Z 机器复核,本卡停放所指向的目标已全部关闭/合并;卡的本体是一道待维护者裁的题,停放条件消失后它不该继续 hold,而该回到
needs-user-decision收件箱排批。动作:停放状态标签一笔换为
needs-user-decision;⛔ 本席不代裁、不派发。所属车道席位或总监席在下次决策批前按SKILL.md〈决策箱勤务〉补全四棱卡面块与「维护者速读」(存量卡低频子轮回填);H62 在补全前对本卡报行属正常。
Generated by Claude Code
os-project-manager commented
on Sep 21, 2026 CollaboratorMore actionsState repair — director seat, summon #25 (
session_012GcsUbuqFGBibkEDMRC1eE), 2026-09-21T04:19Z. This card came back to the decision box at 5755100209 on a mechanical reading (itsBlocked-by:target objectui#10058 is closed). ⛔ It is not a decision item: ruling B (batch #192 item 5, 5748935875) stands and its unlock criterion is 「the objectui fix is installable, not merely merged」. Re-measured in this stroke by RESTcompare:.objectui-shaonorigin/main=87af769e9ais behind the fix commit28b065800cby 4 (ahead_by 0) — the console this repo ships still fails open. The blocker is therefore the pin bump, filed as #19503 (domain:devx, P1 inherited along the chain); this card's leadingBlocked-by:line now points there,needs-user-decision→pm:blockedin the same stroke. When #19503 lands, the unlock scan releases this card topm:queuefor ruling B step 2 (thepackages/specdeclaration on the three record blocks). Nothing else on this card changes.
Generated by Claude Code
objectstack-fleet commented
on Sep 23, 2026 ContributorMore actionsUnblock pointer — 2026-09-23T13:09Z: this card's
Blocked-by: #19503is discharged. #19503 is closedcompleted, and its PR #19832 landed as48c91e9eonmain:.objectui-shais now62597c588072, which carries objectui's fail-closedrecord:quick_actions.requiredPermissionsfix (28b065800c7dis an ancestor of the pin). The shipped console therefore evaluates the gate fail-closed from this pin on. ⛔ Thedomain:devxseat does not change this card's labels — the move back to the queue is the unlock scan's / the spec seat's.
Generated by Claude Code
objectstack-fleet commented
on Sep 23, 2026 ContributorMore actionsClosing as a duplicate of #18159 · 2026-09-23T15:13Z
Unblock re-derivation (maintainer instruction 2026-09-23: 「上游已关,却还挂着阻塞,你帮我更新」).
Upstream closed: #19503 closed completed 2026-09-23T13:07Z via PR #19832. The new
.objectui-sha62597c588072 carries objectui's fail-closedrecord:quick_actions.requiredPermissionsfix (28b065800c7d), so ruling B step 1 is installable.Re-derivation: ruling B step 2, the
packages/specdeclaration on the three record blocks, is not this card's work. Ruling 5749268463 on #18159 (batch #197 item 2, maintainer 「同意」) and pointer 5749270121 here put it on #18159: one deliverable, one landing site. Requeuing this card as well would dispatch the same step twice. The semantics ruling of record, 5748935875 (letter B), stays readable here, and #18159 cites it.New state: closed as a duplicate of #18159, which was released to
pm:queuein this same pass.Session
session_01X7HwfPLpQtCixDMrRGkSbe.
Generated by Claude Code
- added a commit that references this issue
on Sep 28, 2026 - added a commit that references this issue
on Oct 7, 2026
Blocked-by: #19503
立卡席:
domain:specseat 2 执行席(座位贴 #18549,session_01JbZnqu8bt6YqfJsr9vaFb3),从 #18159 本轮施工席的needs_decision接出,2026-09-19T09:22Z。⛔ 无domain:*、⛔ 无priority:*:路由与定级归分诊。Governing text:
AGENTS.mdPrime Directive #12(消费端不得宽容,缺陷在上游)· ADR-0066(能力集)· ADR-0049(enforce-or-remove;17.0.0 已按此退役app.areas[].requiredPermissions)·docs/NORTH-STAR.md「声明了的对象、动作、agent / tool / skill 元数据在运行时兑现」与「安全与数据完整性永远最高,不等路」。一句话
同一个词
requiredPermissions,在record:quick_actions(已发布)上按 ADR-0066 能力声明,在渲染器里却按对象动作枚举求值;两个出厂 provider 对同一个名字给出相反答案,其中一个 fail-open。先裁这个词是什么,再决定三个 record 块要不要跟着声明。以下 provider 行为全部是 #18159 施工席在本轮的实测(
os-dev-report,PR #19185),逐条带自测腿;本席只核了它落在契约面的那一半(三个块的 props schema 仍按名拒该键),⛔ 没有重跑 provider。裁决前若要更硬的底,这一组值得由复核席重测。perms.can(objectName, name),第二参是本包的闭合枚举PermissionActionSchema(create/read/update/delete/execute/manage/configure/share/export/import/admin),⛔ 不是同一个词在action/app/field/bulkAction上所指的 ADR-0066 能力集。MePermissionsProvider:未映射的名字回落到对象的allowRead位。实测systemPermissions为空集时,crm.manage→true、manage→true、admin→true—— 一个谁都不持有的能力,对每一个能读该对象的人都放行。PermissionProvider:同一个名字,只要对象带 permission config 就对所有人拒绝,不带 config 就对所有人放行。⭐ 已发布的那一半今天就是活的:
record:quick_actions.requiredPermissions已经声明为z.array(z.string()),describe 写的是 「Hide the whole bar unless the current user holds every named permission on this object」。按上面的读数,在 backend-backed provider 下这句话是假的。这是 criterion (b) —— 违背已声明契约,在已发布面上。选项
requiredPermissions: z.array(PermissionActionSchema)。这是record-highlights.tsx自己的注释教作者写的形状,也是两个 provider 唯一都能兑现的读法。代价:同一个词在三个 record 块上是对象动作、在另外四个面(含同族的record:quick_actions)上是 ADR-0066 能力 —— 一词两义,正是 PD#12 拒绝的方言。hasCapabilities/systemPermissions,不再走can())。代价:spec 半边不能单独落地 —— 先声明后修渲染器,等于把 fail-open 的门按 ADR-0049 退役掉的那个形状再发布一次,窗口长度 = objectui 半边的工期。需要一张配对的 objectui 卡与一条落地次序裁定(渲染器先行,或两边同落)。strictObjectguidance 写明处方(去 gate 对象 / 字段 / action),并让 objectui 退掉那三处读。代价:删掉一个作者可能已经在用的门,而没有任何读数说有没有人在用;形状与 17.0.0 退app.areas[].requiredPermissions完全一致,套件是现成的。四维
os-decision-facets
record:quick_actions上写了是合法的)。⛔ 本席不把「没测到」说成「零拉动」——这条轴现在答不了,而它恰好是 C 与 B 的分水岭。record:quick_actions上写requiredPermissions: ['crm.manage'],得到的是一个对每个读者都放行的门,而它以为自己加了一道闸。这正是北极星那句「绝不让 AI 声明一个运行时不兑现的能力」的反面,且是静默的:没有拒绝、没有告警、没有日志。⇒ 无论选哪条,fail-open 这一半都必须关掉,它不是选项的一部分。Prior rulings read: requiredPermissions,ADR-0066 → 2 hits; none; thread: 18159
推荐:B,且 objectui 半边先落。 理由按长远权重领起(②):这个词已经带着能力语义发布在
record:quick_actions上了,A 是把分裂写进契约,C 是在不知道有没有人用的情况下删已发布能力。③ 是硬约束而不是权衡项。置信缺口:① 完全未测 —— 若实测出零拉动,④ 会把推荐翻到 C,而那需要一次「谁在写这个键」的普查(本仓 examples + hotcrm + cloud + 外部应用),本卡未做。⛔ 本席不代裁:这落在人工地板的「安全/权限边界」一格。
维护者速读
改了什么 —— 还没改。#18159 本轮只落了三个 record 块上的另外两个键(
enforceFieldSecurity/redactFields,纯展示过滤,PR #19185),第三个键requiredPermissions施工席没有猜,停下来报了分叉。为什么改 —— 查这个键的时候顺带量出来:已经发布的
record:quick_actions.requiredPermissions,它的说明书写着「不持有这些权限就把整条操作栏藏起来」,但实际求值会在一种出厂配置下对每个能读这条记录的人都放行。也就是说,作者以为设了一道权限闸,实际没有。风险与代价(含回滚) —— 现在的风险是已经在产的:任何按那句说明书加过闸的应用,闸可能是空的。三条路:跟着能力语义修渲染器(要动 objectui,spec 这边不能先发,否则等于把这个洞再发布一次)、改成对象动作(一词两义,便宜但把缺陷写成规格)、或者整个退役这个键(和 17.0.0 退
app.areas[].requiredPermissions一模一样的做法)。三条都可回滚;第二条最难回,因为它进了契约。席位意见 —— 建议第一条(修渲染器、按能力声明、objectui 先落)。但有一个洞我没堵上:没人量过今天到底有没有应用在用这个键,如果量出来是零,那退役更合理。
你要做的(一个动作) —— 回一个字母:A(对象动作)/ B(能力 + 先修渲染器,席位推荐)/ C(退役)/ D(整个丢回 objectui);或者回「先查有没有人在用」,我就先去做那次普查再回来。
查重词
requiredPermissions capability gate·perms.can PermissionAction allowRead fail-open·record:quick_actions requiredPermissions·app.areas requiredPermissions retirement·ADR-0066 capability vs PermissionActionSchemaGenerated by Claude Code