Repository navigation
[UX] Studio Access 权限矩阵活栈走查收敛:3 个编辑安全缺陷(已开修)+ 设计迭代清单 #2600
Description
Activity
进展同步(2026-07-16):
- A3 历史/面包屑逃逸 → PR fix(app-shell): Studio Access matrix — history opens in-place sheet, breadcrumb stops escaping the pillar #2599 已开(
embeddedprop 贯通 PageShell/编辑器,历史改右侧抽屉,双模式回归测试),已初审,改法 OK。 - A2 只读贯通 → 修复会话进行中,worktree 已有提交(
lock the Access pillar permission matrix in read-only packages),PR 待开。 - A1 脏状态守卫 → 首次修复会话异常空结(无提交,疑似撞上平台权限分类器故障窗口),已重新拉起。
合并顺序维持 issue 正文建议:A2 → A1/A3 rebase 串行。
- A3 历史/面包屑逃逸 → PR fix(app-shell): Studio Access matrix — history opens in-place sheet, breadcrumb stops escaping the pillar #2599 已开(
活栈回归 + 走查收尾(2026-07-16 下午,main@4b0aee6,真 showcase 后端 :3000 + console dev :5180,agent-browser 实操):
A2 只读贯通 → 已合并(#2570)且活栈回归通过 ✅
- 只读包下:矩阵 180 个复选框全部
disabled、名称/标签锁定、保存按钮消失、行级安全分面字段全禁用(每策略「测试」按钮保留可用——只读求值,合理)。 - 徽标措辞按触发闸区分,顶栏「只读」与编辑器状态不再自相矛盾。
A3 前提活栈实锤:Studio 内点「历史」→ 实际跳转
/home(命中 catch-all),与路由表推断一致;#2599 的 in-place 抽屉方案对症,已初审待合。补完的走查项(此前被工具故障挡住):
- 对象筛选:英文 api-name(invoice → 2/20)与中文标签(发票 → 1/20)均命中,计数徽标联动 ✓
- 行级安全分面:结构化策略编辑器(名称/对象/操作/CEL USING/CHECK)正常 ✓
- 深链:rail 选中集镜像到
?surface=permission:<name>✓(加分项)
B5 修订:「左栏按钮无可访问名称」一条撤销——agent-browser 的可达性树里名称完整,原报告是浏览器面板 read_page 的工具怪癖,非真实 a11y 问题。
- 只读包下:矩阵 180 个复选框全部
- added a commit that references this issue
on Jul 16, 2026 A1 已完成,勾选 ✅ — 修复由 #2588 落地(merge commit
1e8764909,2026-07-16):PermissionMatrixEditPage新增onDirtyChange上抛(ref 稳定化,卸载时归零),AccessPillar 持有matrixDirty;- 四条重挂载路径全部 confirm 门控:rail 切换权限集、切到 OWD 总览、新建权限集、矩阵内 OWD badge 深链(重复点击当前集不误弹);
- 补了根因里点名缺失的
beforeunload(刷新/关 tab); - 测试:
PermissionMatrixEditor.dirty.test.tsx+StudioDesignSurface.accessGuard.test.tsx,6 用例已基于 main(d50977c20)复跑通过。
相邻缺口(已开修):顶栏 pillar 切换 / Home / PackageSwitcher 是 SPA 客户端导航,不触发
beforeunload,dirty 时仍静默丢弃 —— #2606 处理中(AccessmatrixDirty+ InterfacesnavDirty上抛到 StudioDesignSurface 顶层 + surface 级 beforeunload)。同改 AccessPillar 挂载点,按「合并注意」与 #2599 / A2 串行合。再残留(待排,建议补为 A 组条目):
PackageOwdOverviewPanel的批量编辑 dirty(内部dirtyCount)未接入任何守卫 —— OWD 总览有未保存改动时,rail 切回权限集或顶栏导航都不 confirm;A1 与 #2606 均只覆盖matrixDirty/navDirty。等 #2599 / A2 / #2606 落地后再动,避免第四个分支并行改同一挂载点。- added a commit that references this issue
on Jul 16, 2026 - added a commit that references this issue
on Jul 16, 2026 A 组全部落地(2026-07-16,串行合完成,合并顺序 A2 → A3 → 顶栏守卫):
- A2 只读包锁矩阵 → fix(app-shell): lock the Access pillar permission matrix in read-only packages #2570(
57a61b097):PermissionMatrixEditPage新增readOnlyprop 并入writable,一个开关锁全部(对象/字段复选框、批量、名称/标签、能力选择器、高级分面、保存);只读徽标按触发的门分别措辞(包门对齐顶栏芯片,type 门保留 OS_METADATA_WRITABLE 措辞)。RTL 套件覆盖双门 + 可编辑回归路径。 - A3 历史/面包屑逃逸 → fix(app-shell): Studio Access matrix — history opens in-place sheet, breadcrumb stops escaping the pillar #2599(
770e40528):PageShell + PermissionMatrixEditPage 加embedded开关(同 MetadataResourceEditPage 模式)。嵌入态「历史」改右侧 sheet 复用 HistoryPanel(只读、无回滚,ADR-0086 D6/D7);面包屑渲染为纯文本。独立 metadata-admin 行为不变。 - A1 后续:顶栏 SPA 导航同样静默丢编辑 → fix(studio): confirm before header SPA nav discards unsaved pillar edits (#2600) #2606(
99356470f):A1 只守住了 rail/OWD/新建/badge 深链四路,但顶栏 pillar 切换(react-router<Link>)、Home、包切换器都是 SPA 客户端导航,不触发 beforeunload,dirty 时切走整体卸载 AccessPillar。现 AccessPillarmatrixDirty/ InterfacesPillarnavDirty经onDirtyChange上抛到 StudioDesignSurface,三处导航 dirty 时先 confirm,并补了 surface 级 beforeunload(navDirty 原先连刷新守卫都没有)。测试StudioDesignSurface.pillarNavGuard.test.tsx(6 用例)。
三个 PR 同改 AccessPillar 挂载点,按「合并注意」串行 rebase,最终形态:
readOnly={readOnly}+onDirtyChange={reportMatrixDirty}+embedded。已知残留(另行跟踪,不在本 issue A 组范围):
PackageOwdOverviewPanel内部dirtyCount未接入任何离开守卫(rail 从 OWD 切回权限集、顶栏导航均不 confirm)——已起独立任务接入 #2606 的pillarDirty通道。B 组设计迭代现在可以排了:A 组落地后同文件并行打架的约束解除。
- A2 只读包锁矩阵 → fix(app-shell): lock the Access pillar permission matrix in read-only packages #2570(
- added a commit that references this issue
on Jul 16, 2026 - added 7 commits that reference this issue
on Jul 16, 2026 B 组设计迭代全部落地(2026-07-18) — 逐条独立 PR、串行 rebase(每条基于含前一条的 main)、CI 全绿后 squash 合。活栈复验方式与走查一致(真 showcase 后端 :3000 + console,浏览器实操 + DOM/源码对照)。
项 PR commit 活栈实证 B1 首屏见矩阵 #2649 8d5534f24名称/标签折叠成一行摘要( basicsOpen)、写包零授予能力从铺 7 芯片改「无附加系统能力 + 添加」(capsOpen);矩阵头升进首屏;展开双向可用B2 解释面板对象下拉 #2650 a6c4f4d5aAccessExplainPanel加packageId,对象字段改本包对象<select>(label (api-name),22 项,无crm_lead);未选禁用 opacity-0.5、选中启用;无 packageId 回退自由文本B3 窄宽批量列可达 #2652 4d6fb926e矩阵表加 min-w-[960px],外层 overflow-auto 真横滚;820px 验:table 960 / 容器 612 canScrollX,右滚露出「批量」列(读/增改删/全选/清空)B4 字段级批量+筛选 #2651 d121cb3d5展开对象加字段筛选(>6 字段显)+ 全部可读/全部可写/清空(作用于筛选后可见字段)+ visible/total 计数;只读包 writable-gated 隐藏批量钮。活栈只读验筛选+计数( name→1/12),批量逻辑 RTL 覆盖B5 分组标题 i18n #2653 e4e8d3fe1能力选择器 PLATFORM/ORGANIZATION → capability.group.<scope>翻译束,全 11 语言包;中文验:平台 / 组织B5 能力标签 i18n #2657 be0712c9d见下 B5 标签本地化的分叉记录:原计划「sys_capability registry label 走翻译束」= framework。深挖后确认 framework 没有记录级 i18n 约定可复用——schema 翻译束(
translateObject/*.objects.generated.ts)只译 object/field schema;能力 label 是走通用/api/v1/data/sys_capability的记录数据;后端修得新引入一整套 pattern(read middleware + 翻译存储 + locale 来源问题:数据路径只有ctx.context.locale=租户/用户 localization 设置,不是 metadata 层用的 Accept-Language)。对本 issue 最低优先级项不划算,故改走 objectui 客户端映射:7 个 curated 平台能力(固定已知集)走capability.label.<name>翻译束,package/admin 自建能力保留注册表 label。中文验:管理元数据 / 管理平台设置 / 管理用户 / 访问 Setup / 访问 Studio / 管理组织用户 / 保存设置。撤销/闭环的 B5 子项:「左栏权限集按钮无可访问名称」此前已在走查中撤销(agent-browser 可达性树名称完整,系浏览器面板 read_page 工具怪癖);列头缩写 tooltip 触屏不可达由前置图例缓解,不再单列。
至此 A 组(A1/A2/A3 编辑安全缺陷)+ B 组(B1–B5 设计迭代)全部收敛。
对 Studio Access pillar(权限矩阵,
/studio/:packageId/access)做了一次活栈 UI/UX 走查:真 framework showcase 后端(:3000)+ console dev(:5180),浏览器实操(勾选/切换/筛选/解释面板/窄宽渲染),关键行为与源码逐一对照。总体:信息架构(左栏集 → 对象×CRUD 矩阵 → 字段级展开 → 折叠分面)和包作用域(ADR-0086,矩阵 20/85 对象)是对的;问题集中在编辑安全感和嵌入缝隙两类。本 issue 跟踪全部发现的收敛。A. 缺陷(已全部修复落地)
setCurrent,矩阵key={current}重挂载,内部dirty未上抛,无确认、无 unload 守卫(StudioDesignSurface.tsx~3327/3389)。修复方向:onDirtyChange上抛 + 切换前确认(同文件navDirty模式)。readOnly只挡了「新建权限集」,未传给PermissionMatrixEditPage(props 无此口子);内部writable=allowOrgOverride是 type 级另一概念。同屏「只读」徽标 + 「可写」徽标 + 蓝色保存钮三者矛盾。修复方向:编辑器加readOnlyprop 与writable取与,驱动复选框 disabled / 保存隐藏 / 行内提示,并统一徽标语义。navigate('./history?type=permission')在 Studio 路由下解析为/studio/…/access/history,无该路由,命中App.tsx:354的path="*" → Navigate to "/":点「历史」= 静默弹回平台首页,Studio 上下文全丢。面包屑「元数据 › 权限集」同样链出 Studio 到/metadata。修复方向:嵌入模式下历史改抽屉/对话框,面包屑隐藏或改包内返回。B. 设计迭代(按优先级,待排)
AccessExplainPanel.tsx~286 自由文本),本包对象仅 20 个应给下拉;占位示例crm_lead在本包不存在;「解释」未填对象时看似可点实际禁用;面板占 70% 宽大面积留白。<table className="w-full">无 min-width/overflow-x 容器);不同集之间行高从 ~70px 跳到 ~200px;左栏固定 208px 不自适应。做得好的(保持)
服务端包作用域(20/85 对象、8/15 集);缩写图例前置展开;破坏性变更 409 → 明细确认对话框;CEL 错误阻断保存;行内 OWD 徽标深链总览;「只看已授权」+ 计数徽标;高级分面默认折叠;移动端 rail 抽屉;矩阵复选框 aria-label 完整。
合并注意
A1/A2/A3 三个分支改同两个文件(
StudioDesignSurface.tsxAccessPillar 挂载点、PermissionMatrixEditor.tsxprops/头部),A1 与 A2 都给PermissionMatrixEditPage加新 prop,必然冲突——串行合:建议 A2(props 改动最大)先进,A1/A3 rebase 后再进;不要三个同时 merge-on-green。B 组刻意排在 A 组落地之后,避免同文件并行打架。关联