Skip to content

fix(example-showcase): my-work 的 admin 卡片改用 ADR-0089 组件级 visibleWhen (#6274) - #6513

Merged
qq9340100 merged 1 commit into
mainfrom
claude/issue-6274-page-card-visiblewhen
Aug 8, 2026
Merged

fix(example-showcase): my-work 的 admin 卡片改用 ADR-0089 组件级 visibleWhen (#6274)#6513
qq9340100 merged 1 commit into
mainfrom
claude/issue-6274-page-card-visiblewhen

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes #6274

做了什么

examples/app-showcase/src/ui/pages/my-work.page.ts 里 "Leadership View" 那张 page:card,
可见性谓词原先写在 properties.visibleproperties 是控件自己的 prop 包(PageCardProps,
ComponentPropsMap),它不声明任何可见性键 —— 那行之所以能生效,只是因为 objectui 的
SchemaRenderer 在求值前把 properties 的每个键 hoist 到节点上,是渲染器的巧合而非契约,
#5068component-props-unknown-key 闸门正是这样报的它。

改为 ADR-0089 的规范拼法:组件节点的兄弟键 visibleWhen(不是 properties 里的键),
绑定根 current_user

- properties: { title: 'Leadership View', visible: "user.email == '...'", children: [...] }
+ visibleWhen: "current_user.email == '...'",
+ properties: { title: 'Leadership View', children: [...] }

侧栏共 2 处 page:card:"Shortcuts" 不带任何可见性键(其 title / children 都是
PageCardProps 声明的键,闸门不报),无需改写;带谓词的只有 "Leadership View" 这一处。

浏览器实测证据(绑定名判定 + 双身份可见性)

分诊把「绑定名」标为 load-bearing:ADR-0089 声明 page 组件谓词绑定 record /
current_user / page.,没有 user,机械改写疑似会得到恒假谓词。所以先量后写。

环境:worktree 内 objectstack dev --ui --seed-admin -p 3862,console 用
@objectstack/console@17.0.0-rc.5 的 dist —— 其 CHANGELOG 记为 "refreshed to 7dfbeb704e1e",
正是本仓 .objectui-sha pin 的那个 objectui commit,所以量到的就是 main 会 serve 的那份 UI。
非 admin 身份由 POST /api/v1/auth/sign-up/email 新建(analyst@objectos.ai,role user)。

探针:临时在同一侧栏加 4 张 page:card,各带一个组件级 visibleWhen,双身份各看一次
(探针已在提交前删除,不在本 PR 的 diff 里):

卡片 组件级 visibleWhen admin 非 admin
PROBE ALWAYS 1 == 1 显示 显示
PROBE CURRENT_USER current_user.email == 'admin@objectos.ai' 显示 不显示
PROBE USER user.email == 'admin@objectos.ai' 显示 不显示
PROBE UNKNOWN ROOT nosuchroot.email == 'admin@objectos.ai' 显示 显示
Leadership View(改写前基线,properties.visible) 显示 不显示

服务端下发的 page 元数据确认 visibleWhen 过了 parse 并以 CEL 信封到达前端:
{"dialect":"cel","source":"current_user.email == 'admin@objectos.ai'"}

结论 1 — 绑定名:current_user 实测可用。选它而不是 user,因为 ADR-0089 为这层声明的
身份根就是 current_user(user 只是 ADR-0068 那组向后兼容别名之一,由 app-shell 的
ExpressionProvider 一起喂进谓词 scope:current_user / user / ctx.user / os.user)。

结论 2 — 分诊那条陷阱假设,实测两半都不成立(照实报,不套模板):

  • user 不在绑定里 ⇒ 机械改写会得到恒假谓词」:不成立。user 在这层是活的绑定,
    机械改写并不会让卡片消失。
  • 「静默消失且无诊断」:方向也反了。真正解析不了的根(nosuchroot.)是 fail-open —— 卡片
    照常渲染,并在 console 打出一条实名警告:
    [object-ui] A conditional predicate failed to evaluate and was treated as its safe default (true): "nosuchroot.email == ..." . Reason: [type] Unknown variable: nosuchroot
    所以既不静默、也不消失。

这两点不改变本单的结论(properties.visible 仍是写错了位置的键,仍该改成组件级 visibleWhen),
只是把「为什么要先量」的那条理由校正掉,免得下一个读者按错误的失败模型去推断。

结论 3 — 改写后双身份复验(最终代码,探针已删除):

身份 Shortcuts Leadership View 页面渲染 pageerror 谓词警告
admin@objectos.ai 显示 显示(正文为新的 visibleWhen 措辞) 正常 0 0
analyst@objectos.ai(非 admin) 显示 不显示 正常 0 0

截图两份(admin / 非 admin)均已目视确认,行为与改写前的 properties.visible 基线一致。

#5068 闸门(component-props-unknown-key)

os lint 对 showcase config,反向验证按预期方向(before 红 / after 绿):

  • before(origin/main 的写法):4 条,含
    ⚠ page "showcase_my_work" · page:card: 'visible' is not a prop 'page:card' declares
    at pages[18].regions[2].components[1].properties.visible;总计 490 warning(s)
  • after(本 PR):3 条,page:card.visible 那条消失;总计 489 warning(s)

整份 lint 输出 diff 只有那一行的删除,没有任何新增诊断(既没有新的
visibility-root-mislayered,也没有 #6472 新加的 visibility-predicate-syntax)。

测试

  • 新增 examples/app-showcase/test/my-work-visibility.test.ts,同时钉形状与语义:谓词必须在
    组件级、任何 page:cardproperties 里不得再出现可见性键(visible / visibleWhen /
    visibleOn / visibility / hidden)、绑定根是 current_user 且不是 data.、以及谓词
    按页面自己声称的方式门控(admin 真 / 非 admin 假)。
  • pnpm --filter @objectstack/example-showcase typecheck → 通过。
  • pnpm --filter @objectstack/example-showcase test → 14 files / 150 tests 全绿。

changeset

@objectstack/example-showcaseprivate: true 的示例包,不在 .changeset/config.json
的 fixed 组里,本 PR 不发布任何包 —— 因此打 skip-changeset,不写 changeset。


Generated by Claude Code

…6274)

`page:card` 的可见性谓词原先写在 `properties.visible` 里,靠 objectui
SchemaRenderer 把 `properties` hoist 到节点上才生效 —— 是渲染器的巧合,
不是契约。`PageCardProps` 不声明任何可见性键,#5068 的
`component-props-unknown-key` 闸门正是这样报的它。

改为组件节点的兄弟键 `visibleWhen`(ADR-0089 唯一规范拼法),绑定根用
`current_user` —— ADR-0089 为 page 组件谓词声明的身份根(`record` /
`current_user` / `page.<var>`)。绑定名是浏览器实测确定的,不是读 ADR 推断:
对 pin 住的 console(objectui 7dfbeb70)以 admin / 非 admin 双身份各看一次
My Work 页。

新增 test/my-work-visibility.test.ts 同时钉住形状与语义:谓词在组件级、
任何 page:card 的 properties 里不再出现可见性键、绑定根是 `current_user`、
以及谓词按页面自己声称的方式门控。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011M7UwH25Unfi73UHim7ajY
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 2:53am

Request Review

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

Labels

skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

page:card.visible 是页面该改、不是 schema 该补:showcase 两处改写为 ADR-0089 组件级 visibleWhen(#5775 拆出)

2 participants