Commit 1ac8d30
feat(operations): replace
Scope reduction, per kriszyp's review on #2347: one operation instead of a flag
plus a per-record directive.
{ "operation": "put", "database": "dev", "table": "dog",
"records": [{ "id": 1, "dog_name": "Penny" }] }
The stored record becomes exactly that, so an attribute the request omits is
removed. Creates a missing record and replaces an existing one — the same
`Table.put` REST's `PUT /Table/id` performs, so the same audit type, replication
shape, and retained `__createdtime__`. `update`/`upsert` keep merging, which is the
v4-compatible behaviour existing clients depend on and the reason this is a
separate operation rather than semantics changed in place.
This covers what studio#1643 actually needs: its row editor holds the whole record
already. Removed with the flag and the directive:
- `full_record` as a client-facing field on update/upsert
- `__unset__`, its reserved key, its validation, the attribute-collector
divergence in both `insertUpdateValidate.js` and `insert.ts`, and the
`getRecordAttributes` name expansion
- `takeUnsetAttributes` and its latch
Three problems retire with them, all raised in review and none now reachable:
`__unset__` degrading a merge to a whole-record put under contention (kept as a
feature request, see below), the reserved key reinterpreting a pre-existing
`__unset__` attribute with no migration, and the directive's interaction with
dynamic attribute expansion.
The internal marker is an ARGUMENT, not a field: `putRecords` calls
`upsertRecords(obj, true)`. Reading it off the request — which the first draft of
this commit did — let a client send `full_record: true` with an `update` and get a
replace, which makes the operation name stop describing the write and bypasses the
attribute-scoped denial, since that is keyed on the operation. A test pins it;
restoring the request read fails that test and nothing else.
Kept from the previous rounds, unchanged in substance:
- The attribute-scoped denial, now keyed on `op === write.put.name`. A replace
removes what the request omits, and `checkAttributePerms` only sees what it
supplies.
- The target-database resolution fix and its fail-closed backstop, including the
numeric `table: 0` guard.
- The bulk-load opt-out keyed on the operation rather than a caller-supplied
`action`. The `__unset__` half of that fix goes away with the directive; the
pre-existing half — a direct request skipping every attribute check by attaching
`action` — stays fixed and stays tested.
Wired as a first-class operation: `OPERATIONS_ENUM.PUT`, the dispatch map, the
replication catchup switch, `requiredPermissions` with `[insert, update]` (what
`upsert` and REST `PUT` both require), the grantable `data` operation group, and
the `new_attributes`/`txn_time` result cleanup. Returns `put_hashes`; a put never
skips.
Tests: `integrationTests/database/put-operation.test.ts`, renamed from
full-record-write — 18 probes, all passing. Every guard mutation-checked: making
put ignore the marker fails 5, reading the marker off the request fails 1, dropping
the attribute-scoped denial fails 1. 143 tests across the security, terminology,
auto-fields and patch-merge suites pass, plus 575 in northwind, which exercises the
CSV and bulk-load paths.
`__unset__` is not abandoned — #2350 is being reworked from "this
is broken" into "add it properly", with concurrency-safe removal at the patch
layer rather than a read-then-replace in the bridge.
Refs: HarperFast/studio#1643
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>full_record and __unset__ with a put operation1 parent 341be57 commit 1ac8d30
14 files changed
Lines changed: 669 additions & 1224 deletions
File tree
- dataLayer
- harperBridge
- bridgeUtility
- integrationTests/database
- put-operation
- server/serverHelpers
- utility
- errors
- validation
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
12 | 11 | | |
13 | 12 | | |
14 | 13 | | |
| |||
24 | 23 | | |
25 | 24 | | |
26 | 25 | | |
27 | | - | |
| 26 | + | |
28 | 27 | | |
29 | 28 | | |
30 | 29 | | |
| |||
36 | 35 | | |
37 | 36 | | |
38 | 37 | | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | 38 | | |
48 | 39 | | |
49 | 40 | | |
| |||
208 | 199 | | |
209 | 200 | | |
210 | 201 | | |
211 | | - | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
212 | 214 | | |
213 | 215 | | |
214 | 216 | | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
220 | 221 | | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
226 | 226 | | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
232 | 231 | | |
233 | 232 | | |
234 | 233 | | |
| |||
290 | 289 | | |
291 | 290 | | |
292 | 291 | | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
301 | | - | |
302 | | - | |
303 | | - | |
304 | | - | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
309 | | - | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | 292 | | |
315 | | - | |
316 | | - | |
317 | | - | |
318 | | - | |
319 | | - | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
320 | 298 | | |
321 | 299 | | |
322 | 300 | | |
| |||
823 | 801 | | |
824 | 802 | | |
825 | 803 | | |
826 | | - | |
827 | | - | |
828 | | - | |
829 | | - | |
830 | | - | |
831 | | - | |
832 | | - | |
833 | | - | |
834 | | - | |
835 | | - | |
836 | | - | |
837 | | - | |
838 | | - | |
839 | | - | |
840 | | - | |
841 | | - | |
842 | | - | |
843 | | - | |
844 | | - | |
845 | | - | |
846 | | - | |
847 | | - | |
848 | | - | |
849 | | - | |
850 | | - | |
851 | | - | |
852 | | - | |
853 | | - | |
854 | | - | |
855 | | - | |
856 | | - | |
857 | | - | |
858 | | - | |
859 | | - | |
860 | | - | |
861 | | - | |
862 | | - | |
863 | | - | |
864 | | - | |
865 | | - | |
866 | | - | |
867 | | - | |
868 | | - | |
869 | | - | |
870 | | - | |
871 | | - | |
872 | | - | |
873 | | - | |
874 | | - | |
875 | | - | |
876 | | - | |
877 | | - | |
878 | | - | |
879 | | - | |
880 | | - | |
881 | | - | |
882 | | - | |
Lines changed: 0 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
8 | 7 | | |
9 | 8 | | |
10 | 9 | | |
| |||
74 | 73 | | |
75 | 74 | | |
76 | 75 | | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | 76 | | |
87 | 77 | | |
88 | 78 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | 18 | | |
20 | 19 | | |
21 | 20 | | |
22 | 21 | | |
23 | 22 | | |
24 | 23 | | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| |||
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | 93 | | |
120 | 94 | | |
121 | 95 | | |
| |||
245 | 219 | | |
246 | 220 | | |
247 | 221 | | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
248 | 258 | | |
249 | 259 | | |
250 | 260 | | |
| |||
281 | 291 | | |
282 | 292 | | |
283 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
284 | 300 | | |
285 | 301 | | |
286 | 302 | | |
| |||
290 | 306 | | |
291 | 307 | | |
292 | 308 | | |
293 | | - | |
| 309 | + | |
0 commit comments