Skip to content

filterAppForUser 只走 app 顶层 navigation —— areas[] 里的 nav 项权限过滤仅客户端生效(#4651 移除假闸门后剩下的真缺口) #4722

Description

@os-zhuang

#4651 / #4718 分出的独立记录。未指派 —— 只是记录。

现象

服务端权威可见性闸门 filterAppForUserpackages/rest/src/rest-server.ts)只过滤 app 的顶层 navigation 树:

:1814  检 app 级 requiredPermissions —— 不满足 return null
:1823  const nav = Array.isArray(item.navigation) ? item.navigation : null;
       if (!nav) return item;                       ← 没有 navigation 就直接原样返回
:1826  filterNav 递归检 nav 项级 requiredPermissions / requiresService

item.areas 从头到尾没有被读到。所以一个写在 area 内部的 nav 项上的 requiredPermissions / requiresService

  • 服务端不剥离 —— 该条目连同它的 objectName / pageName / componentRef 等指向,照常出现在 /meta 响应里;
  • 只有客户端 NavigationRenderer.tsx:894checkPerm 会把它藏起来。

也就是说,对 areas 型 app 而言,导航项级权限目前是渲染层的礼貌,不是服务端强制。改一次前端状态、或者直接读 /meta 的 JSON,就能看到本该被 gate 掉的条目。

#4651 的关系(这是剩下的那一半)

#4651 处理的是 area 级的两个键 areas[].visible / areas[].requiredPermissions——它们任何一层都没有消费者,是纯粹 fail-open 的假闸门,已按维护者裁决在 17.0.0 走路线 B 移除(#4718)。

本单是另一件事:area 里面的 nav 项闸门是真的被消费的,只是只被客户端消费#4651 的处方对此没有回避,明写了限定并落进了三处:

  • 退役处方本身(ui/app.zod.tsAREA_REQUIRED_PERMISSIONS_RETIRED:「Items nested under areas[] are gated in the shell only — the server does not walk areas」);
  • 活性账本 packages/spec/liveness/app.jsonareas.navigation 条目 note;
  • 一条 characterisation pin(packages/rest/src/rest.test.tsfilterAppForUser — the enforced permission layers (#4651) 里的最后一条),它故意把当前行为钉住,并在注释里写明:谁让它开始走 areas,就应该看到这条断言红掉、然后连同账本 note 一起有意识地改写。

所以现状是「已知、已记录、已钉住」,但没有 open issue 跟踪——#4651 已随 #4718 关闭。本单补上这个跟踪位。

需要决定(与 #4651 的路线 A 是同一组语义问题)

要让服务端也过滤 areas,先得回答:

  1. 一个 area 里的项被过滤光之后,这个 area 本身还返不返回?(返回一个空 area,客户端切过去是一片空白)
  2. 顶层 navigationareas[].navigation 同时存在时(schema 允许,AppSchema with areas 的 backward-compat 用例就是这个形状),两棵树的过滤要不要一致?
  3. 是否顺带补服务端的 visible CEL 求值?目前 visible 任何层级都只在客户端求值(AppSidebar.tsx:236 经 ExpressionProvider),服务端从不绑定 user 上下文——所以「服务端强制」在 requiredPermissions / requiresService 上成立,在 visible 上不成立,这个不对称本身也值得写进文档而不是让人自己发现。

影响面

关联

#4651(area 级假闸门,已移除)、#4718(实现 PR,含上述三处记录与 pin)、ADR-0045(hidden app 可见性)、ADR-0057 D10(requiresService 能力闸门)、ADR-0049(enforce-or-remove)、ADR-0078(false compliance)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions