Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .changeset/24187-docblock-mechanisms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'@objectstack/spec': patch
---

Clause-②: no

The `ActionParam` `options` docblock in `src/ui/action.zod.ts` no longer quotes objectui's inline
param branch as `options: param.options`. At the console pin (`.objectui-sha` `5e15928b4631`) that
branch of `resolveActionParam` reads `options: authoredOptions`, where `authoredOptions` is
`resolveOptionLabels(param.options, ctx.locale)`: the authored array itself when every `label` is
already a string, and otherwise only the entries with an inline per-locale `label` re-spread with
that label resolved. The docblock's point is unchanged: an inline param's options, `visibleWhen`
included, reach the widget as authored. No key, schema, export, accepted value or message text
changes.
18 changes: 15 additions & 3 deletions packages/spec/src/conversions/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14461,9 +14461,21 @@ const pageAssignedProfilesRemoved: MetadataConversion = {
* `master_detail` under this sharing model into `required: true`
* (`forceCbpMasterDetailRequired`, `data/object.zod.ts`), so the converted row
* is exactly the object the builder would have produced from the same source.
* The relation it resolves is the one the second tier resolved, and the write
* the row could not legally take (an insert without its master, an update
* nulling it) was refused before as well, by the security gate.
* The relation it resolves is the one the second tier resolved. Of the two
* writes the row could not legally take, the insert without its master was
* refused before as well, by the security gate: on an insert
* `packages/plugins/plugin-security/src/security-plugin.ts#assertControlledByParentWrite`
* reads the master FK from the incoming body. The update nulling it was not.
* On a by-id update that gate reads the STORED row's FK, never the incoming
* value, so the write was accepted and left a detail row with a null master
* FK, which the `controlled_by_parent` read filter
* (`masterFK IN (accessible master ids)`) never matches. The refusal for that
* update is the record validator's ADR-0113 check, a PATCH may not null out a
* required field (the update branch of
* `packages/objectql/src/validation/record-validator.ts#validateRecordInScope`),
* and only `required: true` arms it. So the converted row loses no write the
* contract allows: it gains the refusal the builder's force already gives an
* authored object.
*
* **Deliberately narrow — exactly one shape, nothing else.**
* - An explicit `required: false` is NOT converted. The builder refuses it
Expand Down
9 changes: 7 additions & 2 deletions packages/spec/src/ui/action.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,13 @@ export const ActionParamSchema = lazySchema(() => strictObject(
* guessed at here, and #5016 answered it **per key, on measurement**:
*
* - **`visibleWhen` — opened.** The reader is on this exact path and it works
* today. An inline param's `options` are lowered VERBATIM (objectui
* `resolveActionParam`'s inline branch does `options: param.options`;
* today. An inline param's `options` are lowered VERBATIM (at the console
* pin, `.objectui-sha` `5e15928b4631`, objectui `resolveActionParam`'s
* inline branch does `options: authoredOptions`, and `authoredOptions` is
* `resolveOptionLabels(param.options, ctx.locale)`, which returns the
* authored array itself when every `label` is already a string and
* otherwise re-spreads only the entries whose `label` is an inline
* per-locale map, resolving that `label`;
* `ActionParamDialog` re-spreads each entry to localise `label`;
* `paramToField` passes the array straight into the widget's field
* metadata), and `SelectField` / `MultiSelectField` / `RadioField` /
Expand Down
Loading