Repository navigation
Commit ff648d7
fix(app-shell): Studio Access pillar polish — plain-words draft race refusal, OWD banner clears on revert, live rail label, field table count and pinned name column (#27148)
<!-- claude-projects-attribution: {"github_login":"os-warren"} -->
_Requested by **Warren** · [project
thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8SS6ia75ydEcRpPoKXe7Wi8)_
Fixes #26846
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:Studio 访问(Access)支柱四处小修:草稿抢先创建时的拒绝改成作者能懂的话;OWD
总览撤回改动后拒绝提示随之消失;权限集改名后左侧列表立即显示新标签;字段子表的「可见/总数」计数挪到筛选框旁、字段名列横向滚动时固定在左侧。第五项(恢复已忽略的建议绑定)服务端没有对应接口,本
PR 不做,交席位立服务端卡。
- 为什么改:QA 在一次 Studio 巡检里实测到这五处,单个都小,合起来让访问支柱显得不可靠(卡 #26846,分诊 p3)。
- 风险与回滚:只动 `@object-ui/app-shell` 三个组件与 `@object-ui/i18n`
新增一个键,无契约、无服务端改动;回滚即 revert 本 PR。
- 先看:`StudioDesignSurface.tsx`(AccessPillar
的创建拒绝映射与矩阵保存后重读列表)、`PackageOwdOverviewPanel.tsx`(回到无改动时清除拒绝)、`PermissionMatrixEditor.tsx`(字段子表的计数位置与固定列)。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/app-shell/src/views/studio-design/PackageOwdOverviewPanel.refusalClearsOnRevert-26846.test.tsx
packages/app-shell/src/views/studio-design/StudioDesignSurface.accessRailLabelLive-26846.test.tsx
packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.fieldTableLayout-26846.test.tsx
packages/app-shell/src/views/studio-design/StudioDesignSurface.accessCreateTaken-26836.test.tsx`,预期
4 个文件、15 个测试全绿。
- 需要你做的:无,席位落地。
## What changes
Each item was re-reproduced on `origin/main` `07d18e69` first (the QA
run was at `3fcafcd3`).
1. **Duplicate-draft refusal in plain words (item 1, narrowed).** The
card's path no longer reproduces: since #26836 the Access "+ New" reads
`findTakenIdentifier` before its save and refuses a taken identifier
with an author-facing notice, writing nothing. The server's
first-write-pin sentence still reached the dialog in the window between
that check and the save, and the existing race test pinned it verbatim.
`AccessPillar.doCreate` now reads that refusal by its code: this create
always sends the pin (`ifNoneMatch: '*'`), so `METADATA_CONFLICT` means
the identifier holds a draft, and the dialog shows
`engine.studio.access.createDraftTaken` (en + zh, new in
`@object-ui/i18n`). Any other refusal keeps its own text. The server
message is unchanged.
2. **OWD refusal banner outlives its revert (item 2).** The refusal
state lives in `PackageOwdOverviewPanel` (the Access pillar's
sharing-baseline overview), not in `PermissionMatrixEditor`. Its
`saveError` now clears on the dirty-to-clean transition, when every row
is back at its loaded value ("No changes"). A row that is still dirty
keeps the banner.
3. **Stale set label in the Access rail (item 3).** The matrix page's
`onDraftSaved` in `AccessPillar` updated only the draft-name set; the
rail list was read on mount, publish and the live-metadata pulse. That
callback now also calls the pillar's own `load()`, so a label an
autosave changed shows at once, with no polling.
4. **Clipped field counter, non-sticky name column (item 4).** The
studio matrix has a `min-w-[1304px]` floor, wider than the Studio
content column beside the rail at 1440 px, so the field sub-table's
`ml-auto` counter sat past the visible edge of the scroll container. The
counter now sits right after the field filter (`shrink-0
whitespace-nowrap`), and the field-name header and cells carry
`FIELD_NAME_CELL` (`sticky left-0 z-[1] bg-background`), so the column
stays in view while the matrix scrolls sideways. The sub-table is
shared, so the non-Studio matrix page gets the same.
5. **No re-grant for a dismissed suggestion (item 5): left out.**
Measured: the server exposes only `GET /security/suggested-bindings`,
`POST …/:id/confirm` and `POST …/:id/dismiss`;
`confirmAudienceBindingSuggestion` in plugin-security refuses any row
whose status is not `pending` ("only pending suggestions can be
accepted"), and no route re-opens a dismissed row. Per the dispatch
order no endpoint is invented here; the seat can file a server-side
card.
## Why
Five small Access-pillar defects measured in one Studio QA pass
(#26846). Triage graded them p3 together: "One PR is fine."
## Tests
All at head `8220f32d` (after merging `origin/main`, which brought
#26999 into the same two files).
- New `PackageOwdOverviewPanel.refusalClearsOnRevert-26846.test.tsx`: a
revert to the loaded value clears the banner; CONTROL: a still-dirty
edit keeps it.
- New `StudioDesignSurface.accessRailLabelLive-26846.test.tsx`: the real
`AccessPillar` with a matrix stand-in that reports one draft save; the
rail row goes from "Dispatcher" to "Dispatcher v2".
- New `PermissionMatrixEditor.fieldTableLayout-26846.test.tsx`: the
count is the filter's next sibling and has no `ml-auto`; the name header
and every name cell carry the pinned classes; CONTROL: a box cell is not
sticky. jsdom lays nothing out, so this pins structure and classes, not
pixels.
- Updated `StudioDesignSurface.accessCreateTaken-26836.test.tsx`: the
race test now expects the author-facing sentence and the absence of the
pin sentence; a new CONTROL keeps a `VALIDATION_ERROR` refusal's own
text.
<details><summary>Runs</summary>
- The four files: `Test Files 4 passed (4)`, `Tests 15 passed (15)`
(lock VERDICT command-exit 0).
- Every app-shell test file naming `PermissionMatrixEdit`,
`AccessPillar`, `PackageOwdOverviewPanel` or an `engine.studio.access.`
key (65 files): `Test Files 65 passed (65)`, `Tests 595 passed (595)`
(lock VERDICT command-exit 0, 5m37s).
- `pnpm --filter @object-ui/app-shell run type-check` exit 0; `pnpm
--filter @object-ui/i18n run type-check` exit 0; `pnpm --dir ui run
type-check:scripts` exit 0.
- Ablations, one per behaviour, each through
`scripts/ablation-replace.mjs` with the restore proved by blob equal to
HEAD and an empty `git diff HEAD`:
- item 1, the `METADATA_CONFLICT` test replaced by `false`: the race
test fails, 9 others pass.
- item 2, the clear replaced by `void 0;`: the revert test fails, its
CONTROL passes.
- item 3, the `void load();` deleted: the rail-label test fails. (A
first attempt that replaced the line was refused by the tool before any
run, the replacement count not rising; the delete form ran.)
- item 4, `FIELD_NAME_CELL` emptied: the pinned-column test fails, the
counter test passes.
- item 4, the counter's class put back to `ml-auto …`: the counter test
fails, the pinned-column test passes.
</details>
## Acceptance notes
- Item 1: the card's reproduction no longer reproduces on main (#26836
added the pre-save check); only the check-to-save race reached the
author, and that is what is mapped. Other Studio creates (flow, object,
app, interfaces) share the same race shape and still show the door's
sentence there; noted, not changed here.
- Item 3: the rail shows a PUBLISHED set by its published label and a
draft-only set by its `_drafts` row label (ruling 6053526025, question
1). A label edit on a published set's pending draft therefore still
shows the published label until publish; this PR does not change that
reading.
- Item 4 was reasoned from the matrix's `min-w-[1304px]` floor against
the Studio column width, not measured in a browser at 1440 x 900.
## Verification
- Derived gates (`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` at `8220f32d`): 34 commands, all exit 0;
`--ran` reconciliation: "34 derived famil(ies) accounted for — 34 run, 0
NOT-MEASURED". Also run outside the derivation: `pnpm
check:changeset-fixed` exit 0 and `pnpm --dir ui run
check:new-line-citations` exit 0 ("0 new citation(s)").
- `dispatch-gates --tier`: no path-derived mandate; 349 changed lines
(+341 / -8), under the 3000 threshold.
- Changeset `.changeset/26846-studio-access-polish.md`:
`@object-ui/i18n` patch (new key), `@object-ui/app-shell` patch.
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(untouched)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` is CI's.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: n/a.
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English (the 维护者速读 block is the
dispatch order's Chinese section).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JQwxbYZa5ViBSW4Et4fr91)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent a315560 commit ff648d7
10 files changed
Lines changed: 341 additions & 8 deletions
File tree
- .changeset
- ui/packages
- app-shell/src/views
- metadata-admin
- studio-design
- i18n/src/namespaces/studio
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3007 | 3007 | | |
3008 | 3008 | | |
3009 | 3009 | | |
| 3010 | + | |
| 3011 | + | |
| 3012 | + | |
| 3013 | + | |
| 3014 | + | |
| 3015 | + | |
| 3016 | + | |
3010 | 3017 | | |
3011 | 3018 | | |
3012 | 3019 | | |
| |||
3164 | 3171 | | |
3165 | 3172 | | |
3166 | 3173 | | |
| 3174 | + | |
| 3175 | + | |
| 3176 | + | |
| 3177 | + | |
3167 | 3178 | | |
3168 | 3179 | | |
3169 | 3180 | | |
| |||
3174 | 3185 | | |
3175 | 3186 | | |
3176 | 3187 | | |
| 3188 | + | |
| 3189 | + | |
| 3190 | + | |
| 3191 | + | |
| 3192 | + | |
| 3193 | + | |
3177 | 3194 | | |
3178 | 3195 | | |
3179 | 3196 | | |
| |||
3205 | 3222 | | |
3206 | 3223 | | |
3207 | 3224 | | |
3208 | | - | |
3209 | | - | |
3210 | | - | |
3211 | 3225 | | |
3212 | 3226 | | |
3213 | 3227 | | |
| |||
3221 | 3235 | | |
3222 | 3236 | | |
3223 | 3237 | | |
3224 | | - | |
| 3238 | + | |
| 3239 | + | |
| 3240 | + | |
3225 | 3241 | | |
3226 | 3242 | | |
3227 | 3243 | | |
| |||
3237 | 3253 | | |
3238 | 3254 | | |
3239 | 3255 | | |
3240 | | - | |
| 3256 | + | |
3241 | 3257 | | |
3242 | 3258 | | |
3243 | 3259 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
334 | 334 | | |
335 | 335 | | |
336 | 336 | | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
337 | 343 | | |
338 | 344 | | |
339 | 345 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| |||
221 | 222 | | |
222 | 223 | | |
223 | 224 | | |
224 | | - | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
225 | 231 | | |
226 | 232 | | |
227 | 233 | | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
228 | 248 | | |
229 | 249 | | |
230 | 250 | | |
| |||
0 commit comments