Repository navigation
Commit 9598405
fix(fields): a user field's person object is always sys_user (user cell and picker) (#26050)
Fixes #25937
Clause-②: no
Metadata-protocol: none
## What
A `user` field's person object is now always `sys_user` in the console,
matching the spec contract from #24952 (PR #25074): `FieldSchema`
refuses a `user` field whose `reference` names any object but
`sys_user`, and `referenceTargetOf` resolves every `user` field to
`sys_user` whatever the field carries.
- `ui/packages/fields/src/index.tsx`, `UserCellRenderer`: the read
gate's object was `field.reference || 'sys_user'`. It is now the
constant `'sys_user'`, and the renderer no longer reads `field` at all.
The JSDoc is rewritten: it said the person's object is "the field's
`reference`".
- `ui/packages/fields/src/widgets/UserField.tsx`: the picker's target
was `meta?.reference || 'sys_user'`. It is now `'sys_user'`, with the
comment rewritten to match.
- `ui/packages/fields/src/__tests__/userCell.readGate-10535.test.tsx`:
the `crm_member` case flips. A `{ type: 'user', reference: 'crm_member'
}` field is now gated by the `sys_user` policy, and its drawing is
byte-equal to a plain `{ type: 'user' }` field under the same policy. A
`crm_member` policy no longer reaches it. The header bullet and the test
title no longer say the person's object is the field's `reference`. The
retired `reference_to` case is unchanged and still passes.
- `scripts/sdui-manifest.record.json`: re-recorded with `node
scripts/gen-sdui-manifest-node.mjs`, because `ui/packages/fields/src` is
a registry source the record digests.
- `.changeset/25937-user-cell-sys-user.md`: `@object-ui/fields` patch.
The route is the type's constant, not a call to `referenceTargetOf`.
That helper reads the field's reference carrier first and throws when
the carrier is unreadable (`referenceCarrierOf`), so it does not belong
in a render path. objectui also does not import the spec's field
helpers.
## Behaviour change to note: which policy gates a stored foreign
`reference`
The renderer read gate (`withoutDeniedFields`) is keyed by object name.
A stored object saved before the spec refusal can still carry a `user`
field with a foreign `reference`, for example `crm_member`. The cell
used to gate that field by the `crm_member` policy. It now gates it by
the **`sys_user` policy**. That is the object the runtime expands the
field into (`referenceTargetOf`), so the cell now hides exactly what the
served row's own object denies. The picker also searches `sys_user` for
such a field now, not the foreign object. This is the card's intent: a
link to another object is a `lookup`.
## Verification
All readings were taken at head `11a85a02`, after `main` was merged in
at `c8cb510a`, on a shared box.
- `cd ui && pnpm exec vitest run --maxWorkers=2 packages/fields/` under
the verify lock: **Test Files 277 passed | 1 skipped (278), Tests 4290
passed | 7 skipped (4297)**, VERDICT command-exit 0.
- `pnpm --filter @object-ui/fields type-check` (`tsc --noEmit && tsc -p
tsconfig.test.json`; the test config compiles `__tests__`): VERDICT
command-exit 0.
- `eslint` over the three edited ui files: 0 errors. The 152 warnings
were already there.
- Ablation, one leg, with the fix committed first.
`scripts/ablation-replace.mjs` put the old read back in place of `const
personObject = 'sys_user';`, that is `field.reference || 'sys_user'`.
The tool reported the anchor going 1 to 0 and the blob going
`2ac4abd3f41c` to `644362b7ff75`. Result:
`userCell.readGate-10535.test.tsx` **1 failed | 6 passed**. The flipped
case failed at `:164`: `expected … not to contain 'Amy Lin'`, because
the `crm_member` field was no longer gated by the `sys_user` policy. On
restore, the blob was back to the HEAD blob `2ac4abd3f41c` and `git diff
HEAD` was empty. The green leg at the same head: 7 of 7 passed.
- The test imports `../index` (source), so the ablation needs no `dist/`
rebuild.
- `node scripts/gen-sdui-manifest-node.mjs` (under the lock, exit 0)
re-recorded only `inTree.registrySourcesSha256`. `sdui.manifest.json` is
byte-identical: sha256 `1f6e1ccb925a…`, 106 components. `node
scripts/check-sdui-manifest.mjs` passes.
- Derived gates: `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` gave 46 commands, and all 46 exited 0. `pnpm
check:type-check-debt` hit a 300 s local timeout on its first run and
passed on the rerun, with no surplus. `--ran` reconciliation: 46
derived, 46 run, 0 NOT-MEASURED, 0 UNRUN.
- `node scripts/check-changeset-fixed.mjs`: in sync. Its roster sits
under `.changeset/`, which this PR touches.
- Full dogfood: not run. The title has no `!` and `Clause-②` has no
`(narrowing)` arm.
## Acceptance notes
- `LookupCellRenderer`'s comment in `ui/packages/fields/src/index.tsx`
still lists `UserField` among the readers that read `reference`. That is
now stale, because `UserField` fixes the target. The comment sits
outside this card's declared file region (`UserCellRenderer` only), so
this PR leaves it alone. Carrier: none.
- `RecordMetaFooter`'s `UserRef` (`ui/packages/plugin-detail`) still
builds `reference: fieldDef?.reference || 'sys_user'` for audit fields.
When the field is typed `user`, the cell renderer now ignores that
`reference`, so nothing visible changes. Observation only.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01SMps7wq7rBTk53e8KTSEup)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent b239a01 commit 9598405
7 files changed
Lines changed: 52 additions & 26 deletions
File tree
- .changeset
- scripts/sdui-manifest.sources
- ui/packages
- fields/src
- __tests__
- widgets
- plugin-grid/src
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
29 | | - | |
30 | | - | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
31 | 33 | | |
32 | 34 | | |
33 | 35 | | |
| |||
151 | 153 | | |
152 | 154 | | |
153 | 155 | | |
154 | | - | |
155 | | - | |
156 | | - | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
157 | 161 | | |
158 | | - | |
| 162 | + | |
| 163 | + | |
159 | 164 | | |
| 165 | + | |
160 | 166 | | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
165 | 171 | | |
166 | 172 | | |
167 | 173 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3142 | 3142 | | |
3143 | 3143 | | |
3144 | 3144 | | |
3145 | | - | |
3146 | | - | |
3147 | | - | |
| 3145 | + | |
| 3146 | + | |
| 3147 | + | |
| 3148 | + | |
| 3149 | + | |
| 3150 | + | |
| 3151 | + | |
3148 | 3152 | | |
3149 | | - | |
| 3153 | + | |
3150 | 3154 | | |
3151 | 3155 | | |
3152 | 3156 | | |
3153 | | - | |
3154 | | - | |
3155 | | - | |
| 3157 | + | |
3156 | 3158 | | |
3157 | 3159 | | |
3158 | 3160 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
47 | 50 | | |
48 | 51 | | |
49 | | - | |
| 52 | + | |
50 | 53 | | |
51 | 54 | | |
52 | 55 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
330 | 330 | | |
331 | 331 | | |
332 | 332 | | |
333 | | - | |
| 333 | + | |
334 | 334 | | |
335 | 335 | | |
336 | 336 | | |
| |||
0 commit comments