Commit 4fedb11
* fix(objectql): retire `sys_fetch_previous_delete` so the delete-path per-object gate is honest (#5929)
`delete()`'s prior-row read is gated per object on
`hasHooksFor('beforeDelete', object) || hasHooksFor('afterDelete', object)
|| getSummaryDescriptors(object).length > 0`. On any kernel-hosted engine the
first term was constant true, because `ObjectQLPlugin` registered its own
`sys_fetch_previous_delete` builtin with `object: '*'` — so the per-object skip
the gate exists to perform never happened outside the bare engines unit tests
boot.
The builtin could not use what it held open. Since #5272 (by-id) and #6697
(predicate path, per matched row) the engine reads the pre-image and binds
`previous` before `beforeDelete` dispatches, so its `!ctx.previous` guard was
permanently false and it issued no read. Its only remaining effect was holding
open the gate that made it redundant. Retired under ADR-0049 enforce-or-remove;
the measurement #5846 recorded in `plugin.ts` was re-verified on this branch
rather than taken on trust.
The gate's three terms are unchanged — no term was added or removed. What
changed is that term 1 now reflects real hooks. `engine.ts` gains the
enumeration of the delete-phase hooks that still register globally
(plugin-auth, plugin-sharing, service-storage; plugin-audit narrows at the
engine face with `excludeObjects`), so nobody reads a skip into a trace that
will not show one.
New `engine-delete-prior-read-scope.test.ts` pins the three terms per object,
the `excludeObjects` subtraction on both phases, the predicate path's twin
gate, and — on a real `ObjectKernel` + `ObjectQLPlugin`, the only configuration
where the defect was observable — the zero-read skip and the still-bound
`previous`. It replays the retired builtin's own shape and measures its guard
short-circuiting, so "the guard can no longer be true" stays a measurement.
The by-id `beforeDelete` REPOINT behaviour is deliberately untouched (#6752).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UNT8SWDEsDQp2TrmSBizKq
* test(objectql): keep the new delete-gate pins inside the erasure ratchets (#5929)
Two lint.yml gates caught the new test file on the first full run:
* `check:slot-lookup` / `no-restricted-syntax` — `kernel.getService('objectql')
as any` erased the slot's contract for every `engine.*` call in the kernel
section, which is where the measurement lives. Typed as
`getService<ObjectQL>('objectql')`.
* `check:query-options-erasure` — three `count(obj, {} as any)` calls grew the
test-surface count 263 → 266. The empty options bag is already on contract;
the assertion was never needed.
No assertion changed; the file still passes 16/16.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UNT8SWDEsDQp2TrmSBizKq
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent f012f55 commit 4fedb11
5 files changed
Lines changed: 713 additions & 47 deletions
File tree
- .changeset
- packages
- objectql/src
- plugins/plugin-auth/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 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
0 commit comments