Repository navigation
Commit 534a287
feat(console): the sharing-rule object picker lists only shareable objects, business objects first (#31274)
<!-- claude-projects-attribution: {"github_login":"os-project-manager"}
-->
_Requested by **Leehom** · [project
thread](https://claude.ai/code/project/chan_01TenzsRopZj4jMbvjX8uz1X?thread=cmsg_01TenzsRopZj4jMbvjX8uz1XBy2QatVq72fKr8HLn4oAbE)_
Fixes #31217
Clause-②: yes (widening)
Metadata-protocol: none
## 维护者速读
- 改了什么:新建共享规则时,「对象」下拉框改为只列「规则存得进、也能生效」的对象,业务对象在前、平台对象在后,顺序照服务器 `GET
/api/v1/sharing/shareable-objects` 给的原样显示。新增字段控件
`shareable-object-ref`,`sys_sharing_rule.object_name` 的控件提示从
`object-ref` 改为它(同一个 PR 注册、同一个 PR 切换)。
- 为什么改:原来下拉框列出全部 86 个对象,多数是 `sys_*`,还包括存了会被 `SHARING_NOT_ENABLED`
拒绝的对象和会话、凭据类对象;#30209 第 5 行方案 B 的控制台半边,服务器半边 PR #31207 已合并。
- 风险与回滚:接口答 403(不是共享规则管理员)、501(本部署没跑共享规则)或任何读不出列表的情况,字段退回原来的
`object-ref`
全量列表,不会出现空下拉框;保存时服务器仍是最终裁决。已存的规则对象不在列表里时仍保留为选项,编辑不会丢值。列表格子和只读面沿用
`object-ref` 的对象名标签。回滚即 revert。
-
先看:`ui/packages/fields/src/widgets/ShareableObjectRefField.tsx`(读接口与退回逻辑),`ui/packages/plugin-form/src/__tests__/objectFormShareableObjectRef-31217.test.tsx`(在新建表单上点选、保存、403/501
退回),`packages/plugins/plugin-sharing/src/objects/sys-sharing-rule.object.ts`(控件提示)。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/plugin-form/src/__tests__/objectFormShareableObjectRef-31217.test.tsx`,预期
`Tests 5 passed (5)`。
- 需要你做的:无,席位落地。
## What changes
- **The widget** (`@object-ui/fields`, new
`widgets/ShareableObjectRefField.tsx`, registered as
`field:shareable-object-ref`). It reads `GET
/api/v1/sharing/shareable-objects` through the host's authenticated
fetch (`SchemaRendererContext.apiFetch`, the route the
`notification-topic` picker reads its door by) and offers `data.objects`
in the order the door sends: business objects, then platform objects,
each by label. Options use `objectRefOptionLabel`, the `Label (name)`
spelling `object-ref` uses, and a pick writes the object's machine name.
A stored name the list does not hold is kept as its own leading option,
so editing a rule on an object that no longer takes one never drops the
value. No new translation key: the loading, placeholder, search and
empty strings are `object-ref`'s.
- **The fallback.** When the door does not answer a readable list, the
field renders `ObjectRefField` unchanged: every registered object from
`dataSource.getObjects()`. That covers the two states the card names,
`403 PERMISSION_DENIED` (not a sharing-rule administrator) and `501
NOT_IMPLEMENTED` (sharing rules not running), and also any other
non-2xx, a body that is not the door's shape, a network failure, and a
host with no `apiFetch`. Never an empty picker. The read-only face is
also `object-ref`'s, so a record page does not call an admin-only door.
- **The declaration** (`@objectstack/plugin-sharing`).
`sys_sharing_rule.object_name` declares `widget:
'shareable-object-ref'`, flipped in the PR that registers the widget.
The `by_object` pin moves with it, and the census of fields that store
an object API name (`sys-sharing-rule.by-object.test.ts`) counts the new
widget beside `object-ref`, so the no-grouping rule still reaches this
field.
- **The other faces of the key**, each the row `object-ref` already has:
the list cell promotes to the same object label face
(`WIDGET_CELL_RENDERER_TYPES`, the default text face in
`@object-ui/fields` and the console's `ObjectRefCell` in
`@object-ui/app-shell`); the record form threads `dataSource` to it
(`DATA_SOURCE_ONLY_WIDGET_TYPES` in `@object-ui/components`, which the
fallback reads); it is not edited inline in a grid (`FieldEditWidget`);
it is a widget-hint-only string in `paramValueShape`; and
`field:shareable-object-ref` joins the known schema types of
`@object-ui/cli`.
- **Registry censuses** that enumerate every registered widget gain the
row: `widget-aria-invalid-registry-e2e`, `widget-dom-leak-e2e`,
`cellRenderers.objectLiteral-8596`, `summaryChip.badgeFitCensus-8464`
(fit side 41 to 42), `inlineEditTypeCoverage`, and the `className`
readers in `form-field-channel-census-12130`.
- **Changeset** `.changeset/31217-shareable-object-picker.md`, patch on
the five shipping packages, both declaration lines.
### Declaration lines, as measured
- `Clause-②: yes (widening)`. The claim started at `no`; the diff adds a
registered widget key, which widens the published
`RegisteredFieldWidgetType` union of `@object-ui/fields` and the known
schema types of `@object-ui/cli` (the precedent is
`.changeset/31062-notification-topic-channel-pickers.md`). No
translation key is added, removed or reworded; no export is added (the
widget is reached only through the lazy registry, not the package
barrel); nothing is narrowed.
- `Metadata-protocol: none`. The spec's `FieldSchema.widget` is an open
string, so no authorable key or accepted value changes. The flip changes
the value one server object declares, which only picks the console
control.
## Tests
- New `objectFormShareableObjectRef-31217.test.tsx` drives `ObjectForm`
in create mode inside `SchemaRendererProvider` (as the console mounts
it), opening the real combobox and submitting the real form: (1) the
door's list in its order and nothing else (no `sys_session`, no
`sys_api_key`, no object the door leaves out), the registry list never
read; (2) CONTROL: a shareable object is selectable and the form saves
`object_name: 'crm_opportunity'`; (3) a stored name the door does not
list stays an option; (4, 5) a 403 and a 501 give the `object-ref` list
of every registered object, and a pick from it saves.
- Ablations on the final head, each through
`scripts/ablation-replace.mjs` (anchor hit, restore proved by blob
equality and an empty `git diff HEAD`): ignoring the door's list
(`objects: null`) reds tests 1 and 3; answering a refused door with an
empty list (`return []`) reds tests 4 and 5.
## Acceptance notes
- The door withholds localization (its header: "the list is the same in
every language"), so the picker shows the labels the server declares.
`object-ref`'s list (`GET /meta/object`) carries declared labels too, so
no language loses a translation here.
- A failure other than 403/501 also falls back rather than showing a
notice. The save doors stay the authority (`SHARING_NOT_ENABLED`), so
the wider list costs a refusal at save, never a wrong rule, and adding a
notice would add translation keys this card did not ask for.
## Verification
Head `309f44a0`; every count below is read off the tool's own verdict
line.
- `pnpm --dir ui exec vitest run` over `packages/fields/`,
`packages/plugin-form/`, `packages/components/src/renderers/form/`,
`packages/app-shell/src/views/widget-ref-cells/`,
`packages/app-shell/src/utils/`, `packages/cli/src/__tests__/` and the
census files above (under `os-verify-lock`): `Test Files 696 passed | 2
skipped`, with 6 census files red on the first run, each the missing row
for the new key; after adding the rows the 7 touched files pass, `Tests
456 passed (456)`, re-run on `309f44a0`.
- `pnpm --filter @objectstack/plugin-sharing test`: `Test Files 70
passed (70)`, `Tests 1464 passed (1464)`.
- `type-check` for `@object-ui/fields`, `@object-ui/components`,
`@object-ui/plugin-form`, `@object-ui/plugin-detail`,
`@object-ui/app-shell`, and `pnpm --filter @objectstack/plugin-sharing
typecheck`: all exit 0.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` on `309f44a0`: 67 derived families, all 67
run with exit 0 (codes captured before any pipe); `--ran`: "67 derived
famil(ies) accounted for — 67 run, 0 NOT-MEASURED". The branch merges
cleanly onto `origin/main` `abc7a940` (`git merge-tree`). `pnpm
check:new-line-citations` (ui): 0 new citations.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01FEkQ5ntiCZev2cDL6r5VLw)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent ebc2cdc commit 534a287
17 files changed
Lines changed: 379 additions & 13 deletions
File tree
- .changeset
- packages/plugins/plugin-sharing/src/objects
- ui
- examples/schema-catalog/test
- packages
- app-shell/src
- utils
- views/widget-ref-cells
- cli/src/utils
- components/src/renderers/form
- fields/src
- __tests__
- widgets
- plugin-detail/src/__tests__
- plugin-form/src/__tests__
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| |||
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
43 | | - | |
| 44 | + | |
44 | 45 | | |
45 | 46 | | |
46 | 47 | | |
| |||
77 | 78 | | |
78 | 79 | | |
79 | 80 | | |
80 | | - | |
| 81 | + | |
81 | 82 | | |
82 | 83 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
74 | | - | |
| 74 | + | |
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
| |||
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
139 | 141 | | |
140 | 142 | | |
141 | 143 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
368 | 368 | | |
369 | 369 | | |
370 | 370 | | |
371 | | - | |
| 371 | + | |
372 | 372 | | |
373 | 373 | | |
374 | 374 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
| 178 | + | |
178 | 179 | | |
179 | 180 | | |
180 | 181 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
47 | 47 | | |
48 | 48 | | |
49 | 49 | | |
| 50 | + | |
| 51 | + | |
50 | 52 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
| 166 | + | |
166 | 167 | | |
167 | 168 | | |
168 | 169 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
740 | 740 | | |
741 | 741 | | |
742 | 742 | | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
743 | 746 | | |
744 | 747 | | |
745 | 748 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
188 | 188 | | |
189 | 189 | | |
190 | 190 | | |
191 | | - | |
| 191 | + | |
192 | 192 | | |
193 | 193 | | |
194 | 194 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
297 | 297 | | |
298 | 298 | | |
299 | 299 | | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
300 | 303 | | |
301 | 304 | | |
302 | 305 | | |
| |||
364 | 367 | | |
365 | 368 | | |
366 | 369 | | |
| 370 | + | |
367 | 371 | | |
368 | 372 | | |
369 | 373 | | |
| |||
0 commit comments