Repository navigation
feat(fields, spec): show a referenceNameVisible lookup's served name as plain text, and offer its field-form row - #29639
Conversation
…as plain text, and offer its field-form row Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTfRUqsXsgEtuXogw2
…ield-form row; translate the row Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTfRUqsXsgEtuXogw2
… no link under a displayField Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTfRUqsXsgEtuXogw2
…ow among the labels translated in all three locales Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTfRUqsXsgEtuXogw2
📓 Docs Drift Check5 anchor(s) derived from 2 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 168 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 218b83b6c98d33ff01e54d869da5c7ed4aff4248 && git checkout 218b83b6c98d33ff01e54d869da5c7ed4aff4248
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 3482f3d8d2c48ec8d2e3306f1ce26c0364e800c2 511e63991b63c91a77762b5c708eb31678c2b644 && git checkout -B drift-repro 3482f3d8d2c48ec8d2e3306f1ce26c0364e800c2 && git merge --no-ff 511e63991b63c91a77762b5c708eb31678c2b644
node scripts/docs-audit/affected-docs.mjs --json 3482f3d8d2c48ec8d2e3306f1ce26c0364e800c2 |
… to 91) The #7010 corpus pin over METADATA_FORM_REGISTRY counts the new field.form.ts row's visibleWhen "data.type in ['lookup','user']". It is an in-list, so the literal-comparison censuses stay at 65 and 18. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jTfRUqsXsgEtuXogw2
|
domain:ui#3 · zhuangjianguo · session_01QsR2jV4dWohojjbTJTQq5m 席位核对 · ACCEPT · 2026-11-03T00:16ZHead-sha:
|
Requested by Steedos · project thread
Fixes #29462
Clause-②: no
Metadata-protocol: none
Claim: 6588482199 (amendments 6588547542, 6590220295)
维护者速读
referenceNameVisible: true的 lookup / user 字段,当服务端对读者无权读取的目标返回{ id, name, readRefused: true }时,列表单元格与记录详情页把名称显示为纯文本:不带链接、不弹悬浮卡、不读取目标记录;多值字段每个元素一个文本标签。字段表单(field元数据表单)新增该开关,只在 lookup 与 user 类型上显示,并补了中日西三语文案。referenceNameVisiblelookup when the caller cannot read the target (#29171 ruling B) #29460,PR feat(objectql): a referenceNameVisible lookup or user field names a target the reader is refused, on $expand (#29460) #29576)已开始下发名称;按裁决 6574398310 字母 B,控制台要显示名称而不是「受限记录」占位,且不得链接到读者打不开的记录。readRefused: true的值;不带该键的字段、可读目标、裸 id 的「受限记录」占位全部不变([finding]skills/**/references/_index.mdis generator-owned but not routed tomerge=os-regen— two branches that regenerate it text-merge instead #13335 测试原样通过)。回滚即 revert 本 PR。ui/packages/fields/src/index.tsx的isReferenceNameOnly/ReferenceNameOnly与LookupCellRenderer、UserCellRenderer中的三处分支;packages/spec/src/data/field.form.ts新增的一行。pnpm --dir ui exec vitest run packages/fields/src/__tests__/lookupCell.referenceNameVisible-29462.test.tsx,预期 11 个用例全部通过。What changes
The console half of
FieldSchema.referenceNameVisible(director ruling 6574398310, letter B), rendered against the shape PR #29576 serves: on$expand, alookup/userfield declaring the key answers a target the reader is refused as{ id, name, readRefused: true }, once per element onmultiple: true, with the floorRecord #IDunder a field-level rule on the name column.{ id, name, readRefused: true }on alookupnameas plain text (data-slot="reference-name-only"), no link, no hover card, no readusernameas plain text, no avatarmultiple: true)isReferenceNameOnlyjudges the in-bandreadRefused === truethe server writes, never the shape of the rest, so a readable record expanded with a narrow projection stays a link.displayFielddoes not re-name it.useRefObjectSchemagets no object), so the cell makes no read at all.DetailSection) draws lookup and user values through these same cells, so it changes with them;plugin-detailsource is untouched.packages/spec/src/data/field.form.tsgains thereferenceNameVisiblerow ("Show Name When Unreadable"),visibleWhen: data.type in ['lookup','user']. That predicate is also the key's parse gate:FieldSchemarefuses the key on every other type, an authoredfalseincluded. Theomitledger entry inmetadata-form-zod-reconciliation.test.tsis removed with the row (the card's one spec edit). The row's label and help text are regenerated into theplatform-objectsmetadata-form bundles and translated for zh-CN, ja-JP and es-ES.Tests
ui/packages/fields/src/__tests__/lookupCell.referenceNameVisible-29462.test.tsx(new, 11): served name as text with no anchor, and a recording data source (find, findOne, getObjectSchema all answering) asked nothing, after hover and focus; the floorRecord #l1drawn as served;displayFielddoes not re-name it;multiple: trueone chip per element; a mixed array keeps the readable element's link;usersingle and multiple; CONTROLS: a record without the marker andreadRefused: 'yes'stay links, a field without the key keeps the restricted placeholder, an expanded user keeps its avatar.ui/packages/plugin-detail/src/__tests__/DetailSection.referenceNameVisible-29462.test.tsx(new, 5): the realDetailSectiondraws lookup, user and multi-value user rows as text with no anchor, reads nothing about the refused targets, and keeps a readable sibling's link.packages/spec/src/data/field-form-reference-name-visible.test.ts(new, 3): the row is declared once, its predicate shows it onlookupanduseronly over everyFieldType, and that set equals the setFieldSchemaaccepts the key on.lookupCell.restrictedRecord-13335.test.tsxgreen, unmodified.scripts/ablation-replace.mjs, WRAP mode, each restored to the HEAD blob), each red: A1 lookup single branch removed, 3 failed; A2 array element branch removed, 2 failed; A3 user single branch removed, 2 failed; A4 user array branch removed, 2 failed; A5 schema read no longer skipped, 1 failed; A6 the row's predicate widened tomaster_detail, 2 failed.Acceptance notes
dispatch-gates --tierderives no path mandate (default tier). It prints a Clause-② SUSPECT hint onpackages/spec/src/data/field.form.ts(packages/spec/src/**). The row offers a keyFieldSchemaalready accepts on exactly these types (the accept set does not move), so the claim'sClause-②: nois kept; the seat reads the hint.object-lifecycle-panel-echo-decisions.test.tscounts metadata-form labels authored in all three locales, 699 → 700 with its comment line, as every new form row does.ObjectFieldInspector, which does not readfield.form.ts. A live probe as the admin (lookup selected in the designer) shows no such control there. The seat files that control as its own card; this PR leaves the inspector alone.7fb3a29d:dispatch-gates --commandsderives 85 commands; each ran with exit 0 (check:type-check-debtandpnpm --dir ui exec vitest run scripts/under the verify lock), and--ranreconciles 85 derived, 85 run, 0 NOT-MEASURED, 0 UNRUN. Type-checks exit 0: spec, platform-objects, andturbo run type-checkfor@object-ui/fieldsand@object-ui/plugin-detail. Suites: spec 891/891 files (25223 tests) and fields 295 files / plugin-detail 369 files before the main merge; on the merged head platform-objects 110/110 files, specsrc/system/plus the field-form tests 70/70 files, the four lookup/detail files 31/31, andspec check:generatedexit 0. The repo-wide sweep (pnpm lintand the rest of the farm) is CI's.Verification
Real backend and the source Console, on head
5c25e7f3(before the main merge; this PR's cell and form code is unchanged since). Screenshots and the scripts are in the project folder (issue-29462/shots/,live-setup.mjs,live-grant.mjs,live-shot.cjs), not on GitHub.pnpm dev:crm -- --freshplus the Console Vite dev server, a member who may read the expense but not the payroll runrnv_payroll(sharingModel: private, admin-owned rows) andrnv_expense(public_read) withpayroll(lookup,referenceNameVisible: true),payroll_plain(the same lookup without the key) andpayrolls(multiple: true, with the key). A member created withadmin/create-user, granted read onrnv_expenseonly by a package permission set, then impersonated.GET /api/v1/data/rnv_payroll/IDas the member: 403.GET /api/v1/data/rnv_expense/ID?expand=payroll,payroll_plain,payrollsas the member:payroll={ id, name: "Payroll Q3 2026", readRefused: true },payrolls= two such values,payroll_plain= the bare id. As the admin, all three are the full records./apps/com.example.rnv/rnv_expense) and record page, as the member:Payroll (name visible)reads "Payroll Q3 2026" as plain text;Payrollsshows two text chips "Payroll Q3 2026" and "Payroll Q4 2026"; threereference-name-onlyelements, none inside a link. Hovering each of them made no request. The onlyrnv_payrollrequests on the page (one record read, one object definition read) and the only link tornv_payrollbelong toPayroll (no key), the control field, which draws as before.Generated by Claude Code