|
| 1 | +--- |
| 2 | +"@objectstack/plugin-approvals": minor |
| 3 | +"@objectstack/spec": minor |
| 4 | +"@objectstack/rest": minor |
| 5 | +--- |
| 6 | + |
| 7 | +fix(approvals,rest): tell the truth about what a write did — `locks_record` on the request, `droppedFields` on the cross-object batch (#3794) |
| 8 | + |
| 9 | +Two halves of the same complaint: in an approval flow the platform reported |
| 10 | +record writability wrong in *both* directions — what you could change said |
| 11 | +"locked", and what you couldn't said "updated successfully". |
| 12 | + |
| 13 | +**`locks_record` on the approval request.** The lock hook reads one thing to |
| 14 | +decide whether a pending approval blocks writes: the node config snapshot's |
| 15 | +`lockRecord` (`=== false` ⇒ the update goes through). Nothing exposed that, so a |
| 16 | +client had only "a pending request exists" and had to guess — and the Console |
| 17 | +guessed "locked", every time. A `lockRecord: false` node exists precisely so the |
| 18 | +approver can amend the record while deciding on it; painting "Locked for |
| 19 | +approval" over that hides the whole feature, and approvers never try. Request |
| 20 | +rows (`getRequest` / `listRequests`, and therefore `GET /api/v1/approvals/requests`) |
| 21 | +now carry `locks_record`, read from the same snapshot the hook reads, with the |
| 22 | +same default-true. Absent on rows from an older server ⇒ assume locked. |
| 23 | + |
| 24 | +**`droppedFields` on `POST /batch`.** The engine strips writes to `readonly` |
| 25 | +(#2948) and `readonlyWhen`-locked (#3042) fields and completes the write without |
| 26 | +them. Every write path already reported which fields it dropped (#3431/#3455) — |
| 27 | +except the cross-object transactional batch, which never wired |
| 28 | +`onFieldsDropped` at all. That path is the Console record form's save for a |
| 29 | +master-detail record, so it is exactly where a *user* edits a `readonlyWhen` |
| 30 | +field: they changed it, the form said "updated successfully", the value never |
| 31 | +moved, and nothing anywhere said so. The response now carries a top-level |
| 32 | +`droppedFields` list, each event tagged with the `index` of the operation that |
| 33 | +produced it (`results` entries are bare record echoes with no envelope to hang a |
| 34 | +per-row list on). Omitted entirely when nothing was dropped, so the shape stays |
| 35 | +backward-compatible; the batch still commits either way — a strip is legal |
| 36 | +semantics, not an error. |
| 37 | + |
| 38 | +The Console half of both fixes ships in objectui: the detail band now |
| 39 | +distinguishes "in approval (editable)" from "locked for approval", and the |
| 40 | +write-warning toast fires on batch saves. |
0 commit comments